mirror of
https://github.com/pezkuwichain/pezkuwi-subquery.git
synced 2026-10-20 18:56:24 +00:00
The indexer image installed @subql/node and the @polkadot -> @pezkuwi aliases with an unlocked npm install, and the build cache kept the layer from the day it was first built: the indexers ran @pezkuwi/wasm-crypto 7.5.17/7.5.18, the build whose ed25519 and secp256k1 are stubs, plus vm2 3.9.19 (the mapping sandbox, 54 advisories). No lockfile meant Dependabot never saw that tree. - docker/indexer holds the image's package.json and package-lock.json: @subql/node 6.4.6 as today, @pezkuwi 16.5.39 / 14.0.26 / 7.5.21, overrides for vm2 3.12.2, uuid 11 and package-json 7 (got 11). The Dockerfile runs npm ci on Node 24 (Node 20 is out of support). - The pruned-state patch stops the build when a pattern matches nothing, instead of reporting success with the fallback missing. - CI builds the indexer image and runs the crypto smoke test inside it through the @polkadot aliases, the way subql-node loads them. - The root yarn.lock, which the host installs as root on every deploy to run subql codegen/build, moves the advisory ranges forward with targeted resolutions and @pezkuwi/braces. Left: elliptic (low, via ethers 5 in @subql/cli) and sprintf-js (moderate, via jest's argparse 1); neither has a fixed release.
77 lines
2.9 KiB
JavaScript
77 lines
2.9 KiB
JavaScript
// Runs from a bot's directory (in its image: mounted at /app/bot-smoke.mjs) and fails unless the
|
|
// installed crypto stack is the one package-lock.json records and can sign and
|
|
// verify with every key type. A stack that only loads is not enough: the broken
|
|
// @pezkuwi/wasm-crypto 7.5.17 loaded fine and failed at ed25519 and ecdsa.
|
|
//
|
|
// node bot-smoke.mjs <esm|cjs|indexer>
|
|
//
|
|
// indexer: the subql-node image, which loads @pezkuwi through @polkadot aliases
|
|
// (CommonJS); the aliases are checked against the lock too.
|
|
|
|
import fs from 'node:fs';
|
|
import { createRequire } from 'node:module';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const mode = process.argv[2];
|
|
const require = createRequire(import.meta.url);
|
|
const dir = path.dirname(fileURLToPath(import.meta.url));
|
|
let failed = 0;
|
|
|
|
function check (name, ok, detail = '') {
|
|
console.log(`${ok ? 'ok ' : 'FAIL'} ${name}${detail ? ` (${detail})` : ''}`);
|
|
|
|
if (!ok) {
|
|
failed++;
|
|
}
|
|
}
|
|
|
|
const lock = JSON.parse(fs.readFileSync(path.join(dir, 'package-lock.json'), 'utf8'));
|
|
|
|
const scope = mode === 'indexer' ? '@polkadot' : '@pezkuwi';
|
|
const locked = ['@pezkuwi/wasm-crypto', '@pezkuwi/util-crypto', '@pezkuwi/api', '@pezkuwi/keyring'];
|
|
|
|
if (mode === 'indexer') {
|
|
locked.push('@polkadot/wasm-crypto', '@polkadot/util-crypto', '@polkadot/api', '@polkadot/keyring');
|
|
}
|
|
|
|
for (const name of locked) {
|
|
const want = lock.packages[`node_modules/${name}`]?.version;
|
|
const have = JSON.parse(fs.readFileSync(path.join(dir, 'node_modules', name, 'package.json'), 'utf8')).version;
|
|
|
|
check(`${name} is the locked version`, !!want && want === have, `lock ${want}, installed ${have}`);
|
|
}
|
|
|
|
// Load the stack the way the image does: the noter is an ES module, the payout
|
|
// bot and subql-node are CommonJS.
|
|
const load = (name) => mode === 'esm' ? import(`${scope}/${name}`) : require(`${scope}/${name}`);
|
|
const { Keyring } = await load('api');
|
|
const { cryptoWaitReady, mnemonicGenerate } = await load('util-crypto');
|
|
|
|
check('crypto initialises', await cryptoWaitReady());
|
|
|
|
try {
|
|
check('a mnemonic can be generated', mnemonicGenerate().split(' ').length === 12);
|
|
} catch (error) {
|
|
check('a mnemonic can be generated', false, error.message);
|
|
}
|
|
|
|
// Derived from the public development phrase, so the check needs no secret
|
|
// and does not depend on mnemonic generation working.
|
|
const message = new TextEncoder().encode('pezkuwi bot smoke');
|
|
|
|
for (const type of ['sr25519', 'ed25519', 'ecdsa']) {
|
|
try {
|
|
const pair = new Keyring({ type }).addFromUri('//Smoke');
|
|
const signature = pair.sign(message);
|
|
|
|
check(`${type} signs and verifies`, pair.verify(message, signature, pair.publicKey));
|
|
check(`${type} rejects a tampered message`, !pair.verify(new TextEncoder().encode('tampered'), signature, pair.publicKey));
|
|
} catch (error) {
|
|
check(`${type} signs and verifies`, false, error.message);
|
|
}
|
|
}
|
|
|
|
console.log(failed ? `FAILED: ${failed}` : `all ${mode} smoke checks passed`);
|
|
process.exit(failed ? 1 : 0);
|