UNPKG

lisk-framework

Version:

Lisk blockchain application platform

236 lines 12.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ValidatorsMethod = void 0; const lisk_cryptography_1 = require("@liskhq/lisk-cryptography"); const lisk_validator_1 = require("@liskhq/lisk-validator"); const base_method_1 = require("../base_method"); const constants_1 = require("./constants"); const generator_key_registration_1 = require("./events/generator_key_registration"); const validator_keys_1 = require("./stores/validator_keys"); const bls_keys_1 = require("./stores/bls_keys"); const bls_key_registration_1 = require("./events/bls_key_registration"); const validators_params_1 = require("./stores/validators_params"); class ValidatorsMethod extends base_method_1.BaseMethod { init(args) { this._blockTime = args.config.blockTime; } async registerValidatorKeys(methodContext, validatorAddress, blsKey, generatorKey, proofOfPossession) { this._validateLengths({ validatorAddress, blsKey, proofOfPossession }); const validatorAccount = { generatorKey, blsKey, }; lisk_validator_1.validator.validate(validator_keys_1.validatorKeysSchema, validatorAccount); const validatorsSubStore = this.stores.get(validator_keys_1.ValidatorKeysStore); const addressExists = await validatorsSubStore.has(methodContext, validatorAddress); if (addressExists) { this.events.get(generator_key_registration_1.GeneratorKeyRegistrationEvent).log(methodContext, validatorAddress, { generatorKey, result: 2, }); throw new Error('This address is already registered as validator.'); } const blsKeysSubStore = this.stores.get(bls_keys_1.BLSKeyStore); const blsKeyExists = await blsKeysSubStore.has(methodContext, blsKey); if (blsKeyExists) { this.events.get(bls_key_registration_1.BlsKeyRegistrationEvent).log(methodContext, validatorAddress, { blsKey, proofOfPossession, result: 3, }); throw new Error(`The BLS key ${blsKey.toString('hex')} has already been registered in the chain.`); } if (!lisk_cryptography_1.bls.popVerify(blsKey, proofOfPossession)) { this.events.get(bls_key_registration_1.BlsKeyRegistrationEvent).log(methodContext, validatorAddress, { blsKey, proofOfPossession, result: 4, }); throw new Error('Invalid proof of possession for the given BLS key.'); } await validatorsSubStore.set(methodContext, validatorAddress, validatorAccount); await blsKeysSubStore.set(methodContext, blsKey, { address: validatorAddress }); this.events .get(generator_key_registration_1.GeneratorKeyRegistrationEvent) .log(methodContext, validatorAddress, { generatorKey, result: 0 }); this.events.get(bls_key_registration_1.BlsKeyRegistrationEvent).log(methodContext, validatorAddress, { blsKey, proofOfPossession, result: 0, }); } async registerValidatorWithoutBLSKey(methodContext, validatorAddress, generatorKey) { this._validateLengths({ validatorAddress }); const validatorAccount = { generatorKey, blsKey: constants_1.INVALID_BLS_KEY, }; lisk_validator_1.validator.validate(validator_keys_1.validatorKeysSchema, validatorAccount); const validatorsSubStore = this.stores.get(validator_keys_1.ValidatorKeysStore); const addressExists = await validatorsSubStore.has(methodContext, validatorAddress); if (addressExists) { this.events.get(generator_key_registration_1.GeneratorKeyRegistrationEvent).log(methodContext, validatorAddress, { generatorKey, result: 2, }); throw new Error('This address is already registered as validator.'); } await validatorsSubStore.set(methodContext, validatorAddress, validatorAccount); this.events .get(generator_key_registration_1.GeneratorKeyRegistrationEvent) .log(methodContext, validatorAddress, { generatorKey, result: 0 }); return true; } async getAddressFromBLSKey(methodContext, blsKey) { this._validateLengths({ blsKey }); const blsKeysSubStore = this.stores.get(bls_keys_1.BLSKeyStore); const blsKeyExists = await blsKeysSubStore.has(methodContext, blsKey); if (!blsKeyExists) { throw new Error(`The BLS key ${blsKey.toString('hex')} has not been registered in the chain.`); } return blsKeysSubStore.get(methodContext, blsKey); } async getValidatorKeys(methodContext, address) { this._validateLengths({ validatorAddress: address }); const validatorsSubStore = this.stores.get(validator_keys_1.ValidatorKeysStore); const addressExists = await validatorsSubStore.has(methodContext, address); if (!addressExists) { throw new Error('No validator account found for the input address.'); } return validatorsSubStore.get(methodContext, address); } async setValidatorBLSKey(methodContext, validatorAddress, blsKey, proofOfPossession) { this._validateLengths({ validatorAddress, blsKey, proofOfPossession }); const validatorsSubStore = this.stores.get(validator_keys_1.ValidatorKeysStore); const addressExists = await validatorsSubStore.has(methodContext, validatorAddress); if (!addressExists) { this.events.get(bls_key_registration_1.BlsKeyRegistrationEvent).log(methodContext, validatorAddress, { blsKey, proofOfPossession, result: 1, }); throw new Error('This address is not registered as validator. Only validators can register a BLS key.'); } const blsKeysSubStore = this.stores.get(bls_keys_1.BLSKeyStore); const blsKeyExists = await blsKeysSubStore.has(methodContext, blsKey); if (blsKeyExists) { this.events.get(bls_key_registration_1.BlsKeyRegistrationEvent).log(methodContext, validatorAddress, { blsKey, proofOfPossession, result: 3, }); throw new Error(`The BLS key ${blsKey.toString('hex')} has already been registered in the chain.`); } const validatorAccount = await validatorsSubStore.get(methodContext, validatorAddress); if (!lisk_cryptography_1.bls.popVerify(blsKey, proofOfPossession)) { this.events.get(bls_key_registration_1.BlsKeyRegistrationEvent).log(methodContext, validatorAddress, { blsKey, proofOfPossession, result: 4, }); throw new Error('Invalid proof of possession for the given BLS key.'); } validatorAccount.blsKey = blsKey; await validatorsSubStore.set(methodContext, validatorAddress, validatorAccount); await blsKeysSubStore.set(methodContext, blsKey, { address: validatorAddress }); this.events.get(bls_key_registration_1.BlsKeyRegistrationEvent).log(methodContext, validatorAddress, { blsKey, proofOfPossession, result: 0, }); return true; } async setValidatorGeneratorKey(methodContext, validatorAddress, generatorKey) { this._validateLengths({ validatorAddress, generatorKey }); const validatorsSubStore = this.stores.get(validator_keys_1.ValidatorKeysStore); const addressExists = await validatorsSubStore.has(methodContext, validatorAddress); if (!addressExists) { this.events .get(generator_key_registration_1.GeneratorKeyRegistrationEvent) .log(methodContext, validatorAddress, { generatorKey, result: 1 }); throw new Error('This address is not registered as validator. Only validators can register a generator key.'); } const validatorAccount = await validatorsSubStore.get(methodContext, validatorAddress); validatorAccount.generatorKey = generatorKey; await validatorsSubStore.set(methodContext, validatorAddress, validatorAccount); this.events .get(generator_key_registration_1.GeneratorKeyRegistrationEvent) .log(methodContext, validatorAddress, { generatorKey, result: 0 }); return true; } async isKeyRegistered(methodContext, blsKey) { const blsKeysSubStore = this.stores.get(bls_keys_1.BLSKeyStore); return blsKeysSubStore.has(methodContext, blsKey); } async getGeneratorsBetweenTimestamps(methodContext, startTimestamp, endTimestamp) { if (endTimestamp < startTimestamp) { throw new Error('End timestamp must be greater than or equal to start timestamp.'); } const result = {}; const startSlotNumber = Math.floor(startTimestamp / this._blockTime) + 1; const endSlotNumber = Math.floor(endTimestamp / this._blockTime) - 1; if (startSlotNumber > endSlotNumber) { return {}; } let totalSlots = endSlotNumber - startSlotNumber + 1; const { validators } = await this.stores .get(validators_params_1.ValidatorsParamsStore) .get(methodContext, constants_1.EMPTY_KEY); const generatorAddresses = validators.map(validator => validator.address.toString('binary')); const baseSlots = Math.floor(totalSlots / generatorAddresses.length); if (baseSlots > 0) { totalSlots -= baseSlots * generatorAddresses.length; for (const generatorAddress of generatorAddresses) { result[generatorAddress] = baseSlots; } } for (let slotNumber = startSlotNumber; slotNumber < startSlotNumber + totalSlots; slotNumber += 1) { const slotIndex = slotNumber % generatorAddresses.length; const generatorAddress = generatorAddresses[slotIndex]; if (Object.prototype.hasOwnProperty.call(result, generatorAddress)) { result[generatorAddress] += 1; } else { result[generatorAddress] = 1; } } return result; } async getValidatorsParams(methodContext) { return this.stores.get(validators_params_1.ValidatorsParamsStore).get(methodContext, constants_1.EMPTY_KEY); } async setValidatorsParams(methodContext, validatorSetter, preCommitThreshold, certificateThreshold, validators) { const validatorsSubStore = this.stores.get(validator_keys_1.ValidatorKeysStore); const validatorsWithKey = []; for (const validator of validators) { const keys = await validatorsSubStore.get(methodContext, validator.address); validatorsWithKey.push({ ...validator, generatorKey: keys.generatorKey, blsKey: keys.blsKey, }); } await this.stores.get(validators_params_1.ValidatorsParamsStore).set(methodContext, constants_1.EMPTY_KEY, { certificateThreshold, preCommitThreshold, validators: validatorsWithKey, }); validatorSetter.setNextValidators(preCommitThreshold, certificateThreshold, validatorsWithKey); } _validateLengths(args) { if (args.validatorAddress && args.validatorAddress.length !== constants_1.ADDRESS_LENGTH) { throw new Error(`Validator address must be ${constants_1.ADDRESS_LENGTH} bytes long.`); } if (args.blsKey && args.blsKey.length !== constants_1.BLS_PUBLIC_KEY_LENGTH) { throw new Error(`BLS public key must be ${constants_1.BLS_PUBLIC_KEY_LENGTH} bytes long.`); } if (args.proofOfPossession && args.proofOfPossession.length !== constants_1.BLS_POP_LENGTH) { throw new Error(`Proof of possesion must be ${constants_1.BLS_POP_LENGTH} bytes long.`); } if (args.generatorKey && args.generatorKey.length !== constants_1.ED25519_PUBLIC_KEY_LENGTH) { throw new Error(`Generator key must be ${constants_1.ED25519_PUBLIC_KEY_LENGTH} bytes long.`); } } } exports.ValidatorsMethod = ValidatorsMethod; //# sourceMappingURL=method.js.map