UNPKG

lisk-framework

Version:

Lisk blockchain application platform

217 lines 9.27 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ChainEndpoint = void 0; const lisk_chain_1 = require("@liskhq/lisk-chain"); const lisk_db_1 = require("@liskhq/lisk-db"); const lisk_validator_1 = require("@liskhq/lisk-validator"); const lisk_cryptography_1 = require("@liskhq/lisk-cryptography"); const constants_1 = require("../bft/constants"); const schemas_1 = require("../bft/schemas"); const utils_1 = require("../bft/utils"); const bft_params_1 = require("../bft/bft_params"); const constants_2 = require("../consensus/constants"); const proveEventsRequestSchema = { $id: '/node/endpoint/proveEventsRequestSchema', type: 'object', required: ['height', 'queries'], properties: { height: { type: 'integer', minimum: 0, }, queries: { type: 'array', items: { type: 'string', format: 'hex', }, }, }, }; class ChainEndpoint { constructor(args) { this._chain = args.chain; this._bftMethod = args.bftMethod; } init(db) { this._db = db; } async getBlockByID(context) { const { id } = context.params; if (!(0, lisk_validator_1.isHexString)(id)) { throw new Error('Invalid parameters. id must be a valid hex string.'); } const block = await this._chain.dataAccess.getBlockByID(Buffer.from(id, 'hex')); return block.toJSON(); } async getBlocksByIDs(context) { const { ids } = context.params; if (!Array.isArray(ids) || ids.length === 0) { throw new Error('Invalid parameters. ids must be a non empty array.'); } if (!ids.every(id => (0, lisk_validator_1.isHexString)(id))) { throw new Error('Invalid parameters. id must a valid hex string.'); } const blocks = []; try { for (const id of ids) { const block = await this._chain.dataAccess.getBlockByID(Buffer.from(id, 'hex')); blocks.push(block); } } catch (error) { if (!(error instanceof lisk_db_1.NotFoundError)) { throw error; } } return blocks.map(block => block.toJSON()); } async getBlockByHeight(context) { const { height } = context.params; if (typeof height !== 'number') { throw new Error('Invalid parameters. height must be a number.'); } const block = await this._chain.dataAccess.getBlockByHeight(height); return block.toJSON(); } async getBlocksByHeightBetween(context) { const { from, to } = context.params; if (typeof from !== 'number' || typeof to !== 'number') { throw new Error('Invalid parameters. from and to must be a number.'); } const blocks = await this._chain.dataAccess.getBlocksByHeightBetween(from, to); return blocks.map(b => b.toJSON()); } async getTransactionByID(context) { const { id } = context.params; if (!(0, lisk_validator_1.isHexString)(id)) { throw new Error('Invalid parameters. id must be a valid hex string.'); } const transaction = await this._chain.dataAccess.getTransactionByID(Buffer.from(id, 'hex')); return transaction.toJSON(); } async getTransactionsByIDs(context) { const { ids } = context.params; if (!Array.isArray(ids) || ids.length === 0) { throw new Error('Invalid parameters. ids must be a non empty array.'); } if (!ids.every(id => (0, lisk_validator_1.isHexString)(id))) { throw new Error('Invalid parameters. id must a valid hex string.'); } const transactions = []; try { for (const id of ids) { const transaction = await this._chain.dataAccess.getTransactionByID(Buffer.from(id, 'hex')); transactions.push(transaction); } } catch (error) { if (!(error instanceof lisk_db_1.NotFoundError)) { throw error; } } return transactions.map(tx => tx.toJSON()); } async getTransactionsByHeight(context) { const { height } = context.params; if (typeof height !== 'number' || height < 0) { throw new Error('Invalid parameters. height must be zero or a positive number.'); } const block = await this._chain.dataAccess.getBlockByHeight(height); return block.transactions.map(tx => tx.toJSON()); } async getAssetsByHeight(context) { const { height } = context.params; if (typeof height !== 'number' || height < 0) { throw new Error('Invalid parameters. height must be zero or a positive number.'); } const block = await this._chain.dataAccess.getBlockByHeight(height); return block.assets.toJSON(); } getLastBlock() { return this._chain.lastBlock.toJSON(); } async getEvents(context) { const { height } = context.params; if (typeof height !== 'number' || height < 0) { throw new Error('Invalid parameters. height must be zero or a positive number.'); } const events = await this._chain.dataAccess.getEvents(height); return events.map(e => e.toJSON()); } async getInclusionProofsAtHeight(context) { const { height } = context.params; if (typeof height !== 'number' || height < 0) { throw new Error('Invalid parameters. height must be zero or a positive number.'); } const inclusionProof = await this._chain.dataAccess.getInclusionProofs(height); return { proof: { queries: inclusionProof.queries.map(q => ({ bitmap: q.bitmap.toString('hex'), key: q.key.toString('hex'), value: q.value.toString('hex'), })), siblingHashes: inclusionProof.siblingHashes.map(h => h.toString('hex')), }, }; } async proveEvents(context) { lisk_validator_1.validator.validate(proveEventsRequestSchema, context.params); const { height, queries } = context.params; const queryBytes = queries.map(q => Buffer.from(q, 'hex')); const events = await this._chain.dataAccess.getEvents(height); const eventSMT = new lisk_db_1.SparseMerkleTree(lisk_chain_1.EVENT_KEY_LENGTH); const data = []; for (const e of events) { const pairs = e.keyPair(); for (const pair of pairs) { data.push(pair); } } const root = await eventSMT.update(constants_2.EMPTY_HASH, data); const proof = await eventSMT.prove(root, queryBytes); return { queries: proof.queries.map(q => ({ bitmap: q.bitmap.toString('hex'), key: q.key.toString('hex'), value: q.value.toString('hex'), })), siblingHashes: proof.siblingHashes.map(h => h.toString('hex')), }; } async getGeneratorList(_) { const stateStore = new lisk_chain_1.StateStore(this._db); const votesStore = stateStore.getStore(constants_1.MODULE_STORE_PREFIX_BFT, constants_1.STORE_PREFIX_BFT_VOTES); const bftVotes = await votesStore.getWithSchema(constants_1.EMPTY_KEY, schemas_1.bftVotesSchema); const { height: currentHeight } = bftVotes.blockBFTInfos.length > 0 ? bftVotes.blockBFTInfos[0] : { height: 0 }; const bftStore = stateStore.getStore(constants_1.MODULE_STORE_PREFIX_BFT, constants_1.STORE_PREFIX_BFT_PARAMETERS); const bftParams = await (0, bft_params_1.getBFTParameters)(bftStore, currentHeight + 1); const slot = this._bftMethod.getSlotNumber(Math.floor(Date.now() / 1000)); const startTime = this._bftMethod.getSlotTime(slot); let nextAllocatedTime = startTime; const slotInRound = slot % bftParams.validators.length; const generatorsInfo = []; for (let i = slotInRound; i < slotInRound + bftParams.validators.length; i += 1) { generatorsInfo.push({ address: lisk_cryptography_1.address.getLisk32AddressFromAddress(bftParams.validators[i % bftParams.validators.length].address), nextAllocatedTime, }); nextAllocatedTime += this._bftMethod.blockTime(); } return { list: generatorsInfo, }; } async areHeadersContradicting(context) { lisk_validator_1.validator.validate(schemas_1.areHeadersContradictingRequestSchema, context.params); const bftHeader1 = lisk_chain_1.BlockHeader.fromBytes(Buffer.from(context.params.header1, 'hex')); const bftHeader2 = lisk_chain_1.BlockHeader.fromBytes(Buffer.from(context.params.header2, 'hex')); if (bftHeader1.id.equals(bftHeader2.id)) { return { valid: false }; } return { valid: (0, utils_1.areDistinctHeadersContradicting)(bftHeader1, bftHeader2) }; } } exports.ChainEndpoint = ChainEndpoint; //# sourceMappingURL=chain.js.map