From 6d5a7a1c7df20b67889ef014456b8cc512f0e113 Mon Sep 17 00:00:00 2001 From: Serban Iorga Date: Wed, 1 May 2024 15:47:34 +0300 Subject: [PATCH] Add P<>K bridge manual zombienet test for asset transfer (#198) - [x] Does not require a CHANGELOG entry This PR adds a P<>K bridge zombienet test which checks the following: - transfering DOT from AssetHub Polkadot to AssetHub Kusama works - transfering wDOT from AssetHub Kusama to AssetHub Polkadot works - transfering KSM from AssetHub Kusama to AssetHub Polkadot works - transfering wKSM from AssetHub Polkadot to AssetHub Kusama works The test is meant to be ran manually as per the instructions in the `README.md` and is based on the naive bridge testing "orchestrator" defined in the `polkadot-sdk` repo: https://github.com/paritytech/polkadot-sdk/tree/master/bridges/testing . The "orchestrator" is downloaded using `git sparse checkout` directly from the `polkadot-sdk` repo (I couldn't find a better way to package the `bash` and `js` files on which the test depends). Proposing to add the test in this repo as per the feedback from the bridges team and since this way it would be more convenient to run it before a release or when performing a change to the bridge hubs for example. If there are concerns about this, the second option would be to add it to the `parity-bridges-common` repo. Closes: https://github.com/paritytech/polkadot-sdk/issues/3400 --- integration-tests/bridges/README.md | 30 ++ .../bridge_hub_kusama_local_network.toml | 79 ++++ .../bridge_hub_polkadot_local_network.toml | 77 ++++ .../bridges_polkadot_kusama.sh | 385 ++++++++++++++++++ .../polkadot-kusama/generate_bh_spec.sh | 13 + .../environments/polkadot-kusama/helper.sh | 3 + .../polkadot-kusama/kusama-bridge.zndsl | 5 + .../polkadot-kusama/kusama-init.zndsl | 6 + .../polkadot-kusama/polkadot-bridge.zndsl | 5 + .../polkadot-kusama/polkadot-init.zndsl | 7 + .../environments/polkadot-kusama/spawn.sh | 49 +++ .../polkadot-kusama/start_relayer.sh | 23 ++ integration-tests/bridges/run-test.sh | 36 ++ .../dot-reaches-kusama.zndsl | 12 + .../ksm-reaches-polkadot.zndsl | 12 + .../run.sh | 28 ++ .../wdot-reaches-polkadot.zndsl | 10 + .../wksm-reaches-kusama.zndsl | 10 + 18 files changed, 790 insertions(+) create mode 100644 integration-tests/bridges/README.md create mode 100644 integration-tests/bridges/environments/polkadot-kusama/bridge_hub_kusama_local_network.toml create mode 100644 integration-tests/bridges/environments/polkadot-kusama/bridge_hub_polkadot_local_network.toml create mode 100755 integration-tests/bridges/environments/polkadot-kusama/bridges_polkadot_kusama.sh create mode 100755 integration-tests/bridges/environments/polkadot-kusama/generate_bh_spec.sh create mode 100755 integration-tests/bridges/environments/polkadot-kusama/helper.sh create mode 100644 integration-tests/bridges/environments/polkadot-kusama/kusama-bridge.zndsl create mode 100644 integration-tests/bridges/environments/polkadot-kusama/kusama-init.zndsl create mode 100644 integration-tests/bridges/environments/polkadot-kusama/polkadot-bridge.zndsl create mode 100644 integration-tests/bridges/environments/polkadot-kusama/polkadot-init.zndsl create mode 100755 integration-tests/bridges/environments/polkadot-kusama/spawn.sh create mode 100755 integration-tests/bridges/environments/polkadot-kusama/start_relayer.sh create mode 100755 integration-tests/bridges/run-test.sh create mode 100644 integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/dot-reaches-kusama.zndsl create mode 100644 integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/ksm-reaches-polkadot.zndsl create mode 100755 integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/run.sh create mode 100644 integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/wdot-reaches-polkadot.zndsl create mode 100644 integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/wksm-reaches-kusama.zndsl diff --git a/integration-tests/bridges/README.md b/integration-tests/bridges/README.md new file mode 100644 index 0000000000..08e4cc0a65 --- /dev/null +++ b/integration-tests/bridges/README.md @@ -0,0 +1,30 @@ +# Bridges Tests for Local Polkadot <> Kusama Bridge + +This folder contains zombienet based integration test for both onchain and offchain bridges code. +The tests are designed to be run manually. + +To start a test, you need to: + +- download latest [zombienet release](https://github.com/paritytech/zombienet/releases) to +`~/local_bridge_testing/bin/zombienet`. + +- 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 `yarn global add @polkadot/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 binary to `~/local_bridge_testing/bin/substrate-relay`. + +- add the `sudo` pallet to the Polkadot and Kusama runtimes and give sudo rights to Alice. With this change build +the chain spec generator by running `cargo build --release -p chain-spec-generator --features fast-runtime` +command. Copy the binary to `~/local_bridge_testing/bin/chain-spec-generator`. + +- change the `POLKADOT_BINARY` and `POLKADOT_PARACHAIN_BINARY` paths (and ensure that the nearby variables +have correct values) in the `./run-test.sh`. + +After that, you can run `./run-tests.sh ` command. diff --git a/integration-tests/bridges/environments/polkadot-kusama/bridge_hub_kusama_local_network.toml b/integration-tests/bridges/environments/polkadot-kusama/bridge_hub_kusama_local_network.toml new file mode 100644 index 0000000000..e790b90553 --- /dev/null +++ b/integration-tests/bridges/environments/polkadot-kusama/bridge_hub_kusama_local_network.toml @@ -0,0 +1,79 @@ +[settings] +node_spawn_timeout = 240 + +[relaychain] +default_command = "{{POLKADOT_BINARY}}" +default_args = ["-lparachain=debug,xcm=trace"] +chain = "kusama-local" +chain_spec_command = "{{CHAIN_SPEC_GEN_BINARY}} {% raw %} {{chainName}} {% endraw %}" + +[[relaychain.nodes]] +name = "alice" +validator = true +rpc_port = 9935 +ws_port = 9945 +balance = 2000000000000 + +[[relaychain.nodes]] +name = "bob" +validator = true +rpc_port = 9936 +ws_port = 9946 +balance = 2000000000000 + +[[relaychain.nodes]] +name = "charlie" +validator = true +rpc_port = 9937 +ws_port = 9947 +balance = 2000000000000 + +[[parachains]] +id = 1000 +chain = "asset-hub-kusama-local" +chain_spec_command = "{{CHAIN_SPEC_GEN_BINARY}} {% raw %} {{chainName}} {% endraw %}" +cumulus_based = true + +[[parachains.collators]] +name = "asset-hub-kusama-collator-1" +rpc_port = 9011 +ws_port = 9010 +command = "{{POLKADOT_PARACHAIN_BINARY}}" +args = [ + "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace" +] + +[[parachains.collators]] +name = "asset-hub-kusama-collator-2" +command = "{{POLKADOT_PARACHAIN_BINARY}}" +args = [ + "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace" +] + +[[parachains]] +id = 1002 +chain = "bridge-hub-kusama-local" +chain_spec_command = "{{ENV_PATH}}/generate_bh_spec.sh Polkadot {% raw %} {{chainName}} {% endraw %}" +cumulus_based = true + +# run alice as parachain collator +[[parachains.collators]] +name = "bridge-hub-kusama-collator-1" +validator = true +command = "{{POLKADOT_PARACHAIN_BINARY}}" +rpc_port = 8935 +ws_port = 8945 +args = [ + "-lparachain=debug,runtime::mmr=info,substrate=info,runtime=info,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace" +] + +# run bob as parachain collator +[[parachains.collators]] +name = "bridge-hub-kusama-collator-2" +validator = true +command = "{{POLKADOT_PARACHAIN_BINARY}}" +rpc_port = 8936 +ws_port = 8946 +args = [ + "-lparachain=trace,runtime::mmr=info,substrate=info,runtime=info,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace" +] diff --git a/integration-tests/bridges/environments/polkadot-kusama/bridge_hub_polkadot_local_network.toml b/integration-tests/bridges/environments/polkadot-kusama/bridge_hub_polkadot_local_network.toml new file mode 100644 index 0000000000..d2ec0207a9 --- /dev/null +++ b/integration-tests/bridges/environments/polkadot-kusama/bridge_hub_polkadot_local_network.toml @@ -0,0 +1,77 @@ +[settings] +node_spawn_timeout = 240 + +[relaychain] +default_command = "{{POLKADOT_BINARY}}" +default_args = ["-lparachain=debug,xcm=trace"] +chain = "polkadot-local" +chain_spec_command = "{{CHAIN_SPEC_GEN_BINARY}} {% raw %} {{chainName}} {% endraw %}" + +[[relaychain.nodes]] +name = "alice" +validator = true +rpc_port = 9932 +ws_port = 9942 +balance = 2000000000000 + +[[relaychain.nodes]] +name = "bob" +validator = true +rpc_port = 9933 +ws_port = 9943 +balance = 2000000000000 + +[[relaychain.nodes]] +name = "charlie" +validator = true +rpc_port = 9934 +ws_port = 9944 +balance = 2000000000000 + +[[parachains]] +id = 1000 +chain = "asset-hub-polkadot-local" +chain_spec_command = "{{CHAIN_SPEC_GEN_BINARY}} {% raw %} {{chainName}} {% endraw %}" +cumulus_based = true + +[[parachains.collators]] +name = "asset-hub-polkadot-collator-1" +rpc_port = 9911 +ws_port = 9910 +command = "{{POLKADOT_PARACHAIN_BINARY}}" +args = [ + "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace" +] + +[[parachains.collators]] +name = "asset-hub-polkadot-collator-2" +command = "{{POLKADOT_PARACHAIN_BINARY}}" +args = [ + "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace" +] + +[[parachains]] +id = 1002 +chain = "bridge-hub-polkadot-local" +chain_spec_command = "{{ENV_PATH}}/generate_bh_spec.sh Kusama {% raw %} {{chainName}} {% endraw %}" +cumulus_based = true + +[[parachains.collators]] +name = "bridge-hub-polkadot-collator-1" +validator = true +command = "{{POLKADOT_PARACHAIN_BINARY}}" +rpc_port = 8933 +ws_port = 8943 +args = [ + "-lparachain=debug,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace" +] + +[[parachains.collators]] +name = "bridge-hub-polkadot-collator-2" +validator = true +command = "{{POLKADOT_PARACHAIN_BINARY}}" +rpc_port = 8934 +ws_port = 8944 +args = [ + "-lparachain=trace,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace" +] diff --git a/integration-tests/bridges/environments/polkadot-kusama/bridges_polkadot_kusama.sh b/integration-tests/bridges/environments/polkadot-kusama/bridges_polkadot_kusama.sh new file mode 100755 index 0000000000..040db39db3 --- /dev/null +++ b/integration-tests/bridges/environments/polkadot-kusama/bridges_polkadot_kusama.sh @@ -0,0 +1,385 @@ +#!/bin/bash + +# import common functions +source "$FRAMEWORK_PATH/utils/bridges.sh" + +# Expected sovereign accounts. +# +# Generated by: +# +##[test] +#fn generate_sovereign_accounts() { +# use polkadot_parachain_primitives::primitives::Sibling; +# use sp_core::crypto::Ss58Codec; +# +# parameter_types! { +# pub UniversalLocationAHP: InteriorLocation = [GlobalConsensus(Polkadot), Parachain(1000)].into(); +# pub UniversalLocationAHK: InteriorLocation = [GlobalConsensus(Kusama), Parachain(1000)].into(); +# } +# +# +# println!( +# "GLOBAL_CONSENSUS_POLKADOT_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusConvertsFor::::convert_location( +# &Location { parents: 2, interior: [GlobalConsensus(Polkadot)].into() } +# ) +# .unwrap() +# ) +# .to_ss58check_with_version(2_u16.into()) +# ); +# +# println!( +# "ASSET_HUB_KUSAMA_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_KUSAMA=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# SiblingParachainConvertsVia::::convert_location(&Location { +# parents: 1, +# interior: [Parachain(1000)].into() +# }) +# .unwrap() +# ) +# .to_ss58check_with_version(2_u16.into()) +# ); +# +# +# println!( +# "GLOBAL_CONSENSUS_KUSAMA_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusConvertsFor::::convert_location( +# &Location { parents: 2, interior: [GlobalConsensus(Kusama)].into() } +# ) +# .unwrap() +# ) +# .to_ss58check_with_version(0_u16.into()) +# ); +# println!( +# "ASSET_HUB_POLKADOT_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_POLKADOT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# SiblingParachainConvertsVia::::convert_location(&Location { +# parents: 1, +# interior: [Parachain(1000)].into() +# }) +# .unwrap() +# ) +# .to_ss58check_with_version(0_u16.into()) +# ); +#} +GLOBAL_CONSENSUS_POLKADOT_SOVEREIGN_ACCOUNT="FxqimVubBRPqJ8kTwb3wL7G4q645hEkBEnXPyttLsTrFc5Q" +ASSET_HUB_KUSAMA_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_KUSAMA="FBeL7EFTDeHnuViqaUHUXvhhUusN5FawDmHgfvzF97DXFr3" +GLOBAL_CONSENSUS_KUSAMA_SOVEREIGN_ACCOUNT="14zcUAhP5XypiFQWA3b1AnGKrhZqR4XWUo4deWkwuN5y983G" +ASSET_HUB_POLKADOT_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_POLKADOT="13cKp89SgdtqUngo2WiEijPrQWdHFhzYZLf2TJePKRvExk7o" + +# Expected sovereign accounts for rewards on BridgeHubs. +# +# Generated by: +##[test] +#fn generate_sovereign_accounts_for_rewards() { +# use bp_messages::LaneId; +# use bp_relayers::{PayRewardFromAccount, RewardsAccountOwner, RewardsAccountParams}; +# use sp_core::crypto::Ss58Codec; +# +# println!( +# "ON_BRIDGE_HUB_POLKADOT_SOVEREIGN_ACCOUNT_FOR_LANE_00000001_bhks_ThisChain=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# PayRewardFromAccount::<[u8; 32], [u8; 32]>::rewards_account(RewardsAccountParams::new( +# LaneId([0, 0, 0, 1]), +# *b"bhks", +# RewardsAccountOwner::ThisChain +# )) +# ) +# .to_ss58check_with_version(0_u16.into()) +# ); +# +# println!( +# "ON_BRIDGE_HUB_POLKADOT_SOVEREIGN_ACCOUNT_FOR_LANE_00000001_bhks_BridgedChain=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# PayRewardFromAccount::<[u8; 32], [u8; 32]>::rewards_account(RewardsAccountParams::new( +# LaneId([0, 0, 0, 1]), +# *b"bhks", +# RewardsAccountOwner::BridgedChain +# )) +# ) +# .to_ss58check_with_version(0_u16.into()) +# ); +# +# +# println!( +# "ON_BRIDGE_HUB_KUSAMA_SOVEREIGN_ACCOUNT_FOR_LANE_00000001_bhpd_ThisChain=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# PayRewardFromAccount::<[u8; 32], [u8; 32]>::rewards_account(RewardsAccountParams::new( +# LaneId([0, 0, 0, 1]), +# *b"bhpd", +# RewardsAccountOwner::ThisChain +# )) +# ) +# .to_ss58check_with_version(2_u16.into()) +# ); +# +# println!( +# "ON_BRIDGE_HUB_KUSAMA_SOVEREIGN_ACCOUNT_FOR_LANE_00000001_bhpd_BridgedChain=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# PayRewardFromAccount::<[u8; 32], [u8; 32]>::rewards_account(RewardsAccountParams::new( +# LaneId([0, 0, 0, 1]), +# *b"bhpd", +# RewardsAccountOwner::BridgedChain +# )) +# ) +# .to_ss58check_with_version(2_u16.into()) +# ); +#} +ON_BRIDGE_HUB_POLKADOT_SOVEREIGN_ACCOUNT_FOR_LANE_00000001_bhks_ThisChain="13E5fui93Uyua5RtDv2LQj4aVBBHo6YREe3n6CBwYdqNqoxj" +ON_BRIDGE_HUB_POLKADOT_SOVEREIGN_ACCOUNT_FOR_LANE_00000001_bhks_BridgedChain="13E5fui93Uyua5RtDv2c9kcAbfrVFeeHyJzHe8sn1Ti77Afd" +ON_BRIDGE_HUB_KUSAMA_SOVEREIGN_ACCOUNT_FOR_LANE_00000001_bhpd_ThisChain="EoQBtnwp4jMtCEpV7C88rKrz6x1qMBh2z74ibGSqtZRnuMM" +ON_BRIDGE_HUB_KUSAMA_SOVEREIGN_ACCOUNT_FOR_LANE_00000001_bhpd_BridgedChain="EoQBtnwp4jMtCEpV7CPsssT6bdDHuHZmf3aGXxHJiSA4Dz3" + +LANE_ID="00000001" +XCM_VERSION=3 + +AHK_DOT_ED=10000000 +DOT=10000000000 + +AHP_KSM_ED=10000000 +KSM=1000000000000 + +function init_polkadot_kusama() { + local relayer_path=$(ensure_relayer) + + RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ + $relayer_path init-bridge polkadot-to-bridge-hub-kusama \ + --source-host localhost \ + --source-port 9942 \ + --source-version-mode Auto \ + --target-host localhost \ + --target-port 8945 \ + --target-version-mode Auto \ + --target-signer //Alice +} + +function init_kusama_polkadot() { + local relayer_path=$(ensure_relayer) + + RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ + $relayer_path init-bridge kusama-to-bridge-hub-polkadot \ + --source-host localhost \ + --source-port 9945 \ + --source-version-mode Auto \ + --target-host localhost \ + --target-port 8943 \ + --target-version-mode Auto \ + --target-signer //Alice +} + +function run_relay() { + local relayer_path=$(ensure_relayer) + + RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ + $relayer_path relay-headers-and-messages bridge-hub-kusama-bridge-hub-polkadot \ + --polkadot-host localhost \ + --polkadot-port 9942 \ + --polkadot-version-mode Auto \ + --bridge-hub-polkadot-host localhost \ + --bridge-hub-polkadot-port 8943 \ + --bridge-hub-polkadot-version-mode Auto \ + --bridge-hub-polkadot-signer //Charlie \ + --bridge-hub-polkadot-transactions-mortality 4 \ + --kusama-host localhost \ + --kusama-port 9945 \ + --kusama-version-mode Auto \ + --bridge-hub-kusama-host localhost \ + --bridge-hub-kusama-port 8945 \ + --bridge-hub-kusama-version-mode Auto \ + --bridge-hub-kusama-signer //Charlie \ + --bridge-hub-kusama-transactions-mortality 4 \ + --lane "${LANE_ID}" +} + +case "$1" in + run-relay) + init_kusama_polkadot + init_polkadot_kusama + run_relay + ;; + init-asset-hub-polkadot-local) + ensure_polkadot_js_api + # create foreign assets for native Kusama token (governance call on Polkadot) + force_create_foreign_asset \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1000 \ + "ws://127.0.0.1:9910" \ + "$(jq --null-input '{ "parents": 2, "interior": { "X1": { "GlobalConsensus": "Kusama" } } }')" \ + "$GLOBAL_CONSENSUS_KUSAMA_SOVEREIGN_ACCOUNT" \ + $AHP_KSM_ED \ + true + # HRMP + open_hrmp_channels \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1000 1002 4 524288 + open_hrmp_channels \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1002 1000 4 524288 + # set XCM version of remote AssetHubKusama + 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": "Kusama" }, { "Parachain": 1000 } ] } }')" \ + $XCM_VERSION + ;; + init-bridge-hub-polkadot-local) + ensure_polkadot_js_api + # SA of sibling asset hub pays for the execution + transfer_balance \ + "ws://127.0.0.1:8943" \ + "//Alice" \ + "$ASSET_HUB_POLKADOT_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_POLKADOT" \ + $((25 * $DOT)) + # 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_POLKADOT_SOVEREIGN_ACCOUNT_FOR_LANE_00000001_bhks_ThisChain" \ + $((25 * $DOT)) + # 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_POLKADOT_SOVEREIGN_ACCOUNT_FOR_LANE_00000001_bhks_BridgedChain" \ + $((25 * $DOT)) + # set XCM version of remote BridgeHubKusama + force_xcm_version \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1002 \ + "ws://127.0.0.1:8943" \ + "$(jq --null-input '{ "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Kusama" }, { "Parachain": 1002 } ] } }')" \ + $XCM_VERSION + ;; + init-asset-hub-kusama-local) + ensure_polkadot_js_api + # create foreign assets for native Polkadot token (governance call on Kusama) + force_create_foreign_asset \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1000 \ + "ws://127.0.0.1:9010" \ + "$(jq --null-input '{ "parents": 2, "interior": { "X1": { "GlobalConsensus": "Polkadot" } } }')" \ + "$GLOBAL_CONSENSUS_POLKADOT_SOVEREIGN_ACCOUNT" \ + $AHK_DOT_ED \ + true + # HRMP + open_hrmp_channels \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1000 1002 4 524288 + open_hrmp_channels \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1002 1000 4 524288 + # set XCM version of remote AssetHubPolkadot + 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": "Polkadot" }, { "Parachain": 1000 } ] } }')" \ + $XCM_VERSION + ;; + init-bridge-hub-kusama-local) + # SA of sibling asset hub pays for the execution + transfer_balance \ + "ws://127.0.0.1:8945" \ + "//Alice" \ + "$ASSET_HUB_KUSAMA_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_KUSAMA" \ + $((25 * $KSM)) + # 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_KUSAMA_SOVEREIGN_ACCOUNT_FOR_LANE_00000001_bhpd_ThisChain" \ + $((25 * $KSM)) + # 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_KUSAMA_SOVEREIGN_ACCOUNT_FOR_LANE_00000001_bhpd_BridgedChain" \ + $((25 * $KSM)) + # set XCM version of remote BridgeHubPolkadot + 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": "Polkadot" }, { "Parachain": 1002 } ] } }')" \ + $XCM_VERSION + ;; + reserve-transfer-assets-from-asset-hub-polkadot-local) + amount=$2 + ensure_polkadot_js_api + # send DOTs to Alice account on AHK + limited_reserve_transfer_assets \ + "ws://127.0.0.1:9910" \ + "//Alice" \ + "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Kusama" }, { "Parachain": 1000 } ] } } }')" \ + "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": '$amount' } } ] }')" \ + 0 \ + "Unlimited" + ;; + withdraw-reserve-assets-from-asset-hub-polkadot-local) + amount=$2 + ensure_polkadot_js_api + # send back some wrappedKSMs to Alice account on AHK + limited_reserve_transfer_assets \ + "ws://127.0.0.1:9910" \ + "//Alice" \ + "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Kusama" }, { "Parachain": 1000 } ] } } }')" \ + "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 2, "interior": { "X1": { "GlobalConsensus": "Kusama" } } } }, "fun": { "Fungible": '$amount' } } ] }')" \ + 0 \ + "Unlimited" + ;; + reserve-transfer-assets-from-asset-hub-kusama-local) + amount=$2 + ensure_polkadot_js_api + # send KSMs to Alice account on AHP + limited_reserve_transfer_assets \ + "ws://127.0.0.1:9010" \ + "//Alice" \ + "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Polkadot" }, { "Parachain": 1000 } ] } } }')" \ + "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": '$amount' } } ] }')" \ + 0 \ + "Unlimited" + ;; + withdraw-reserve-assets-from-asset-hub-kusama-local) + amount=$2 + ensure_polkadot_js_api + # send back some wrappedDOTs to Alice account on AHP + limited_reserve_transfer_assets \ + "ws://127.0.0.1:9010" \ + "//Alice" \ + "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Polkadot" }, { "Parachain": 1000 } ] } } }')" \ + "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 2, "interior": { "X1": { "GlobalConsensus": "Polkadot" } } } }, "fun": { "Fungible": '$amount' } } ] }')" \ + 0 \ + "Unlimited" + ;; + *) + echo "A command is require. Supported commands for: + Local (zombienet) run: + - run-relay + - init-asset-hub-polkadot-local + - init-bridge-hub-polkadot-local + - init-asset-hub-kusama-local + - init-bridge-hub-kusama-local + - reserve-transfer-assets-from-asset-hub-polkadot-local + - withdraw-reserve-assets-from-asset-hub-polkadot-local + - reserve-transfer-assets-from-asset-hub-kusama-local + - withdraw-reserve-assets-from-asset-hub-kusama-local"; + exit 1 + ;; +esac diff --git a/integration-tests/bridges/environments/polkadot-kusama/generate_bh_spec.sh b/integration-tests/bridges/environments/polkadot-kusama/generate_bh_spec.sh new file mode 100755 index 0000000000..b4fcbb8bae --- /dev/null +++ b/integration-tests/bridges/environments/polkadot-kusama/generate_bh_spec.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +bridged_chain=$1 +shift + +# Add Alice as bridge owner +# We do this only if there is a `.genesis.runtimeGenesis.patch` object. +# Otherwise we're working with the raw chain spec. +$CHAIN_SPEC_GEN_BINARY "$@" \ + | jq 'if .genesis.runtimeGenesis.patch + then .genesis.runtimeGenesis.patch.bridge'$bridged_chain'Grandpa.owner = "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" + else . + end' diff --git a/integration-tests/bridges/environments/polkadot-kusama/helper.sh b/integration-tests/bridges/environments/polkadot-kusama/helper.sh new file mode 100755 index 0000000000..ab48938386 --- /dev/null +++ b/integration-tests/bridges/environments/polkadot-kusama/helper.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +$ENV_PATH/bridges_polkadot_kusama.sh "$@" diff --git a/integration-tests/bridges/environments/polkadot-kusama/kusama-bridge.zndsl b/integration-tests/bridges/environments/polkadot-kusama/kusama-bridge.zndsl new file mode 100644 index 0000000000..e2902892aa --- /dev/null +++ b/integration-tests/bridges/environments/polkadot-kusama/kusama-bridge.zndsl @@ -0,0 +1,5 @@ +Network: ./bridge_hub_kusama_local_network.toml +Creds: config + +# relay is already started - let's wait until with-Rococo GRANPDA pallet is initialized at Polkadot +bridge-hub-kusama-collator-1: js-script {{FRAMEWORK_PATH}}/js-helpers/best-finalized-header-at-bridged-chain.js with "Polkadot,0" within 400 seconds diff --git a/integration-tests/bridges/environments/polkadot-kusama/kusama-init.zndsl b/integration-tests/bridges/environments/polkadot-kusama/kusama-init.zndsl new file mode 100644 index 0000000000..4f6bac65af --- /dev/null +++ b/integration-tests/bridges/environments/polkadot-kusama/kusama-init.zndsl @@ -0,0 +1,6 @@ +Network: ./bridge_hub_kusama_local_network.toml +Creds: config + +# ensure that initialization has completed +asset-hub-kusama-collator-1: js-script {{FRAMEWORK_PATH}}/js-helpers/wait-hrmp-channel-opened.js with "1002" within 300 seconds + diff --git a/integration-tests/bridges/environments/polkadot-kusama/polkadot-bridge.zndsl b/integration-tests/bridges/environments/polkadot-kusama/polkadot-bridge.zndsl new file mode 100644 index 0000000000..7dac894542 --- /dev/null +++ b/integration-tests/bridges/environments/polkadot-kusama/polkadot-bridge.zndsl @@ -0,0 +1,5 @@ +Network: ./bridge_hub_polkadot_local_network.toml +Creds: config + +# relay is already started - let's wait until with-Rococo GRANPDA pallet is initialized at Polkadot +bridge-hub-polkadot-collator-1: js-script {{FRAMEWORK_PATH}}/js-helpers/best-finalized-header-at-bridged-chain.js with "Kusama,0" within 400 seconds diff --git a/integration-tests/bridges/environments/polkadot-kusama/polkadot-init.zndsl b/integration-tests/bridges/environments/polkadot-kusama/polkadot-init.zndsl new file mode 100644 index 0000000000..4d7fb281bb --- /dev/null +++ b/integration-tests/bridges/environments/polkadot-kusama/polkadot-init.zndsl @@ -0,0 +1,7 @@ +Network: ./bridge_hub_polkadot_local_network.toml +Creds: config + +# ensure that initialization has completed +asset-hub-polkadot-collator-1: js-script {{FRAMEWORK_PATH}}/js-helpers/wait-hrmp-channel-opened.js with "1002" within 300 seconds + + diff --git a/integration-tests/bridges/environments/polkadot-kusama/spawn.sh b/integration-tests/bridges/environments/polkadot-kusama/spawn.sh new file mode 100755 index 0000000000..3786ce1d4d --- /dev/null +++ b/integration-tests/bridges/environments/polkadot-kusama/spawn.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +set -e + +trap "trap - SIGTERM && kill -9 -$$" SIGINT SIGTERM EXIT + +source "$FRAMEWORK_PATH/utils/zombienet.sh" + +logs_dir=$TEST_DIR/logs +helper_script="${BASH_SOURCE%/*}/helper.sh" + +polkadot_def=${BASH_SOURCE%/*}/bridge_hub_polkadot_local_network.toml +start_zombienet $TEST_DIR $polkadot_def polkadot_dir polkadot_pid +echo + +kusama_def=${BASH_SOURCE%/*}/bridge_hub_kusama_local_network.toml +start_zombienet $TEST_DIR $kusama_def kusama_dir kusama_pid +echo + +polkadot_init_log=$logs_dir/polkadot-init.log +echo -e "Setting up the polkadot side of the bridge. Logs available at: $polkadot_init_log\n" + +kusama_init_log=$logs_dir/kusama-init.log +echo -e "Setting up the kusama side of the bridge. Logs available at: $kusama_init_log\n" + +$helper_script init-asset-hub-polkadot-local >> $polkadot_init_log 2>&1 & +polkadot_init_pid=$! +$helper_script init-asset-hub-kusama-local >> $kusama_init_log 2>&1 & +kusama_init_pid=$! +wait -n $polkadot_init_pid $kusama_init_pid + + +$helper_script init-bridge-hub-polkadot-local >> $polkadot_init_log 2>&1 & +polkadot_init_pid=$! +$helper_script init-bridge-hub-kusama-local >> $kusama_init_log 2>&1 & +kusama_init_pid=$! +wait -n $polkadot_init_pid $kusama_init_pid + +run_zndsl ${BASH_SOURCE%/*}/polkadot-init.zndsl $polkadot_dir +run_zndsl ${BASH_SOURCE%/*}/kusama-init.zndsl $kusama_dir + +${BASH_SOURCE%/*}/start_relayer.sh $polkadot_dir $kusama_dir relayer_pid + +echo $polkadot_dir > $TEST_DIR/polkadot.env +echo $kusama_dir > $TEST_DIR/kusama.env +echo + +wait -n $polkadot_pid $kusama_pid $relayer_pid +kill -9 -$$ diff --git a/integration-tests/bridges/environments/polkadot-kusama/start_relayer.sh b/integration-tests/bridges/environments/polkadot-kusama/start_relayer.sh new file mode 100755 index 0000000000..73e51f99a7 --- /dev/null +++ b/integration-tests/bridges/environments/polkadot-kusama/start_relayer.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +set -e + +source "$FRAMEWORK_PATH/utils/common.sh" +source "$FRAMEWORK_PATH/utils/zombienet.sh" + +polkadot_dir=$1 +kusama_dir=$2 +__relayer_pid=$3 + +logs_dir=$TEST_DIR/logs +helper_script="${BASH_SOURCE%/*}/helper.sh" + +relayer_log=$logs_dir/relayer.log +echo -e "Starting polkadot-kusama relayer. Logs available at: $relayer_log\n" +start_background_process "$helper_script run-relay" $relayer_log relayer_pid + +run_zndsl ${BASH_SOURCE%/*}/polkadot-bridge.zndsl $polkadot_dir +run_zndsl ${BASH_SOURCE%/*}/kusama-bridge.zndsl $kusama_dir + +eval $__relayer_pid="'$relayer_pid'" + diff --git a/integration-tests/bridges/run-test.sh b/integration-tests/bridges/run-test.sh new file mode 100755 index 0000000000..baa542825e --- /dev/null +++ b/integration-tests/bridges/run-test.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +set -e + +trap 'kill -9 -$$ || echo "Environment already teared down"' SIGINT SIGTERM EXIT + +test=$1 + +export LOCAL_BRIDGE_TESTING_PATH=~/local_bridge_testing +export DOWNLOADS_PATH=$LOCAL_BRIDGE_TESTING_PATH/downloads +mkdir -p $DOWNLOADS_PATH + +# Download the bridge testing "framework" from the `polkadot-sdk` repo +# to `~/local_bridge_testing/downloads/polkadot-sdk`. +framework_repo_path=$DOWNLOADS_PATH/polkadot-sdk +rm -rf $framework_repo_path +git clone --branch master -n --depth=1 --filter=tree:0 \ + https://github.com/paritytech/polkadot-sdk.git $framework_repo_path +pushd $framework_repo_path +git sparse-checkout set --no-cone bridges/testing/framework +git fetch --tags +git checkout polkadot-v1.11.0 +popd +export FRAMEWORK_PATH=$framework_repo_path/bridges/testing/framework +echo + +export ZOMBIENET_BINARY=$LOCAL_BRIDGE_TESTING_PATH/bin/zombienet +export POLKADOT_BINARY=/home/serban/workplace/sources/polkadot-sdk/target/release/polkadot +export POLKADOT_PARACHAIN_BINARY=/home/serban/workplace/sources/polkadot-sdk/target/release/polkadot-parachain +export CHAIN_SPEC_GEN_BINARY=$LOCAL_BRIDGE_TESTING_PATH/bin/chain-spec-generator +export SUBSTRATE_RELAY_BINARY=$LOCAL_BRIDGE_TESTING_PATH/bin/substrate-relay + +export TEST_DIR=`mktemp -d /tmp/bridges-tests-run-XXXXX` +echo -e "Test folder: $TEST_DIR\n" + +${BASH_SOURCE%/*}/tests/$test/run.sh diff --git a/integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/dot-reaches-kusama.zndsl b/integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/dot-reaches-kusama.zndsl new file mode 100644 index 0000000000..13db4cca35 --- /dev/null +++ b/integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/dot-reaches-kusama.zndsl @@ -0,0 +1,12 @@ +Description: User is able to transfer DOT from Polkadot Asset Hub to Kusama Asset Hub +Network: {{ENV_PATH}}/bridge_hub_kusama_local_network.toml +Creds: config + +# send 5 DOT to //Alice from Polkadot AH to Kusama AH +asset-hub-kusama-collator-1: run {{ENV_PATH}}/helper.sh with "reserve-transfer-assets-from-asset-hub-polkadot-local 50000000000" within 120 seconds + +# check that //Alice received at least 4.8 DOT on Kusama AH +asset-hub-kusama-collator-1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,48000000000,Polkadot" within 300 seconds + +# check that the relayer //Charlie is rewarded by Kusama AH +bridge-hub-kusama-collator-1: js-script {{FRAMEWORK_PATH}}/js-helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000001,0x62687064,ThisChain,0" within 30 seconds diff --git a/integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/ksm-reaches-polkadot.zndsl b/integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/ksm-reaches-polkadot.zndsl new file mode 100644 index 0000000000..c07bfa9732 --- /dev/null +++ b/integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/ksm-reaches-polkadot.zndsl @@ -0,0 +1,12 @@ +Description: User is able to transfer KSM from Kusama Asset Hub to Polkadot Asset Hub +Network: {{ENV_PATH}}/bridge_hub_polkadot_local_network.toml +Creds: config + +# send 5 KSM to //Alice from Kusama AH to Polkadot AH +asset-hub-polkadot-collator-1: run {{ENV_PATH}}/helper.sh with "reserve-transfer-assets-from-asset-hub-kusama-local 5000000000000" within 120 seconds + +# check that //Alice received at least 4.8 KSM on Polkadot AH +asset-hub-polkadot-collator-1: js-script {{FRAMEWORK_PATH}}/js-helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,4800000000000,Kusama" within 300 seconds + +# check that the relayer //Charlie is rewarded by Polkadot AH +bridge-hub-polkadot-collator-1: js-script {{FRAMEWORK_PATH}}/js-helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000001,0x62686b73,ThisChain,0" within 30 seconds diff --git a/integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/run.sh b/integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/run.sh new file mode 100755 index 0000000000..0cfc116119 --- /dev/null +++ b/integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/run.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Test that checks if asset transfer works on P<>K bridge. +# This test is intentionally not added to the CI. It is meant to be ran manually. + +set -e + +source "$FRAMEWORK_PATH/utils/common.sh" +source "$FRAMEWORK_PATH/utils/zombienet.sh" + +export ENV_PATH=`realpath ${BASH_SOURCE%/*}/../../environments/polkadot-kusama` + +$ENV_PATH/spawn.sh & +env_pid=$! + +ensure_process_file $env_pid $TEST_DIR/polkadot.env 600 +polkadot_dir=`cat $TEST_DIR/polkadot.env` +echo + +ensure_process_file $env_pid $TEST_DIR/kusama.env 300 +kusama_dir=`cat $TEST_DIR/kusama.env` +echo + +run_zndsl ${BASH_SOURCE%/*}/dot-reaches-kusama.zndsl $kusama_dir +run_zndsl ${BASH_SOURCE%/*}/ksm-reaches-polkadot.zndsl $polkadot_dir + +run_zndsl ${BASH_SOURCE%/*}/wdot-reaches-polkadot.zndsl $polkadot_dir +run_zndsl ${BASH_SOURCE%/*}/wksm-reaches-kusama.zndsl $kusama_dir diff --git a/integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/wdot-reaches-polkadot.zndsl b/integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/wdot-reaches-polkadot.zndsl new file mode 100644 index 0000000000..f1546b2a16 --- /dev/null +++ b/integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/wdot-reaches-polkadot.zndsl @@ -0,0 +1,10 @@ +Description: User is able to transfer wDOT back from Kusama Asset Hub to Polkadot Asset Hub +Network: {{ENV_PATH}}/bridge_hub_polkadot_local_network.toml +Creds: config + +# send 3 wDOT back to Alice from Kusama AH to Polkadot AH +asset-hub-polkadot-collator-1: run {{ENV_PATH}}/helper.sh with "withdraw-reserve-assets-from-asset-hub-kusama-local 30000000000" within 120 seconds + +# check that //Alice received at least 2.8 wDOT on Polkadot AH +# (we wait until //Alice account increases here - there are no other transactions that may increase it) +asset-hub-polkadot-collator-1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY, 28000000000" within 300 seconds diff --git a/integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/wksm-reaches-kusama.zndsl b/integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/wksm-reaches-kusama.zndsl new file mode 100644 index 0000000000..7bb680f080 --- /dev/null +++ b/integration-tests/bridges/tests/0001-polkadot-kusama-asset-transfer/wksm-reaches-kusama.zndsl @@ -0,0 +1,10 @@ +Description: User is able to transfer wKSM from Polkadot Asset Hub back to Kusama Asset Hub +Network: {{ENV_PATH}}/bridge_hub_kusama_local_network.toml +Creds: config + +# send 3 wKSM back to Alice from Polkadot AH to Kusama AH +asset-hub-kusama-collator-1: run {{ENV_PATH}}/helper.sh with "withdraw-reserve-assets-from-asset-hub-polkadot-local 3000000000000" within 120 seconds + +# check that //Alice received at least 2.8 wKSM on Westend AH +# (we wait until //Alice account increases here - there are no other transactions that may increase it) +asset-hub-kusama-collator-1: js-script {{FRAMEWORK_PATH}}/js-helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,2800000000000" within 300 seconds