UNPKG

lisk-framework

Version:

Lisk blockchain application platform

168 lines 8.41 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.calculateNewActiveValidators = exports.emptyActiveValidatorsUpdate = exports.getDecodedCCMAndID = exports.getEncodedCCMAndID = exports.getIDFromCCMBytes = exports.getTokenIDLSK = exports.getMainchainID = exports.verifyLivenessConditionForRegisteredChains = exports.chainAccountToJSON = exports.checkCertificateTimestamp = exports.checkLivenessRequirement = exports.isOutboxRootWitnessEmpty = exports.isInboxUpdateEmpty = exports.swapReceivingAndSendingChainIDs = exports.sortValidatorsByBLSKey = exports.computeValidatorsHash = exports.isValidName = exports.validNameChars = exports.handlePromiseErrorWithNull = exports.getEncodedSidechainTerminatedCCMParam = exports.getCCMSize = exports.validateFormat = void 0; const lisk_codec_1 = require("@liskhq/lisk-codec"); const lisk_cryptography_1 = require("@liskhq/lisk-cryptography"); const lisk_validator_1 = require("@liskhq/lisk-validator"); const lisk_chain_1 = require("@liskhq/lisk-chain"); const constants_1 = require("./constants"); const schemas_1 = require("./schemas"); const state_machine_1 = require("../../state_machine"); const schema_1 = require("../../engine/consensus/certificate_generation/schema"); const certificates_1 = require("./certificates"); const validateFormat = (ccm) => { lisk_validator_1.validator.validate(schemas_1.ccmSchema, ccm); const serializedCCM = lisk_codec_1.codec.encode(schemas_1.ccmSchema, ccm); for (const field of ['module', 'crossChainCommand']) { if (!new RegExp(lisk_chain_1.NAME_REGEX).test(ccm[field])) { throw new Error(`Cross-chain message ${field} name must be alphanumeric.`); } } if (serializedCCM.byteLength > constants_1.MAX_CCM_SIZE) { throw new Error(`Cross-chain message size is larger than ${constants_1.MAX_CCM_SIZE}.`); } }; exports.validateFormat = validateFormat; const getCCMSize = (ccm) => { const serializedCCM = lisk_codec_1.codec.encode(schemas_1.ccmSchema, ccm); return BigInt(serializedCCM.byteLength); }; exports.getCCMSize = getCCMSize; const getEncodedSidechainTerminatedCCMParam = (ccm, receivingChainAccount) => { const params = { chainID: ccm.receivingChainID, stateRoot: receivingChainAccount.lastCertificate.stateRoot, }; const encodedParams = lisk_codec_1.codec.encode(schemas_1.sidechainTerminatedCCMParamsSchema, params); return encodedParams; }; exports.getEncodedSidechainTerminatedCCMParam = getEncodedSidechainTerminatedCCMParam; const handlePromiseErrorWithNull = async (promise) => { let result; try { result = await promise; } catch { result = null; } return result; }; exports.handlePromiseErrorWithNull = handlePromiseErrorWithNull; exports.validNameChars = 'a-z0-9!@$&_.'; const isValidName = (username) => new RegExp(`^[${exports.validNameChars}]+$`, 'g').test(username); exports.isValidName = isValidName; const computeValidatorsHash = (initValidators, certificateThreshold) => { const input = { activeValidators: initValidators, certificateThreshold, }; const encodedValidatorsHashInput = lisk_codec_1.codec.encode(schemas_1.validatorsHashInputSchema, input); return lisk_cryptography_1.utils.hash(encodedValidatorsHashInput); }; exports.computeValidatorsHash = computeValidatorsHash; const sortValidatorsByBLSKey = (validators) => validators.sort((a, b) => a.blsKey.compare(b.blsKey)); exports.sortValidatorsByBLSKey = sortValidatorsByBLSKey; const swapReceivingAndSendingChainIDs = (ccm) => ({ ...ccm, receivingChainID: ccm.sendingChainID, sendingChainID: ccm.receivingChainID, }); exports.swapReceivingAndSendingChainIDs = swapReceivingAndSendingChainIDs; const isInboxUpdateEmpty = (inboxUpdate) => inboxUpdate.crossChainMessages.length === 0 && inboxUpdate.messageWitnessHashes.length === 0 && inboxUpdate.outboxRootWitness.siblingHashes.length === 0 && inboxUpdate.outboxRootWitness.bitmap.length === 0; exports.isInboxUpdateEmpty = isInboxUpdateEmpty; const isOutboxRootWitnessEmpty = (outboxRootWitness) => outboxRootWitness.siblingHashes.length === 0 || outboxRootWitness.bitmap.length === 0; exports.isOutboxRootWitnessEmpty = isOutboxRootWitnessEmpty; const checkLivenessRequirement = (partnerChainAccount, txParams) => { if (partnerChainAccount.status === 0 && txParams.certificate.equals(constants_1.EMPTY_BYTES)) { return { status: state_machine_1.VerifyStatus.FAIL, error: new Error(`Sending partner chain ${txParams.sendingChainID.readInt32BE(0)} has a registered status so certificate cannot be empty.`), }; } return { status: state_machine_1.VerifyStatus.OK, }; }; exports.checkLivenessRequirement = checkLivenessRequirement; const checkCertificateTimestamp = (txParams, certificate, header) => { if (txParams.certificate.equals(constants_1.EMPTY_BYTES)) { return; } if (certificate.timestamp >= header.timestamp) { throw Error('Certificate is invalid due to invalid timestamp.'); } }; exports.checkCertificateTimestamp = checkCertificateTimestamp; const chainAccountToJSON = (chainAccount) => { const { lastCertificate, name, status } = chainAccount; return { lastCertificate: (0, certificates_1.certificateToJSON)(lastCertificate), name, status, }; }; exports.chainAccountToJSON = chainAccountToJSON; const verifyLivenessConditionForRegisteredChains = (blockTimestamp, certificateBytes) => { const certificate = lisk_codec_1.codec.decode(schema_1.certificateSchema, certificateBytes); lisk_validator_1.validator.validate(schema_1.certificateSchema, certificate); const limitSecond = constants_1.LIVENESS_LIMIT / 2; if (blockTimestamp - certificate.timestamp > limitSecond) { throw new Error(`The first CCU with a non-empty inbox update cannot contain a certificate older than ${limitSecond} seconds.`); } }; exports.verifyLivenessConditionForRegisteredChains = verifyLivenessConditionForRegisteredChains; const getMainchainID = (chainID) => { const networkID = chainID.slice(0, 1); return Buffer.concat([networkID, Buffer.alloc(constants_1.CHAIN_ID_LENGTH - 1, 0)]); }; exports.getMainchainID = getMainchainID; const getTokenIDLSK = (chainID) => { const networkID = chainID.slice(0, 1); return Buffer.concat([networkID, Buffer.alloc(7, 0)]); }; exports.getTokenIDLSK = getTokenIDLSK; const getIDFromCCMBytes = (ccmBytes) => lisk_cryptography_1.utils.hash(ccmBytes); exports.getIDFromCCMBytes = getIDFromCCMBytes; const getEncodedCCMAndID = (ccm) => { const encodedCCM = lisk_codec_1.codec.encode(schemas_1.ccmSchema, ccm); return { encodedCCM, ccmID: (0, exports.getIDFromCCMBytes)(encodedCCM) }; }; exports.getEncodedCCMAndID = getEncodedCCMAndID; const getDecodedCCMAndID = (ccmBytes) => { const decodedCCM = lisk_codec_1.codec.decode(schemas_1.ccmSchema, ccmBytes); return { decodedCCM, ccmID: (0, exports.getIDFromCCMBytes)(ccmBytes), }; }; exports.getDecodedCCMAndID = getDecodedCCMAndID; const emptyActiveValidatorsUpdate = (value) => value.blsKeysUpdate.length === 0 && value.bftWeightsUpdate.length === 0 && value.bftWeightsUpdateBitmap.length === 0; exports.emptyActiveValidatorsUpdate = emptyActiveValidatorsUpdate; const calculateNewActiveValidators = (activeValidators, blskeysUpdate, bftWeightsUpdate, bftWeightsUpdateBitmap) => { const newValidators = blskeysUpdate.map(blsKey => ({ blsKey, bftWeight: BigInt(0), })); const newActiveValidators = [...activeValidators, ...newValidators]; newActiveValidators.sort((a, b) => a.blsKey.compare(b.blsKey)); const intBitmap = BigInt(`0x${bftWeightsUpdateBitmap.toString('hex')}`); let weightUsed = 0; for (let i = 0; i < newActiveValidators.length; i += 1) { if (((intBitmap >> BigInt(i)) & BigInt(1)) === BigInt(1)) { newActiveValidators[i].bftWeight = bftWeightsUpdate[weightUsed]; weightUsed += 1; } } if (weightUsed !== bftWeightsUpdate.length) { throw new Error('No BFT weights should be left.'); } return newActiveValidators.filter(v => v.bftWeight > BigInt(0)); }; exports.calculateNewActiveValidators = calculateNewActiveValidators; //# sourceMappingURL=utils.js.map