lisk-framework
Version:
Lisk blockchain application platform
151 lines • 8.06 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AuthModule = void 0;
const lisk_utils_1 = require("@liskhq/lisk-utils");
const lisk_codec_1 = require("@liskhq/lisk-codec");
const lisk_validator_1 = require("@liskhq/lisk-validator");
const base_module_1 = require("../base_module");
const state_machine_1 = require("../../state_machine");
const method_1 = require("./method");
const constants_1 = require("./constants");
const endpoint_1 = require("./endpoint");
const schemas_1 = require("./schemas");
const utils_1 = require("./utils");
const auth_account_1 = require("./stores/auth_account");
const multisignature_registration_1 = require("./events/multisignature_registration");
const register_multisignature_1 = require("./commands/register_multisignature");
const invalid_signature_1 = require("./events/invalid_signature");
const errors_1 = require("./errors");
class AuthModule extends base_module_1.BaseModule {
constructor() {
super();
this.method = new method_1.AuthMethod(this.stores, this.events);
this.endpoint = new endpoint_1.AuthEndpoint(this.stores, this.offchainStores);
this.configSchema = schemas_1.configSchema;
this._registerMultisignatureCommand = new register_multisignature_1.RegisterMultisignatureCommand(this.stores, this.events);
this.commands = [this._registerMultisignatureCommand];
this.stores.register(auth_account_1.AuthAccountStore, new auth_account_1.AuthAccountStore(this.name, 0));
this.events.register(multisignature_registration_1.MultisignatureRegistrationEvent, new multisignature_registration_1.MultisignatureRegistrationEvent(this.name));
this.events.register(invalid_signature_1.InvalidSignatureEvent, new invalid_signature_1.InvalidSignatureEvent(this.name));
}
metadata() {
return {
...this.baseMetadata(),
endpoints: [
{
name: this.endpoint.getAuthAccount.name,
request: schemas_1.addressRequestSchema,
response: auth_account_1.authAccountSchema,
},
{
name: this.endpoint.isValidNonce.name,
request: schemas_1.transactionRequestSchema,
response: schemas_1.verifyResultSchema,
},
{
name: this.endpoint.isValidSignature.name,
request: schemas_1.transactionRequestSchema,
response: schemas_1.verifyResultSchema,
},
{
name: this.endpoint.getMultiSigRegMsgSchema.name,
response: schemas_1.multisigRegMsgSchema,
},
{
name: this.endpoint.sortMultisignatureGroup.name,
request: schemas_1.sortMultisignatureGroupRequestSchema,
response: schemas_1.sortMultisignatureGroupResponseSchema,
},
{
name: this.endpoint.getMultiSigRegMsgTag.name,
response: schemas_1.multiSigRegMsgTagSchema,
},
],
assets: [
{
version: 0,
data: schemas_1.genesisAuthStoreSchema,
},
],
};
}
async init(args) {
const { moduleConfig } = args;
const config = lisk_utils_1.objects.mergeDeep({}, constants_1.defaultConfig, moduleConfig);
lisk_validator_1.validator.validate(schemas_1.configSchema, config);
this._moduleConfig = { maxNumberOfSignatures: config.maxNumberOfSignatures };
this._registerMultisignatureCommand.init({
maxNumberOfSignatures: config.maxNumberOfSignatures,
});
}
async initGenesisState(context) {
const assetBytes = context.assets.getAsset(this.name);
if (!assetBytes) {
return;
}
const genesisStore = lisk_codec_1.codec.decode(schemas_1.genesisAuthStoreSchema, assetBytes);
const store = this.stores.get(auth_account_1.AuthAccountStore);
const keys = [];
for (const { address, authAccount } of genesisStore.authDataSubstore) {
if (address.length !== constants_1.ADDRESS_LENGTH) {
throw new Error('Invalid store key length for auth module.');
}
keys.push(address);
lisk_validator_1.validator.validate(auth_account_1.authAccountSchema, authAccount);
const { mandatoryKeys, optionalKeys, numberOfSignatures } = authAccount;
if (!lisk_utils_1.objects.isBufferArrayOrdered(mandatoryKeys)) {
throw new Error('Invalid store value for auth module. MandatoryKeys are not sorted lexicographically.');
}
if (!lisk_utils_1.objects.bufferArrayUniqueItems(mandatoryKeys)) {
throw new Error('Invalid store value for auth module. MandatoryKeys are not unique.');
}
if (!lisk_utils_1.objects.isBufferArrayOrdered(optionalKeys)) {
throw new Error('Invalid store value for auth module. OptionalKeys are not sorted lexicographically.');
}
if (!lisk_utils_1.objects.bufferArrayUniqueItems(optionalKeys)) {
throw new Error('Invalid store value for auth module. OptionalKeys are not unique.');
}
if (mandatoryKeys.length + optionalKeys.length > this._moduleConfig.maxNumberOfSignatures) {
throw new Error(`The count of Mandatory and Optional keys should be maximum ${this._moduleConfig.maxNumberOfSignatures}.`);
}
const repeatedKeys = mandatoryKeys.filter(value => optionalKeys.find(optional => optional.equals(value)) !== undefined);
if (repeatedKeys.length > 0) {
throw new Error('Invalid combination of Mandatory and Optional keys. Repeated keys across Mandatory and Optional were found.');
}
if (mandatoryKeys.length + optionalKeys.length < numberOfSignatures) {
throw new Error('The numberOfSignatures is bigger than the count of Mandatory and Optional keys.');
}
if (mandatoryKeys.length > numberOfSignatures) {
throw new Error('The numberOfSignatures is smaller than the count of Mandatory keys.');
}
await store.set(context, address, authAccount);
}
if (!lisk_utils_1.objects.bufferArrayUniqueItems(keys)) {
throw new Error('Duplicate address in the for auth module.');
}
}
async verifyTransaction(context) {
const { transaction, chainID } = context;
const authAccountStore = this.stores.get(auth_account_1.AuthAccountStore);
const senderAccount = await authAccountStore.getOrDefault(context, transaction.senderAddress);
const nonceStatus = (0, utils_1.verifyNonce)(transaction, senderAccount);
if (nonceStatus.status === state_machine_1.VerifyStatus.FAIL) {
throw new errors_1.InvalidNonceError(`Transaction with id:${transaction.id.toString('hex')} nonce is lower than account nonce.`, transaction.nonce, senderAccount.nonce);
}
(0, utils_1.verifySignatures)(transaction, chainID, senderAccount);
return nonceStatus;
}
async beforeCommandExecute(context) {
const { transaction } = context;
const authAccountStore = this.stores.get(auth_account_1.AuthAccountStore);
const senderAccount = await authAccountStore.getOrDefault(context, transaction.senderAddress);
await authAccountStore.set(context, transaction.senderAddress, {
nonce: senderAccount.nonce + BigInt(1),
numberOfSignatures: senderAccount.numberOfSignatures,
mandatoryKeys: senderAccount.mandatoryKeys,
optionalKeys: senderAccount.optionalKeys,
});
}
}
exports.AuthModule = AuthModule;
//# sourceMappingURL=module.js.map