UNPKG

lisk-framework

Version:

Lisk blockchain application platform

209 lines 11.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SidechainInteroperabilityModule = void 0; const lisk_codec_1 = require("@liskhq/lisk-codec"); const lisk_validator_1 = require("@liskhq/lisk-validator"); const base_interoperability_module_1 = require("../base_interoperability_module"); const method_1 = require("./method"); const cc_method_1 = require("./cc_method"); const register_mainchain_1 = require("./commands/register_mainchain"); const endpoint_1 = require("./endpoint"); const schemas_1 = require("../schemas"); const chain_account_1 = require("../stores/chain_account"); const channel_data_1 = require("../stores/channel_data"); const own_chain_account_1 = require("../stores/own_chain_account"); const terminated_state_1 = require("../stores/terminated_state"); const terminated_outbox_1 = require("../stores/terminated_outbox"); const internal_method_1 = require("./internal_method"); const commands_1 = require("./commands"); const initialize_state_recovery_1 = require("./commands/initialize_state_recovery"); const recover_state_1 = require("./commands/recover_state"); const cc_commands_1 = require("./cc_commands"); const constants_1 = require("../constants"); const utils_1 = require("../utils"); const errors_1 = require("../errors"); class SidechainInteroperabilityModule extends base_interoperability_module_1.BaseInteroperabilityModule { constructor() { super(...arguments); this.crossChainMethod = new cc_method_1.SidechainCCMethod(this.stores, this.events); this.internalMethod = new internal_method_1.SidechainInteroperabilityInternalMethod(this.stores, this.events, this.interoperableCCMethods); this.method = new method_1.SidechainInteroperabilityMethod(this.stores, this.events, this.interoperableCCMethods, this.internalMethod); this.endpoint = new endpoint_1.SidechainInteroperabilityEndpoint(this.stores, this.offchainStores); this._mainchainRegistrationCommand = new register_mainchain_1.RegisterMainchainCommand(this.stores, this.events, this.interoperableCCMethods, this.interoperableCCCommands, this.internalMethod); this._crossChainUpdateCommand = new commands_1.SubmitSidechainCrossChainUpdateCommand(this.stores, this.events, this.interoperableCCMethods, this.interoperableCCCommands, this.internalMethod); this._stateRecoveryInitCommand = new initialize_state_recovery_1.InitializeStateRecoveryCommand(this.stores, this.events, this.interoperableCCMethods, this.interoperableCCCommands, this.internalMethod); this._stateRecoveryCommand = new recover_state_1.RecoverStateCommand(this.stores, this.events, this.interoperableCCMethods, this.interoperableCCCommands, this.internalMethod); this.commands = [ this._mainchainRegistrationCommand, this._crossChainUpdateCommand, this._stateRecoveryInitCommand, this._stateRecoveryCommand, ]; this.crossChainCommand = [ new cc_commands_1.SidechainCCRegistrationCommand(this.stores, this.events, this.interoperableCCMethods, this.internalMethod), new cc_commands_1.SidechainCCChannelTerminatedCommand(this.stores, this.events, this.interoperableCCMethods, this.internalMethod), ]; } addDependencies(validatorsMethod, tokenMethod) { this._validatorsMethod = validatorsMethod; this._crossChainUpdateCommand.init(this.method, tokenMethod); this.internalMethod.addDependencies(tokenMethod); this.tokenMethod = tokenMethod; } metadata() { return { ...this.baseMetadata(), endpoints: [ { name: this.endpoint.getChainAccount.name, request: schemas_1.getChainAccountRequestSchema, response: chain_account_1.chainDataSchema, }, { name: this.endpoint.getAllChainAccounts.name, request: schemas_1.getChainAccountRequestSchema, response: chain_account_1.allChainAccountsSchema, }, { name: this.endpoint.getChannel.name, request: schemas_1.getChannelRequestSchema, response: channel_data_1.channelSchema, }, { name: this.endpoint.getOwnChainAccount.name, response: own_chain_account_1.ownChainAccountSchema, }, { name: this.endpoint.getTerminatedStateAccount.name, request: schemas_1.getTerminatedStateAccountRequestSchema, response: terminated_state_1.terminatedStateSchema, }, { name: this.endpoint.getTerminatedOutboxAccount.name, request: schemas_1.getTerminatedOutboxAccountRequestSchema, response: terminated_outbox_1.terminatedOutboxSchema, }, { name: this.endpoint.getChainValidators.name, request: schemas_1.getChainValidatorsRequestSchema, response: schemas_1.getChainValidatorsResponseSchema, }, { name: this.endpoint.getMainchainID.name, request: schemas_1.getMainchainIDRequestSchema, response: schemas_1.getMainchainIDResponseSchema, }, { name: this.endpoint.getCCMSchema.name, response: schemas_1.getCCMSchemaResponseSchema, }, ], assets: [ { version: 0, data: schemas_1.genesisInteroperabilitySchema, }, ], stores: this.stores.values().map(v => ({ key: v.key.toString('hex'), data: v.schema, })), }; } async init(_args) { this._mainchainRegistrationCommand.addDependencies(this._validatorsMethod); } async initGenesisState(ctx) { const genesisBlockAssetBytes = ctx.assets.getAsset(constants_1.MODULE_NAME_INTEROPERABILITY); if (!genesisBlockAssetBytes) { return; } const genesisInteroperability = lisk_codec_1.codec.decode(schemas_1.genesisInteroperabilitySchema, genesisBlockAssetBytes); lisk_validator_1.validator.validate(schemas_1.genesisInteroperabilitySchema, genesisInteroperability); this._verifyChainInfos(ctx, genesisInteroperability); const { terminatedStateAccounts, terminatedOutboxAccounts } = genesisInteroperability; this._verifyTerminatedStateAccounts(ctx, terminatedStateAccounts, (0, utils_1.getMainchainID)(ctx.chainID)); if (terminatedOutboxAccounts.length !== 0) { throw new Error('terminatedOutboxAccounts must be empty.'); } await super.processGenesisState(ctx, genesisInteroperability); } _verifyChainInfos(ctx, genesisInteroperability) { const { ownChainName, ownChainNonce, chainInfos, terminatedStateAccounts } = genesisInteroperability; if (chainInfos.length === 0) { const ifChainInfosIsEmpty = 'if chainInfos is empty.'; if (ownChainName !== '') { throw new Error(`ownChainName must be empty string, ${ifChainInfosIsEmpty}.`); } if (ownChainNonce !== BigInt(0)) { throw new Error(`ownChainNonce must be 0, ${ifChainInfosIsEmpty}.`); } if (terminatedStateAccounts.length !== 0) { throw new Error(`terminatedStateAccounts must be empty, ${ifChainInfosIsEmpty}.`); } } else { if (ownChainName.length < constants_1.MIN_CHAIN_NAME_LENGTH || ownChainName.length > constants_1.MAX_CHAIN_NAME_LENGTH) { throw new Error(`ownChainName.length must be between ${constants_1.MIN_CHAIN_NAME_LENGTH} and ${constants_1.MAX_CHAIN_NAME_LENGTH}`); } if (!(0, utils_1.isValidName)(ownChainName)) { throw new errors_1.InvalidNameError('ownChainName'); } if (ownChainName === constants_1.CHAIN_NAME_MAINCHAIN) { throw new Error(`ownChainName must be not equal to ${constants_1.CHAIN_NAME_MAINCHAIN}.`); } if (ownChainNonce <= 0) { throw new Error('ownChainNonce must be > 0.'); } if (chainInfos.length !== 1) { throw new Error('chainInfos must contain exactly one entry.'); } const mainchainInfo = chainInfos[0]; const mainchainID = (0, utils_1.getMainchainID)(ctx.chainID); if (!mainchainInfo.chainID.equals(mainchainID)) { throw new Error(`mainchainInfo.chainID must be equal to ${mainchainID.toString('hex')}.`); } if (mainchainInfo.chainData.name !== constants_1.CHAIN_NAME_MAINCHAIN) { throw new Error(`chainData.name must be equal to ${constants_1.CHAIN_NAME_MAINCHAIN}.`); } const validStatuses = [0, 1]; if (!validStatuses.includes(mainchainInfo.chainData.status)) { throw new Error(`chainData.status must be one of ${validStatuses.join(', ')}.`); } if (mainchainInfo.chainData.lastCertificate.timestamp >= ctx.header.timestamp) { throw new Error('chainData.lastCertificate.timestamp must be < header.timestamp.'); } this._verifyChannelData(ctx, mainchainInfo); this._verifyChainValidators(mainchainInfo); } } _verifyTerminatedStateAccounts(ctx, terminatedStateAccounts, mainchainID) { this._verifyTerminatedStateAccountsIDs(terminatedStateAccounts.map(a => a.chainID)); for (const stateAccount of terminatedStateAccounts) { this._verifyChainID(stateAccount.chainID, mainchainID, 'stateAccount.'); if (stateAccount.chainID.equals(ctx.chainID)) { throw new Error(`stateAccount.chainID must not be equal to OWN_CHAIN_ID.`); } const { terminatedStateAccount } = stateAccount; if (terminatedStateAccount.initialized) { if (terminatedStateAccount.stateRoot.equals(constants_1.EMPTY_HASH)) { throw new Error(`stateAccount.stateRoot mst be not equal to "${constants_1.EMPTY_HASH.toString('hex')}", if initialized is true.`); } if (!terminatedStateAccount.mainchainStateRoot.equals(constants_1.EMPTY_HASH)) { throw new Error(`terminatedStateAccount.mainchainStateRoot must be equal to "${constants_1.EMPTY_HASH.toString('hex')}", if initialized is true`); } } else { if (!terminatedStateAccount.stateRoot.equals(constants_1.EMPTY_HASH)) { throw new Error(`stateAccount.stateRoot mst be equal to "${constants_1.EMPTY_HASH.toString('hex')}", if initialized is false.`); } if (terminatedStateAccount.mainchainStateRoot.equals(constants_1.EMPTY_HASH)) { throw new Error(`terminatedStateAccount.mainchainStateRoot must be not equal to "${constants_1.EMPTY_HASH.toString('hex')}", if initialized is false.`); } } } } } exports.SidechainInteroperabilityModule = SidechainInteroperabilityModule; //# sourceMappingURL=module.js.map