@zombienet/orchestrator
Version:
ZombieNet aim to be a testing framework for substrate based blockchains, providing a simple cli tool that allow users to spawn and test ephemeral Substrate based networks
725 lines (724 loc) โข 31.8 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.specHaveSessionsKeys = specHaveSessionsKeys;
exports.clearAuthorities = clearAuthorities;
exports.addBalances = addBalances;
exports.getNodeKey = getNodeKey;
exports.addAuthority = addAuthority;
exports.addStaking = addStaking;
exports.addCollatorSelection = addCollatorSelection;
exports.addParaCustom = addParaCustom;
exports.addAuraAuthority = addAuraAuthority;
exports.addGrandpaAuthority = addGrandpaAuthority;
exports.generateNominators = generateNominators;
exports.addParachainToGenesis = addParachainToGenesis;
exports.changeGenesisConfig = changeGenesisConfig;
exports.addBootNodes = addBootNodes;
exports.addHrmpChannelsToGenesis = addHrmpChannelsToGenesis;
exports.getRuntimeConfig = getRuntimeConfig;
exports.readAndParseChainSpec = readAndParseChainSpec;
exports.writeChainSpec = writeChainSpec;
exports.isRawSpec = isRawSpec;
exports.getChainIdFromSpec = getChainIdFromSpec;
exports.customizePlainRelayChain = customizePlainRelayChain;
exports.customizeParachainRawSpec = customizeParachainRawSpec;
const util_crypto_1 = require("@polkadot/util-crypto");
const utils_1 = require("@zombienet/utils");
const crypto_1 = __importDefault(require("crypto"));
const fs_1 = __importDefault(require("fs"));
const keys_1 = require("./keys");
const chain_decorators_1 = require("./chain-decorators");
const JSONbig = require("json-bigint")({ useNativeBigInt: true });
const debug = require("debug")("zombie::chain-spec");
const JSONStream = require("JSONStream");
// track 1st staking as default;
let stakingBond;
// Check if the chainSpec have session keys
function specHaveSessionsKeys(chainSpec) {
// Check runtime_genesis_config key for rococo compatibility.
const runtimeConfig = getRuntimeConfig(chainSpec);
return ((runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.session) ||
(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.palletSession) ||
(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.authorMapping));
}
// Get authority keys from within chainSpec data
function getAuthorityKeys(chainSpec, keyType = "session") {
const runtimeConfig = getRuntimeConfig(chainSpec);
switch (keyType) {
case "session":
if (runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.session)
return runtimeConfig.session.keys;
break;
case "aura":
if (runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.aura)
return runtimeConfig.aura.authorities;
break;
case "grandpa":
if (runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.grandpa)
return runtimeConfig.grandpa.authorities;
break;
}
const errorMsg = `โ ${keyType} keys not found in runtimeConfig`;
console.error(`\n\t\t ${utils_1.decorators.yellow(errorMsg)}`);
}
// Remove all existing keys from `session.keys` / aura.authorities / grandpa.authorities
function clearAuthorities(specPath) {
try {
const chainSpec = readAndParseChainSpec(specPath);
const runtimeConfig = getRuntimeConfig(chainSpec);
// clear keys
if (runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.session)
runtimeConfig.session.keys.length = 0;
// clear aura
if (runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.aura)
runtimeConfig.aura.authorities.length = 0;
// clear grandpa
if (runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.grandpa)
runtimeConfig.grandpa.authorities.length = 0;
// clear collatorSelection
if (runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.collatorSelection)
runtimeConfig.collatorSelection.invulnerables = [];
// clear staking (IFF not a para)
// TODO: in the future we should add an option to override or not
if ((runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.staking) && !runtimeConfig.parachainInfo) {
// Set `stakingBond` IFF there is at least one
if (runtimeConfig.staking.stakers[0])
stakingBond = BigInt(runtimeConfig.staking.stakers[0][2]);
runtimeConfig.staking.stakers = [];
runtimeConfig.staking.invulnerables = [];
runtimeConfig.staking.validatorCount = 0;
}
writeChainSpec(specPath, chainSpec);
const logTable = new utils_1.CreateLogTable({
colWidths: [120],
});
logTable.pushToPrint([
[utils_1.decorators.green("๐งน Starting with a fresh authority set...")],
]);
}
catch (err) {
console.error(`\n${utils_1.decorators.red("Fail to clear authorities")}`);
throw err;
}
}
function addBalances(specPath, nodes) {
return __awaiter(this, void 0, void 0, function* () {
try {
const chainSpec = readAndParseChainSpec(specPath);
const runtimeConfig = getRuntimeConfig(chainSpec);
if (!runtimeConfig.balances) {
console.error(`\n ๐ง ${utils_1.decorators.yellow("NO 'balances' key in runtimeConfig, skipping...")} ๐ง \n`);
return;
}
// Create a balance map
const balanceMap = runtimeConfig.balances.balances.reduce((memo, balance) => {
memo[balance[0]] = balance[1];
return memo;
}, {});
for (const node of nodes) {
if (node.balance) {
const stashKey = node.accounts.sr_stash.address;
const balanceToAdd = stakingBond
? node.validator && node.balance > stakingBond
? node.balance
: stakingBond * BigInt(2) // Double the balance we use for stake
: node.balance;
balanceMap[stashKey] = balanceToAdd;
const logLine = `๐ค Added Balance ${balanceToAdd} for ${utils_1.decorators.green(node.name)} - ${utils_1.decorators.magenta(stashKey)}`;
new utils_1.CreateLogTable({
colWidths: [120],
doubleBorder: true,
}).pushToPrint([[logLine]]);
}
}
runtimeConfig.balances.balances = Object.entries(balanceMap);
writeChainSpec(specPath, chainSpec);
}
catch (err) {
console.error(`\n${utils_1.decorators.red(`Fail to add balance for nodes: ${nodes}`)}`);
throw err;
}
});
}
function getNodeKey(node, useStash = true) {
try {
const { sr_stash, sr_account, ed_account, ec_account } = node.accounts;
const address = useStash ? sr_stash.address : sr_account.address;
const key = [
address,
address,
{
grandpa: ed_account.address,
babe: sr_account.address,
im_online: sr_account.address,
parachain_validator: sr_account.address,
authority_discovery: sr_account.address,
para_validator: sr_account.address,
para_assignment: sr_account.address,
beefy: (0, util_crypto_1.encodeAddress)(ec_account.publicKey),
aura: sr_account.address,
nimbus: sr_account.address,
vrf: sr_account.address,
mixnet: sr_account.address,
bcsv: sr_account.address,
ftsv: ed_account.address,
},
];
return key;
}
catch (err) {
console.error(`\n${utils_1.decorators.red(`Fail to generate key for node: ${node}`)}`);
throw err;
}
}
// Add additional authorities to chain spec in `session.keys`
function addAuthority(specPath, node, key) {
return __awaiter(this, void 0, void 0, function* () {
try {
const chainSpec = readAndParseChainSpec(specPath);
const { sr_stash } = node.accounts;
const keys = getAuthorityKeys(chainSpec);
if (!keys)
return;
keys.push(key);
new utils_1.CreateLogTable({
colWidths: [30, 20, 70],
}).pushToPrint([
[
utils_1.decorators.cyan("๐ค Added Genesis Authority"),
utils_1.decorators.green(node.name),
utils_1.decorators.magenta(sr_stash.address),
],
]);
writeChainSpec(specPath, chainSpec);
}
catch (err) {
console.error(`\n${utils_1.decorators.red(`Fail to add authority for node: ${node}`)}`);
throw err;
}
});
}
/// Add node to staking
function addStaking(specPath, node) {
return __awaiter(this, void 0, void 0, function* () {
try {
const chainSpec = readAndParseChainSpec(specPath);
const runtimeConfig = getRuntimeConfig(chainSpec);
if (!(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.staking))
return;
const { sr_stash } = node.accounts;
runtimeConfig.staking.stakers.push([
sr_stash.address,
sr_stash.address,
stakingBond || BigInt(1000000000000),
"Validator",
]);
runtimeConfig.staking.validatorCount += 1;
// add to invulnerables
if (node.invulnerable)
runtimeConfig.staking.invulnerables.push(sr_stash.address);
new utils_1.CreateLogTable({
colWidths: [30, 20, 70],
}).pushToPrint([
[
utils_1.decorators.cyan("๐ค Added Staking"),
utils_1.decorators.green(node.name),
utils_1.decorators.magenta(sr_stash.address),
],
]);
writeChainSpec(specPath, chainSpec);
}
catch (err) {
console.error(`\n${utils_1.decorators.red(`Fail to add staking for node: ${node}`)}`);
throw err;
}
});
}
/// Add collators
function addCollatorSelection(specPath, node) {
return __awaiter(this, void 0, void 0, function* () {
var _a;
try {
const chainSpec = readAndParseChainSpec(specPath);
const runtimeConfig = getRuntimeConfig(chainSpec);
if (!((_a = runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.collatorSelection) === null || _a === void 0 ? void 0 : _a.invulnerables))
return;
const { sr_account } = node.accounts;
runtimeConfig.collatorSelection.invulnerables.push(sr_account.address);
new utils_1.CreateLogTable({
colWidths: [30, 20, 70],
}).pushToPrint([
[
utils_1.decorators.cyan("๐ค Added CollatorSelection "),
utils_1.decorators.green(node.name),
utils_1.decorators.magenta(sr_account.address),
],
]);
writeChainSpec(specPath, chainSpec);
}
catch (err) {
console.error(`\n${utils_1.decorators.red(`Fail to add collator: ${node}`)}`);
throw err;
}
});
}
function addParaCustom() {
return __awaiter(this, void 0, void 0, function* () {
/// noop
});
}
function addAuraAuthority(specPath, name, accounts) {
return __awaiter(this, void 0, void 0, function* () {
try {
const { sr_account } = accounts;
const chainSpec = readAndParseChainSpec(specPath);
const keys = getAuthorityKeys(chainSpec, "aura");
if (!keys)
return;
keys.push(sr_account.address);
writeChainSpec(specPath, chainSpec);
new utils_1.CreateLogTable({
colWidths: [30, 20, 70],
}).pushToPrint([
[
utils_1.decorators.cyan("๐ค Added Genesis Authority"),
utils_1.decorators.green(name),
utils_1.decorators.magenta(sr_account.address),
],
]);
}
catch (err) {
console.error(`\n${utils_1.decorators.red(`Fail to add Aura account for node: ${name}`)}`);
throw err;
}
});
}
function addGrandpaAuthority(specPath, name, accounts) {
return __awaiter(this, void 0, void 0, function* () {
try {
const { ed_account } = accounts;
const chainSpec = readAndParseChainSpec(specPath);
const keys = getAuthorityKeys(chainSpec, "grandpa");
if (!keys)
return;
keys.push([ed_account.address, 1]);
writeChainSpec(specPath, chainSpec);
const logLine = `๐ค Added Genesis Authority (GRANDPA) ${utils_1.decorators.green(name)} - ${utils_1.decorators.magenta(ed_account.address)}`;
new utils_1.CreateLogTable({ colWidths: [120], doubleBorder: true }).pushToPrint([
[logLine],
]);
}
catch (err) {
console.error(`\n${utils_1.decorators.red(`Fail to add GrandPa account for node: ${name}`)}`);
throw err;
}
});
}
function generateNominators(specPath, randomNominatorsCount, maxNominations, validators) {
return __awaiter(this, void 0, void 0, function* () {
try {
const chainSpec = readAndParseChainSpec(specPath);
const runtimeConfig = getRuntimeConfig(chainSpec);
if (!(runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.staking))
return;
// ensure maxNominations doesn't exceed available validators
const actualMaxNominations = Math.min(maxNominations, validators.length);
if (actualMaxNominations < maxNominations) {
console.warn(utils_1.decorators.yellow(`โ ๏ธ Adjusting max_nominations from ${maxNominations} to ${actualMaxNominations} to match validator count.`));
}
let logLine = `๐ค Generating random Nominators (${utils_1.decorators.green(randomNominatorsCount)})`;
new utils_1.CreateLogTable({ colWidths: [120], doubleBorder: true }).pushToPrint([
[logLine],
]);
const maxForRandom = Math.pow(2, 48) - 1;
for (let i = 0; i < randomNominatorsCount; i++) {
// create account
const nom = yield (0, keys_1.generateKeyFromSeed)(`nom-${i}`);
// add to balances
const balanceToAdd = stakingBond + BigInt(1);
runtimeConfig.balances.balances.push([nom.address, balanceToAdd]);
// random nominations
const count = crypto_1.default.randomInt(maxForRandom) % actualMaxNominations;
const nominations = (0, utils_1.getRandom)(validators, count || count + 1);
// push to stakers
runtimeConfig.staking.stakers.push([
nom.address,
nom.address,
stakingBond,
{
Nominator: nominations,
},
]);
}
writeChainSpec(specPath, chainSpec);
logLine = `๐ค Added random Nominators (${utils_1.decorators.green(randomNominatorsCount)})`;
new utils_1.CreateLogTable({ colWidths: [120], doubleBorder: true }).pushToPrint([
[logLine],
]);
}
catch (err) {
console.error(`\n${utils_1.decorators.red(`Fail to generate staking config with count : ${randomNominatorsCount} and max : ${maxNominations}`)}`);
throw err;
}
});
}
// Add parachains to the chain spec at genesis.
function addParachainToGenesis(specPath_1, para_id_1, head_1, wasm_1) {
return __awaiter(this, arguments, void 0, function* (specPath, para_id, head, wasm, parachain = true) {
try {
const chainSpec = readAndParseChainSpec(specPath);
const runtimeConfig = getRuntimeConfig(chainSpec);
let paras = undefined;
if (runtimeConfig.paras) {
paras = runtimeConfig.paras.paras;
}
// For retro-compatibility with substrate pre Polkadot 0.9.5
else if (runtimeConfig.parachainsParas) {
paras = runtimeConfig.parachainsParas.paras;
}
// The config may not contain paras. Since chainspec allows to contain the RuntimeGenesisConfig patch we can inject it.
else {
runtimeConfig.paras = { paras: [] };
paras = runtimeConfig.paras.paras;
}
if (paras) {
const new_para = [
parseInt(para_id),
[(0, utils_1.readDataFile)(head), (0, utils_1.readDataFile)(wasm), parachain],
];
paras.push(new_para);
writeChainSpec(specPath, chainSpec);
const logLine = `${utils_1.decorators.green("โ Added Genesis Parachain")} ${para_id}`;
new utils_1.CreateLogTable({ colWidths: [120], doubleBorder: true }).pushToPrint([
[logLine],
]);
}
else {
console.error(`\n${utils_1.decorators.reverse(utils_1.decorators.red(" โ paras not found in runtimeConfig"))}`);
process.exit(1);
}
}
catch (err) {
console.error(`\n${utils_1.decorators.red(`Fail to add para: ${para_id} to genesis`)}`);
throw err;
}
});
}
// Update the runtime config in the genesis.
// It will try to match keys which exist within the configuration and update the value.
function changeGenesisConfig(specPath, updates) {
return __awaiter(this, void 0, void 0, function* () {
try {
const chainSpec = readAndParseChainSpec(specPath);
const msg = `โ Updating Chain Genesis Configuration (path: ${specPath})`;
new utils_1.CreateLogTable({ colWidths: [120], doubleBorder: true }).pushToPrint([
[`\n\t ${utils_1.decorators.green(msg)}`],
]);
if (chainSpec.genesis) {
const config = chainSpec.genesis;
findAndReplaceConfig(updates, config);
writeChainSpec(specPath, chainSpec);
}
}
catch (err) {
console.error(`\n${utils_1.decorators.red("Fail to customize genesis")}`);
throw err;
}
});
}
function addBootNodes(specPath, addresses) {
return __awaiter(this, void 0, void 0, function* () {
let chainSpec;
try {
chainSpec = readAndParseChainSpec(specPath);
}
catch (e) {
if (e.code !== "ERR_FS_FILE_TOO_LARGE")
throw e;
// can't customize bootnodes
const logLine = ` ๐ง ${utils_1.decorators.yellow(`Chain Spec file ${specPath} is TOO LARGE to customize (more than 2G).`)} ๐ง`;
new utils_1.CreateLogTable({ colWidths: [120], doubleBorder: true }).pushToPrint([
[logLine],
]);
return;
}
// prevent dups bootnodes
chainSpec.bootNodes = [...new Set(addresses)];
writeChainSpec(specPath, chainSpec);
const logTable = new utils_1.CreateLogTable({ colWidths: [120] });
if (addresses.length) {
logTable.pushToPrint([
[`${utils_1.decorators.green(chainSpec.name)} โ Added Boot Nodes`],
[addresses.join("\n")],
]);
}
else {
logTable.pushToPrint([
[`${utils_1.decorators.green(chainSpec.name)} โ Clear Boot Nodes`],
]);
}
});
}
function addHrmpChannelsToGenesis(specPath, hrmp_channels) {
return __awaiter(this, void 0, void 0, function* () {
try {
new utils_1.CreateLogTable({ colWidths: [120], doubleBorder: true }).pushToPrint([
[`\n\t ${utils_1.decorators.green("Adding Genesis HRMP Channels")}`],
]);
const chainSpec = readAndParseChainSpec(specPath);
for (const h of hrmp_channels) {
const newHrmpChannel = [
h.sender,
h.recipient,
h.max_capacity,
h.max_message_size,
];
const runtimeConfig = getRuntimeConfig(chainSpec);
let hrmp = undefined;
if (runtimeConfig.hrmp) {
hrmp = runtimeConfig.hrmp;
}
// For retro-compatibility with substrate pre Polkadot 0.9.5
else if (runtimeConfig.parachainsHrmp) {
hrmp = runtimeConfig.parachainsHrmp;
}
else {
// No hrmp key in the current chain-spec
// let's create the struct and assign
runtimeConfig["hrmp"] = {
preopenHrmpChannels: [],
};
hrmp = runtimeConfig.hrmp;
}
if (hrmp && hrmp.preopenHrmpChannels) {
hrmp.preopenHrmpChannels.push(newHrmpChannel);
new utils_1.CreateLogTable({
colWidths: [120],
doubleBorder: true,
}).pushToPrint([
[
utils_1.decorators.green(`โ Added HRMP channel ${h.sender} -> ${h.recipient}`),
],
]);
}
else {
console.error(`${utils_1.decorators.reverse(utils_1.decorators.red(` โ hrmp not found in runtimeConfig`))}`);
process.exit(1);
}
writeChainSpec(specPath, chainSpec);
}
}
catch (err) {
console.error(`\n${utils_1.decorators.red(`Fail to add hrmp channels: ${hrmp_channels}`)}`);
throw err;
}
});
}
// Look at the key + values from `obj1` (updates) and try to replace them in `obj2` (config)
function findAndReplaceConfig(obj1, obj2) {
// create new Object without null prototype, this is a copy from the `config`.
const tempObj = Object.assign({}, obj2);
// Look at keys of obj1
Object.keys(obj1).forEach((key) => {
// See if obj2 also has this key
if (tempObj.hasOwnProperty(key)) {
// If it goes deeper, recurse...
if (obj1[key] !== null &&
obj1[key] !== undefined &&
JSON.parse(JSON.stringify(obj1[key])).constructor === Object) {
findAndReplaceConfig(obj1[key], obj2[key]);
}
else {
obj2[key] = obj1[key];
new utils_1.CreateLogTable({
colWidths: [120],
doubleBorder: true,
}).pushToPrint([
[
`${utils_1.decorators.green("โ Updated Genesis Configuration")} [ key : ${key} ]`,
],
]);
debug(`[ ${key}: ${JSON.stringify(obj2[key])} ]`);
}
}
else {
// Allow to add keys, see (https://github.com/paritytech/zombienet/issues/1614)
const logLine = ` ๐ ${utils_1.decorators.yellow(`Key ${key} not present in the current config, adding...`)}`;
new utils_1.CreateLogTable({ colWidths: [120], doubleBorder: true }).pushToPrint([
[logLine],
]);
obj2[key] = obj1[key];
new utils_1.CreateLogTable({
colWidths: [120],
doubleBorder: true,
}).pushToPrint([
[
`${utils_1.decorators.green("โ Updated Genesis Configuration (added key)")} [ key : ${key} ]`,
],
]);
debug(`[ ${key}: ${JSON.stringify(obj2[key])} ]`);
}
});
}
function getRuntimeConfig(chainSpec) {
var _a, _b, _c;
// runtime_genesis_config is no longer in ChainSpec after rococo runtime rework (refer to: https://github.com/paritytech/polkadot-sdk/pull/1256)
// ChainSpec may contain a RuntimeGenesisConfigPatch
return (((_a = chainSpec.genesis.runtimeGenesis) === null || _a === void 0 ? void 0 : _a.config) ||
((_b = chainSpec.genesis.runtimeGenesis) === null || _b === void 0 ? void 0 : _b.patch) ||
((_c = chainSpec.genesis.runtime) === null || _c === void 0 ? void 0 : _c.runtime_genesis_config) ||
chainSpec.genesis.runtime);
}
function readAndParseChainSpec(specPath) {
const rawdata = fs_1.default.readFileSync(specPath);
let chainSpec;
try {
chainSpec = JSONbig.parse(rawdata);
return chainSpec;
}
catch (_a) {
console.error(`\n\t\t ${utils_1.decorators.red(" โ failed to parse the chain spec")}`);
process.exit(1);
}
}
function writeChainSpec(specPath, chainSpec) {
try {
const data = JSONbig.stringify(chainSpec, null, 2);
fs_1.default.writeFileSync(specPath, (0, utils_1.convertExponentials)(data));
}
catch (_a) {
console.error(`\n\t\t ${utils_1.decorators.reverse(utils_1.decorators.red(" โ failed to write the chain spec with path: "))} ${specPath}`);
process.exit(1);
}
}
function isRawSpec(specPath) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((res) => {
const stream = fs_1.default.createReadStream(specPath, { encoding: "utf8" });
const parser = JSONStream.parse(["genesis", "raw", "top", /^0x/]);
stream.pipe(parser);
parser.on("data", (e) => {
debug(`data: ${e}`);
stream.destroy();
return res(true);
});
stream.on("end", () => {
return res(false);
});
});
});
}
function getChainIdFromSpec(specPath) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((res) => {
const stream = fs_1.default.createReadStream(specPath, { encoding: "utf8" });
const parser = JSONStream.parse(["id"]);
stream.pipe(parser);
parser.on("data", (id) => {
debug(`data: ${id}`);
stream.destroy();
return res(id);
});
stream.on("end", () => {
return res("");
});
});
});
}
function customizePlainRelayChain(specPath, networkSpec) {
return __awaiter(this, void 0, void 0, function* () {
try {
// Relay-chain spec customization logic
const plainRelayChainSpec = readAndParseChainSpec(specPath);
const keyType = specHaveSessionsKeys(plainRelayChainSpec)
? "session"
: "aura";
// make genesis overrides first.
if (networkSpec.relaychain.genesis) {
yield changeGenesisConfig(specPath, networkSpec.relaychain.genesis);
}
// Clear all defaults
clearAuthorities(specPath);
// add balances for nodes
yield addBalances(specPath, networkSpec.relaychain.nodes);
// add authorities for nodes
const validatorKeys = [];
for (const node of networkSpec.relaychain.nodes) {
if (node.validator) {
validatorKeys.push(node.accounts.sr_stash.address);
if (keyType === "session") {
const chain = (0, chain_decorators_1.whichChain)(networkSpec.relaychain.chain, networkSpec.relaychain.force_decorator);
const [decoratedGetNodeKey] = (0, chain_decorators_1.decorate)(chain, [getNodeKey]);
const key = decoratedGetNodeKey(node, networkSpec.relaychain.useStashForValidators);
yield addAuthority(specPath, node, key);
}
else {
yield addAuraAuthority(specPath, node.name, node.accounts);
yield addGrandpaAuthority(specPath, node.name, node.accounts);
}
yield addStaking(specPath, node);
}
}
if (networkSpec.relaychain.randomNominatorsCount) {
yield generateNominators(specPath, networkSpec.relaychain.randomNominatorsCount, networkSpec.relaychain.maxNominations, validatorKeys);
}
if (networkSpec.hrmp_channels) {
yield addHrmpChannelsToGenesis(specPath, networkSpec.hrmp_channels);
}
}
catch (err) {
console.log(`\n ${utils_1.decorators.red("Unexpected error: ")} \t ${utils_1.decorators.bright(err)}\n`);
}
});
}
function customizeParachainRawSpec(specPath, parachain) {
try {
const paraSpecRaw = readAndParseChainSpec(specPath);
// Customize the chain-spec fields
if (parachain.withCustomProps) {
// name: <para_id>-[parachain-name]
paraSpecRaw.name = `${parachain.id}-${parachain.name}`;
// id: <para_id>_testnet
paraSpecRaw.id = `${parachain.id}_testnet`;
// protocolId: <para_id>-[parachain-name]
paraSpecRaw.protocolId = `${parachain.id}-${parachain.name}`;
debug(`Customized parachain chain-spec for ${parachain.name}:`);
debug(` name: ${paraSpecRaw.name}`);
debug(` id: ${paraSpecRaw.id}`);
debug(` protocolId: ${paraSpecRaw.protocolId}`);
}
writeChainSpec(specPath, paraSpecRaw);
}
catch (err) {
console.log(`\n ${utils_1.decorators.red("Error customizing parachain chain-spec: ")} \t ${utils_1.decorators.bright(err)}\n`);
throw err;
}
}
exports.default = {
addAuraAuthority,
addAuthority,
changeGenesisConfig,
clearAuthorities,
readAndParseChainSpec,
specHaveSessionsKeys,
writeChainSpec,
getNodeKey,
addParaCustom,
addCollatorSelection,
isRawSpec,
getChainIdFromSpec,
customizePlainRelayChain,
customizeParachainRawSpec,
};