Skip to content
This repository has been archived by the owner on Jun 11, 2024. It is now read-only.

Commit

Permalink
Merge pull request #7095 from LiskHQ/7044_terminate_internal
Browse files Browse the repository at this point in the history
Implement `terminateChainInternal` - Closes #7044
  • Loading branch information
mitsuaki-u authored Apr 1, 2022
2 parents 8bcece9 + 92e24f6 commit 9e18d6e
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import { hash } from '@liskhq/lisk-cryptography';
import { regularMerkleTree } from '@liskhq/lisk-tree';
import { SubStore } from '../../node/state_machine/types';
import {
CROSS_CHAIN_COMMAND_ID_CHANNEL_TERMINATED,
CCM_STATUS_OK,
EMPTY_BYTES,
MODULE_ID_INTEROPERABILITY,
STORE_PREFIX_CHAIN_DATA,
STORE_PREFIX_TERMINATED_STATE,
Expand All @@ -38,6 +41,7 @@ import {
} from './schema';
import { BaseInteroperableModule } from './base_interoperable_module';
import {
BeforeSendCCMsgAPIContext,
ChannelData,
CCMsg,
CCUpdateParams,
Expand Down Expand Up @@ -136,7 +140,7 @@ export abstract class BaseInteroperabilityStore {
return chainSubstore.getWithSchema<ChainAccount>(chainID, chainAccountSchema);
}

public async chainAccountExist(chainID: Buffer): Promise<Boolean> {
public async chainAccountExist(chainID: Buffer): Promise<boolean> {
const chainSubstore = this.getStore(MODULE_ID_INTEROPERABILITY, STORE_PREFIX_CHAIN_DATA);
try {
await chainSubstore.getWithSchema<ChainAccount>(chainID, chainAccountSchema);
Expand Down Expand Up @@ -181,14 +185,39 @@ export abstract class BaseInteroperabilityStore {
await terminatedOutboxSubstore.setWithSchema(chainID, terminatedOutbox, terminatedOutboxSchema);
}

public async terminateChainInternal(
chainID: number,
beforeSendContext: BeforeSendCCMsgAPIContext,
): Promise<boolean> {
const messageSent = await this.sendInternal({
moduleID: MODULE_ID_INTEROPERABILITY,
crossChainCommandID: CROSS_CHAIN_COMMAND_ID_CHANNEL_TERMINATED,
receivingChainID: chainID,
fee: BigInt(0),
status: CCM_STATUS_OK,
params: EMPTY_BYTES,
timestamp: Date.now(),
beforeSendContext,
});

if (!messageSent) {
return false;
}

return this.createTerminatedStateAccount(chainID);
}

// Different in mainchain and sidechain so to be implemented in each module store separately
public abstract isLive(chainID: Buffer, timestamp?: number): Promise<boolean>;
public abstract sendInternal(sendContext: SendInternalContext): Promise<boolean>;

// To be implemented in base class
public abstract apply(ccu: CCUpdateParams, ccm: CCMsg): Promise<void>;
public abstract terminateChainInternal(chainID: number): Promise<void>;
public abstract createTerminatedStateAccount(chainID: Buffer, stateRoot?: Buffer): Promise<void>;

public abstract createTerminatedStateAccount(
chainID: number,
stateRoot?: Buffer,
): Promise<boolean>;
public abstract getInboxRoot(chainID: number): Promise<void>;
public abstract getOutboxRoot(chainID: number): Promise<void>;
public abstract getChannel(chainID: number): Promise<void>; // TODO: Update to Promise<ChannelData> after implementation
Expand Down
6 changes: 6 additions & 0 deletions framework/src/modules/interoperability/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export const MODULE_NAME_INTEROPERABILITY = 'interoperability';
export const MAINCHAIN_ID = 1;
export const LIVENESS_LIMIT = 2592000; // 30*24*3600
export const MAX_CCM_SIZE = 10240;
export const EMPTY_FEE_ADDRESS = Buffer.alloc(0);
export const EMPTY_BYTES = Buffer.alloc(0);

// Store prefixes
export const STORE_PREFIX_OUTBOX_ROOT = 0x0000;
Expand All @@ -35,3 +37,7 @@ export const STORE_PREFIX_REGISTERED_NETWORK_IDS = 0xf000;
export const CHAIN_REGISTERED = 0;
export const CHAIN_ACTIVE = 1;
export const CHAIN_TERMINATED = 2;

// Cross chain commands
export const CROSS_CHAIN_COMMAND_ID_CHANNEL_TERMINATED = 1;
export const CCM_STATUS_OK = 0;
9 changes: 3 additions & 6 deletions framework/src/modules/interoperability/mainchain/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,12 @@ export class MainchainInteroperabilityStore extends BaseInteroperabilityStore {
}

// eslint-disable-next-line @typescript-eslint/require-await
public async createTerminatedStateAccount(chainID: Buffer, stateRoot?: Buffer): Promise<void> {
public async createTerminatedStateAccount(chainID: number, stateRoot?: Buffer): Promise<boolean> {
// eslint-disable-next-line no-console
console.log(chainID, stateRoot);
}

// eslint-disable-next-line @typescript-eslint/require-await
public async terminateChainInternal(chainID: number): Promise<void> {
// eslint-disable-next-line no-console
console.log(chainID);
// TODO: Update after implementation
return true;
}

// eslint-disable-next-line @typescript-eslint/require-await
Expand Down
9 changes: 3 additions & 6 deletions framework/src/modules/interoperability/sidechain/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,12 @@ export class SidechainInteroperabilityStore extends BaseInteroperabilityStore {
}

// eslint-disable-next-line @typescript-eslint/require-await
public async createTerminatedStateAccount(chainID: Buffer, stateRoot?: Buffer): Promise<void> {
public async createTerminatedStateAccount(chainID: number, stateRoot?: Buffer): Promise<boolean> {
// eslint-disable-next-line no-console
console.log(chainID, stateRoot);
}

// eslint-disable-next-line @typescript-eslint/require-await
public async terminateChainInternal(chainID: number): Promise<void> {
// eslint-disable-next-line no-console
console.log(chainID);
// TODO: Update after implementation
return true;
}

// eslint-disable-next-line @typescript-eslint/require-await
Expand Down
62 changes: 62 additions & 0 deletions framework/test/unit/modules/interoperability/store.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* Removal or modification of this copyright notice is prohibited.
*/

import { getRandomBytes } from '@liskhq/lisk-cryptography';
import { regularMerkleTree } from '@liskhq/lisk-tree';
import { when } from 'jest-when';
import {
Expand All @@ -26,6 +27,7 @@ import {
outboxRootSchema,
terminatedOutboxSchema,
} from '../../../../src/modules/interoperability/schema';
import { testing } from '../../../../src';

describe('Base interoperability store', () => {
const chainID = Buffer.from('01', 'hex');
Expand Down Expand Up @@ -188,4 +190,64 @@ describe('Base interoperability store', () => {
);
});
});

describe('terminateChainInternal', () => {
const SIDECHAIN_ID = 2;
const ccm = {
nonce: BigInt(0),
moduleID: 1,
crossChainCommandID: 1,
sendingChainID: 2,
receivingChainID: 3,
fee: BigInt(1),
status: 1,
params: Buffer.alloc(0),
};
const beforeSendCCMContext = testing.createBeforeSendCCMsgAPIContext({
ccm,
feeAddress: getRandomBytes(32),
});

beforeEach(() => {
mainchainInteroperabilityStore.sendInternal = jest.fn().mockResolvedValue(true);
mainchainInteroperabilityStore.createTerminatedStateAccount = jest
.fn()
.mockResolvedValue(true);
});

it('should return true if sendInternal and createTerminatedStateAccount return true', async () => {
expect(
await mainchainInteroperabilityStore.terminateChainInternal(
SIDECHAIN_ID,
beforeSendCCMContext,
),
).toBe(true);
});

it('should return false if sendInternal returns false', async () => {
// Arrange
mainchainInteroperabilityStore.sendInternal = jest.fn().mockResolvedValue(false);

expect(
await mainchainInteroperabilityStore.terminateChainInternal(
SIDECHAIN_ID,
beforeSendCCMContext,
),
).toBe(false);
});

it('should return false if createTerminatedStateAccount returns false', async () => {
// Arrange
mainchainInteroperabilityStore.createTerminatedStateAccount = jest
.fn()
.mockResolvedValue(false);

expect(
await mainchainInteroperabilityStore.terminateChainInternal(
SIDECHAIN_ID,
beforeSendCCMContext,
),
).toBe(false);
});
});
});

0 comments on commit 9e18d6e

Please sign in to comment.