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

Commit

Permalink
🌱 Add new auxiliary functions
Browse files Browse the repository at this point in the history
  • Loading branch information
shuse2 committed Nov 4, 2022
1 parent 0ca0709 commit b83af81
Show file tree
Hide file tree
Showing 16 changed files with 535 additions and 164 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
CCMApplyContext,
TerminateChainContext,
CreateTerminatedStateAccountContext,
CrossChainUpdateTransactionParams,
} from './types';
import { getCCMSize, getIDAsKeyForStore } from './utils';
import {
Expand All @@ -54,6 +55,10 @@ import { TerminatedOutboxAccount, TerminatedOutboxStore } from './stores/termina
import { ChainAccountUpdatedEvent } from './events/chain_account_updated';
import { TerminatedStateCreatedEvent } from './events/terminated_state_created';
import { BaseInternalMethod } from '../BaseInternalMethod';
import { ChainValidatorsStore } from './stores/chain_validators';
import { MethodContext } from '../../state_machine';
import { certificateSchema } from '../../engine/consensus/certificate_generation/schema';
import { Certificate } from '../../engine/consensus/certificate_generation/types';

export abstract class BaseInteroperabilityInternalMethod extends BaseInternalMethod {
public readonly context: StoreGetter;
Expand Down Expand Up @@ -363,6 +368,40 @@ export abstract class BaseInteroperabilityInternalMethod extends BaseInternalMet
await ccCommand.execute(ccCommandExecuteContext);
}

public async updateValidators(
context: MethodContext,
ccu: CrossChainUpdateTransactionParams,
): Promise<void> {
await this.stores.get(ChainValidatorsStore).updateValidators(context, ccu.sendingChainID, {
activeValidators: ccu.activeValidatorsUpdate,
certificateThreshold: ccu.newCertificateThreshold,
});
}

public async updateCertificate(
context: MethodContext,
ccu: CrossChainUpdateTransactionParams,
): Promise<void> {
const certificate = codec.decode<Certificate>(certificateSchema, ccu.certificate);
const updatedAccountStore = await this.stores
.get(ChainAccountStore)
.updateLastCertificate(context, ccu.sendingChainID, certificate);
this.events.get(ChainAccountUpdatedEvent).log(context, ccu.sendingChainID, updatedAccountStore);
}

public async updatePartnerChainOutboxRoot(
context: MethodContext,
ccu: CrossChainUpdateTransactionParams,
): Promise<void> {
await this.stores
.get(ChannelDataStore)
.updatePartnerChainOutboxRoot(
context,
ccu.sendingChainID,
ccu.inboxUpdate.messageWitnessHashes,
);
}

// 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>;
Expand Down
20 changes: 5 additions & 15 deletions framework/src/modules/interoperability/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
MAX_CROSS_CHAIN_COMMAND_NAME_LENGTH,
} from './constants';
import { chainAccountSchema } from './stores/chain_account';
// eslint-disable-next-line import/no-cycle
import { chainValidatorsSchema } from './stores/chain_validators';
import { channelSchema } from './stores/channel_data';
import { outboxRootSchema } from './stores/outbox_root';
Expand Down Expand Up @@ -240,28 +241,17 @@ export const crossChainUpdateTransactionParams = {
inboxUpdate: {
type: 'object',
fieldNumber: 5,
required: ['crossChainMessages', 'messageWitness', 'outboxRootWitness'],
required: ['crossChainMessages', 'messageWitnessHashes', 'outboxRootWitness'],
properties: {
crossChainMessages: {
type: 'array',
fieldNumber: 1,
items: { dataType: 'bytes' },
},
messageWitness: {
type: 'object',
messageWitnessHashes: {
type: 'array',
fieldNumber: 2,
required: ['partnerChainOutboxSize', 'siblingHashes'],
properties: {
partnerChainOutboxSize: {
dataType: 'uint64',
fieldNumber: 1,
},
siblingHashes: {
type: 'array',
fieldNumber: 2,
items: { dataType: 'bytes' },
},
},
items: { dataType: 'bytes' },
},
outboxRootWitness: {
type: 'object',
Expand Down
25 changes: 20 additions & 5 deletions framework/src/modules/interoperability/stores/chain_account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@
* Removal or modification of this copyright notice is prohibited.
*/
import { utils } from '@liskhq/lisk-cryptography';
import { ModuleEndpointContext } from '../../../types';
import { BaseStore } from '../../base_store';
import { HASH_LENGTH } from '../constants';
import { MAX_UINT32 } from '../constants';
import { BaseStore, ImmutableStoreGetter, StoreGetter } from '../../base_store';
import { HASH_LENGTH, MAX_UINT32 } from '../constants';

export interface LastCertificate {
height: number;
Expand Down Expand Up @@ -101,7 +99,7 @@ export class ChainAccountStore extends BaseStore<ChainAccount> {
public schema = chainAccountSchema;

public async getAllAccounts(
context: ModuleEndpointContext,
context: ImmutableStoreGetter,
startChainID: Buffer,
): Promise<ChainAccount[]> {
const endBuf = utils.intToBuffer(MAX_UINT32, 4);
Expand All @@ -114,4 +112,21 @@ export class ChainAccountStore extends BaseStore<ChainAccount> {
chainAccounts.map(async chainAccount => this.get(context, chainAccount.key)),
);
}

public async updateLastCertificate(
context: StoreGetter,
chainID: Buffer,
certificate: LastCertificate,
): Promise<ChainAccount> {
const chainAccount = await this.get(context, chainID);
chainAccount.lastCertificate = {
height: certificate.height,
stateRoot: certificate.stateRoot,
timestamp: certificate.timestamp,
validatorsHash: certificate.validatorsHash,
};
await this.set(context, chainID, chainAccount);

return chainAccount;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@
*
* Removal or modification of this copyright notice is prohibited.
*/
import { BaseStore } from '../../base_store';
import { BaseStore, StoreGetter } from '../../base_store';
import { ActiveValidator } from '../types';
import { BLS_PUBLIC_KEY_LENGTH } from '../constants';
// TODO: Fix with #7742
// eslint-disable-next-line import/no-cycle
import { updateActiveValidators } from '../utils';

export interface ChainValidators {
activeValidators: ActiveValidator[];
Expand Down Expand Up @@ -55,4 +58,20 @@ export const chainValidatorsSchema = {

export class ChainValidatorsStore extends BaseStore<ChainValidators> {
public schema = chainValidatorsSchema;

public async updateValidators(
context: StoreGetter,
chainID: Buffer,
chainValidators: ChainValidators,
): Promise<void> {
const currentValidators = await this.get(context, chainID);

currentValidators.certificateThreshold = chainValidators.certificateThreshold;
currentValidators.activeValidators = updateActiveValidators(
currentValidators.activeValidators,
chainValidators.activeValidators,
);

await this.set(context, chainID, currentValidators);
}
}
21 changes: 20 additions & 1 deletion framework/src/modules/interoperability/stores/channel_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
*
* Removal or modification of this copyright notice is prohibited.
*/
import { BaseStore } from '../../base_store';
import { regularMerkleTree } from '@liskhq/lisk-tree';
import { BaseStore, StoreGetter } from '../../base_store';
import { HASH_LENGTH } from '../constants';
import { ChannelData } from '../types';
import { TOKEN_ID_LENGTH } from '../../token/constants';
Expand Down Expand Up @@ -73,4 +74,22 @@ export const channelSchema = {

export class ChannelDataStore extends BaseStore<ChannelData> {
public schema = channelSchema;

public async updatePartnerChainOutboxRoot(
context: StoreGetter,
chainID: Buffer,
messageWitnessHashes: Buffer[],
): Promise<void> {
const channel = await this.get(context, chainID);

const outboxRoot = regularMerkleTree.calculateRootFromRightWitness(
channel.inbox.size,
channel.inbox.appendPath,
messageWitnessHashes,
);

channel.partnerChainOutboxRoot = outboxRoot;

await this.set(context, chainID, channel);
}
}
7 changes: 1 addition & 6 deletions framework/src/modules/interoperability/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,14 @@ export interface ActiveValidatorJSON {
bftWeight: string;
}

export interface MsgWitness {
partnerChainOutboxSize: bigint;
siblingHashes: Buffer[];
}

export interface OutboxRootWitness {
bitmap: Buffer;
siblingHashes: Buffer[];
}

export interface InboxUpdate {
crossChainMessages: Buffer[];
messageWitness: MsgWitness;
messageWitnessHashes: Buffer[];
outboxRootWitness: OutboxRootWitness;
}

Expand Down
37 changes: 17 additions & 20 deletions framework/src/modules/interoperability/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import {
CrossChainUpdateTransactionParams,
ChainValidators,
InboxUpdate,
MsgWitness,
GenesisInteroperabilityInternalMethod,
} from './types';
import {
Expand All @@ -46,6 +45,7 @@ import {
HASH_LENGTH,
TOKEN_ID_LSK,
} from './constants';
// eslint-disable-next-line import/no-cycle
import {
ccmSchema,
genesisInteroperabilityInternalMethodSchema,
Expand All @@ -66,10 +66,14 @@ import { NamedRegistry } from '../named_registry';
import { OutboxRootStore } from './stores/outbox_root';
import { OwnChainAccountStore } from './stores/own_chain_account';
import { ChannelDataStore } from './stores/channel_data';
// TODO: Fix with #7742
// eslint-disable-next-line import/no-cycle
import { ChainValidatorsStore } from './stores/chain_validators';
import { ChainAccountStore } from './stores/chain_account';
import { TerminatedOutboxAccount, TerminatedOutboxStore } from './stores/terminated_outbox';
import { TerminatedStateStore } from './stores/terminated_state';
// TODO: Fix with #7742
// eslint-disable-next-line import/no-cycle
import { RegisteredNamesStore } from './stores/registered_names';
import { splitTokenID } from '../token/utils';

Expand Down Expand Up @@ -237,8 +241,7 @@ export const swapReceivingAndSendingChainIDs = (ccm: CCMsg) => ({

export const isInboxUpdateEmpty = (inboxUpdate: InboxUpdate) =>
inboxUpdate.crossChainMessages.length === 0 &&
inboxUpdate.messageWitness.siblingHashes.length === 0 &&
inboxUpdate.messageWitness.partnerChainOutboxSize === BigInt(0) &&
inboxUpdate.messageWitnessHashes.length === 0 &&
inboxUpdate.outboxRootWitness.siblingHashes.length === 0 &&
inboxUpdate.outboxRootWitness.bitmap.length === 0;

Expand All @@ -248,9 +251,6 @@ export const isCertificateEmpty = (decodedCertificate: Certificate) =>
decodedCertificate.validatorsHash.equals(EMPTY_BYTES) ||
decodedCertificate.timestamp === 0;

export const isMessageWitnessEmpty = (messageWitness: MsgWitness) =>
messageWitness.partnerChainOutboxSize === BigInt(0) && messageWitness.siblingHashes.length === 0;

export const checkLivenessRequirementFirstCCU = (
partnerChainAccount: ChainAccount,
txParams: CrossChainUpdateTransactionParams,
Expand Down Expand Up @@ -350,7 +350,7 @@ export const checkInboxUpdateValidity = (
};
}
const decodedCertificate = codec.decode<Certificate>(certificateSchema, txParams.certificate);
const { crossChainMessages, messageWitness, outboxRootWitness } = txParams.inboxUpdate;
const { crossChainMessages, messageWitnessHashes, outboxRootWitness } = txParams.inboxUpdate;
const ccmHashes = crossChainMessages.map(ccm => utils.hash(ccm));

let newInboxRoot;
Expand All @@ -368,12 +368,12 @@ export const checkInboxUpdateValidity = (
}
// non-empty certificate and an inboxUpdate
if (!isCertificateEmpty(decodedCertificate)) {
// If inboxUpdate contains a non-empty messageWitness, then update newInboxRoot to the output
if (!isMessageWitnessEmpty(txParams.inboxUpdate.messageWitness)) {
// If inboxUpdate contains a non-empty messageWitnessHashes, then update newInboxRoot to the output
if (txParams.inboxUpdate.messageWitnessHashes.length !== 0) {
newInboxRoot = regularMerkleTree.calculateRootFromRightWitness(
newInboxSize,
newInboxAppendPath,
messageWitness.siblingHashes,
messageWitnessHashes,
);
}
const outboxStore = stores.get(OutboxRootStore);
Expand All @@ -399,27 +399,27 @@ export const checkInboxUpdateValidity = (
return {
status: VerifyStatus.FAIL,
error: new Error(
'Failed at verifying state root when messageWitness and certificate are non-empty.',
'Failed at verifying state root when messageWitnessHashes and certificate are non-empty.',
),
};
}
}

// empty certificate and a non-empty inboxUpdate
if (isCertificateEmpty(decodedCertificate)) {
// If inboxUpdate contains a non-empty messageWitness, then update newInboxRoot to the output
if (!isMessageWitnessEmpty(txParams.inboxUpdate.messageWitness)) {
// If inboxUpdate contains a non-empty messageWitnessHashes, then update newInboxRoot to the output
if (txParams.inboxUpdate.messageWitnessHashes.length !== 0) {
newInboxRoot = regularMerkleTree.calculateRootFromRightWitness(
newInboxSize,
newInboxAppendPath,
messageWitness.siblingHashes,
messageWitnessHashes,
);
}
if (!(newInboxRoot as Buffer).equals(partnerChannelData.partnerChainOutboxRoot)) {
return {
status: VerifyStatus.FAIL,
error: new Error(
'Failed at verifying state root when messageWitness is non-empty and certificate is empty.',
'Failed at verifying state root when messageWitnessHashes is non-empty and certificate is empty.',
),
};
}
Expand Down Expand Up @@ -591,16 +591,13 @@ export const commonCCUExecutelogic = async (args: CommonExecutionLogicArgs) => {
const partnerChannelStore = stores.get(ChannelDataStore);
const partnerChannelData = await partnerChannelStore.get(context, chainIDBuffer);
const { inboxUpdate } = context.params;
if (
inboxUpdate.messageWitness.partnerChainOutboxSize === BigInt(0) ||
inboxUpdate.messageWitness.siblingHashes.length === 0
) {
if (inboxUpdate.messageWitnessHashes.length === 0) {
partnerChannelData.partnerChainOutboxRoot = partnerChannelData.inbox.root;
} else {
partnerChannelData.partnerChainOutboxRoot = regularMerkleTree.calculateRootFromRightWitness(
partnerChannelData.inbox.size,
partnerChannelData.inbox.appendPath,
inboxUpdate.messageWitness.siblingHashes,
inboxUpdate.messageWitnessHashes,
);
}
await partnerChannelStore.set(context, chainIDBuffer, partnerChannelData);
Expand Down
Loading

0 comments on commit b83af81

Please sign in to comment.