UNPKG

@kba-tools/genesis-tool

Version:

A forked repo from ConsenSys which helps to generate genesis block for Besu Network with xemptyBlockPeriod field.

266 lines 18.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; 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.generateNetworkConfig = void 0; exports.main = main; const questions_1 = require("./questions"); const questionRenderer_1 = require("./questionRenderer"); const networkGenerate_1 = require("./lib/networkGenerate"); const yargs_1 = __importDefault(require("yargs/yargs")); const chalk_1 = __importDefault(require("chalk")); // import { CryptoCurve } from "./types/cryptoCurve"; function main() { return __awaiter(this, void 0, void 0, function* () { if (process.platform === "win32") { console.error(chalk_1.default.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 = yield (0, yargs_1.default)(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) => { 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_1.QuestionRenderer(questions_1.rootQuestion); answers = yield qr.render(); // begin rendering the questions // console.log(answers); // log answer output for debugging } yield (0, networkGenerate_1.generateNetworkConfig)(answers); // 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) { 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}`); // 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}`); } else if (err) { console.error(`Fatal error: ${err}`); } else { console.error(`Fatal error: unknown`); } process.exit(1); } } var networkGenerate_2 = require("./lib/networkGenerate"); Object.defineProperty(exports, "generateNetworkConfig", { enumerable: true, get: function () { return networkGenerate_2.generateNetworkConfig; } }); __exportStar(require("./types"), exports); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFRQSxvQkF5TUM7QUFqTkQsMkNBQTJDO0FBQzNDLHlEQUFzRDtBQUN0RCwyREFBOEQ7QUFFOUQsd0RBQWdDO0FBQ2hDLGtEQUEwQjtBQUMxQixxREFBcUQ7QUFFckQsU0FBc0IsSUFBSTs7UUFDeEIsSUFBSSxPQUFPLENBQUMsUUFBUSxLQUFLLE9BQU8sRUFBRSxDQUFDO1lBQ2pDLE9BQU8sQ0FBQyxLQUFLLENBQ1gsZUFBSyxDQUFDLEdBQUcsQ0FDUCx5RUFBeUU7Z0JBQ3ZFLG9GQUFvRjtnQkFDcEYscUVBQXFFO2dCQUNyRSw4REFBOEQ7Z0JBQzlELGlEQUFpRCxDQUNwRCxDQUNGLENBQUM7WUFDRixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xCLENBQUM7UUFFRCxJQUFJLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDakIsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDckMsTUFBTSxJQUFJLEdBQUcsTUFBTSxJQUFBLGVBQUssRUFBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztpQkFDNUMsT0FBTyxDQUFDO2dCQUNQLFNBQVMsRUFBRTtvQkFDVCxJQUFJLEVBQUUsUUFBUTtvQkFDZCxZQUFZLEVBQUUsSUFBSTtvQkFDbEIsT0FBTyxFQUFFLE1BQU07b0JBQ2YsT0FBTyxFQUFFLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQztvQkFDcEQsUUFBUSxFQUFFLDRCQUE0QjtpQkFDdkM7Z0JBQ0QsT0FBTyxFQUFFO29CQUNQLElBQUksRUFBRSxRQUFRO29CQUNkLFlB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