Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 63 additions & 18 deletions src/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
exportGenesisWasm,
exportGenesisState,
startSimpleCollator,
getParachainIdFromSpec,
} from "./spawn";
import { connect, registerParachain, setBalance } from "./rpc";
import { checkConfig } from "./check";
Expand All @@ -23,7 +24,12 @@ import { ApiPromise } from "@polkadot/api";

import { resolve } from "path";
import fs from "fs";
import { LaunchConfig, ParachainConfig, HrmpChannelsConfig } from "./types";
import {
LaunchConfig,
ResolvedParachainConfig,
HrmpChannelsConfig,
ResolvedLaunchConfig,
} from "./types";

function loadTypeDef(types: string | object): object {
if (typeof types === "string") {
Expand All @@ -43,11 +49,12 @@ function loadTypeDef(types: string | object): object {
// keep track of registered parachains
let registeredParachains: { [key: string]: boolean } = {};

export async function run(config_dir: string, config: LaunchConfig) {
export async function run(config_dir: string, rawConfig: LaunchConfig) {
// Verify that the `config.json` has all the expected properties.
if (!checkConfig(config)) {
if (!checkConfig(rawConfig)) {
return;
}
const config = await resolveParachainId(config_dir, rawConfig);

const relay_chain_bin = resolve(config_dir, config.relaychain.bin);
if (!fs.existsSync(relay_chain_bin)) {
Expand Down Expand Up @@ -87,20 +94,31 @@ export async function run(config_dir: string, config: LaunchConfig) {

// Then launch each parachain
for (const parachain of config.parachains) {
const { id, balance, chain } = parachain;
const { id, resolvedId, balance, chain } = parachain;
const bin = resolve(config_dir, parachain.bin);
if (!fs.existsSync(bin)) {
console.error("Parachain binary does not exist: ", bin);
process.exit();
}
let account = parachainAccount(id);
let account = parachainAccount(resolvedId);

for (const node of parachain.nodes) {
const { wsPort, port, flags, name } = node;
console.log(
`Starting a Collator for parachain ${id}: ${account}, Collator port : ${port} wsPort : ${wsPort}`
`Starting a Collator for parachain ${resolvedId}: ${account}, Collator port : ${port} wsPort : ${wsPort}`
);
const skipIdArg = !id;
await startCollator(
bin,
resolvedId,
wsPort,
port,
name,
chain,
spec,
flags,
skipIdArg
);
await startCollator(bin, id, wsPort, port, name, chain, spec, flags);
}

// Allow time for the TX to complete, avoiding nonce issues.
Expand All @@ -113,16 +131,17 @@ export async function run(config_dir: string, config: LaunchConfig) {
// Then launch each simple parachain (e.g. an adder-collator)
if (config.simpleParachains) {
for (const simpleParachain of config.simpleParachains) {
const { id, port, balance } = simpleParachain;
const { id, resolvedId, port, balance } = simpleParachain;
const bin = resolve(config_dir, simpleParachain.bin);
if (!fs.existsSync(bin)) {
console.error("Simple parachain binary does not exist: ", bin);
process.exit();
}

let account = parachainAccount(id);
console.log(`Starting Parachain ${id}: ${account}`);
await startSimpleCollator(bin, id, spec, port);
let account = parachainAccount(resolvedId);
console.log(`Starting Parachain ${resolvedId}: ${account}`);
const skipIdArg = !id;
await startSimpleCollator(bin, resolvedId, spec, port, skipIdArg);

// Get the information required to register the parachain on the relay chain.
let genesisState;
Expand All @@ -137,10 +156,10 @@ export async function run(config_dir: string, config: LaunchConfig) {
process.exit(1);
}

console.log(`Registering Parachain ${id}`);
console.log(`Registering Parachain ${resolvedId}`);
await registerParachain(
relayChainApi,
id,
resolvedId,
genesisWasm,
genesisState,
config.finalization
Expand All @@ -163,18 +182,18 @@ export async function run(config_dir: string, config: LaunchConfig) {
async function addParachainsToGenesis(
config_dir: string,
spec: string,
parachains: ParachainConfig[]
parachains: ResolvedParachainConfig[]
) {
console.log("\n⛓ Adding Genesis Parachains");
for (const parachain of parachains) {
const { id, chain } = parachain;
const { id, resolvedId, chain } = parachain;
const bin = resolve(config_dir, parachain.bin);
if (!fs.existsSync(bin)) {
console.error("Parachain binary does not exist: ", bin);
process.exit();
}
// If it isn't registered yet, register the parachain in genesis
if (!registeredParachains[id]) {
if (!registeredParachains[resolvedId]) {
// Get the information required to register the parachain in genesis.
let genesisState;
let genesisWasm;
Expand All @@ -186,8 +205,14 @@ async function addParachainsToGenesis(
process.exit(1);
}

await addGenesisParachain(spec, id, genesisState, genesisWasm, true);
registeredParachains[id] = true;
await addGenesisParachain(
spec,
resolvedId,
genesisState,
genesisWasm,
true
);
registeredParachains[resolvedId] = true;
}
}
}
Expand All @@ -201,3 +226,23 @@ async function addHrmpChannelsToGenesis(
await addGenesisHrmpChannel(spec, hrmpChannel);
}
}

// Resolves parachain id from chain spec if not specified
async function resolveParachainId(
config_dir: string,
config: LaunchConfig
): Promise<ResolvedLaunchConfig> {
console.log(`\n🧹 Resolving parachain id...`);
const resolvedConfig = config as ResolvedLaunchConfig;
for (const parachain of resolvedConfig.parachains) {
if (parachain.id) {
parachain.resolvedId = parachain.id;
} else {
const bin = resolve(config_dir, parachain.bin);
const paraId = await getParachainIdFromSpec(bin, parachain.chain);
console.log(` ✓ Read parachain id for ${parachain.bin}: ${paraId}`);
parachain.resolvedId = paraId.toString();
}
}
return resolvedConfig;
}
50 changes: 45 additions & 5 deletions src/spawn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,38 @@ export async function generateChainSpecRaw(bin: string, chain: string) {
});
}

export async function getParachainIdFromSpec(
bin: string,
chain?: string
): Promise<number> {
const data = await new Promise<string>(function (resolve, reject) {
let args = ["build-spec"];
if (chain) {
args.push("--chain=" + chain);
}

let data = "";

p["spec"] = spawn(bin, args);
p["spec"].stdout.on("data", (chunk) => {
data += chunk;
});

p["spec"].stderr.pipe(process.stderr);

p["spec"].on("close", () => {
resolve(data);
});

p["spec"].on("error", (err) => {
reject(err);
});
});

const spec = JSON.parse(data);
return spec.para_id;
}

// Spawn a new relay chain node.
// `name` must be `alice`, `bob`, `charlie`, etc... (hardcoded in Substrate).
export function startNode(
Expand Down Expand Up @@ -147,15 +179,15 @@ export function startCollator(
name?: string,
chain?: string,
spec?: string,
flags?: string[]
flags?: string[],
skip_id_arg?: boolean
) {
return new Promise<void>(function (resolve) {
// TODO: Make DB directory configurable rather than just `tmp`
let args = [
"--tmp",
"--ws-port=" + wsPort,
"--port=" + port,
"--parachain-id=" + id,
"--collator",
"--force-authoring",
];
Expand All @@ -164,7 +196,10 @@ export function startCollator(
args.push(`--${name.toLowerCase()}`);
console.log(`Added --${name.toLowerCase()}`);
}

if (!skip_id_arg) {
args.push("--parachain-id=" + id);
console.log(`Added --parachain-id=${id}`);
}
if (chain) {
args.push("--chain=" + chain);
console.log(`Added --chain=${chain}`);
Expand Down Expand Up @@ -215,17 +250,22 @@ export function startSimpleCollator(
bin: string,
id: string,
spec: string,
port: string
port: string,
skip_id_arg?: boolean
) {
return new Promise<void>(function (resolve) {
let args = [
"--tmp",
"--parachain-id=" + id,
"--port=" + port,
"--chain=" + spec,
"--execution=wasm",
];

if (!skip_id_arg) {
args.push("--parachain-id=" + id);
console.log(`Added --parachain-id=${id}`);
}

p[port] = spawn(bin, args);

let log = fs.createWriteStream(`${port}.log`);
Expand Down
15 changes: 13 additions & 2 deletions src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ export interface ParachainNodeConfig {
}
export interface ParachainConfig {
bin: string;
id: string;
id?: string;
balance: string;
chain?: string;
nodes: ParachainNodeConfig[];
}
export interface SimpleParachainConfig {
bin: string;
id: string;
id?: string;
port: string;
balance: string;
}
Expand Down Expand Up @@ -65,3 +65,14 @@ export interface ChainSpec {
};
};
}

export interface ResolvedParachainConfig extends ParachainConfig {
resolvedId: string;
}
export interface ResolvedSimpleParachainConfig extends SimpleParachainConfig {
resolvedId: string;
}
export interface ResolvedLaunchConfig extends LaunchConfig {
parachains: ResolvedParachainConfig[];
simpleParachains: ResolvedSimpleParachainConfig[];
}