Skip to content

Commit

Permalink
feat: implement client specific query for client state and consensus …
Browse files Browse the repository at this point in the history
…state
  • Loading branch information
cuonglv-smartosc committed Apr 25, 2024
1 parent 45c4392 commit d0932e6
Show file tree
Hide file tree
Showing 12 changed files with 469 additions and 477 deletions.
32 changes: 32 additions & 0 deletions cardano/gateway/src/query/helpers/client.validate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { GrpcInvalidArgumentException } from 'nestjs-grpc-exceptions';
import { QueryClientStateRequest, QueryConsensusStateRequest } from '@plus/proto-types/src/ibc/core/client/v1/query';
import { CLIENT_ID_PREFIX } from '../../constant';

export function validQueryClientStateParam(request: QueryClientStateRequest): QueryClientStateRequest {
if (!request.client_id) throw new GrpcInvalidArgumentException('Invalid argument: "client_id" must be provided');
// validate prefix client id
if (!request.client_id.startsWith(`${CLIENT_ID_PREFIX}-`)) {
throw new GrpcInvalidArgumentException(
`Invalid argument: "client_id". Please use the prefix "${CLIENT_ID_PREFIX}-"`,
);
}

request.client_id = request.client_id.replace(`${CLIENT_ID_PREFIX}-`, '');
return request;
}

