@kba-tools/genesis-tool
Version:
A forked repo from ConsenSys which helps to generate genesis block for Besu Network with xemptyBlockPeriod field.
243 lines (235 loc) • 7.93 kB
text/typescript
import { rootQuestion } from "./questions";
import { QuestionRenderer } from "./questionRenderer";
import { generateNetworkConfig } from "./lib/networkGenerate";
import { QuorumConfig } from "./types/quorumConfig";
import yargs from "yargs/yargs";
import chalk from "chalk";
// import { CryptoCurve } from "./types/cryptoCurve";
export async function main(): Promise<void> {
if (process.platform === "win32") {
console.error(
chalk.red(
"Unfortunately this tool is not compatible with Windows at the moment.\n" +
"We recommend running it under Windows Subsystem For Linux 2 with Docker Desktop.\n" +
"Please visit the following pages for installation instructions.\n\n" +
"https://docs.microsoft.com/en-us/windows/wsl/install-win10\n" +
"https://docs.docker.com/docker-for-windows/wsl/"
)
);
process.exit(1);
}
let answers = {};
if (process.argv.slice(2).length > 0) {
const args = await yargs(process.argv.slice(2))
.options({
consensus: {
type: "string",
demandOption: true,
default: "qbft",
choices: ["ibft", "ibft2", "qbft", "clique", "raft"],
describe: "Consensus algorithm to use",
},
chainID: {
type: "number",
demandOption: true,
default: 1337,
describe: "ChainID for blockchain",
},
blockperiod: {
type: "number",
demandOption: true,
default: 5,
describe: "Number of seconds per block",
},
requestTimeout: {
type: "number",
demandOption: false,
default: 10,
describe: "Minimum request timeout for each round",
},
emptyBlockPeriod: {
type: "number",
demandOption: false,
default: 60,
describe:
"Reduce number (seconds) of blocks produced when there are no transactions",
},
xemptyBlockPeriod: {
type: "boolean",
demandOption: false,
default: false,
describe: "Include xemptyBlockPeriod field in genesis block (Besu only)",
},
epochLength: {
type: "number",
demandOption: true,
default: 30000,
describe: "Number of blocks after which votes reset",
},
difficulty: {
type: "number",
demandOption: true,
default: 1,
describe: "Difficulty of network",
},
gasLimit: {
type: "string",
demandOption: true,
default: "0xFFFF",
describe: "Block gas limit",
},
coinbase: {
type: "string",
demandOption: false,
default: "0x0000000000000000000000000000000000000000",
describe: "Address to pay mining rewards to",
},
maxCodeSize: {
type: "number",
demandOption: false,
default: 64000,
describe: "Maximum contract size (kb)",
},
txnSizeLimit: {
type: "number",
demandOption: false,
default: 64000,
describe: "Maximum transaction size (kb)",
},
validators: {
type: "number",
demandOption: true,
default: 4,
describe: "Number of validator node keys to generate",
},
members: {
type: "number",
demandOption: true,
default: 1,
describe: "Number of member node keys to generate",
},
bootnodes: {
type: "number",
demandOption: true,
default: 2,
describe: "Number of bootnode node keys to generate",
},
// curve: { type: 'string', demandOption: false, default: CryptoCurve.k1, choices: [CryptoCurve.k1, CryptoCurve.r1], describe: 'Type of curve for keys' },
accountPassword: {
type: "string",
demandOption: false,
default: "",
describe: "Password for keys",
},
outputPath: {
type: "string",
demandOption: false,
default: "./output",
describe: "Output path relative to current directory",
},
tesseraEnabled: {
type: "boolean",
demandOption: false,
default: false,
describe: "Whether to generate tessera keys",
},
tesseraPassword: {
type: "string",
demandOption: false,
default: "",
describe: "Set password to encrypt generated keys",
},
quickstartDevAccounts: {
type: "boolean",
demandOption: true,
default: false,
describe: "Include quorum-dev-quickstart test accounts",
},
genesisNodeAllocation: {
type: "string",
demandOption: true,
default: "1000000000000000000000000000",
describe: "Balance allocated to each nodes",
},
alloc: {
type: "string",
demandOption: true,
default: "{}",
describe: "JSON format of the prefunded accounts {'address': { balance: '100000'}}",
},
noOutputTimestamp: {
type: "boolean",
demandOption: false,
default: false,
describe: "Remove generated timestamp from output folder name",
},
})
.coerce(["consensus"], (opt: string) => {
return opt.toLowerCase();
}).argv;
answers = {
consensus: args.consensus,
chainID: args.chainID,
blockperiod: args.blockperiod,
requestTimeout: args.requestTimeout,
xemptyBlockPeriod: args.xemptyBlockPeriod,
emptyBlockPeriod: args.emptyBlockPeriod,
epochLength: args.epochLength,
difficulty: args.difficulty,
gasLimit: args.gasLimit,
coinbase: args.coinbase,
maxCodeSize: args.maxCodeSize,
txnSizeLimit: args.txnSizeLimit,
validators: args.validators,
members: args.members,
bootnodes: args.bootnodes,
curve: args.curve,
accountPassword: args.accountPassword,
outputPath: args.outputPath,
tesseraEnabled: args.tesseraEnabled,
tesseraPassword: args.tesseraPassword,
quickstartDevAccounts: args.quickstartDevAccounts,
noOutputTimestamp: args.noOutputTimestamp,
prefundedAccounts: args.alloc,
genesisNodeAllocation: args.genesisNodeAllocation,
};
} else {
const qr = new QuestionRenderer(rootQuestion);
answers = await qr.render(); // begin rendering the questions
// console.log(answers); // log answer output for debugging
}
await generateNetworkConfig(answers as QuorumConfig); // build artifacts
setTimeout(() => {
process.exit(0);
}, 500);
}
if (require.main === module) {
// note: main returns a Promise<void>, but we don't need to do anything
// special with it, so we use the void operator to indicate to eslint that
// we left this dangling intentionally...
try {
void main();
} catch (err: any) {
if (
err &&
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
err.stack &&
process.argv.length >= 3 &&
process.argv[2] === "--stackTraceOnError"
) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
console.error(`Fatal error: ${err.stack as string}`);
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
} else if (err && err.message) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
console.error(`Fatal error: ${err.message as string}`);
} else if (err) {
console.error(`Fatal error: ${err as string}`);
} else {
console.error(`Fatal error: unknown`);
}
process.exit(1);
}
}
export { generateNetworkConfig } from "./lib/networkGenerate";
export * from "./types";