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

Commit

Permalink
Use max CCU size to collect CCM (#7872)
Browse files Browse the repository at this point in the history
### What was the problem?

This PR resolves #7458

### How was it solved?

Cross chain messages are now grouped into a collection < MAX_CCM_SIZE,
each group could be used to create a CCU

### How was it tested?
Test cases added
  • Loading branch information
ishantiw authored Jan 2, 2023
2 parents d42a371 + c0bf709 commit 41f33fd
Show file tree
Hide file tree
Showing 6 changed files with 240 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
MODULE_NAME_INTEROPERABILITY,
CCM_SEND_SUCCESS,
DB_KEY_SIDECHAIN,
CCU_TOTAL_CCM_SIZE,
} from './constants';
import { ChainConnectorStore, getDBInstance } from './db';
import { Endpoint } from './endpoint';
Expand All @@ -54,6 +55,7 @@ import {
InboxUpdate,
ProveResponse,
BlockHeader,
CrossChainMessagesFromEvents,
} from './types';
import { getActiveValidatorsDiff } from './utils';

Expand Down Expand Up @@ -427,13 +429,82 @@ export class ChainConnectorPlugin extends BasePlugin<ChainConnectorPluginConfig>
// When # of CCMs are there on the outbox to be sent or # of blocks passed from last certified height
if (this._ccuFrequency >= newBlockHeader.height - this._lastCertifiedHeight) {
// TODO: _createCCU needs to be implemented which will create and send the CCU transaction

// @ts-expect-error unused constant ccmsWithHeight
const ccmsWithHeight = await this._sidechainChainConnectorStore.getCrossChainMessages();

// TODO: update `certificate` after 7908 is merged
const certificate = {} as Certificate;

// @ts-expect-error unused constant groupedCCMsBySize
const groupedCCMsBySize = this._groupCCMsBySize(
await this._sidechainChainConnectorStore.getCrossChainMessages(),
certificate,
);
await this._createCCU();
// if the transaction is successfully submitted then update the last certfied height and do the cleanup
// TODO: also check if the state is growing, delete everything from the inMemory state if it goes beyond last 3 rounds
await this._cleanup();
}
}

/**
* This will return lists with sub-lists, where total size of CCMs in each sub-list will be <= CCU_TOTAL_CCM_SIZE
* Each sublist can contain CCMS from DIFFERENT heights
*/
private _groupCCMsBySize(
ccmsFromEvents: CrossChainMessagesFromEvents[],
certificate: Certificate,
): CCMsg[][] {
const groupedCCMsBySize: CCMsg[][] = [];

const filteredCCMsFromEvents = ccmsFromEvents.filter(
ccm => ccm.height <= certificate.height && ccm.height > this._lastCertifiedHeight,
);

if (filteredCCMsFromEvents.length === 0) {
return groupedCCMsBySize;
}

const allCCMs: CCMsg[] = [];
for (const filteredCCMsFromEvent of filteredCCMsFromEvents) {
allCCMs.push(...filteredCCMsFromEvent.ccms);
}

// This will group/bundle CCMs in a list where total size of the list will be <= CCU_TOTAL_CCM_SIZE
const groupBySize = (startIndex: number): [list: CCMsg[], newIndex: number] => {
const newList: CCMsg[] = [];
let totalSize = 0;
let i = startIndex;

for (; i < allCCMs.length; i += 1) {
const ccm = allCCMs[i];
const ccmBytes = codec.encode(ccmSchema, ccm);
const size = ccmBytes.length;
totalSize += size;
if (totalSize > CCU_TOTAL_CCM_SIZE) {
return [newList, i];
}

newList.push(ccm);
}

return [newList, i];
};

const buildGroupsBySize = (startIndex: number) => {
const [list, lastIndex] = groupBySize(startIndex);
groupedCCMsBySize.push(list);

if (lastIndex < allCCMs.length) {
buildGroupsBySize(lastIndex);
}
};

buildGroupsBySize(0);
return groupedCCMsBySize;
}

private async _getCertificateFromAggregateCommit(
aggregateCommit: AggregateCommit,
): Promise<Certificate> {
Expand Down Expand Up @@ -503,7 +574,7 @@ export class ChainConnectorPlugin extends BasePlugin<ChainConnectorPluginConfig>
private async _calculateInboxUpdate(sendingChainID: Buffer): Promise<InboxUpdate> {
// TODO: Fetch as many CCMs as configured in _ccuFrequency.ccm, between lastCertificateHeight and certificateHeight - After #7569
const crossChainMessages = await this._sidechainChainConnectorStore.getCrossChainMessages();
const serialzedCCMs = crossChainMessages.map(ccm => codec.encode(ccmSchema, ccm));
const serializedCCMs = crossChainMessages.map(ccm => codec.encode(ccmSchema, ccm));

// TODO: should use the store prefix with sendingChainID after issue https://github.com/LiskHQ/lisk-sdk/issues/7631
const outboxKey = sendingChainID;
Expand All @@ -517,7 +588,7 @@ export class ChainConnectorPlugin extends BasePlugin<ChainConnectorPluginConfig>
};

return {
crossChainMessages: serialzedCCMs,
crossChainMessages: serializedCCMs,
messageWitnessHashes: [],
outboxRootWitness: inclusionProofOutboxRoot,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
*
* Removal or modification of this copyright notice is prohibited.
*/

import { MAX_CCM_SIZE } from 'lisk-sdk';

// LIP: https://github.com/LiskHQ/lips/blob/main/proposals/lip-0045.md#liveness-condition
export const CCU_FREQUENCY = 864000; // Approximately 10 days which is 33% of 1 month liveness condition
export const EMPTY_BYTES = Buffer.alloc(0);
Expand All @@ -27,3 +30,13 @@ export const DB_KEY_CROSS_CHAIN_MESSAGES = Buffer.from([1]);
export const DB_KEY_BLOCK_HEADERS = Buffer.from([2]);
export const DB_KEY_AGGREGATE_COMMITS = Buffer.from([3]);
export const DB_KEY_VALIDATORS_HASH_PREIMAGE = Buffer.from([4]);

/**
* It’s not really MAX_CCU_SIZE, coz CCU includes other properties
* It’s more max size of a CCM to be included in a mainchain block
* MAX_CCM_SIZE
* Max size of total CCM which can be included in a CCU
* CCU_TOTAL_CCM_SIZE
*/
export const CCU_TOTAL_CCM_SIZE = MAX_CCM_SIZE;
Loading

0 comments on commit 41f33fd

Please sign in to comment.