UNPKG

lisk-framework

Version:

Lisk blockchain application platform

296 lines 13.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Engine = exports.BLOCKCHAIN_DB_NAME = void 0; const path = require("path"); const lisk_chain_1 = require("@liskhq/lisk-chain"); const lisk_cryptography_1 = require("@liskhq/lisk-cryptography"); const lisk_db_1 = require("@liskhq/lisk-db"); const logger_1 = require("../logger"); const network_1 = require("./network"); const consensus_1 = require("./consensus"); const generator_1 = require("./generator"); const endpoint_1 = require("../endpoint"); const bft_1 = require("./bft"); const events_1 = require("./events"); const rpc_server_1 = require("./rpc/rpc_server"); const chain_1 = require("./endpoint/chain"); const system_1 = require("./endpoint/system"); const constants_1 = require("./consensus/constants"); const txpool_1 = require("./endpoint/txpool"); const constants_2 = require("./generator/constants"); const consensus_2 = require("./endpoint/consensus"); const state_1 = require("./endpoint/state"); const genesis_block_1 = require("../utils/genesis_block"); const legacy_chain_handler_1 = require("./legacy/legacy_chain_handler"); const endpoint_2 = require("./legacy/endpoint"); const metrics_1 = require("./metrics/metrics"); const backup_1 = require("../utils/backup"); const isEmpty = (value) => { switch (typeof value) { case 'undefined': return true; case 'string': return value === ''; case 'number': return value === 0; case 'bigint': return value === BigInt(0); case 'object': if (value === null) { return true; } if (Array.isArray(value) && value.length === 0) { return true; } if (Object.keys(value).length === 0) { return true; } return false; default: throw new Error('Unknown type.'); } }; const emptyOrDefault = (value, defaultValue) => (isEmpty(value) ? defaultValue : value); exports.BLOCKCHAIN_DB_NAME = 'blockchain.db'; class Engine { constructor(abi, config) { this._abi = abi; this._config = config; } async generateBlock(input) { return this._generator.generateBlock(input); } async start() { if (this._config.system.enableMetrics) { metrics_1.defaultMetrics.enable(); } await this._init(); await this._network.start(); if (this._config.legacy.sync) { this._logger.info('Legacy block sync started'); await this._legacyChainHandler.sync(); this._logger.info('Legacy block sync completed'); } await this._generator.start(); await this._consensus.start(); await this._rpcServer.start(); await this._abi.init({ lastBlockHeight: this._chain.lastBlock.header.height, chainID: this._chain.chainID, lastStateRoot: this._chain.lastBlock.header.stateRoot, }); this._logger.info('Engine started'); } async stop() { this._logger.info('Engine cleanup started'); await this._network.stop(); await this._generator.stop(); await this._consensus.stop(); this._legacyChainHandler.stop(); this._rpcServer.stop(); this._closeDB(); this._logger.info('Engine cleanup completed'); } async _init() { this._logger = (0, logger_1.createLogger)({ name: 'engine', logLevel: emptyOrDefault(this._config.system.logLevel, 'info'), }); this._logger.info('Engine initialization starting'); this._network = new network_1.Network({ options: this._config.network, }); this._chain = new lisk_chain_1.Chain({ maxTransactionsSize: this._config.genesis.maxTransactionsSize, keepEventsForHeights: this._config.system.keepEventsForHeights, keepInclusionProofsForHeights: this._config.system.keepInclusionProofsForHeights, }); this._bftModule = new bft_1.BFTModule(); this._consensus = new consensus_1.Consensus({ abi: this._abi, network: this._network, chain: this._chain, genesisConfig: this._config.genesis, systemConfig: this._config.system, bft: this._bftModule, }); this._generator = new generator_1.Generator({ abi: this._abi, chain: this._chain, consensus: this._consensus, bft: this._bftModule, config: this._config, network: this._network, }); this._legacyChainHandler = new legacy_chain_handler_1.LegacyChainHandler({ legacyConfig: this._config.legacy, network: this._network, logger: this._logger, }); this._rpcServer = new rpc_server_1.RPCServer(this._config.system.dataPath, this._config.rpc); const genesis = (0, genesis_block_1.readGenesisBlock)(this._config, this._logger); this._blockchainDB = new lisk_db_1.Database(path.join(this._config.system.dataPath, 'data', exports.BLOCKCHAIN_DB_NAME)); this._generatorDB = new lisk_db_1.Database(path.join(this._config.system.dataPath, 'data', 'generator.db')); this._legacyDB = new lisk_db_1.Database(path.join(this._config.system.dataPath, 'data', 'legacy.db')); this._nodeDB = new lisk_db_1.Database(path.join(this._config.system.dataPath, 'data', 'node.db')); this._chainID = Buffer.from(this._config.genesis.chainID, 'hex'); this._chain.init({ db: this._blockchainDB, chainID: this._chainID, genesisBlock: genesis, }); await this._network.init({ nodeDB: this._nodeDB, logger: this._logger, chainID: this._chainID, }); await this._consensus.init({ db: this._blockchainDB, genesisBlock: genesis, logger: this._logger, legacyDB: this._legacyDB, }); await this._generator.init({ blockchainDB: this._blockchainDB, generatorDB: this._generatorDB, logger: this._logger, genesisHeight: genesis.header.height, }); await this._legacyChainHandler.init({ db: this._legacyDB, }); this._registerEventListeners(); this._rpcServer.init({ logger: this._logger, chainID: this._chain.chainID, }); const legacyEndpoint = new endpoint_2.LegacyEndpoint({ db: this._legacyDB, legacyConfig: this._config.legacy, }); const chainEndpoint = new chain_1.ChainEndpoint({ chain: this._chain, bftMethod: this._bftModule.method, }); chainEndpoint.init(this._blockchainDB); const consensusEndpoint = new consensus_2.ConsensusEndpoint({ bftMethod: this._bftModule.method, blockchainDB: this._blockchainDB, }); const stateEndpoint = new state_1.StateEndpoint({ abi: this._abi, chain: this._chain, }); const systemEndpoint = new system_1.SystemEndpoint({ abi: this._abi, chain: this._chain, consensus: this._consensus, generator: this._generator, config: this._config, genesisHeight: genesis.header.height, }); const txpoolEndpoint = new txpool_1.TxpoolEndpoint({ abi: this._abi, broadcaster: this._generator.broadcaster, pool: this._generator.txpool, chain: this._chain, }); for (const [name, handler] of (0, endpoint_1.getEndpointHandlers)(legacyEndpoint)) { this._rpcServer.registerEndpoint('legacy', name, handler); } for (const [name, handler] of (0, endpoint_1.getEndpointHandlers)(chainEndpoint)) { this._rpcServer.registerEndpoint('chain', name, handler); } for (const [name, handler] of (0, endpoint_1.getEndpointHandlers)(consensusEndpoint)) { this._rpcServer.registerEndpoint('consensus', name, handler); } for (const [name, handler] of (0, endpoint_1.getEndpointHandlers)(stateEndpoint)) { this._rpcServer.registerEndpoint('state', name, handler); } for (const [name, handler] of (0, endpoint_1.getEndpointHandlers)(systemEndpoint)) { this._rpcServer.registerEndpoint('system', name, handler); } for (const [name, handler] of (0, endpoint_1.getEndpointHandlers)(txpoolEndpoint)) { this._rpcServer.registerEndpoint('txpool', name, handler); } for (const [name, handler] of (0, endpoint_1.getEndpointHandlers)(this._generator.endpoint)) { this._rpcServer.registerEndpoint('generator', name, handler); } for (const [name, handler] of (0, endpoint_1.getEndpointHandlers)(this._network.endpoint)) { this._rpcServer.registerEndpoint('network', name, handler); } this._rpcServer.registerNotFoundEndpoint(async (namespace, method, context) => { const { data } = await this._abi.query({ header: this._chain.lastBlock.header.toObject(), method: `${namespace}_${method}`, params: Buffer.from(JSON.stringify(context.params), 'utf-8'), }); return JSON.parse(data.toString('utf-8')); }); } _registerEventListeners() { this._consensus.events.on(consensus_1.CONSENSUS_EVENT_BLOCK_NEW, ({ block }) => { this._generator.onNewBlock(block); Promise.all([ this._rpcServer.publish(events_1.EVENT_CHAIN_BLOCK_NEW, { blockHeader: block.header.toJSON() }), this._rpcServer.publish(events_1.EVENT_NETWORK_BLOCK_NEW, { blockHeader: block.header.toJSON() }), ]).catch(err => this._logger.error({ err: err }, 'Fail to publish event')); if (this._config.system.backup.height > 0 && block.header.height === this._config.system.backup.height) { (0, backup_1.backupDatabase)(this._config.system.dataPath, exports.BLOCKCHAIN_DB_NAME, this._blockchainDB).catch(err => { this._logger.error({ err: err, height: this._config.system.backup.height }, 'Failed to create backup for stateDB'); }); } }); this._consensus.events.on(consensus_1.CONSENSUS_EVENT_BLOCK_DELETE, ({ block }) => { this._generator.onDeleteBlock(block); this._rpcServer .publish(events_1.EVENT_CHAIN_BLOCK_DELETE, { blockHeader: block.header.toJSON() }) .catch(err => this._logger.error({ err: err }, 'Fail to publish event')); }); this._consensus.events.on(constants_1.CONSENSUS_EVENT_FORK_DETECTED, ({ block }) => { this._rpcServer .publish(events_1.EVENT_CHAIN_FORK, { blockHeader: block.header.toJSON() }) .catch(err => this._logger.error({ err: err }, 'Fail to publish event')); }); this._consensus.events.on(constants_1.CONSENSUS_EVENT_NETWORK_BLOCK_NEW, ({ block }) => { this._rpcServer .publish(events_1.EVENT_NETWORK_BLOCK_NEW, { blockHeader: block.header.toJSON() }) .catch(err => this._logger.error({ err: err }, 'Fail to publish event')); }); this._consensus.events.on(constants_1.CONSENSUS_EVENT_VALIDATORS_CHANGED, (update) => { this._rpcServer .publish(events_1.EVENT_CHAIN_VALIDATORS_CHANGE, { nextValidators: update.nextValidators.map(v => ({ address: lisk_cryptography_1.address.getLisk32AddressFromAddress(v.address), blsKey: v.blsKey.toString('hex'), generatorKey: v.generatorKey.toString('hex'), bftWeight: v.bftWeight.toString(), })), preCommitThreshold: update.preCommitThreshold.toString(), certificateThreshold: update.certificateThreshold.toString(), }) .catch(err => this._logger.error({ err: err }, 'Fail to publish event')); }); this._generator.events.on(constants_2.GENERATOR_EVENT_NEW_TRANSACTION_ANNOUNCEMENT, (event) => { this._rpcServer .publish(events_1.EVENT_NETWORK_TRANSACTION_NEW, { transactionIDs: event.transactionIds.map(id => id.toString('hex')), }) .catch(err => this._logger.error({ err: err }, 'Fail to publish event')); }); this._generator.events.on(constants_2.GENERATOR_EVENT_NEW_TRANSACTION, (event) => { this._rpcServer .publish(events_1.EVENT_TX_POOL_TRANSACTION_NEW, event) .catch(err => this._logger.error({ err: err }, 'Fail to publish event')); }); } _closeDB() { this._blockchainDB.close(); this._generatorDB.close(); this._legacyDB.close(); this._nodeDB.close(); } } exports.Engine = Engine; //# sourceMappingURL=engine.js.map