mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-21 07:25:44 +00:00
Bridge zombienet tests: move all "framework" files under one folder (#3462)
Related to https://github.com/paritytech/polkadot-sdk/issues/3400 Moving all bridges testing "framework" files under one folder in order to be able to download the entire folder when we want to add tests in other repos No significant functional changes
This commit is contained in:
@@ -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: "bridgeRococoGrandpa",
|
||||
parachainsPalletName: "bridgeRococoParachains",
|
||||
messagesPalletName: "bridgeRococoMessages",
|
||||
bridgedBridgeHubParaId: 1013,
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
grandpaPalletName: "bridgeWestendGrandpa",
|
||||
parachainsPalletName: "bridgeWestendParachains",
|
||||
messagesPalletName: "bridgeWestendMessages",
|
||||
bridgedBridgeHubParaId: 1002,
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
async function run(nodeName, networkInfo, args) {
|
||||
const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName];
|
||||
const api = await zombie.connect(wsUri, userDefinedTypes);
|
||||
|
||||
const accountAddress = args[0];
|
||||
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) {
|
||||
return accountBalance;
|
||||
}
|
||||
|
||||
// else sleep and retry
|
||||
await new Promise((resolve) => setTimeout(resolve, 6000));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { run }
|
||||
@@ -0,0 +1,44 @@
|
||||
const utils = require("./utils");
|
||||
|
||||
async function run(nodeName, networkInfo, args) {
|
||||
const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName];
|
||||
const api = await zombie.connect(wsUri, userDefinedTypes);
|
||||
|
||||
// parse arguments
|
||||
const exitAfterSeconds = Number(args[0]);
|
||||
const bridgedChain = require("./chains/" + args[1]);
|
||||
|
||||
// start listening to new blocks
|
||||
let totalGrandpaHeaders = 0;
|
||||
let initialParachainHeaderImported = false;
|
||||
api.rpc.chain.subscribeNewHeads(async function (header) {
|
||||
const apiAtParent = await api.at(header.parentHash);
|
||||
const apiAtCurrent = await api.at(header.hash);
|
||||
const currentEvents = await apiAtCurrent.query.system.events();
|
||||
|
||||
totalGrandpaHeaders += await utils.ensureOnlyMandatoryGrandpaHeadersImported(
|
||||
bridgedChain,
|
||||
apiAtParent,
|
||||
apiAtCurrent,
|
||||
currentEvents,
|
||||
);
|
||||
initialParachainHeaderImported = await utils.ensureOnlyInitialParachainHeaderImported(
|
||||
bridgedChain,
|
||||
apiAtParent,
|
||||
apiAtCurrent,
|
||||
currentEvents,
|
||||
);
|
||||
});
|
||||
|
||||
// wait given time
|
||||
await new Promise(resolve => setTimeout(resolve, exitAfterSeconds * 1000));
|
||||
// if we haven't seen any new GRANDPA or parachain headers => fail
|
||||
if (totalGrandpaHeaders == 0) {
|
||||
throw new Error("No bridged relay chain headers imported");
|
||||
}
|
||||
if (!initialParachainHeaderImported) {
|
||||
throw new Error("No bridged parachain headers imported");
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { run }
|
||||
@@ -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 }
|
||||
@@ -0,0 +1,28 @@
|
||||
async function run(nodeName, networkInfo, args) {
|
||||
const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName];
|
||||
const api = await zombie.connect(wsUri, userDefinedTypes);
|
||||
|
||||
// TODO: could be replaced with https://github.com/polkadot-js/api/issues/4930 (depends on metadata v15) later
|
||||
const relayerAccountAddress = args[0];
|
||||
const laneId = args[1];
|
||||
const bridgedChainId = args[2];
|
||||
const relayerFundOwner = args[3];
|
||||
const expectedRelayerReward = BigInt(args[4]);
|
||||
while (true) {
|
||||
const relayerReward = await api.query.bridgeRelayers.relayerRewards(
|
||||
relayerAccountAddress,
|
||||
{ laneId: laneId, bridgedChainId: bridgedChainId, owner: relayerFundOwner }
|
||||
);
|
||||
if (relayerReward.isSome) {
|
||||
const relayerRewardBalance = relayerReward.unwrap().toBigInt();
|
||||
if (relayerRewardBalance > expectedRelayerReward) {
|
||||
return relayerRewardBalance;
|
||||
}
|
||||
}
|
||||
|
||||
// else sleep and retry
|
||||
await new Promise((resolve) => setTimeout(resolve, 6000));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { run }
|
||||
@@ -0,0 +1,103 @@
|
||||
module.exports = {
|
||||
logEvents: function(events) {
|
||||
let stringifiedEvents = "";
|
||||
events.forEach((record) => {
|
||||
if (stringifiedEvents != "") {
|
||||
stringifiedEvents += ", ";
|
||||
}
|
||||
stringifiedEvents += record.event.section + "::" + record.event.method;
|
||||
});
|
||||
console.log("Block events: " + stringifiedEvents);
|
||||
},
|
||||
countGrandpaHeaderImports: function(bridgedChain, events) {
|
||||
return events.reduce(
|
||||
(count, record) => {
|
||||
const { event } = record;
|
||||
if (event.section == bridgedChain.grandpaPalletName && event.method == "UpdatedBestFinalizedHeader") {
|
||||
count += 1;
|
||||
}
|
||||
return count;
|
||||
},
|
||||
0,
|
||||
);
|
||||
},
|
||||
countParachainHeaderImports: function(bridgedChain, events) {
|
||||
return events.reduce(
|
||||
(count, record) => {
|
||||
const { event } = record;
|
||||
if (event.section == bridgedChain.parachainsPalletName && event.method == "UpdatedParachainHead") {
|
||||
count += 1;
|
||||
}
|
||||
return count;
|
||||
},
|
||||
0,
|
||||
);
|
||||
},
|
||||
pollUntil: async function(
|
||||
timeoutInSecs,
|
||||
predicate,
|
||||
cleanup,
|
||||
onFailure,
|
||||
) {
|
||||
const begin = new Date().getTime();
|
||||
const end = begin + timeoutInSecs * 1000;
|
||||
while (new Date().getTime() < end) {
|
||||
if (predicate()) {
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
}
|
||||
|
||||
cleanup();
|
||||
onFailure();
|
||||
},
|
||||
ensureOnlyMandatoryGrandpaHeadersImported: async function(
|
||||
bridgedChain,
|
||||
apiAtParent,
|
||||
apiAtCurrent,
|
||||
currentEvents,
|
||||
) {
|
||||
// remember id of bridged relay chain GRANDPA authorities set at parent block
|
||||
const authoritySetAtParent = await apiAtParent.query[bridgedChain.grandpaPalletName].currentAuthoritySet();
|
||||
const authoritySetIdAtParent = authoritySetAtParent["setId"];
|
||||
|
||||
// now read the id of bridged relay chain GRANDPA authorities set at current block
|
||||
const authoritySetAtCurrent = await apiAtCurrent.query[bridgedChain.grandpaPalletName].currentAuthoritySet();
|
||||
const authoritySetIdAtCurrent = authoritySetAtCurrent["setId"];
|
||||
|
||||
// we expect to see no more than `authoritySetIdAtCurrent - authoritySetIdAtParent` new GRANDPA headers
|
||||
const maxNewGrandpaHeaders = authoritySetIdAtCurrent - authoritySetIdAtParent;
|
||||
const newGrandpaHeaders = module.exports.countGrandpaHeaderImports(bridgedChain, currentEvents);
|
||||
|
||||
// check that our assumptions are correct
|
||||
if (newGrandpaHeaders > maxNewGrandpaHeaders) {
|
||||
module.exports.logEvents(currentEvents);
|
||||
throw new Error("Unexpected relay chain header import: " + newGrandpaHeaders + " / " + maxNewGrandpaHeaders);
|
||||
}
|
||||
|
||||
return newGrandpaHeaders;
|
||||
},
|
||||
ensureOnlyInitialParachainHeaderImported: async function(
|
||||
bridgedChain,
|
||||
apiAtParent,
|
||||
apiAtCurrent,
|
||||
currentEvents,
|
||||
) {
|
||||
// remember whether we already know bridged parachain header at a parent block
|
||||
const bestBridgedParachainHeader = await apiAtParent.query[bridgedChain.parachainsPalletName].parasInfo(bridgedChain.bridgedBridgeHubParaId);;
|
||||
const hasBestBridgedParachainHeader = bestBridgedParachainHeader.isSome;
|
||||
|
||||
// we expect to see: no more than `1` bridged parachain header if there were no parachain header before.
|
||||
const maxNewParachainHeaders = hasBestBridgedParachainHeader ? 0 : 1;
|
||||
const newParachainHeaders = module.exports.countParachainHeaderImports(bridgedChain, currentEvents);
|
||||
|
||||
// check that our assumptions are correct
|
||||
if (newParachainHeaders > maxNewParachainHeaders) {
|
||||
module.exports.logEvents(currentEvents);
|
||||
throw new Error("Unexpected parachain header import: " + newParachainHeaders + " / " + maxNewParachainHeaders);
|
||||
}
|
||||
|
||||
return hasBestBridgedParachainHeader;
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
async function run(nodeName, networkInfo, args) {
|
||||
const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName];
|
||||
const api = await zombie.connect(wsUri, userDefinedTypes);
|
||||
|
||||
const sibling = args[0];
|
||||
|
||||
while (true) {
|
||||
const messagingStateAsObj = await api.query.parachainSystem.relevantMessagingState();
|
||||
const messagingState = api.createType("Option<CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot>", 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,26 @@
|
||||
async function run(nodeName, networkInfo, args) {
|
||||
const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName];
|
||||
const api = await zombie.connect(wsUri, userDefinedTypes);
|
||||
|
||||
// TODO: could be replaced with https://github.com/polkadot-js/api/issues/4930 (depends on metadata v15) later
|
||||
const accountAddress = args[0];
|
||||
const expectedForeignAssetBalance = BigInt(args[1]);
|
||||
const bridgedNetworkName = args[2];
|
||||
while (true) {
|
||||
const foreignAssetAccount = await api.query.foreignAssets.account(
|
||||
{ parents: 2, interior: { X1: { GlobalConsensus: bridgedNetworkName } } },
|
||||
accountAddress
|
||||
);
|
||||
if (foreignAssetAccount.isSome) {
|
||||
const foreignAssetAccountBalance = foreignAssetAccount.unwrap().balance.toBigInt();
|
||||
if (foreignAssetAccountBalance > expectedForeignAssetBalance) {
|
||||
return foreignAssetAccountBalance;
|
||||
}
|
||||
}
|
||||
|
||||
// else sleep and retry
|
||||
await new Promise((resolve) => setTimeout(resolve, 6000));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { run }
|
||||
Reference in New Issue
Block a user