feat: initialize Kurdistan SDK - independent fork of Polkadot SDK

This commit is contained in:
2025-12-13 15:44:15 +03:00
commit e4778b4576
6838 changed files with 1847450 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
# Bridges Tests for Local pezkuwichain <> zagros Bridge
This folder contains [zombienet](https://github.com/paritytech/zombienet/) based integration tests for both
onchain and offchain bridges code.
Prerequisites for running the tests locally:
- download latest [zombienet release](https://github.com/paritytech/zombienet/releases) and place it at
`~/local_bridge_testing/bin/zombienet`;
- build PezkuwiChain binary by running `cargo build -p pezkuwi --release --features fast-runtime` command in the
[`pezkuwi-sdk`](https://github.com/pezkuwichain/pezkuwi-sdk) repository clone;
- build PezkuwiChain Teyrchain binary by running `cargo build -p pezkuwi-teyrchain-bin --release` command in the
[`pezkuwi-sdk`](https://github.com/pezkuwichain/pezkuwi-sdk) repository clone;
- ensure that you have [`node`](https://nodejs.org/en) installed. Additionally, we'll need the globally installed
`pezkuwi/api-cli` package. Use `yarn global add @pezkuwi/api-cli` 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 the `substrate-relay` binary, built in the previous step, to `~/local_bridge_testing/bin/substrate-relay`;
On Mac, you'll also need to do the following:
- Install an updated version of bash by installing homebrew and running `brew install bash`;
- Install jq with `brew install jq`;
After that, any test can be run using the `run-test.sh` command.
Example: `./run-test.sh 0001-asset-transfer`
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 teyrchain nodes.
@@ -0,0 +1,74 @@
[settings]
node_spawn_timeout = 240
[relaychain]
default_command = "{{PEZKUWI_BINARY}}"
default_args = ["-lteyrchain=debug,xcm=trace"]
chain = "pezkuwichain-local"
[[relaychain.nodes]]
name = "alice-pezkuwichain-validator"
validator = true
rpc_port = 9942
balance = 2000000000000
[[relaychain.nodes]]
name = "bob-pezkuwichain-validator"
validator = true
rpc_port = 9943
balance = 2000000000000
[[relaychain.nodes]]
name = "charlie-pezkuwichain-validator"
validator = true
rpc_port = 9944
balance = 2000000000000
[[teyrchains]]
id = 1013
chain = "bridge-hub-pezkuwichain-local"
cumulus_based = true
# run alice as teyrchain collator
[[teyrchains.collators]]
name = "bridge-hub-pezkuwichain-collator1"
validator = true
command = "{{PEZKUWI_TEYRCHAIN_BINARY}}"
rpc_port = 8943
args = ["-lteyrchain=debug,runtime::bridge=trace,xcm=trace,txpool=trace"]
# run bob as teyrchain collator
[[teyrchains.collators]]
name = "bridge-hub-pezkuwichain-collator2"
validator = true
command = "{{PEZKUWI_TEYRCHAIN_BINARY}}"
rpc_port = 8944
args = ["-lteyrchain=debug,runtime::bridge=trace,xcm=trace,txpool=trace"]
[[teyrchains]]
id = 1000
chain = "asset-hub-pezkuwichain-local"
cumulus_based = true
[[teyrchains.collators]]
name = "asset-hub-pezkuwichain-collator1"
rpc_port = 9910
command = "{{PEZKUWI_TEYRCHAIN_BINARY}}"
args = ["-lteyrchain=debug,xcm=trace,runtime::bridge=trace,txpool=trace"]
[[teyrchains.collators]]
name = "asset-hub-pezkuwichain-collator2"
command = "{{PEZKUWI_TEYRCHAIN_BINARY}}"
args = ["-lteyrchain=debug,xcm=trace,runtime::bridge=trace,txpool=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
@@ -0,0 +1,74 @@
[settings]
node_spawn_timeout = 240
[relaychain]
default_command = "{{PEZKUWI_BINARY}}"
default_args = ["-lteyrchain=debug,xcm=trace"]
chain = "zagros-local"
[[relaychain.nodes]]
name = "alice-zagros-validator"
validator = true
rpc_port = 9945
balance = 2000000000000
[[relaychain.nodes]]
name = "bob-zagros-validator"
validator = true
rpc_port = 9946
balance = 2000000000000
[[relaychain.nodes]]
name = "charlie-zagros-validator"
validator = true
rpc_port = 9947
balance = 2000000000000
[[teyrchains]]
id = 1002
chain = "bridge-hub-zagros-local"
cumulus_based = true
# run alice as teyrchain collator
[[teyrchains.collators]]
name = "bridge-hub-zagros-collator1"
validator = true
command = "{{PEZKUWI_TEYRCHAIN_BINARY}}"
rpc_port = 8945
args = ["-lteyrchain=debug,runtime::bridge=trace,xcm=trace,txpool=trace"]
# run bob as teyrchain collator
[[teyrchains.collators]]
name = "bridge-hub-zagros-collator2"
validator = true
command = "{{PEZKUWI_TEYRCHAIN_BINARY}}"
rpc_port = 8946
args = ["-lteyrchain=debug,runtime::bridge=trace,xcm=trace,txpool=trace"]
[[teyrchains]]
id = 1000
chain = "asset-hub-zagros-local"
cumulus_based = true
[[teyrchains.collators]]
name = "asset-hub-zagros-collator1"
rpc_port = 9010
command = "{{PEZKUWI_TEYRCHAIN_BINARY}}"
args = ["-lteyrchain=debug,xcm=trace,runtime::bridge=trace,txpool=trace"]
[[teyrchains.collators]]
name = "asset-hub-zagros-collator2"
command = "{{PEZKUWI_TEYRCHAIN_BINARY}}"
args = ["-lteyrchain=debug,xcm=trace,runtime::bridge=trace,txpool=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
@@ -0,0 +1,470 @@
#!/usr/bin/env bash
# import common functions
source "$FRAMEWORK_PATH/utils/bridges.sh"
# Expected sovereign accounts.
#
# Generated by:
#
##[test]
#fn generate_sovereign_accounts() {
# use pezkuwi_teyrchain_primitives::primitives::Sibling;
# use sp_core::crypto::Ss58Codec;
# use staging_xcm_builder::{GlobalConsensusConvertsFor, SiblingTeyrchainConvertsVia};
# use xcm::latest::{prelude::*, PEZKUWICHAIN_GENESIS_HASH, ZAGROS_GENESIS_HASH};
# use xcm_executor::traits::ConvertLocation;
#
# const Pezkuwichain: NetworkId = NetworkId::ByGenesis(PEZKUWICHAIN_GENESIS_HASH);
# const Zagros: NetworkId = NetworkId::ByGenesis(ZAGROS_GENESIS_HASH);
# frame_support::parameter_types! {
# pub UniversalLocationAHR: InteriorLocation = [GlobalConsensus(Pezkuwichain), Teyrchain(1000)].into();
# pub UniversalLocationAHW: InteriorLocation = [GlobalConsensus(Zagros), Teyrchain(1000)].into();
# }
#
# // SS58=42
# println!("ASSET_HUB_ZAGROS_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_ZAGROS=\"{}\"",
# frame_support::sp_runtime::AccountId32::new(
# SiblingTeyrchainConvertsVia::<Sibling, [u8; 32]>::convert_location(
# &Location { parents: 1, interior: Teyrchain(1000).into() }).unwrap()
# ).to_ss58check_with_version(42_u16.into())
# );
#
# // SS58=42
# println!("ASSET_HUB_PEZKUWICHAIN_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_PEZKUWICHAIN=\"{}\"",
# frame_support::sp_runtime::AccountId32::new(
# SiblingTeyrchainConvertsVia::<Sibling, [u8; 32]>::convert_location(
# &Location { parents: 1, interior: Teyrchain(1000).into() }).unwrap()
# ).to_ss58check_with_version(42_u16.into())
# );
#}
ASSET_HUB_ZAGROS_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_ZAGROS="5Eg2fntNprdN3FgH4sfEaaZhYtddZQSQUqvYJ1f2mLtinVhV"
ASSET_HUB_PEZKUWICHAIN_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_PEZKUWICHAIN="5Eg2fntNprdN3FgH4sfEaaZhYtddZQSQUqvYJ1f2mLtinVhV"
BOB_ACCOUNT_AT_PEZKUWICHAIN="5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"
BOB_ACCOUNT_AT_ZAGROS="5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"
# Expected sovereign accounts for rewards on BridgeHubs.
#
# Generated by:
##[test]
#fn generate_sovereign_accounts_for_rewards() {
# use bp_messages::LegacyLaneId;
# use bp_relayers::{PayRewardFromAccount, RewardsAccountOwner, RewardsAccountParams};
# use sp_core::crypto::Ss58Codec;
#
# // SS58=42
# println!(
# "ON_BRIDGE_HUB_PEZKUWICHAIN_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhwd_ThisChain=\"{}\"",
# frame_support::sp_runtime::AccountId32::new(
# PayRewardFromAccount::<[u8; 32], [u8; 32], LegacyLaneId>::rewards_account(RewardsAccountParams::new(
# LegacyLaneId([0, 0, 0, 2]),
# *b"bhwd",
# RewardsAccountOwner::ThisChain
# ))
# )
# .to_ss58check_with_version(42_u16.into())
# );
# // SS58=42
# println!(
# "ON_BRIDGE_HUB_PEZKUWICHAIN_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhwd_BridgedChain=\"{}\"",
# frame_support::sp_runtime::AccountId32::new(
# PayRewardFromAccount::<[u8; 32], [u8; 32], LegacyLaneId>::rewards_account(RewardsAccountParams::new(
# LegacyLaneId([0, 0, 0, 2]),
# *b"bhwd",
# RewardsAccountOwner::BridgedChain
# ))
# )
# .to_ss58check_with_version(42_u16.into())
# );
#
# // SS58=42
# println!(
# "ON_BRIDGE_HUB_ZAGROS_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhro_ThisChain=\"{}\"",
# frame_support::sp_runtime::AccountId32::new(
# PayRewardFromAccount::<[u8; 32], [u8; 32], LegacyLaneId>::rewards_account(RewardsAccountParams::new(
# LegacyLaneId([0, 0, 0, 2]),
# *b"bhro",
# RewardsAccountOwner::ThisChain
# ))
# )
# .to_ss58check_with_version(42_u16.into())
# );
# // SS58=42
# println!(
# "ON_BRIDGE_HUB_ZAGROS_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhro_BridgedChain=\"{}\"",
# frame_support::sp_runtime::AccountId32::new(
# PayRewardFromAccount::<[u8; 32], [u8; 32], LegacyLaneId>::rewards_account(RewardsAccountParams::new(
# LegacyLaneId([0, 0, 0, 2]),
# *b"bhro",
# RewardsAccountOwner::BridgedChain
# ))
# )
# .to_ss58check_with_version(42_u16.into())
# );
#}
ON_BRIDGE_HUB_PEZKUWICHAIN_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhwd_ThisChain="5EHnXaT5GApse1euZWj9hycMbgjKBCNQL9WEwScL8QDx6mhK"
ON_BRIDGE_HUB_PEZKUWICHAIN_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhwd_BridgedChain="5EHnXaT5Tnt4A8aiP9CsuAFRhKPjKZJXRrj4a3mtihFvKpTi"
ON_BRIDGE_HUB_ZAGROS_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhro_ThisChain="5EHnXaT5GApry9tS6yd1FVusPq8o8bQJGCKyvXTFCoEKk5Z9"
ON_BRIDGE_HUB_ZAGROS_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhro_BridgedChain="5EHnXaT5Tnt3VGpEvc6jSgYwVToDGxLRMuYoZ8coo6GHyWbR"
LANE_ID="00000002"
XCM_VERSION=5
# 6408de7737c59c238890533af25896a2c20608d8b380bb01029acb392781063e
PEZKUWICHAIN_GENESIS_HASH=[100,8,222,119,55,197,156,35,136,144,83,58,242,88,150,162,194,6,8,216,179,128,187,1,2,154,203,57,39,129,6,62]
# e143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423e
ZAGROS_GENESIS_HASH=[225,67,242,56,3,172,80,232,246,248,230,38,149,209,206,158,78,29,104,170,54,193,205,44,253,21,52,2,19,243,66,62]
function init_ro_wnd() {
local relayer_path=$(ensure_relayer)
RUST_LOG=runtime=trace,rpc=trace,bridge=trace \
$relayer_path init-bridge pezkuwichain-to-bridge-hub-zagros \
--source-uri ws://localhost:9942 \
--source-version-mode Auto \
--target-uri ws://localhost: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 zagros-to-bridge-hub-pezkuwichain \
--source-uri ws://localhost:9945 \
--source-version-mode Auto \
--target-uri ws://localhost:8943 \
--target-version-mode Auto \
--target-signer //Bob
}
function run_finality_relay() {
local relayer_path=$(ensure_relayer)
RUST_LOG=runtime=trace,rpc=trace,bridge=trace \
$relayer_path relay-headers pezkuwichain-to-bridge-hub-zagros \
--only-free-headers \
--source-uri ws://localhost:9942 \
--source-version-mode Auto \
--target-uri ws://localhost:8945 \
--target-version-mode Auto \
--target-signer //Charlie \
--target-transactions-mortality 4&
RUST_LOG=runtime=trace,rpc=trace,bridge=trace \
$relayer_path relay-headers zagros-to-bridge-hub-pezkuwichain \
--only-free-headers \
--source-uri ws://localhost:9945 \
--source-version-mode Auto \
--target-uri ws://localhost:8943 \
--target-version-mode Auto \
--target-signer //Charlie \
--target-transactions-mortality 4
}
function run_teyrchains_relay() {
local relayer_path=$(ensure_relayer)
RUST_LOG=runtime=trace,rpc=trace,bridge=trace \
$relayer_path relay-teyrchains bridge-hub-pezkuwichain-to-bridge-hub-zagros \
--only-free-headers \
--source-uri ws://localhost:9942 \
--source-version-mode Auto \
--target-uri ws://localhost:8945 \
--target-version-mode Auto \
--target-signer //Dave \
--target-transactions-mortality 4&
RUST_LOG=runtime=trace,rpc=trace,bridge=trace \
$relayer_path relay-teyrchains bridge-hub-zagros-to-bridge-hub-pezkuwichain \
--only-free-headers \
--source-uri ws://localhost:9945 \
--source-version-mode Auto \
--target-uri ws://localhost:8943 \
--target-version-mode Auto \
--target-signer //Dave \
--target-transactions-mortality 4
}
function run_messages_relay() {
local relayer_path=$(ensure_relayer)
RUST_LOG=runtime=trace,rpc=trace,bridge=trace \
$relayer_path relay-messages bridge-hub-pezkuwichain-to-bridge-hub-zagros \
--source-uri ws://localhost:8943 \
--source-version-mode Auto \
--source-signer //Eve \
--source-transactions-mortality 4 \
--target-uri ws://localhost:8945 \
--target-version-mode Auto \
--target-signer //Eve \
--target-transactions-mortality 4 \
--lane $LANE_ID&
RUST_LOG=runtime=trace,rpc=trace,bridge=trace \
$relayer_path relay-messages bridge-hub-zagros-to-bridge-hub-pezkuwichain \
--source-uri ws://localhost:8945 \
--source-version-mode Auto \
--source-signer //Ferdie \
--source-transactions-mortality 4 \
--target-uri ws://localhost:8943 \
--target-version-mode Auto \
--target-signer //Ferdie \
--target-transactions-mortality 4 \
--lane $LANE_ID
}
case "$1" in
run-finality-relay)
init_wnd_ro
init_ro_wnd
run_finality_relay
;;
run-teyrchains-relay)
run_teyrchains_relay
;;
run-messages-relay)
run_messages_relay
;;
init-pezkuwichain-local)
# 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
# governance set XCM version of remote AssetHubZagros on AHR
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": { ByGenesis: '$ZAGROS_GENESIS_HASH' } }, { "Teyrchain": 1000 } ] } }')" \
$XCM_VERSION
# governance set XCM version of remote BridgeHubZagros on BHR
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": { ByGenesis: '$ZAGROS_GENESIS_HASH' } }, { "Teyrchain": 1002 } ] } }')" \
$XCM_VERSION
;;
init-asset-hub-pezkuwichain-local)
ensure_pezkuwi_js_api
# create foreign asset pool
create_pool \
"ws://127.0.0.1:9910" \
"//Bob" \
"$(jq --null-input '{ "parents": 1, "interior": "Here" }')" \
"$(jq --null-input '{ "parents": 2, "interior": { "X1": [{ "GlobalConsensus": { ByGenesis: '$ZAGROS_GENESIS_HASH' } }] } }')"
# Create liquidity in the pool
add_liquidity \
"ws://127.0.0.1:9910" \
"//Bob" \
"$(jq --null-input '{ "parents": 1, "interior": "Here" }')" \
"$(jq --null-input '{ "parents": 2, "interior": { "X1": [{ "GlobalConsensus": { ByGenesis: '$ZAGROS_GENESIS_HASH' } }] } }')" \
1000000000000 \
2500000000000 \
"$BOB_ACCOUNT_AT_PEZKUWICHAIN"
;;
init-bridge-hub-pezkuwichain-local)
ensure_pezkuwi_js_api
# SA of sibling asset hub pays for the execution
transfer_balance \
"ws://127.0.0.1:8943" \
"//Alice" \
"$ASSET_HUB_PEZKUWICHAIN_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_PEZKUWICHAIN" \
100000000000000
# 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_PEZKUWICHAIN_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhwd_ThisChain" \
100000000000000
# 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_PEZKUWICHAIN_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhwd_BridgedChain" \
100000000000000
;;
init-zagros-local)
# 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
# governance set XCM version of remote AssetHubPezkuwichain on AHW
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": { ByGenesis: '$PEZKUWICHAIN_GENESIS_HASH' } }, { "Teyrchain": 1000 } ] } }')" \
$XCM_VERSION
# governance set XCM version of remote BridgeHubPezkuwichain on BHW
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": { ByGenesis: '$PEZKUWICHAIN_GENESIS_HASH' } }, { "Teyrchain": 1013 } ] } }')" \
$XCM_VERSION
;;
init-asset-hub-zagros-local)
ensure_pezkuwi_js_api
# create foreign asset pool
create_pool \
"ws://127.0.0.1:9010" \
"//Bob" \
"$(jq --null-input '{ "parents": 1, "interior": "Here" }')" \
"$(jq --null-input '{ "parents": 2, "interior": { "X1": [{ "GlobalConsensus": { ByGenesis: '$PEZKUWICHAIN_GENESIS_HASH' } }] } }')"
# Create liquidity in the pool
add_liquidity \
"ws://127.0.0.1:9010" \
"//Bob" \
"$(jq --null-input '{ "parents": 1, "interior": "Here" }')" \
"$(jq --null-input '{ "parents": 2, "interior": { "X1": [{ "GlobalConsensus": { ByGenesis: '$PEZKUWICHAIN_GENESIS_HASH' } }] } }')" \
1000000000000 \
4000000000000 \
"$BOB_ACCOUNT_AT_ZAGROS"
;;
init-bridge-hub-zagros-local)
# SA of sibling asset hub pays for the execution
transfer_balance \
"ws://127.0.0.1:8945" \
"//Alice" \
"$ASSET_HUB_ZAGROS_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_ZAGROS" \
100000000000000
# 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_ZAGROS_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhro_ThisChain" \
100000000000000
# 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_ZAGROS_SOVEREIGN_ACCOUNT_FOR_LANE_00000002_bhro_BridgedChain" \
100000000000000
;;
reserve-transfer-assets-from-asset-hub-pezkuwichain-local)
amount=$2
ensure_pezkuwi_js_api
# send TYRs to Alice account on AHW
limited_reserve_transfer_assets \
"ws://127.0.0.1:9910" \
"//Alice" \
"$(jq --null-input '{ "V5": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": { ByGenesis: '$ZAGROS_GENESIS_HASH' } }, { "Teyrchain": 1000 } ] } } }')" \
"$(jq --null-input '{ "V5": { "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 '{ "V5": [ { "id": { "parents": 1, "interior": "Here" }, "fun": { "Fungible": '$amount' } } ] }')" \
"$(jq --null-input '{ "V5": { "parents": 1, "interior": "Here" } }')" \
"Unlimited"
;;
withdraw-reserve-assets-from-asset-hub-pezkuwichain-local)
amount=$2
ensure_pezkuwi_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 '{ "V5": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": { ByGenesis: '$ZAGROS_GENESIS_HASH' } }, { "Teyrchain": 1000 } ] } } }')" \
"$(jq --null-input '{ "V5": { "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 '{ "V5": [ { "id": { "parents": 2, "interior": { "X1": [{ "GlobalConsensus": { ByGenesis: '$ZAGROS_GENESIS_HASH' } }] } }, "fun": { "Fungible": '$amount' } } ] }')" \
"$(jq --null-input '{ "V5": { "parents": 2, "interior": { "X1": [{ "GlobalConsensus": { ByGenesis: '$ZAGROS_GENESIS_HASH' } }] } } }')" \
"Unlimited"
;;
reserve-transfer-assets-from-asset-hub-zagros-local)
amount=$2
ensure_pezkuwi_js_api
# send ZGRs to Alice account on AHR
limited_reserve_transfer_assets \
"ws://127.0.0.1:9010" \
"//Alice" \
"$(jq --null-input '{ "V5": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": { ByGenesis: '$PEZKUWICHAIN_GENESIS_HASH' } }, { "Teyrchain": 1000 } ] } } }')" \
"$(jq --null-input '{ "V5": { "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 '{ "V5": [ { "id": { "parents": 1, "interior": "Here" }, "fun": { "Fungible": '$amount' } } ] }')" \
"$(jq --null-input '{ "V5": { "parents": 1, "interior": "Here" } }')" \
"Unlimited"
;;
withdraw-reserve-assets-from-asset-hub-zagros-local)
amount=$2
ensure_pezkuwi_js_api
# send back only 100000000000 wrappedTYRs to Alice account on AHR
limited_reserve_transfer_assets \
"ws://127.0.0.1:9010" \
"//Alice" \
"$(jq --null-input '{ "V5": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": { ByGenesis: '$PEZKUWICHAIN_GENESIS_HASH' } }, { "Teyrchain": 1000 } ] } } }')" \
"$(jq --null-input '{ "V5": { "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 '{ "V5": [ { "id": { "parents": 2, "interior": { "X1": [{ "GlobalConsensus": { ByGenesis: '$PEZKUWICHAIN_GENESIS_HASH' } }] } }, "fun": { "Fungible": '$amount' } } ] }')" \
"$(jq --null-input '{ "V5": { "parents": 2, "interior": { "X1": [{ "GlobalConsensus": { ByGenesis: '$PEZKUWICHAIN_GENESIS_HASH' } }] } } }')" \
"Unlimited"
;;
claim-rewards-bridge-hub-pezkuwichain-local)
ensure_pezkuwi_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-zagros-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 pezkuwi
pkill -f teyrchain
;;
import)
# to avoid trigger anything here
;;
*)
echo "A command is require. Supported commands for:
Local (zombienet) run:
- run-finality-relay
- run-teyrchains-relay
- run-messages-relay
- init-pezkuwichain-local
- init-asset-hub-pezkuwichain-local
- init-bridge-hub-pezkuwichain-local
- init-zagros-local
- init-asset-hub-zagros-local
- init-bridge-hub-zagros-local
- reserve-transfer-assets-from-asset-hub-pezkuwichain-local
- withdraw-reserve-assets-from-asset-hub-pezkuwichain-local
- reserve-transfer-assets-from-asset-hub-zagros-local
- withdraw-reserve-assets-from-asset-hub-zagros-local
- claim-rewards-bridge-hub-pezkuwichain-local
- claim-rewards-bridge-hub-zagros-local";
exit 1
;;
esac
@@ -0,0 +1,11 @@
#!/usr/bin/env bash
# Pezkuwichain AH
xdg-open https://pezkuwichain.io/?rpc=ws://127.0.0.1:9910#/explorer&
# Pezkuwichain BH
xdg-open https://pezkuwichain.io/?rpc=ws://127.0.0.1:8943#/explorer&
# Zagros BH
xdg-open https://pezkuwichain.io/?rpc=ws://127.0.0.1:8945#/explorer&
# Zagros AH
xdg-open https://pezkuwichain.io/?rpc=ws://127.0.0.1:9010#/explorer&
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
if [ $1 == "auto-log" ]; then
shift # ignore "auto-log"
log_name=$1
$ENV_PATH/bridges_pezkuwichain_zagros.sh "$@" >$TEST_DIR/logs/$log_name.log
else
$ENV_PATH/bridges_pezkuwichain_zagros.sh "$@"
fi
@@ -0,0 +1,7 @@
Description: Check if the with-Zagros 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-Zagros GRANDPA pallet is initialized at Rococo
bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/best-finalized-header-at-bridged-chain.js with "Zagros,0" within 400 seconds
@@ -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
@@ -0,0 +1,8 @@
Description: Check if the Rococo teyrchains started producing blocks reliably
Network: ./bridge_hub_zagros_local_network.toml
Creds: config
# ensure that initialization has completed
asset-hub-rococo-collator1: reports block height is at least 10 within 180 seconds
bridge-hub-rococo-collator1: reports block height is at least 10 within 180 seconds
+77
View File
@@ -0,0 +1,77 @@
#!/usr/bin/env 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"
pezkuwichain_def=${BASH_SOURCE%/*}/bridge_hub_pezkuwichain_local_network.toml
start_zombienet $TEST_DIR $pezkuwichain_def pezkuwichain_dir pezkuwichain_pid
echo
zagros_def=${BASH_SOURCE%/*}/bridge_hub_zagros_local_network.toml
start_zombienet $TEST_DIR $zagros_def zagros_dir zagros_pid
echo
if [[ $init -eq 1 ]]; then
run_zndsl ${BASH_SOURCE%/*}/pezkuwichain-start.zndsl $pezkuwichain_dir
run_zndsl ${BASH_SOURCE%/*}/zagros-start.zndsl $zagros_dir
pezkuwichain_init_log=$logs_dir/pezkuwichain-init.log
echo -e "Setting up the pezkuwichain side of the bridge. Logs available at: $pezkuwichain_init_log\n"
zagros_init_log=$logs_dir/zagros-init.log
echo -e "Setting up the zagros side of the bridge. Logs available at: $zagros_init_log\n"
$helper_script init-pezkuwichain-local >> $pezkuwichain_init_log 2>&1 &
pezkuwichain_init_pid=$!
$helper_script init-zagros-local >> $zagros_init_log 2>&1 &
zagros_init_pid=$!
wait $pezkuwichain_init_pid $zagros_init_pid
run_zndsl ${BASH_SOURCE%/*}/pezkuwichain-init.zndsl $pezkuwichain_dir
run_zndsl ${BASH_SOURCE%/*}/zagros-init.zndsl $zagros_dir
$helper_script init-asset-hub-pezkuwichain-local >> $pezkuwichain_init_log 2>&1 &
pezkuwichain_init_pid=$!
$helper_script init-asset-hub-zagros-local >> $zagros_init_log 2>&1 &
zagros_init_pid=$!
wait $pezkuwichain_init_pid $zagros_init_pid
$helper_script init-bridge-hub-pezkuwichain-local >> $pezkuwichain_init_log 2>&1 &
pezkuwichain_init_pid=$!
$helper_script init-bridge-hub-zagros-local >> $zagros_init_log 2>&1 &
zagros_init_pid=$!
wait $pezkuwichain_init_pid $zagros_init_pid
fi
if [[ $start_relayer -eq 1 ]]; then
${BASH_SOURCE%/*}/start_relayer.sh $pezkuwichain_dir $zagros_dir finality_relayer_pid teyrchains_relayer_pid messages_relayer_pid
fi
echo $pezkuwichain_dir > $TEST_DIR/pezkuwichain.env
echo $zagros_dir > $TEST_DIR/zagros.env
echo
wait -n $pezkuwichain_pid $zagros_pid $finality_relayer_pid $teyrchains_relayer_pid $messages_relayer_pid
kill -9 -$$
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -e
source "$FRAMEWORK_PATH/utils/common.sh"
source "$FRAMEWORK_PATH/utils/zombienet.sh"
pezkuwichain_dir=$1
zagros_dir=$2
__finality_relayer_pid=$3
__teyrchains_relayer_pid=$4
__messages_relayer_pid=$5
logs_dir=$TEST_DIR/logs
helper_script="${BASH_SOURCE%/*}/helper.sh"
# start finality relayer
finality_relayer_log=$logs_dir/relayer_finality.log
echo -e "Starting pezkuwichain-zagros finality relayer. Logs available at: $finality_relayer_log\n"
start_background_process "$helper_script run-finality-relay" $finality_relayer_log finality_relayer_pid
# start teyrchains relayer
teyrchains_relayer_log=$logs_dir/relayer_teyrchains.log
echo -e "Starting pezkuwichain-zagros teyrchains relayer. Logs available at: $teyrchains_relayer_log\n"
start_background_process "$helper_script run-teyrchains-relay" $teyrchains_relayer_log teyrchains_relayer_pid
# start messages relayer
messages_relayer_log=$logs_dir/relayer_messages.log
echo -e "Starting pezkuwichain-zagros messages relayer. Logs available at: $messages_relayer_log\n"
start_background_process "$helper_script run-messages-relay" $messages_relayer_log messages_relayer_pid
run_zndsl ${BASH_SOURCE%/*}/pezkuwichain-bridge.zndsl $pezkuwichain_dir
run_zndsl ${BASH_SOURCE%/*}/zagros-bridge.zndsl $zagros_dir
eval $__finality_relayer_pid="'$finality_relayer_pid'"
eval $__teyrchains_relayer_pid="'$teyrchains_relayer_pid'"
eval $__messages_relayer_pid="'$messages_relayer_pid'"
@@ -0,0 +1,6 @@
Description: Check if the with-Rococo GRANDPA pallet was initialized at Zagros BH
Network: ./bridge_hub_zagros_local_network.toml
Creds: config
# relay is already started - let's wait until with-Rococo GRANDPA pallet is initialized at Zagros
bridge-hub-zagros-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/best-finalized-header-at-bridged-chain.js with "Rococo,0" within 400 seconds
@@ -0,0 +1,7 @@
Description: Check if the HRMP channel between Zagros BH and Zagros AH was opened successfully
Network: ./bridge_hub_zagros_local_network.toml
Creds: config
# ensure that initialization has completed
asset-hub-zagros-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wait-hrmp-channel-opened.js with "1002" within 600 seconds
@@ -0,0 +1,8 @@
Description: Check if the Zagros teyrchains started producing blocks reliably
Network: ./bridge_hub_zagros_local_network.toml
Creds: config
# ensure that initialization has completed
asset-hub-zagros-collator1: reports block height is at least 10 within 180 seconds
bridge-hub-zagros-collator1: reports block height is at least 10 within 180 seconds
@@ -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, 6000));
}
}
module.exports = { run }
@@ -0,0 +1,6 @@
module.exports = {
grandpaPalletName: "bridgePezkuwichainGrandpa",
teyrchainsPalletName: "bridgePezkuwichainTeyrchains",
messagesPalletName: "bridgePezkuwichainMessages",
bridgedBridgeHubParaId: 1013,
}
@@ -0,0 +1,6 @@
module.exports = {
grandpaPalletName: "bridgeZagrosGrandpa",
teyrchainsPalletName: "bridgeZagrosTeyrchains",
messagesPalletName: "bridgeZagrosMessages",
bridgedBridgeHubParaId: 1002,
}
@@ -0,0 +1,34 @@
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 totalTeyrchainHeaders = 0;
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.countGrandpaHeaderImports(bridgedChain, currentEvents);
totalTeyrchainHeaders += await utils.countTeyrchainHeaderImports(bridgedChain, currentEvents);
});
// wait given time
await new Promise(resolve => setTimeout(resolve, exitAfterSeconds * 1000));
// if we haven't seen many (>1) new GRANDPA or teyrchain headers => fail
if (totalGrandpaHeaders <= 1) {
throw new Error("No bridged relay chain headers imported");
}
if (totalTeyrchainHeaders <= 1) {
throw new Error("No bridged teyrchain headers imported");
}
}
module.exports = { run }
@@ -0,0 +1,12 @@
async function run(nodeName, networkInfo, args) {
const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName];
const api = await zombie.connect(wsUri, userDefinedTypes);
const accountAddress = args[0];
const accountData = await api.query.system.account(accountAddress);
const accountBalance = accountData.data['free'];
console.log("Balance of " + accountAddress + ": " + accountBalance);
return accountBalance;
}
module.exports = {run}
@@ -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}
@@ -0,0 +1,85 @@
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 teyrchain headers
await utils.ensureOnlyMandatoryGrandpaHeadersImported(
bridgedChain,
apiAtParent,
apiAtCurrent,
currentEvents,
);
await utils.ensureOnlyInitialTeyrchainHeaderImported(
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 teyrchain header
const newTeyrchainHeaders = utils.countTeyrchainHeaderImports(bridgedChain, currentEvents);
if (newTeyrchainHeaders > 1) {
utils.logEvents(currentEvents);
throw new Error("Unexpected teyrchain header import: " + newTeyrchainHeaders + " / " + 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}
@@ -0,0 +1,24 @@
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.relayerAccountAddress;
const reward = args.reward;
const expectedRelayerReward = BigInt(args.expectedRelayerReward);
console.log("Waiting rewards for relayerAccountAddress: " + relayerAccountAddress + " expecting minimal rewards at least: " + expectedRelayerReward + " for " + JSON.stringify(reward));
while (true) {
const relayerReward = await api.query.bridgeRelayers.relayerRewards(relayerAccountAddress, reward);
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 }
@@ -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,
);
},
countTeyrchainHeaderImports: function(bridgedChain, events) {
return events.reduce(
(count, record) => {
const { event } = record;
if (event.section == bridgedChain.teyrchainsPalletName && event.method == "UpdatedTeyrchainHead") {
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;
},
ensureOnlyInitialTeyrchainHeaderImported: async function(
bridgedChain,
apiAtParent,
apiAtCurrent,
currentEvents,
) {
// remember whether we already know bridged teyrchain header at a parent block
const bestBridgedTeyrchainHeader = await apiAtParent.query[bridgedChain.teyrchainsPalletName].parasInfo(bridgedChain.bridgedBridgeHubParaId);;
const hasBestBridgedTeyrchainHeader = bestBridgedTeyrchainHeader.isSome;
// we expect to see: no more than `1` bridged teyrchain header if there were no teyrchain header before.
const maxNewTeyrchainHeaders = hasBestBridgedTeyrchainHeader ? 0 : 1;
const newTeyrchainHeaders = module.exports.countTeyrchainHeaderImports(bridgedChain, currentEvents);
// check that our assumptions are correct
if (newTeyrchainHeaders > maxNewTeyrchainHeaders) {
module.exports.logEvents(currentEvents);
throw new Error("Unexpected teyrchain header import: " + newTeyrchainHeaders + " / " + maxNewTeyrchainHeaders);
}
return hasBestBridgedTeyrchainHeader;
},
}
@@ -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.teyrchainSystem.relevantMessagingState();
const messagingState = api.createType("Option<CumulusPalletTeyrchainSystemRelayStateSnapshotMessagingStateSnapshot>", 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 }
@@ -0,0 +1,24 @@
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.accountAddress;
const expectedAssetId = args.expectedAssetId;
const expectedAssetBalance = BigInt(args.expectedAssetBalance);
while (true) {
const foreignAssetAccount = await api.query.foreignAssets.account(expectedAssetId, accountAddress);
if (foreignAssetAccount.isSome) {
const foreignAssetAccountBalance = foreignAssetAccount.unwrap().balance.toBigInt();
if (foreignAssetAccountBalance > expectedAssetBalance) {
return foreignAssetAccountBalance;
}
}
// else sleep and retry
await new Promise((resolve) => setTimeout(resolve, 6000));
}
}
module.exports = { run }
+344
View File
@@ -0,0 +1,344 @@
#!/usr/bin/env 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 ./teyrchains/runtimes/bridge-hubs/README.md (Prepare/Build/Deploy)"
exit 1
fi
echo $path
}
function ensure_pezkuwi_js_api() {
if ! which pezkuwi-js-api &> /dev/null; then
echo ''
echo 'Required command `pezkuwi-js-api` not in PATH, please, install, e.g.:'
echo "npm install -g @pezkuwi/api-cli@beta"
echo " or"
echo "yarn global add @pezkuwi/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_pezkuwi_js_api() {
# --noWait: without that argument `pezkuwi-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.
pezkuwi-js-api --nonce -1 "$@" || true
}
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_pezkuwi_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" \
'{ "V4": { "parents": 0, "interior": { "X1": [{ "Teyrchain": $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" \
'
{
"V4": [
{
"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_pezkuwi_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_pezkuwi_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 (PezkuwiXcm::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 create_pool() {
local runtime_para_endpoint=$1
local seed=$2
local native_asset_id=$3
local foreign_asset_id=$4
call_pezkuwi_js_api \
--ws "${runtime_para_endpoint?}" \
--seed "${seed?}" \
tx.assetConversion.createPool \
"${native_asset_id}" \
"${foreign_asset_id}"
}
function add_liquidity() {
local runtime_para_endpoint=$1
local seed=$2
local native_asset_id=$3
local foreign_asset_id=$4
local native_asset_amount=$5
local foreign_asset_amount=$6
local pool_owner_account_id=$7
call_pezkuwi_js_api \
--ws "${runtime_para_endpoint?}" \
--seed "${seed?}" \
tx.assetConversion.addLiquidity \
"${native_asset_id}" \
"${foreign_asset_id}" \
"${native_asset_amount}" \
"${foreign_asset_amount}" \
"1" \
"1" \
"${pool_owner_account_id}"
}
function limited_reserve_transfer_assets() {
local url=$1
local seed=$2
local destination=$3
local beneficiary=$4
local assets=$5
local fee_asset_id=$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_id: ${fee_asset_id}"
echo " weight_limit: ${weight_limit}"
echo ""
echo "--------------------------------------------------"
call_pezkuwi_js_api \
--ws "${url?}" \
--seed "${seed?}" \
tx.pezkuwiXcm.limitedReserveTransferAssets \
"${destination}" \
"${beneficiary}" \
"${assets}" \
"${fee_asset_id}" \
"${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_pezkuwi_js_api \
--ws "${runtime_para_endpoint}" \
--seed "${seed?}" \
tx.bridgeRelayers.claimRewards \
"${rewards_account_params}"
}
+45
View File
@@ -0,0 +1,45 @@
#!/usr/bin/env 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
}
@@ -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 <type> <endpoint> <output hex-encoded data file> <input message>");
exit(1);
}
const type = process.argv[2];
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(` rpcEndpoint: ${rpcEndpoint}`);
console.log(` output: ${output}`);
console.log(` inputArgs: ${inputArgs}`);
switch (type) {
case 'remark-with-event':
remarkWithEvent(rpcEndpoint, output);
break;
case 'add-exporter-config':
addExporterConfig(rpcEndpoint, output, inputArgs[0], inputArgs[1]);
break;
case 'remove-exporter-config':
removeExporterConfig(rpcEndpoint, output, inputArgs[0], inputArgs[1]);
break;
case 'add-universal-alias':
addUniversalAlias(rpcEndpoint, output, inputArgs[0], inputArgs[1]);
break;
case 'add-reserve-location':
addReserveLocation(rpcEndpoint, output, inputArgs[0]);
break;
case 'force-create-asset':
forceCreateAsset(rpcEndpoint, output, inputArgs[0], inputArgs[1], inputArgs[2], inputArgs[3]);
break;
case 'force-xcm-version':
forceXcmVersion(rpcEndpoint, 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!`);
}
@@ -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": {
"@pezkuwi/api": "^14.0",
"@pezkuwi/util": "^13.1"
}
}
@@ -0,0 +1,39 @@
#!/usr/bin/env 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
}
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env 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 PEZKUWI_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 PEZKUWI_BINARY=/usr/local/bin/pezkuwi
export PEZKUWI_TEYRCHAIN_BINARY=/usr/local/bin/pezkuwi-teyrchain
export ZOMBIENET_BINARY=/usr/local/bin/zombie
export SUBSTRATE_RELAY_BINARY=/usr/local/bin/substrate-relay
else
export PEZKUWI_BINARY=$PEZKUWI_SDK_PATH/target/release/pezkuwi
export PEZKUWI_TEYRCHAIN_BINARY=$PEZKUWI_SDK_PATH/target/release/pezkuwi-teyrchain
export ZOMBIENET_BINARY=~/local_bridge_testing/bin/zombienet
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
+7
View File
@@ -0,0 +1,7 @@
#!/usr/bin/env bash
INVOKE_LOG=`mktemp -p $TEST_FOLDER invoke.XXXXX`
pushd $PEZKUWI_SDK_PATH/bridges/testing/environments/pezkuwichain-zagros
./bridges_pezkuwichain_zagros.sh $1 >$INVOKE_LOG 2>&1
popd
+14
View File
@@ -0,0 +1,14 @@
#!/usr/bin/env 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,12 @@
Description: User is able to transfer ROC from Rococo Asset Hub to Zagros Asset Hub and back
Network: {{ENV_PATH}}/bridge_hub_zagros_local_network.toml
Creds: config
# send 5 ROC to //Alice from Rococo AH to Zagros AH
asset-hub-zagros-collator1: run {{ENV_PATH}}/helper.sh with "auto-log reserve-transfer-assets-from-asset-hub-rococo-local 5000000000000" within 120 seconds
# check that //Alice received at least 4.8 ROC on Zagros AH
asset-hub-zagros-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with '{ "accountAddress": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", "expectedAssetBalance": 4800000000000, "expectedAssetId": { "parents": 2, "interior": { "X1": [{ "GlobalConsensus": { "ByGenesis": [100,8,222,119,55,197,156,35,136,144,83,58,242,88,150,162,194,6,8,216,179,128,187,1,2,154,203,57,39,129,6,62] } }] }}}' within 600 seconds
# relayer //Ferdie is rewarded for delivering messages from Rococo BH
bridge-hub-zagros-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/relayer-rewards.js with '{ "relayerAccountAddress": "5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw", "reward": { "RococoZagros": { "laneId": "0x00000002", "bridgedChainId": "0x6268726F", "owner": "ThisChain" }}, "expectedRelayerReward": 1}' within 300 seconds
@@ -0,0 +1,11 @@
Description: Finality and teyrchain relays should have the constant balance, because their transactions are free
Network: {{ENV_PATH}}/bridge_hub_rococo_local_network.toml
Creds: config
# local chain spec gives `1u64 << 60` tokens to every endowed account: if it'll ever
# change, it'd need to be fixed here as well
# //Charlie only submits free and mandatory relay chain headers, so the balance should stay the same
bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-asset-balance.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y" return is 1152921504606846976 within 30 seconds
# //Dave only submits free teyrchain headers, so the balance should stay the same
bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-asset-balance.js with "5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy" return is 1152921504606846976 within 30 seconds
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
set -e
source "${BASH_SOURCE%/*}/../../framework/utils/common.sh"
source "${BASH_SOURCE%/*}/../../framework/utils/zombienet.sh"
export ENV_PATH=`realpath ${BASH_SOURCE%/*}/../../environments/pezkuwichain-zagros`
$ENV_PATH/spawn.sh --init --start-relayer &
env_pid=$!
ensure_process_file $env_pid $TEST_DIR/pezkuwichain.env 600
pezkuwichain_dir=`cat $TEST_DIR/pezkuwichain.env`
echo
ensure_process_file $env_pid $TEST_DIR/zagros.env 300
zagros_dir=`cat $TEST_DIR/zagros.env`
echo
run_zndsl ${BASH_SOURCE%/*}/roc-relayer-balance-does-not-change.zndsl $pezkuwichain_dir
run_zndsl ${BASH_SOURCE%/*}/wnd-relayer-balance-does-not-change.zndsl $zagros_dir
run_zndsl ${BASH_SOURCE%/*}/roc-reaches-zagros.zndsl $zagros_dir
run_zndsl ${BASH_SOURCE%/*}/wnd-reaches-pezkuwichain.zndsl $pezkuwichain_dir
run_zndsl ${BASH_SOURCE%/*}/wroc-reaches-pezkuwichain.zndsl $pezkuwichain_dir
run_zndsl ${BASH_SOURCE%/*}/wwnd-reaches-zagros.zndsl $zagros_dir
run_zndsl ${BASH_SOURCE%/*}/roc-relayer-balance-does-not-change.zndsl $pezkuwichain_dir
run_zndsl ${BASH_SOURCE%/*}/wnd-relayer-balance-does-not-change.zndsl $zagros_dir
@@ -0,0 +1,12 @@
Description: User is able to transfer WND from Zagros 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 Zagros AH to Rococo AH
asset-hub-rococo-collator1: run {{ENV_PATH}}/helper.sh with "auto-log reserve-transfer-assets-from-asset-hub-zagros-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 '{ "accountAddress": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", "expectedAssetBalance": 4800000000000, "expectedAssetId": { "parents": 2, "interior": { "X1": [{ "GlobalConsensus": { "ByGenesis": [225,67,242,56,3,172,80,232,246,248,230,38,149,209,206,158,78,29,104,170,54,193,205,44,253,21,52,2,19,243,66,62] } }] }}}' within 600 seconds
# relayer //Eve is rewarded for delivering messages from Zagros BH
bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/relayer-rewards.js with '{ "relayerAccountAddress": "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL", "reward": { "laneId": "0x00000002", "bridgedChainId": "0x62687764", "owner": "ThisChain" }, "expectedRelayerReward": 1}' within 300 seconds
@@ -0,0 +1,11 @@
Description: Finality and teyrchain relays should have the constant balance, because their transactions are free
Network: {{ENV_PATH}}/bridge_hub_zagros_local_network.toml
Creds: config
# local chain spec gives `1u64 << 60` tokens to every endowed account: if it'll ever
# change, it'd need to be fixed here as well
# //Charlie only submits free and mandatory relay chain headers, so the balance should stay the same
bridge-hub-zagros-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-asset-balance.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y" return is 1152921504606846976 within 30 seconds
# //Dave only submits free teyrchain headers, so the balance should stay the same
bridge-hub-zagros-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-asset-balance.js with "5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy" return is 1152921504606846976 within 30 seconds
@@ -0,0 +1,10 @@
Description: User is able to transfer ROC from Rococo Asset Hub to Zagros Asset Hub and back
Network: {{ENV_PATH}}/bridge_hub_zagros_local_network.toml
Creds: config
# send 3 wROC back to Alice from Zagros AH to Rococo AH
asset-hub-rococo-collator1: run {{ENV_PATH}}/helper.sh with "withdraw-reserve-assets-from-asset-hub-zagros-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
@@ -0,0 +1,10 @@
Description: User is able to transfer ROC from Rococo Asset Hub to Zagros Asset Hub and back
Network: {{ENV_PATH}}/bridge_hub_zagros_local_network.toml
Creds: config
# send 3 wWND back to Alice from Rococo AH to Zagros AH
asset-hub-zagros-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 Zagros AH
# (we wait until //Alice account increases here - there are no other transactions that may increase it)
asset-hub-zagros-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,2800000000000" within 600 seconds
@@ -0,0 +1,20 @@
Description: While relayer is idle, we only sync free Rococo (and a single Rococo BH) headers to Zagros BH.
Network: {{ENV_PATH}}/bridge_hub_zagros_local_network.toml
Creds: config
# local chain spec gives `1u64 << 60` tokens to every endowed account: if it'll ever
# change, it'd need to be fixed here as well
# //Charlie only submits free and mandatory relay chain headers, so the balance should stay the same
bridge-hub-zagros-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-asset-balance.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y" return is 1152921504606846976 within 30 seconds
# //Dave only submits free teyrchain headers, so the balance should stay the same
bridge-hub-zagros-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-asset-balance.js with "5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy" return is 1152921504606846976 within 30 seconds
# ensure that we have synced multiple relay and teyrchain 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-zagros-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/multiple-headers-synced.js with "300,rococo-at-zagros" within 600 seconds
# //Charlie only submits free and mandatory relay chain headers, so the balance should stay the same
bridge-hub-zagros-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-asset-balance.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y" return is 1152921504606846976 within 30 seconds
# //Dave only submits free teyrchain headers, so the balance should stay the same
bridge-hub-zagros-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-asset-balance.js with "5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy" return is 1152921504606846976 within 30 seconds
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -e
source "${BASH_SOURCE%/*}/../../framework/utils/common.sh"
source "${BASH_SOURCE%/*}/../../framework/utils/zombienet.sh"
export ENV_PATH=`realpath ${BASH_SOURCE%/*}/../../environments/pezkuwichain-zagros`
$ENV_PATH/spawn.sh &
env_pid=$!
ensure_process_file $env_pid $TEST_DIR/pezkuwichain.env 600
pezkuwichain_dir=`cat $TEST_DIR/pezkuwichain.env`
echo
ensure_process_file $env_pid $TEST_DIR/zagros.env 300
zagros_dir=`cat $TEST_DIR/zagros.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/pezkuwichain-zagros/start_relayer.sh $pezkuwichain_dir $zagros_dir finality_relayer_pid teyrchains_relayer_pid messages_relayer_pid
run_zndsl ${BASH_SOURCE%/*}/pezkuwichain-to-zagros.zndsl $zagros_dir
run_zndsl ${BASH_SOURCE%/*}/zagros-to-pezkuwichain.zndsl $pezkuwichain_dir
@@ -0,0 +1,20 @@
Description: While relayer is idle, we only sync free Zagros (and a single Zagros BH) headers to Rococo BH.
Network: {{ENV_PATH}}/bridge_hub_rococo_local_network.toml
Creds: config
# local chain spec gives `1u64 << 60` tokens to every endowed account: if it'll ever
# change, it'd need to be fixed here as well
# //Charlie has inital balance
bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-asset-balance.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y" return is 1152921504606846976 within 30 seconds
# //Dave has inital balance
bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-asset-balance.js with "5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy" return is 1152921504606846976 within 30 seconds
# ensure that we have synced multiple relay and teyrchain 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/multiple-headers-synced.js with "300,zagros-at-rococo" within 600 seconds
# //Charlie only submits free and mandatory relay chain headers, so the balance should stay the same
bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-asset-balance.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y" return is 1152921504606846976 within 30 seconds
# //Dave only submits free teyrchain headers, so the balance should stay the same
bridge-hub-rococo-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-asset-balance.js with "5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy" return is 1152921504606846976 within 30 seconds
@@ -0,0 +1,7 @@
Description: While relayer is active, we only sync mandatory and required Rococo (and Rococo BH) headers to Zagros BH.
Network: {{ENV_PATH}}/bridge_hub_zagros_local_network.toml
Creds: config
# ensure that relayer won't sync any extra headers while delivering messages and confirmations
bridge-hub-zagros-collator1: js-script {{FRAMEWORK_PATH}}/js-helpers/only-required-headers-synced-when-active.js with "500,rococo-at-zagros" within 600 seconds
@@ -0,0 +1,44 @@
#!/usr/bin/env bash
set -e
# TODO: This test doesn't work. It was added at a time when we couldn't run it because we didn't have the scafolding.
# It needs to be fixed. For the moment we keep it in the repo as it is since the idea has value.
# But we don't run it in the CI.
source "${BASH_SOURCE%/*}/../../framework/utils/common.sh"
source "${BASH_SOURCE%/*}/../../framework/utils/zombienet.sh"
export ENV_PATH=`realpath ${BASH_SOURCE%/*}/../../environments/pezkuwichain-zagros`
logs_dir=$TEST_DIR/logs
$ENV_PATH/spawn.sh --init &
env_pid=$!
ensure_process_file $env_pid $TEST_DIR/pezkuwichain.env 600
pezkuwichain_dir=`cat $TEST_DIR/pezkuwichain.env`
echo
ensure_process_file $env_pid $TEST_DIR/zagros.env 300
zagros_dir=`cat $TEST_DIR/zagros.env`
echo
echo "Sending message from Pezkuwichain to Zagros"
$ENV_PATH/helper.sh auto-log reserve-transfer-assets-from-asset-hub-pezkuwichain-local 5000000000000
echo
echo "Sending message from Zagros to Pezkuwichain"
$ENV_PATH/helper.sh auto-log reserve-transfer-assets-from-asset-hub-zagros-local 5000000000000
echo
# Start the relayer with a 30s delay
# We want to be sure that the messages won't be relayed before starting the js script in `pezkuwichain-to-zagros.zndsl`
start_relayer_log=$logs_dir/start_relayer.log
echo -e "The pezkuwichain-zagros relayer will be started in 30s. Logs will be available at: $start_relayer_log\n"
(sleep 30 && $ENV_PATH/start_relayer.sh \
$pezkuwichain_dir $zagros_dir finality_relayer_pid teyrchains_relayer_pid messages_relayer_pid > $start_relayer_log)&
run_zndsl ${BASH_SOURCE%/*}/pezkuwichain-to-zagros.zndsl $zagros_dir