ssv-keys
Version:
Tool for splitting a validator key into a predefined threshold of shares via Shamir-Secret-Sharing (SSS), and encrypt them with a set of operator keys.
97 lines • 3.98 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ThresholdInvalidOperatorIdError = exports.ThresholdInvalidOperatorsLengthError = void 0;
const tslib_1 = require("tslib");
const BLS_1 = tslib_1.__importDefault(require("../BLS"));
const base_1 = require("../exceptions/base");
const keystore_1 = require("../exceptions/keystore");
const validators_1 = require("../../commands/actions/validators");
class ThresholdInvalidOperatorsLengthError extends base_1.SSVKeysException {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
constructor(operators, message) {
super(message);
this.operators = operators;
}
}
exports.ThresholdInvalidOperatorsLengthError = ThresholdInvalidOperatorsLengthError;
class ThresholdInvalidOperatorIdError extends base_1.SSVKeysException {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
constructor(operator, message) {
super(message);
this.operator = operator;
}
}
exports.ThresholdInvalidOperatorIdError = ThresholdInvalidOperatorIdError;
/**
* Building threshold for list of operator IDs
*/
class Threshold {
constructor() {
this.shares = [];
}
static get DEFAULT_THRESHOLD_NUMBER() {
return 3;
}
/**
* Receives list of operators IDs.
* len(operator IDs) := 3 * F + 1
*
* If F calculated from this formula is not integer number - it will raise exception.
* Generate keys and return promise
*/
async create(privateKeyString, operatorIds) {
if (!privateKeyString.startsWith('0x')) {
throw new keystore_1.PrivateKeyFormatError(privateKeyString, 'The private key must be provided in the 0x format.');
}
// Validation
operatorIds.map(operatorId => {
if (!Number.isInteger(operatorId)) {
throw new ThresholdInvalidOperatorIdError(operatorId, `Operator must be integer. Got: ${operatorId}`);
}
});
if (!(0, validators_1.isOperatorsLengthValid)(operatorIds.length)) {
throw new ThresholdInvalidOperatorsLengthError(operatorIds, 'Invalid operators amount. Enter an 3f+1 compatible amount of operator ids.');
}
const msk = [];
const mpk = [];
if (!BLS_1.default.deserializeHexStrToSecretKey) {
await BLS_1.default.init(BLS_1.default.BLS12_381);
}
// Master key Polynomial
this.privateKey = BLS_1.default.deserializeHexStrToSecretKey(privateKeyString.replace('0x', ''));
this.publicKey = this.privateKey.getPublicKey();
msk.push(this.privateKey);
mpk.push(this.publicKey);
const F = (operatorIds.length - 1) / 3;
// Construct poly
for (let i = 1; i < operatorIds.length - F; i += 1) {
const sk = new BLS_1.default.SecretKey();
sk.setByCSPRNG();
msk.push(sk);
const pk = sk.getPublicKey();
mpk.push(pk);
}
// Evaluate shares - starting from 1 because 0 is master key
for (const operatorId of operatorIds) {
const id = new BLS_1.default.Id();
id.setInt(operatorId);
const shareSecretKey = new BLS_1.default.SecretKey();
shareSecretKey.share(msk, id);
const sharePublicKey = new BLS_1.default.PublicKey();
sharePublicKey.share(mpk, id);
this.shares.push({
privateKey: `0x${shareSecretKey.serializeToHexStr()}`,
publicKey: `0x${sharePublicKey.serializeToHexStr()}`,
id,
});
}
const response = {
privateKey: `0x${this.privateKey.serializeToHexStr()}`,
publicKey: `0x${this.publicKey.serializeToHexStr()}`,
shares: this.shares,
};
return response;
}
}
exports.default = Threshold;
//# sourceMappingURL=Threshold.js.map