export function validQueryConsensusStateParam(request: QueryConsensusStateRequest): QueryConsensusStateRequest {
if (!request.client_id) throw new GrpcInvalidArgumentException('Invalid argument: "client_id" must be provided');
// validate prefix client id
if (!request.client_id.startsWith(`${CLIENT_ID_PREFIX}-`)) {
throw new GrpcInvalidArgumentException(
`Invalid argument: "client_id". Please use the prefix "${CLIENT_ID_PREFIX}-"`,
);
}
if (!request.height) {
throw new GrpcInvalidArgumentException('Invalid argument: "height" must be provided');
}

request.client_id = request.client_id.replace(`${CLIENT_ID_PREFIX}-`, '');
return request;
}
20 changes: 14 additions & 6 deletions cardano/gateway/src/query/services/query.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,11 @@ import {
normalizeTxsResultFromChannelRedeemer,
normalizeTxsResultFromModuleRedeemer,
} from '@shared/helpers/block-results';
import { ResponseDeliverTx, ResultBlockResults, ResultBlockSearch } from '@plus/proto-types/build/ibc/core/types/v1/block';
import {
ResponseDeliverTx,
ResultBlockResults,
ResultBlockSearch,
} from '@plus/proto-types/build/ibc/core/types/v1/block';
import { DbSyncService } from './db-sync.service';
import { ChannelDatum, decodeChannelDatum } from '@shared/types/channel/channel-datum';
import { getChannelIdByTokenName, getConnectionIdFromConnectionHops } from '@shared/helpers/channel';
Expand All @@ -86,6 +90,7 @@ import {
import { decodeIBCModuleRedeemer } from '../../shared/types/port/ibc_module_redeemer';
import { Packet } from '@shared/types/channel/packet';
import { decodeSpendClientRedeemer } from '@shared/types/client-redeemer';
import { validQueryClientStateParam, validQueryConsensusStateParam } from '../helpers/client.validate';

@Injectable()
export class QueryService {
Expand Down Expand Up @@ -204,26 +209,28 @@ export class QueryService {
return await createStateQueryClient(interactionContext);
}

private async getClientDatum(): Promise<[ClientDatum, UTxO]> {
private async getClientDatum(clientId: string): Promise<[ClientDatum, UTxO]> {
// Get handlerUTXO
const handlerAuthToken = this.configService.get('deployment').handlerAuthToken;
const handlerAuthTokenUnit = handlerAuthToken.policyId + handlerAuthToken.name;
const handlerUtxo = await this.lucidService.findUtxoByUnit(handlerAuthTokenUnit);
const handlerDatum = await decodeHandlerDatum(handlerUtxo.datum, this.lucidService.LucidImporter);

const clientAuthTokenUnit = this.lucidService.getClientAuthTokenUnit(handlerDatum);
const clientAuthTokenUnit = this.lucidService.getClientAuthTokenUnit(handlerDatum, BigInt(clientId));
const spendClientUTXO = await this.lucidService.findUtxoByUnit(clientAuthTokenUnit);

const clientDatum = await decodeClientDatum(spendClientUTXO.datum, this.lucidService.LucidImporter);
return [clientDatum, spendClientUTXO];
}

async queryClientState(request: QueryClientStateRequest): Promise<QueryClientStateResponse> {
this.logger.log(request.client_id, 'queryClientState');
const { client_id: clientId } = validQueryClientStateParam(request);
const { height } = request;
if (!height) {
throw new GrpcInvalidArgumentException('Invalid argument: "height" must be provided');
}
const [clientDatum, spendClientUTXO] = await this.getClientDatum();
const [clientDatum, spendClientUTXO] = await this.getClientDatum(clientId);
const clientStateTendermint = normalizeClientStateFromDatum(clientDatum.state.clientState);

const proofHeight = await this.dbService.findHeightByTxHash(spendClientUTXO.txHash);
Expand All @@ -245,8 +252,9 @@ export class QueryService {
}

async queryConsensusState(request: QueryConsensusStateRequest): Promise<QueryConsensusStateResponse> {
const [clientDatum, spendClientUTXO] = await this.getClientDatum();
const { height } = request;
this.logger.log(`client_id = ${request.client_id}, height = ${request.height}`, 'queryConsensusState');
const { client_id: clientId, height } = validQueryConsensusStateParam(request);
const [clientDatum, spendClientUTXO] = await this.getClientDatum(clientId);
if (!height) {
throw new GrpcInvalidArgumentException('Invalid argument: "height" must be provided');
}
Expand Down
4 changes: 2 additions & 2 deletions cardano/gateway/src/shared/helpers/consensus-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { bytesFromBase64 } from '@plus/proto-types/build/helpers';
import { ConsensusState } from '../types/consensus-state';
import { Height } from '../types/height';
import { toHex } from './hex';
import { GrpcInvalidArgumentException } from 'nestjs-grpc-exceptions';
import { GrpcInvalidArgumentException, GrpcNotFoundException } from 'nestjs-grpc-exceptions';

export function normalizeConsensusStateFromDatum(
consensusStateDatum: Map<Height, ConsensusState>,
Expand All @@ -18,7 +18,7 @@ export function normalizeConsensusStateFromDatum(
consensusState = consensusState_;
}
}
if (!consensusState) return undefined; // Return undefined if no matching entry is found
if (!consensusState) throw new GrpcNotFoundException(`Unable to find Consensus State at height ${requestHeight}`); // Return undefined if no matching entry is found
const consensus: ConsensusStateTendermint = {
timestamp: Timestamp.fromPartial({
seconds: BigInt(Math.round(Number(consensusState.timestamp) / 1e9)),
Expand Down
8 changes: 2 additions & 6 deletions cardano/gateway/src/shared/modules/lucid/lucid.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,15 +121,11 @@ export class LucidService {
public getChannelPolicyId(): string {
return this.configService.get('deployment').validators.mintChannel.scriptHash;
}
public getClientAuthTokenUnit(handlerDatum: HandlerDatum): string {
public getClientAuthTokenUnit(handlerDatum: HandlerDatum, clientId: bigint): string {
const mintClientPolicyId = this.configService.get('deployment').validators.mintClient.scriptHash;
// const encodedNextClientSequence = this.LucidImporter.Data.to(handlerDatum.state.next_client_sequence - 1n);
const baseToken = handlerDatum.token;
const clientStateTokenName = this.generateTokenName(
baseToken,
CLIENT_PREFIX,
handlerDatum.state.next_client_sequence - 1n,
);
const clientStateTokenName = this.generateTokenName(baseToken, CLIENT_PREFIX, clientId);
return mintClientPolicyId + clientStateTokenName;
}

Expand Down

0 comments on commit d0932e6

Please sign in to comment.