Skip to content
utils.js 4.07 KiB
Newer Older
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;
    },
}