diff --git a/bridges/zombienet/helpers/chains/rococo-at-westend.js b/bridges/zombienet/helpers/chains/rococo-at-westend.js new file mode 100644 index 000000000000..eb9510e46f0b --- /dev/null +++ b/bridges/zombienet/helpers/chains/rococo-at-westend.js @@ -0,0 +1,6 @@ +module.exports = { + grandpaPalletName: "bridgeRococoGrandpa", + parachainsPalletName: "bridgeRococoParachains", + messagesPalletName: "bridgeRococoMessages", + bridgedBridgeHubParaId: 1013, +} diff --git a/bridges/zombienet/helpers/chains/westend-at-rococo.js b/bridges/zombienet/helpers/chains/westend-at-rococo.js new file mode 100644 index 000000000000..771a0778cb09 --- /dev/null +++ b/bridges/zombienet/helpers/chains/westend-at-rococo.js @@ -0,0 +1,6 @@ +module.exports = { + grandpaPalletName: "bridgeWestendGrandpa", + parachainsPalletName: "bridgeWestendParachains", + messagesPalletName: "bridgeWestendMessages", + bridgedBridgeHubParaId: 1002, +} diff --git a/bridges/zombienet/helpers/only-mandatory-headers-synced-when-idle.js b/bridges/zombienet/helpers/only-mandatory-headers-synced-when-idle.js new file mode 100644 index 000000000000..3a3432cfaf38 --- /dev/null +++ b/bridges/zombienet/helpers/only-mandatory-headers-synced-when-idle.js @@ -0,0 +1,44 @@ +const utils = require("./utils"); + +async function run(nodeName, networkInfo, args) { + const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName]; + const api = await zombie.connect(wsUri, userDefinedTypes); + + // parse arguments + const exitAfterSeconds = Number(args[0]); + const bridgedChain = require("./chains/" + args[1]); + + // start listening to new blocks + let totalGrandpaHeaders = 0; + let totalParachainHeaders = 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.ensureOnlyMandatoryGrandpaHeadersImported( + bridgedChain, + apiAtParent, + apiAtCurrent, + currentEvents, + ); + totalParachainHeaders += await utils.ensureOnlyInitialParachainHeaderImported( + bridgedChain, + apiAtParent, + apiAtCurrent, + currentEvents, + ); + }); + + // wait given time + await new Promise(resolve => setTimeout(resolve, exitAfterSeconds * 1000)); + // if we haven't seen any new GRANDPA or parachain headers => fail + if (totalGrandpaHeaders == 0) { + throw new Error("No bridged relay chain headers imported"); + } + if (totalParachainHeaders == 0) { + throw new Error("No bridged parachain headers imported"); + } +} + +module.exports = { run } diff --git a/bridges/zombienet/helpers/only-required-headers-synced-when-idle.js b/bridges/zombienet/helpers/only-required-headers-synced-when-idle.js new file mode 100644 index 000000000000..8c3130e4fd96 --- /dev/null +++ b/bridges/zombienet/helpers/only-required-headers-synced-when-idle.js @@ -0,0 +1,81 @@ +const utils = require("./utils"); + +async function run(nodeName, networkInfo, args) { + const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName]; + const api = await zombie.connect(wsUri, userDefinedTypes); + + // parse arguments + const exitAfterSeconds = Number(args[0]); + const bridgedChain = require("./chains/" + args[1]); + + // start listening to new blocks + let atLeastOneMessageReceived = false; + let atLeastOneMessageDelivered = false; + const unsubscribe = await api.rpc.chain.subscribeNewHeads(async function (header) { + const apiAtParent = await api.at(header.parentHash); + const apiAtCurrent = await api.at(header.hash); + const currentEvents = await apiAtCurrent.query.system.events(); + + const messagesReceived = currentEvents.find((record) => { + return record.event.section == bridgedChain.messagesPalletName + && record.event.method == "MessagesReceived"; + }) != undefined; + const messagesDelivered = currentEvents.find((record) => { + return record.event.section == bridgedChain.messagesPalletName && + record.event.method == "MessagesDelivered"; + }) != undefined; + const hasMessageUpdates = messagesReceived || messagesDelivered; + atLeastOneMessageReceived = atLeastOneMessageReceived || messagesReceived; + atLeastOneMessageDelivered = atLeastOneMessageDelivered || messagesDelivered; + + if (!hasMessageUpdates) { + // if there are no any message update transactions, we only expect mandatory GRANDPA + // headers and initial parachain headers + await utils.ensureOnlyMandatoryGrandpaHeadersImported( + bridgedChain, + apiAtParent, + apiAtCurrent, + currentEvents, + ); + await utils.ensureOnlyInitialParachainHeaderImported( + bridgedChain, + apiAtParent, + apiAtCurrent, + currentEvents, + ); + } else { + const messageTransactions = (messagesReceived ? 1 : 0) + (messagesDelivered ? 1 : 0); + + // otherwise we only accept at most one GRANDPA header + const newGrandpaHeaders = utils.countGrandpaHeaderImports(bridgedChain, currentEvents); + if (newGrandpaHeaders > 1) { + utils.logEvents(currentEvents); + throw new Error("Unexpected relay chain header import: " + newGrandpaHeaders + " / " + messageTransactions); + } + + // ...and at most one parachain header + const newParachainHeaders = utils.countParachainHeaderImports(bridgedChain, currentEvents); + if (newParachainHeaders > 1) { + utils.logEvents(currentEvents); + throw new Error("Unexpected parachain header import: " + newParachainHeaders + " / " + messageTransactions); + } + } + }); + + // wait until we have received + delivered messages OR until timeout + await utils.pollUntil( + exitAfterSeconds, + () => { return atLeastOneMessageReceived && atLeastOneMessageDelivered; }, + () => { unsubscribe(); }, + () => { + if (!atLeastOneMessageReceived) { + throw new Error("No messages received from bridged chain"); + } + if (!atLeastOneMessageDelivered) { + throw new Error("No messages delivered to bridged chain"); + } + }, + ); +} + +module.exports = { run } diff --git a/bridges/zombienet/helpers/utils.js b/bridges/zombienet/helpers/utils.js new file mode 100644 index 000000000000..5a5542b56dfc --- /dev/null +++ b/bridges/zombienet/helpers/utils.js @@ -0,0 +1,103 @@ +module.exports = { + logEvents: function(events) { + let stringifiedEvents = ""; + events.forEach((record) => { + if (stringifiedEvents != "") { + stringifiedEvents += ", "; + } + stringifiedEvents += record.event.section + "::" + record.event.method; + }); + console.log("Block events: " + stringifiedEvents); + }, + countGrandpaHeaderImports: function(bridgedChain, events) { + return events.reduce( + (count, record) => { + const { event } = record; + if (event.section == bridgedChain.grandpaPalletName && event.method == "UpdatedBestFinalizedHeader") { + count += 1; + } + return count; + }, + 0, + ); + }, + countParachainHeaderImports: function(bridgedChain, events) { + return events.reduce( + (count, record) => { + const { event } = record; + if (event.section == bridgedChain.parachainsPalletName && event.method == "UpdatedParachainHead") { + count += 1; + } + return count; + }, + 0, + ); + }, + pollUntil: async function( + timeoutInSecs, + predicate, + cleanup, + onFailure, + ) { + const begin = new Date().getTime(); + const end = begin + timeoutInSecs * 1000; + while (new Date().getTime() < end) { + if (predicate()) { + cleanup(); + return; + } + await new Promise(resolve => setTimeout(resolve, 100)); + } + + cleanup(); + onFailure(); + }, + ensureOnlyMandatoryGrandpaHeadersImported: async function( + bridgedChain, + apiAtParent, + apiAtCurrent, + currentEvents, + ) { + // remember id of bridged relay chain GRANDPA authorities set at parent block + const authoritySetAtParent = await apiAtParent.query[bridgedChain.grandpaPalletName].currentAuthoritySet(); + const authoritySetIdAtParent = authoritySetAtParent["setId"]; + + // now read the id of bridged relay chain GRANDPA authorities set at current block + const authoritySetAtCurrent = await apiAtCurrent.query[bridgedChain.grandpaPalletName].currentAuthoritySet(); + const authoritySetIdAtCurrent = authoritySetAtCurrent["setId"]; + + // we expect to see no more than `authoritySetIdAtCurrent - authoritySetIdAtParent` new GRANDPA headers + const maxNewGrandpaHeaders = authoritySetIdAtCurrent - authoritySetIdAtParent; + const newGrandpaHeaders = module.exports.countGrandpaHeaderImports(bridgedChain, currentEvents); + + // check that our assumptions are correct + if (newGrandpaHeaders > maxNewGrandpaHeaders) { + module.exports.logEvents(currentEvents); + throw new Error("Unexpected relay chain header import: " + newGrandpaHeaders + " / " + maxNewGrandpaHeaders); + } + + return newGrandpaHeaders; + }, + ensureOnlyInitialParachainHeaderImported: async function( + bridgedChain, + apiAtParent, + apiAtCurrent, + currentEvents, + ) { + // remember whether we already know bridged parachain header at a parent block + const bestBridgedParachainHeader = await apiAtParent.query[bridgedChain.parachainsPalletName].parasInfo(bridgedChain.bridgedBridgeHubParaId);; + const hasBestBridgedParachainHeader = bestBridgedParachainHeader.isSome; + + // we expect to see: no more than `1` bridged parachain header if there were no parachain header before. + const maxNewParachainHeaders = hasBestBridgedParachainHeader ? 0 : 1; + const newParachainHeaders = module.exports.countParachainHeaderImports(bridgedChain, currentEvents); + + // check that our assumptions are correct + if (newParachainHeaders > maxNewParachainHeaders) { + module.exports.logEvents(currentEvents); + throw new Error("Unexpected parachain header import: " + newParachainHeaders + " / " + maxNewParachainHeaders); + } + + return newParachainHeaders; + }, +} diff --git a/bridges/zombienet/run-tests.sh b/bridges/zombienet/run-tests.sh index 34487e13261f..cf3b529e6a9d 100755 --- a/bridges/zombienet/run-tests.sh +++ b/bridges/zombienet/run-tests.sh @@ -1,10 +1,12 @@ #!/bin/bash -#set -eu set -x shopt -s nullglob -trap "trap - SIGINT SIGTERM EXIT && kill -- -$$" SIGINT SIGTERM EXIT +trap "trap - SIGINT SIGTERM EXIT && killall -q -9 substrate-relay && kill -- -$$" SIGINT SIGTERM EXIT +# run tests in range [TESTS_BEGIN; TESTS_END) +TESTS_BEGIN=1 +TESTS_END=1000 # whether to use paths for zombienet+bridges tests container or for local testing ZOMBIENET_DOCKER_PATHS=0 while [ $# -ne 0 ] @@ -14,6 +16,11 @@ do --docker) ZOMBIENET_DOCKER_PATHS=1 ;; + --test) + shift + TESTS_BEGIN="$1" + TESTS_END="$1" + ;; esac shift done @@ -57,7 +64,8 @@ ALL_TESTS_FOLDER=`mktemp -d /tmp/bridges-zombienet-tests.XXXXX` function start_coproc() { local command=$1 local name=$2 - local coproc_log=`mktemp -p $TEST_FOLDER` + local logname=`basename $name` + local coproc_log=`mktemp -p $TEST_FOLDER $logname.XXXXX` coproc COPROC { # otherwise zombienet uses some hardcoded paths unset RUN_IN_CONTAINER @@ -73,7 +81,7 @@ function start_coproc() { } # execute every test from tests folder -TEST_INDEX=1 +TEST_INDEX=$TESTS_BEGIN while true do declare -A TEST_COPROCS @@ -81,7 +89,7 @@ do TEST_PREFIX=$(printf "%04d" $TEST_INDEX) # it'll be used by the `sync-exit.sh` script - export TEST_FOLDER=`mktemp -d -p $ALL_TESTS_FOLDER` + export TEST_FOLDER=`mktemp -d -p $ALL_TESTS_FOLDER test-$TEST_PREFIX.XXXXX` # check if there are no more tests zndsl_files=($BRIDGE_TESTS_FOLDER/$TEST_PREFIX-*.zndsl) @@ -89,12 +97,6 @@ do break fi - # start relay - if [ -f $BRIDGE_TESTS_FOLDER/$TEST_PREFIX-start-relay.sh ]; then - start_coproc "${BRIDGE_TESTS_FOLDER}/${TEST_PREFIX}-start-relay.sh" "relay" - RELAY_COPROC=$COPROC_PID - ((TEST_COPROCS_COUNT++)) - fi # start tests for zndsl_file in "${zndsl_files[@]}"; do start_coproc "$ZOMBIENET_BINARY_PATH --provider native test $zndsl_file" "$zndsl_file" @@ -102,7 +104,6 @@ do ((TEST_COPROCS_COUNT++)) done # wait until all tests are completed - relay_exited=0 for n in `seq 1 $TEST_COPROCS_COUNT`; do if [ "$IS_BASH_5_1" -eq 1 ]; then wait -n -p COPROC_PID @@ -110,7 +111,6 @@ do coproc_name=${TEST_COPROCS[$COPROC_PID, 0]} coproc_log=${TEST_COPROCS[$COPROC_PID, 1]} coproc_stdout=$(cat $coproc_log) - relay_exited=$(expr "${coproc_name}" == "relay") else wait -n exit_code=$? @@ -124,18 +124,20 @@ do echo "=====================================================================" echo "=== Shutting down. Log of failed process below ===" echo "=====================================================================" - echo $coproc_stdout + echo "$coproc_stdout" exit 1 fi - - # if last test has exited, exit relay too - if [ $n -eq $(($TEST_COPROCS_COUNT - 1)) ] && [ $relay_exited -eq 0 ]; then - kill $RELAY_COPROC - break - fi done + + # proceed to next index ((TEST_INDEX++)) + if [ "$TEST_INDEX" -ge "$TESTS_END" ]; then + break + fi + + # kill relay here - it is started manually by tests + killall substrate-relay done echo "=====================================================================" diff --git a/bridges/zombienet/scripts/invoke-script.sh b/bridges/zombienet/scripts/invoke-script.sh index 6a3754a88240..835b4fe500f0 100755 --- a/bridges/zombienet/scripts/invoke-script.sh +++ b/bridges/zombienet/scripts/invoke-script.sh @@ -1,5 +1,7 @@ #!/bin/bash +INVOKE_LOG=`mktemp -p $TEST_FOLDER invoke.XXXXX` + pushd $POLKADOT_SDK_FOLDER/cumulus/scripts -./bridges_rococo_westend.sh $1 +./bridges_rococo_westend.sh $1 >$INVOKE_LOG 2>&1 popd diff --git a/bridges/zombienet/scripts/start-relayer.sh b/bridges/zombienet/scripts/start-relayer.sh new file mode 100755 index 000000000000..2f72b5ee556b --- /dev/null +++ b/bridges/zombienet/scripts/start-relayer.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +RELAY_LOG=`mktemp -p $TEST_FOLDER relay.XXXXX` + +pushd $POLKADOT_SDK_FOLDER/cumulus/scripts +./bridges_rococo_westend.sh run-relay >$RELAY_LOG 2>&1& +popd diff --git a/bridges/zombienet/tests/0001-asset-transfer-works-rococo-to-westend.zndsl b/bridges/zombienet/tests/0001-asset-transfer-works-rococo-to-westend.zndsl index fe7dc26b0011..82d1eee2f45c 100644 --- a/bridges/zombienet/tests/0001-asset-transfer-works-rococo-to-westend.zndsl +++ b/bridges/zombienet/tests/0001-asset-transfer-works-rococo-to-westend.zndsl @@ -2,31 +2,36 @@ Description: User is able to transfer ROC from Rococo Asset Hub to Westend Asset Network: ../../../cumulus/zombienet/bridge-hubs/bridge_hub_westend_local_network.toml Creds: config +# step 0: start relayer +# (started by sibling 0001-asset-transfer-works-westend-to-rococo.zndsl test) + # step 1: initialize Westend AH -asset-hub-westend-collator1: run ../scripts/invoke-script.sh with "init-asset-hub-westend-local" within 240 seconds -asset-hub-westend-collator1: js-script ../helpers/wait-hrmp-channel-opened.js with "1002" within 400 seconds +asset-hub-westend-collator1: run ../scripts/invoke-script.sh with "init-asset-hub-westend-local" within 60 seconds # step 2: initialize Westend bridge hub -bridge-hub-westend-collator1: run ../scripts/invoke-script.sh with "init-bridge-hub-westend-local" within 120 seconds +bridge-hub-westend-collator1: run ../scripts/invoke-script.sh with "init-bridge-hub-westend-local" within 60 seconds + +# step 3: ensure that initialization has completed +asset-hub-westend-collator1: js-script ../helpers/wait-hrmp-channel-opened.js with "1002" within 600 seconds -# step 3: relay is started elsewhere - let's wait until with-Rococo GRANPDA pallet is initialized at Westend +# step 4: relay is already started - let's wait until with-Rococo GRANPDA pallet is initialized at Westend bridge-hub-westend-collator1: js-script ../helpers/best-finalized-header-at-bridged-chain.js with "Rococo,0" within 400 seconds -# step 4: send WND to //Alice on Rococo AH +# step 5: send WND to //Alice on Rococo AH # (that's a required part of a sibling 0001-asset-transfer-works-westend-to-rococo.zndsl test) -asset-hub-westend-collator1: run ../scripts/invoke-script.sh with "reserve-transfer-assets-from-asset-hub-westend-local" within 120 seconds +asset-hub-westend-collator1: run ../scripts/invoke-script.sh with "reserve-transfer-assets-from-asset-hub-westend-local" within 60 seconds -# step 5: elsewhere Rococo has sent ROC to //Alice - let's wait for it +# step 6: elsewhere Rococo has sent ROC to //Alice - let's wait for it asset-hub-westend-collator1: js-script ../helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,0,Rococo" within 600 seconds -# step 6: check that the relayer //Charlie is rewarded by both our AH and target AH +# step 7: check that the relayer //Charlie is rewarded by both our AH and target AH bridge-hub-westend-collator1: js-script ../helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000002,0x6268726f,BridgedChain,0" within 300 seconds bridge-hub-westend-collator1: js-script ../helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000002,0x6268726F,ThisChain,0" within 300 seconds -# step 7: send wROC back to Alice at Rococo AH -asset-hub-westend-collator1: run ../scripts/invoke-script.sh with "withdraw-reserve-assets-from-asset-hub-westend-local" within 120 seconds +# step 8: send wROC back to Alice at Rococo AH +asset-hub-westend-collator1: run ../scripts/invoke-script.sh with "withdraw-reserve-assets-from-asset-hub-westend-local" within 60 seconds -# step 8: elsewhere Rococo has sent wWND to //Alice - let's wait for it +# step 9: elsewhere Rococo has sent wWND to //Alice - let's wait for it # (we wait until //Alice account increases here - there are no other transactionc that may increase it) asset-hub-westend-collator1: js-script ../helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" within 600 seconds diff --git a/bridges/zombienet/tests/0001-asset-transfer-works-westend-to-rococo.zndsl b/bridges/zombienet/tests/0001-asset-transfer-works-westend-to-rococo.zndsl index 610b4ca7acdc..acfe0df03d26 100644 --- a/bridges/zombienet/tests/0001-asset-transfer-works-westend-to-rococo.zndsl +++ b/bridges/zombienet/tests/0001-asset-transfer-works-westend-to-rococo.zndsl @@ -2,31 +2,36 @@ Description: User is able to transfer WND from Westend Asset Hub to Rococo Asset Network: ../../../cumulus/zombienet/bridge-hubs/bridge_hub_rococo_local_network.toml Creds: config +# step 0: start relayer +bridge-hub-rococo-collator1: run ../scripts/start-relayer.sh within 60 seconds + # step 1: initialize Rococo AH -asset-hub-rococo-collator1: run ../scripts/invoke-script.sh with "init-asset-hub-rococo-local" within 240 seconds -asset-hub-rococo-collator1: js-script ../helpers/wait-hrmp-channel-opened.js with "1013" within 400 seconds +asset-hub-rococo-collator1: run ../scripts/invoke-script.sh with "init-asset-hub-rococo-local" within 60 seconds # step 2: initialize Rococo bridge hub -bridge-hub-rococo-collator1: run ../scripts/invoke-script.sh with "init-bridge-hub-rococo-local" within 120 seconds +bridge-hub-rococo-collator1: run ../scripts/invoke-script.sh with "init-bridge-hub-rococo-local" within 60 seconds + +# step 3: ensure that initialization has completed +asset-hub-rococo-collator1: js-script ../helpers/wait-hrmp-channel-opened.js with "1013" within 600 seconds -# step 3: relay is started elsewhere - let's wait until with-Westend GRANPDA pallet is initialized at Rococo +# step 4: relay is already started - let's wait until with-Westend GRANPDA pallet is initialized at Rococo bridge-hub-rococo-collator1: js-script ../helpers/best-finalized-header-at-bridged-chain.js with "Westend,0" within 400 seconds -# step 4: send ROC to //Alice on Westend AH +# step 5: send ROC to //Alice on Westend AH # (that's a required part of a sibling 0001-asset-transfer-works-rococo-to-westend.zndsl test) -asset-hub-rococo-collator1: run ../scripts/invoke-script.sh with "reserve-transfer-assets-from-asset-hub-rococo-local" within 120 seconds +asset-hub-rococo-collator1: run ../scripts/invoke-script.sh with "reserve-transfer-assets-from-asset-hub-rococo-local" within 60 seconds -# step 5: elsewhere Westend has sent WND to //Alice - let's wait for it +# step 6: elsewhere Westend has sent WND to //Alice - let's wait for it asset-hub-rococo-collator1: js-script ../helpers/wrapped-assets-balance.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY,0,Westend" within 600 seconds -# step 6: check that the relayer //Charlie is rewarded by both our AH and target AH +# step 7: check that the relayer //Charlie is rewarded by both our AH and target AH bridge-hub-rococo-collator1: js-script ../helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000002,0x62687764,BridgedChain,0" within 300 seconds bridge-hub-rococo-collator1: js-script ../helpers/relayer-rewards.js with "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y,0x00000002,0x62687764,ThisChain,0" within 300 seconds -# step 7: send wWND back to Alice at Westend AH -asset-hub-rococo-collator1: run ../scripts/invoke-script.sh with "withdraw-reserve-assets-from-asset-hub-rococo-local" within 120 seconds +# step 8: send wWND back to Alice at Westend AH +asset-hub-rococo-collator1: run ../scripts/invoke-script.sh with "withdraw-reserve-assets-from-asset-hub-rococo-local" within 60 seconds -# step 8: elsewhere Westend has sent wROC to //Alice - let's wait for it +# step 9: elsewhere Westend has sent wROC to //Alice - let's wait for it # (we wait until //Alice account increases here - there are no other transactionc that may increase it) asset-hub-rococo-collator1: js-script ../helpers/native-assets-balance-increased.js with "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" within 600 seconds diff --git a/bridges/zombienet/tests/0001-start-relay.sh b/bridges/zombienet/tests/0001-start-relay.sh deleted file mode 100755 index 7be2cf4d5938..000000000000 --- a/bridges/zombienet/tests/0001-start-relay.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -pushd $POLKADOT_SDK_FOLDER/cumulus/scripts -./bridges_rococo_westend.sh run-relay -popd diff --git a/bridges/zombienet/tests/0002-mandatory-headers-synced-while-idle-rococo-to-westend.zndsl b/bridges/zombienet/tests/0002-mandatory-headers-synced-while-idle-rococo-to-westend.zndsl new file mode 100644 index 000000000000..eb6a75c373c7 --- /dev/null +++ b/bridges/zombienet/tests/0002-mandatory-headers-synced-while-idle-rococo-to-westend.zndsl @@ -0,0 +1,26 @@ +Description: While relayer is idle, we only sync mandatory Rococo (and a single Rococo BH) headers to Westend BH. +Network: ../../../cumulus/zombienet/bridge-hubs/bridge_hub_westend_local_network.toml +Creds: config + +# step 1: initialize Westend bridge hub +bridge-hub-westend-collator1: run ../scripts/invoke-script.sh with "init-bridge-hub-westend-local" within 60 seconds + +# step 2: sleep some time before starting relayer. We want to sleep for at least 1 session, which is expected to +# be 60 seconds for test environment. +sleep 120 seconds + +# step 3: start relayer +# (it is started by the sibling 0002-mandatory-headers-synced-while-idle-westend-to-rococo.zndsl test file) + +# it also takes some time for relayer to initialize bridge, so let's sleep for 5 minutes to be sure that parachain +# header has been synced + +# step 4: ensure that relayer is only syncing mandatory headers while idle. This includes both headers that were +# born while relay was offline and those in the next 100 seconds while script is active. +bridge-hub-westend-collator1: js-script ../helpers/only-mandatory-headers-synced-when-idle.js with "300,rococo-at-westend" within 600 seconds + +# wait until other network test has completed OR exit with an error too +asset-hub-westend-collator1: run ../scripts/sync-exit.sh within 600 seconds + +# wait until other network test has completed OR exit with an error too +asset-hub-westend-collator1: run ../scripts/sync-exit.sh within 600 seconds diff --git a/bridges/zombienet/tests/0002-mandatory-headers-synced-while-idle-westend-to-rococo.zndsl b/bridges/zombienet/tests/0002-mandatory-headers-synced-while-idle-westend-to-rococo.zndsl new file mode 100644 index 000000000000..728d54d586a9 --- /dev/null +++ b/bridges/zombienet/tests/0002-mandatory-headers-synced-while-idle-westend-to-rococo.zndsl @@ -0,0 +1,26 @@ +Description: While relayer is idle, we only sync mandatory Westend (and a single Westend BH) headers to Rococo BH. +Network: ../../../cumulus/zombienet/bridge-hubs/bridge_hub_rococo_local_network.toml +Creds: config + +# step 1: initialize Rococo bridge hub +bridge-hub-rococo-collator1: run ../scripts/invoke-script.sh with "init-bridge-hub-rococo-local" within 60 seconds + +# step 2: sleep some time before starting relayer. We want to sleep for at least 1 session, which is expected to +# be 60 seconds for test environment. +sleep 120 seconds + +# step 3: start relayer +bridge-hub-rococo-collator1: run ../scripts/start-relayer.sh within 60 seconds + +# it also takes some time for relayer to initialize bridge, so let's sleep for 5 minutes to be sure that parachain +# header has been synced + +# step 4: ensure that relayer is only syncing mandatory headers while idle. This includes both headers that were +# born while relay was offline and those in the next 100 seconds while script is active. +bridge-hub-rococo-collator1: js-script ../helpers/only-mandatory-headers-synced-when-idle.js with "300,westend-at-rococo" within 600 seconds + +# wait until other network test has completed OR exit with an error too +asset-hub-rococo-collator1: run ../scripts/sync-exit.sh within 600 seconds + +# wait until other network test has completed OR exit with an error too +asset-hub-rococo-collator1: run ../scripts/sync-exit.sh within 600 seconds diff --git a/bridges/zombienet/tests/0003-required-headers-synced-while-active-rococo-to-westend.zndsl b/bridges/zombienet/tests/0003-required-headers-synced-while-active-rococo-to-westend.zndsl new file mode 100644 index 000000000000..a4960344f0a0 --- /dev/null +++ b/bridges/zombienet/tests/0003-required-headers-synced-while-active-rococo-to-westend.zndsl @@ -0,0 +1,26 @@ +Description: While relayer is active, we only sync mandatory and required Rococo (and Rococo BH) headers to Westend BH. +Network: ../../../cumulus/zombienet/bridge-hubs/bridge_hub_westend_local_network.toml +Creds: config + +# step 1: initialize Westend AH +asset-hub-westend-collator1: run ../scripts/invoke-script.sh with "init-asset-hub-westend-local" within 60 seconds + +# step 2: initialize Westend bridge hub +bridge-hub-westend-collator1: run ../scripts/invoke-script.sh with "init-bridge-hub-westend-local" within 60 seconds + +# step 3: ensure that initialization has completed +asset-hub-westend-collator1: js-script ../helpers/wait-hrmp-channel-opened.js with "1002" within 600 seconds + +# step 4: send message from Westend to Rococo +asset-hub-westend-collator1: run ../scripts/invoke-script.sh with "reserve-transfer-assets-from-asset-hub-westend-local" within 60 seconds + +# step 5: start relayer +# (we are starting it after sending the message to be sure that relayer won't relay messages before our js script +# will be started at step 6) +# (it is started by sibling 0003-required-headers-synced-while-active-westend-to-rococo.zndsl) + +# step 6: ensure that relayer won't sync any extra headers while delivering messages and confirmations +bridge-hub-westend-collator1: js-script ../helpers/only-required-headers-synced-when-active.js with "500,rococo-at-westend" within 600 seconds + +# wait until other network test has completed OR exit with an error too +asset-hub-westend-collator1: run ../scripts/sync-exit.sh within 600 seconds diff --git a/bridges/zombienet/tests/0003-required-headers-synced-while-active-westend-to-rococo.zndsl b/bridges/zombienet/tests/0003-required-headers-synced-while-active-westend-to-rococo.zndsl new file mode 100644 index 000000000000..33c3ceebcf84 --- /dev/null +++ b/bridges/zombienet/tests/0003-required-headers-synced-while-active-westend-to-rococo.zndsl @@ -0,0 +1,26 @@ +Description: While relayer is active, we only sync mandatory and required Westend (and Westend BH) headers to Rococo BH. +Network: ../../../cumulus/zombienet/bridge-hubs/bridge_hub_rococo_local_network.toml +Creds: config + +# step 1: initialize Rococo AH +asset-hub-rococo-collator1: run ../scripts/invoke-script.sh with "init-asset-hub-rococo-local" within 60 seconds + +# step 2: initialize Rococo bridge hub +bridge-hub-rococo-collator1: run ../scripts/invoke-script.sh with "init-bridge-hub-rococo-local" within 60 seconds + +# step 3: ensure that initialization has completed +asset-hub-rococo-collator1: js-script ../helpers/wait-hrmp-channel-opened.js with "1013" within 600 seconds + +# step 4: send message from Rococo to Westend +asset-hub-rococo-collator1: run ../scripts/invoke-script.sh with "reserve-transfer-assets-from-asset-hub-rococo-local" within 60 seconds + +# step 5: start relayer +# (we are starting it after sending the message to be sure that relayer won't relay messages before our js script +# will be started at step 6) +bridge-hub-rococo-collator1: run ../scripts/start-relayer.sh within 60 seconds + +# step 6: ensure that relayer won't sync any extra headers while delivering messages and confirmations +bridge-hub-rococo-collator1: js-script ../helpers/only-required-headers-synced-when-active.js with "500,westend-at-rococo" within 600 seconds + +# wait until other network test has completed OR exit with an error too +asset-hub-rococo-collator1: run ../scripts/sync-exit.sh within 600 seconds diff --git a/cumulus/scripts/bridges_common.sh b/cumulus/scripts/bridges_common.sh index 5d5b7b7a482a..029d4cd4ff74 100755 --- a/cumulus/scripts/bridges_common.sh +++ b/cumulus/scripts/bridges_common.sh @@ -48,6 +48,14 @@ function ensure_polkadot_js_api() { fi } +function call_polkadot_js_api() { + # --noWait: without that argument `polkadot-js-api` waits until transaction is included into the block. + # With it, it just submits it to the tx pool and exits. + # --nonce -1: means to compute transaction nonce using `system_accountNextIndex` RPC, which includes all + # transaction that are in the tx pool. + polkadot-js-api --noWait --nonce -1 "$@" +} + function generate_hex_encoded_call_data() { local type=$1 local endpoint=$2 @@ -80,7 +88,7 @@ function transfer_balance() { echo " amount: ${amount}" echo "--------------------------------------------------" - polkadot-js-api \ + call_polkadot_js_api \ --ws "${runtime_para_endpoint}" \ --seed "${seed?}" \ tx.balances.transferAllowDeath \ @@ -145,7 +153,7 @@ function send_governance_transact() { echo "" echo "--------------------------------------------------" - polkadot-js-api \ + call_polkadot_js_api \ --ws "${relay_url?}" \ --seed "${relay_chain_seed?}" \ --sudo \ @@ -170,7 +178,7 @@ function open_hrmp_channels() { echo " max_message_size: ${max_message_size}" echo " params:" echo "--------------------------------------------------" - polkadot-js-api \ + call_polkadot_js_api \ --ws "${relay_url?}" \ --seed "${relay_chain_seed?}" \ --sudo \ @@ -254,7 +262,7 @@ function limited_reserve_transfer_assets() { echo "" echo "--------------------------------------------------" - polkadot-js-api \ + call_polkadot_js_api \ --ws "${url?}" \ --seed "${seed?}" \ tx.polkadotXcm.limitedReserveTransferAssets \ @@ -293,7 +301,7 @@ function claim_rewards() { echo "${rewards_account_params}" echo "--------------------------------------------------" - polkadot-js-api \ + call_polkadot_js_api \ --ws "${runtime_para_endpoint}" \ --seed "${seed?}" \ tx.bridgeRelayers.claimRewards \