[testnet] Add AssetHubRococo <-> AssetHubWestend asset bridging support (#1967)

## Summary

Asset bridging support for AssetHub**Rococo** <-> AssetHub**Wococo** was
added [here](https://github.com/paritytech/polkadot-sdk/pull/1215), so
now we aim to bridge AssetHub**Rococo** and AssetHub**Westend**. (And
perhaps retire AssetHubWococo and the Wococo chains).

## Solution

**bridge-hub-westend-runtime**
- added new runtime as a copy of `bridge-hub-rococo-runtime`
- added support for bridging to `BridgeHubRococo`
- added tests and benchmarks

**bridge-hub-rococo-runtime**
- added support for bridging to `BridgeHubWestend`
- added tests and benchmarks
- internal refactoring by splitting bridge configuration per network,
e.g., `bridge_to_whatevernetwork_config.rs`.

**asset-hub-rococo-runtime**
- added support for asset bridging to `AssetHubWestend` (allows to
receive only WNDs)
- added new xcm router for `Westend`
- added tests and benchmarks

**asset-hub-westend-runtime**
- added support for asset bridging to `AssetHubRococo` (allows to
receive only ROCs)
- added new xcm router for `Rococo`
- added tests and benchmarks

## Deployment

All changes will be deployed as a part of
https://github.com/paritytech/polkadot-sdk/issues/1988.

## TODO

- [x] benchmarks for all pallet instances
- [x] integration tests
- [x] local run scripts


Relates to:
https://github.com/paritytech/parity-bridges-common/issues/2602
Relates to: https://github.com/paritytech/polkadot-sdk/issues/1988

---------

Co-authored-by: command-bot <>
Co-authored-by: Adrian Catangiu <adrian@parity.io>
Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
This commit is contained in:
Branislav Kontur
2023-11-02 00:39:49 +01:00
committed by GitHub
parent c66ae375e6
commit 1b1fab0da3
112 changed files with 10028 additions and 1638 deletions
+43 -1
View File
@@ -325,6 +325,12 @@ pub mod pallet {
rewards_account_params,
new_reward,
);
Self::deposit_event(Event::<T>::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<T: Config> {
/// 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::<TestRuntime>::reset_events();
}
#[test]
fn register_relayer_reward_emit_event() {
run_test(|| {
get_ready_for_events();
Pallet::<TestRuntime>::register_relayer_reward(
TEST_REWARDS_ACCOUNT_PARAMS,
&REGULAR_RELAYER,
100,
);
// Check if the `RewardRegistered` event was emitted.
assert_eq!(
System::<TestRuntime>::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(|| {
@@ -335,7 +335,7 @@ impl<T: Config<I>, I: 'static> SendXcm for Pallet<T, I> {
// 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::<T, I>::validate(dest, xcm)
@@ -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.
@@ -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 = { path = "../../../substrate/frame/support", 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",
]
@@ -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 <http://www.gnu.org/licenses/>.
//! 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 BridgeHubWestendBaseFeeInWnds: u128 = 487441010000;
}
/// Identifier of AssetHubWestend in the Westend relay chain.
pub const ASSET_HUB_WESTEND_PARACHAIN_ID: u32 = 1000;
@@ -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.
@@ -68,15 +68,17 @@ pub type Address = MultiAddress<AccountId, ()>;
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_WOCOCO_TO_ROCOCO_MESSAGES_PALLET_NAME: &str =
"BridgeWococoToRococoMessages";
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";
/// Pallet index of `BridgeRococoToWococoMessages: pallet_bridge_messages::<Instance1>`.
/// Pallet index of `BridgeWococoMessages: pallet_bridge_messages::<Instance1>`.
pub const WITH_BRIDGE_ROCOCO_TO_WOCOCO_MESSAGES_PALLET_INDEX: u8 = 46;
/// Pallet index of `BridgeWestendMessages: pallet_bridge_messages::<Instance3>`.
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);
@@ -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 = { path = "../../../substrate/frame/support", default-features = false }
sp-api = { path = "../../../substrate/primitives/api", default-features = false }
sp-runtime = { path = "../../../substrate/primitives/runtime", default-features = false }
sp-std = { path = "../../../substrate/primitives/std", 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",
]
@@ -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 <http://www.gnu.org/licenses/>.
//! 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::<Instance1>`.
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);
@@ -62,14 +62,13 @@ impl Parachain for BridgeHubWococo {
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_ROCOCO_TO_WOCOCO_MESSAGES_PALLET_NAME: &str =
"BridgeRococoToWococoMessages";
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 `BridgeWococoToRococoMessages: pallet_bridge_messages::<Instance2>`.
/// Pallet index of `BridgeRococoMessages: pallet_bridge_messages::<Instance2>`.
pub const WITH_BRIDGE_WOCOCO_TO_ROCOCO_MESSAGES_PALLET_INDEX: u8 = 45;
decl_bridge_finality_runtime_apis!(bridge_hub_wococo);
@@ -2,8 +2,8 @@
name = "bp-polkadot-bulletin"
description = "Primitives of Polkadot Bulletin chain runtime."
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
authors.workspace = true
edition.workspace = true
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[dependencies]
+1 -1
View File
@@ -16,9 +16,9 @@ bp-runtime = { path = "../runtime", default-features = false }
# Substrate Based Dependencies
frame-support = { path = "../../../substrate/frame/support", default-features = false }
sp-api = { path = "../../../substrate/primitives/api", default-features = false }
sp-std = { path = "../../../substrate/primitives/std", default-features = false }
frame-support = { path = "../../../substrate/frame/support", default-features = false }
[features]
default = [ "std" ]
@@ -0,0 +1,32 @@
[package]
name = "bp-westend"
description = "Primitives of Westend 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 }
# Substrate Based Dependencies
frame-support = { path = "../../../substrate/frame/support", default-features = false }
sp-api = { path = "../../../substrate/primitives/api", default-features = false }
sp-std = { path = "../../../substrate/primitives/std", default-features = false }
[features]
default = [ "std" ]
std = [
"bp-header-chain/std",
"bp-polkadot-core/std",
"bp-runtime/std",
"frame-support/std",
"sp-api/std",
"sp-std/std",
]
@@ -0,0 +1,79 @@
// 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 <http://www.gnu.org/licenses/>.
#![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};
/// Westend Chain
pub struct Westend;
impl Chain for Westend {
type BlockNumber = <PolkadotLike as Chain>::BlockNumber;
type Hash = <PolkadotLike as Chain>::Hash;
type Hasher = <PolkadotLike as Chain>::Hasher;
type Header = <PolkadotLike as Chain>::Header;
type AccountId = <PolkadotLike as Chain>::AccountId;
type Balance = <PolkadotLike as Chain>::Balance;
type Nonce = <PolkadotLike as Chain>::Nonce;
type Signature = <PolkadotLike as Chain>::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;
}
parameter_types! {
pub const SS58Prefix: u8 = 42;
}
// 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";
/// Name of the With-Westend GRANDPA pallet instance that is deployed at bridged chains.
pub const WITH_WESTEND_GRANDPA_PALLET_NAME: &str = "BridgeWestendGrandpa";
/// 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;
decl_bridge_finality_runtime_apis!(westend, grandpa);
+3 -1
View File
@@ -23,7 +23,6 @@ use frame_support::{
pallet_prelude::DispatchResult, weights::Weight, PalletError, StorageHasher, StorageValue,
};
use frame_system::RawOrigin;
use log;
use scale_info::TypeInfo;
use serde::{Deserialize, Serialize};
use sp_core::storage::StorageKey;
@@ -98,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";
-1
View File
@@ -74,7 +74,6 @@ rm -rf $BRIDGES_FOLDER/primitives/beefy
rm -rf $BRIDGES_FOLDER/primitives/chain-millau
rm -rf $BRIDGES_FOLDER/primitives/chain-rialto
rm -rf $BRIDGES_FOLDER/primitives/chain-rialto-parachain
rm -rf $BRIDGES_FOLDER/primitives/chain-westend
rm -rf $BRIDGES_FOLDER/relays
rm -rf $BRIDGES_FOLDER/scripts/add_license.sh
rm -rf $BRIDGES_FOLDER/scripts/build-containers.sh
+31
View File
@@ -0,0 +1,31 @@
# Bridges Tests for Local Rococo <> Wococo Bridge
This folder contains [zombienet](https://github.com/paritytech/zombienet/) based integration tests for both
onchain and offchain bridges code. Due to some
[technical diffuculties](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` 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_FOLDER` 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.
@@ -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<BpRuntimeHeaderId>", 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, 12000));
}
}
module.exports = { run }
@@ -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, 12000));
}
}
module.exports = { run }
@@ -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, 12000));
}
}
module.exports = { run }
+97
View File
@@ -0,0 +1,97 @@
#!/bin/bash
#set -eu
shopt -s nullglob
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
# 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_FOLDER=`realpath $(dirname "$0")/../..`
export BRIDGE_TESTS_FOLDER=$POLKADOT_SDK_FOLDER/bridges/zombienet/tests
export POLKADOT_BINARY_PATH=$POLKADOT_SDK_FOLDER/target/release/polkadot
export POLKADOT_PARACHAIN_BINARY_PATH=$POLKADOT_SDK_FOLDER/target/release/polkadot-parachain
export POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_ROCOCO=$POLKADOT_PARACHAIN_BINARY_PATH
export POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_WOCOCO=$POLKADOT_PARACHAIN_BINARY_PATH
export ZOMBIENET_BINARY_PATH=~/local_bridge_testing/bin/zombienet-linux
# bridge configuration
export LANE_ID="00000001"
# tests configuration
ALL_TESTS_FOLDER=`mktemp -d`
function start_coproc() {
local command=$1
local name=$2
local coproc_log=`mktemp -p $TEST_FOLDER`
coproc COPROC {
$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=1
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`
# check if there are no more tests
zndsl_files=($BRIDGE_TESTS_FOLDER/$TEST_PREFIX-*.zndsl)
if [ ${#zndsl_files[@]} -eq 0 ]; then
break
fi
# start relay
if [ -f $BRIDGE_TESTS_FOLDER/$TEST_PREFIX-start-relay.sh ]; then
start_coproc "${BRIDGE_TESTS_FOLDER}/${TEST_PREFIX}-start-relay.sh" "relay"
RELAY_COPROC=$COPROC_PID
((TEST_COPROCS_COUNT++))
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
relay_exited=0
for n in `seq 1 $TEST_COPROCS_COUNT`; do
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)
relay_exited=$(expr "${coproc_name}" == "relay")
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
# if last test has exited, exit relay too
if [ $n -eq $(($TEST_COPROCS_COUNT - 1)) ] && [ $relay_exited -eq 0 ]; then
kill $RELAY_COPROC
break
fi
done
((TEST_INDEX++))
done
echo "====================================================================="
echo "=== All tests have completed successfully ==="
echo "====================================================================="
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
pushd $POLKADOT_SDK_FOLDER/cumulus/scripts
./bridges_rococo_wococo.sh $1
popd
+14
View File
@@ -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
@@ -0,0 +1,25 @@
Description: User is able to transfer ROC from Rococo Asset Hub to Wococo Asset Hub
Network: ../../../cumulus/zombienet/bridge-hubs/bridge_hub_wococo_local_network.toml
Creds: config
# step 1: initialize Wococo asset hub
asset-hub-wococo-collator1: run ../scripts/invoke-script.sh with "init-asset-hub-wococo-local" within 120 seconds
# step 2: initialize Wococo bridge hub
bridge-hub-wococo-collator1: run ../scripts/invoke-script.sh with "init-bridge-hub-wococo-local" within 120 seconds
# step 3: relay is started elsewhere - let's wait until with-Rococo GRANPDA pallet is initialized at Wococo
bridge-hub-wococo-collator1: js-script ../helpers/best-finalized-header-at-bridged-chain.js with "Rococo,0" within 400 seconds
# step 2: send WOC to Rococo
asset-hub-wococo-collator1: run ../scripts/invoke-script.sh with "reserve-transfer-assets-from-asset-hub-wococo-local" within 60 seconds
# step 3: elsewhere Rococo has sent ROC to //Alice - let's wait for it
asset-hub-wococo-collator1: js-script ../helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,0,Rococo" within 600 seconds
# step 4: check that the relayer //Charlie is rewarded by both our AH and target AH
bridge-hub-wococo-collator1: js-script ../helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000001,0x6268726F,BridgedChain,0" within 300 seconds
bridge-hub-wococo-collator1: js-script ../helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000001,0x6268726F,ThisChain,0" within 300 seconds
# wait until other network test has completed OR exit with an error too
asset-hub-wococo-collator1: run ../scripts/sync-exit.sh within 600 seconds
@@ -0,0 +1,25 @@
Description: User is able to transfer WOC from Wococo Asset Hub to Rococo Asset Hub
Network: ../../../cumulus/zombienet/bridge-hubs/bridge_hub_rococo_local_network.toml
Creds: config
# step 1: initialize Rococo asset hub
asset-hub-rococo-collator1: run ../scripts/invoke-script.sh with "init-asset-hub-rococo-local" within 120 seconds
# step 2: initialize Rococo bridge hub
bridge-hub-rococo-collator1: run ../scripts/invoke-script.sh with "init-bridge-hub-rococo-local" within 120 seconds
# step 3: relay is started elsewhere - let's wait until with-Wococo GRANPDA pallet is initialized at Rococo
bridge-hub-rococo-collator1: js-script ../helpers/best-finalized-header-at-bridged-chain.js with "Wococo,0" within 400 seconds
# step 4: send ROC to Wococo
asset-hub-rococo-collator1: run ../scripts/invoke-script.sh with "reserve-transfer-assets-from-asset-hub-rococo-local" within 60 seconds
# step 5: elsewhere Wococo has sent WOC to //Alice - let's wait for it
asset-hub-rococo-collator1: js-script ../helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,0,Wococo" within 600 seconds
# step 6: check that the relayer //Charlie is rewarded by both our AH and target AH
bridge-hub-rococo-collator1: js-script ../helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000001,0x6268776F,BridgedChain,0" within 300 seconds
bridge-hub-rococo-collator1: js-script ../helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000001,0x6268776F,ThisChain,0" within 300 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
@@ -0,0 +1,5 @@
#!/bin/bash
pushd $POLKADOT_SDK_FOLDER/cumulus/scripts
./bridges_rococo_wococo.sh run-relay
popd