lisk-framework
Version:
Lisk blockchain application platform
134 lines • 6.62 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.SubmitMainchainCrossChainUpdateCommand = void 0;
const lisk_codec_1 = require("@liskhq/lisk-codec");
const state_machine_1 = require("../../../../state_machine");
const base_cross_chain_update_command_1 = require("../../base_cross_chain_update_command");
const constants_1 = require("../../constants");
const ccm_processed_1 = require("../../events/ccm_processed");
const schemas_1 = require("../../schemas");
const chain_account_1 = require("../../stores/chain_account");
const utils_1 = require("../../utils");
const panic_1 = require("../../../../utils/panic");
class SubmitMainchainCrossChainUpdateCommand extends base_cross_chain_update_command_1.BaseCrossChainUpdateCommand {
async verify(context) {
const { params } = context;
await this.verifyCommon(context, true);
const sendingChainAccount = (await this.stores
.get(chain_account_1.ChainAccountStore)
.getOrUndefined(context, params.sendingChainID));
if (sendingChainAccount.status === 0 &&
!(0, utils_1.isInboxUpdateEmpty)(params.inboxUpdate)) {
(0, utils_1.verifyLivenessConditionForRegisteredChains)(context.header.timestamp, context.params.certificate);
}
return {
status: state_machine_1.VerifyStatus.OK,
};
}
async execute(context) {
const { params } = context;
await this.verifyCertificateSignatureAndPartnerChainOutboxRoot(context);
const [decodedCCMs, ok] = await this.beforeCrossChainMessagesExecution(context, true);
if (!ok) {
return;
}
try {
context.contextStore.set(constants_1.CONTEXT_STORE_KEY_CCM_PROCESSING, true);
for (let i = 0; i < decodedCCMs.length; i += 1) {
const ccm = decodedCCMs[i];
const ccmBytes = params.inboxUpdate.crossChainMessages[i];
const ccmID = (0, utils_1.getIDFromCCMBytes)(ccmBytes);
const ccmContext = {
...context,
ccm,
eventQueue: context.eventQueue.getChildQueue(Buffer.concat([constants_1.EVENT_TOPIC_CCM_EXECUTION, ccmID])),
};
if (ccm.receivingChainID.equals((0, utils_1.getMainchainID)(context.chainID))) {
await this.apply(ccmContext);
}
else {
await this._forward(ccmContext);
}
await this.internalMethod.appendToInboxTree(context, params.sendingChainID, ccmBytes);
}
}
catch (error) {
(0, panic_1.panic)(context.logger, error);
}
finally {
context.contextStore.delete(constants_1.CONTEXT_STORE_KEY_CCM_PROCESSING);
}
await this.afterCrossChainMessagesExecute(context);
}
async _beforeCrossChainMessageForwarding(context, eventSnapshotID, stateSnapshotID) {
const { ccm, logger } = context;
const { ccmID } = (0, utils_1.getEncodedCCMAndID)(ccm);
try {
for (const [module, method] of this.interoperableCCMethods.entries()) {
if (method.beforeCrossChainMessageForwarding) {
logger.debug({
moduleName: module,
commandName: ccm.crossChainCommand,
ccmID: ccmID.toString('hex'),
}, 'Execute beforeCrossChainMessageForwarding');
await method.beforeCrossChainMessageForwarding(context);
}
}
}
catch (error) {
context.eventQueue.restoreSnapshot(eventSnapshotID);
context.stateStore.restoreSnapshot(stateSnapshotID);
logger.info({ err: error, moduleName: ccm.module, commandName: ccm.crossChainCommand }, 'Fail to execute beforeCrossChainMessageForwarding.');
await this.internalMethod.terminateChainInternal(context, ccm.sendingChainID);
this.events.get(ccm_processed_1.CcmProcessedEvent).log(context, ccm.sendingChainID, ccm.receivingChainID, {
code: 12,
result: 3,
ccm,
});
return false;
}
return true;
}
async _forward(context) {
const { ccm } = context;
const { ccmID, encodedCCM } = (0, utils_1.getEncodedCCMAndID)(ccm);
if (!(await this.verifyCCM(context, ccmID))) {
return;
}
let ccmFailed = false;
const chainAccountStore = this.stores.get(chain_account_1.ChainAccountStore);
const receivingChainAccount = await chainAccountStore.getOrUndefined(context, ccm.receivingChainID);
if (!receivingChainAccount || receivingChainAccount.status === 0) {
ccmFailed = true;
}
else {
const live = await this.internalMethod.isLive(context, ccm.receivingChainID, context.header.timestamp);
if (!live) {
ccmFailed = true;
await this.internalMethod.terminateChainInternal(context, ccm.receivingChainID);
await this.internalMethod.sendInternal(context, constants_1.EMPTY_FEE_ADDRESS, constants_1.MODULE_NAME_INTEROPERABILITY, constants_1.CROSS_CHAIN_COMMAND_SIDECHAIN_TERMINATED, ccm.sendingChainID, BigInt(0), 0, lisk_codec_1.codec.encode(schemas_1.sidechainTerminatedCCMParamsSchema, {
chainID: ccm.receivingChainID,
stateRoot: receivingChainAccount === null || receivingChainAccount === void 0 ? void 0 : receivingChainAccount.lastCertificate.stateRoot,
}));
}
}
const stateSnapshotID = context.stateStore.createSnapshot();
const eventSnapshotID = context.eventQueue.createSnapshot();
if (!(await this._beforeCrossChainMessageForwarding({ ...context, ccmFailed }, eventSnapshotID, stateSnapshotID))) {
return;
}
if (ccmFailed) {
await this.bounce(context, encodedCCM.length, 1, 1);
}
else {
await this.internalMethod.addToOutbox(context, ccm.receivingChainID, ccm);
this.events.get(ccm_processed_1.CcmProcessedEvent).log(context, ccm.sendingChainID, ccm.receivingChainID, {
code: 0,
result: 1,
ccm,
});
}
}
}
exports.SubmitMainchainCrossChainUpdateCommand = SubmitMainchainCrossChainUpdateCommand;
//# sourceMappingURL=submit_mainchain_cross_chain_update.js.map
;