Skip to content

Commit

Permalink
Merge pull request #1915 from IntersectMBO/fix/1894-drep-metdata-vali…
Browse files Browse the repository at this point in the history
…dation

fix(#1894) fix DRep Metadata validation
  • Loading branch information
MSzalowski authored Sep 3, 2024
2 parents 9f11a7b + eff5ba9 commit 1a36035
Show file tree
Hide file tree
Showing 19 changed files with 175 additions and 372 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ export const GovernanceActionDetailsCardData = ({
rationale={rationale}
/>
),
visible: !!abstract || !!motivation || !!rationale,
visible:
!isDataMissing && (!!abstract || !!motivation || !!rationale),
},
{
label: "Parameters",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
PROTOCOL_PARAMS_KEY,
} from "@utils";
import { useWalletErrorModal } from "@hooks";
import { MetadataStandard, MetadataValidationStatus } from "@models";
import { MetadataValidationStatus } from "@models";
import {
GovernanceActionFieldSchemas,
GovernanceActionType,
Expand Down Expand Up @@ -201,7 +201,6 @@ export const useCreateGovernanceActionForm = (
const { status } = await validateMetadata({
url: data.storingURL,
hash,
standard: MetadataStandard.CIP108,
});

if (status) {
Expand Down
3 changes: 1 addition & 2 deletions govtool/frontend/src/hooks/forms/useEditDRepInfoForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from "@consts";
import { useCardano, useModal, useAppContext } from "@context";
import { downloadJson, generateJsonld, generateMetadataBody } from "@utils";
import { MetadataStandard, MetadataValidationStatus } from "@models";
import { MetadataValidationStatus } from "@models";
import { useWalletErrorModal } from "@hooks";
import { DRepDataFormValues } from "@/types/dRep";
import { useValidateMutation } from "../mutations";
Expand Down Expand Up @@ -152,7 +152,6 @@ export const useEditDRepInfoForm = (
const { status } = await validateMetadata({
url,
hash,
standard: MetadataStandard.CIP119,
});

if (status) {
Expand Down
3 changes: 1 addition & 2 deletions govtool/frontend/src/hooks/forms/useRegisterAsdRepForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
storageInformationErrorModals,
} from "@consts";
import { useCardano, useModal, useAppContext } from "@context";
import { MetadataStandard, MetadataValidationStatus } from "@models";
import { MetadataValidationStatus } from "@models";
import {
downloadJson,
ellipsizeText,
Expand Down Expand Up @@ -191,7 +191,6 @@ export const useRegisterAsdRepForm = (
const { status } = await validateMetadata({
url: data.storingURL,
hash,
standard: MetadataStandard.CIP119,
});

if (status) {
Expand Down
8 changes: 1 addition & 7 deletions govtool/frontend/src/models/metadataValidation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@ export enum MetadataValidationStatus {
INCORRECT_FORMAT = "INCORRECT_FORMAT",
}

export enum MetadataStandard {
CIP108 = "CIP108",
CIP119 = "CIP119",
}

export type ValidateMetadataResult<MetadataType> = {
status?: MetadataValidationStatus;
valid: boolean;
Expand All @@ -20,7 +15,6 @@ export type ValidateMetadataResult<MetadataType> = {
export type MetadataValidationDTO = {
url: string;
hash: string;
standard?: MetadataStandard;
};

export type DRepMetadata = {
Expand All @@ -39,4 +33,4 @@ export type ProposalMetadata = {
rationale?: string;
references?: string[];
title?: string;
}
};
9 changes: 4 additions & 5 deletions govtool/frontend/src/utils/mapDtoToDrep.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DRepData, DRepMetadata, DrepDataDTO, MetadataStandard } from "@/models";
import { DRepData, DRepMetadata, DrepDataDTO } from "@/models";
import { postValidate } from "@/services";

export const mapDtoToDrep = async (dto: DrepDataDTO): Promise<DRepData> => {
Expand All @@ -17,10 +17,9 @@ export const mapDtoToDrep = async (dto: DrepDataDTO): Promise<DRepData> => {

if (dto.metadataHash && dto.url) {
const validationResponse = await postValidate<DRepMetadata>({
url: dto.url,
hash: dto.metadataHash,
standard: MetadataStandard.CIP119,
});
url: dto.url,
hash: dto.metadataHash,
});
return {
...dto,
...emptyMetadata,
Expand Down
31 changes: 16 additions & 15 deletions govtool/frontend/src/utils/mapDtoToProposal.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
import { MetadataStandard, ProposalData, ProposalDataDTO, ProposalMetadata } from "@/models";
import { ProposalData, ProposalDataDTO, ProposalMetadata } from "@/models";
import { postValidate } from "@/services";

export const mapDtoToProposal = async (dto: ProposalDataDTO): Promise<ProposalData> => {
export const mapDtoToProposal = async (
dto: ProposalDataDTO,
): Promise<ProposalData> => {
if (dto.url && dto.metadataHash) {
const validationResponse = await postValidate<ProposalMetadata>({
url: dto.url,
hash: dto.metadataHash,
standard: MetadataStandard.CIP108,
});

return {
...dto,
title: validationResponse.metadata?.title,
abstract: validationResponse.metadata?.abstract,
motivation: validationResponse.metadata?.motivation,
rationale: validationResponse.metadata?.rationale,
references: validationResponse.metadata?.references,
metadataStatus: validationResponse.status || null,
metadataValid: validationResponse.valid,
};
...dto,
title: validationResponse.metadata?.title,
abstract: validationResponse.metadata?.abstract,
motivation: validationResponse.metadata?.motivation,
rationale: validationResponse.metadata?.rationale,
references: validationResponse.metadata?.references,
metadataStatus: validationResponse.status || null,
metadataValid: validationResponse.valid,
};
}

return {
...dto,
metadataStatus: null,
metadataValid: true,
...dto,
metadataStatus: null,
metadataValid: true,
};
};
16 changes: 10 additions & 6 deletions govtool/metadata-validation/src/app.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ describe('AppService', () => {
it('should validate metadata correctly', async () => {
const url = 'http://example.com';
const hash = 'correctHash';
const standard = MetadataStandard.CIP108;
const validateMetadataDTO: ValidateMetadataDTO = { hash, url, standard };
const validateMetadataDTO: ValidateMetadataDTO = { hash, url };
const data = {
body: 'testBody',
headers: {},
Expand Down Expand Up @@ -65,8 +64,14 @@ describe('AppService', () => {
valid: true,
metadata: parsedMetadata,
});
expect(validateMetadataStandard).toHaveBeenCalledWith(data, standard);
expect(parseMetadata).toHaveBeenCalledWith(data.body, standard);
expect(validateMetadataStandard).toHaveBeenCalledWith(
data,
MetadataStandard.CIP108,
);
expect(parseMetadata).toHaveBeenCalledWith(
data.body,
MetadataStandard.CIP108,
);
});

it('should handle URL_NOT_FOUND error', async () => {
Expand All @@ -92,8 +97,7 @@ describe('AppService', () => {
it('should handle INVALID_HASH error', async () => {
const url = 'http://example.com';
const hash = 'incorrectHash';
const standard = MetadataStandard.CIP108;
const validateMetadataDTO: ValidateMetadataDTO = { hash, url, standard };
const validateMetadataDTO: ValidateMetadataDTO = { hash, url };
const data = {
body: 'testBody',
};
Expand Down
30 changes: 25 additions & 5 deletions govtool/metadata-validation/src/app.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import { catchError, firstValueFrom, timeout } from 'rxjs';
import { HttpService } from '@nestjs/axios';
import * as blake from 'blakejs';
import { AxiosRequestConfig } from 'axios';
import * as jsonld from 'jsonld';

import { ValidateMetadataDTO } from '@dto';
import { LoggerMessage, MetadataValidationStatus } from '@enums';
import { validateMetadataStandard, parseMetadata } from '@utils';
import { validateMetadataStandard, parseMetadata, getStandard } from '@utils';
import { ValidateMetadataResult } from '@types';

const axiosConfig: AxiosRequestConfig = {
Expand All @@ -22,7 +23,6 @@ export class AppService {
async validateMetadata({
hash,
url,
standard,
}: ValidateMetadataDTO): Promise<ValidateMetadataResult> {
let status: MetadataValidationStatus;
let metadata: Record<string, unknown>;
Expand All @@ -37,9 +37,15 @@ export class AppService {
),
);

if (!data?.body) {
throw MetadataValidationStatus.INCORRECT_FORMAT;
}

const standard = getStandard(data);

if (standard) {
await validateMetadataStandard(data, standard);
metadata = parseMetadata(data.body, standard);
await validateMetadataStandard(data.body, standard);
metadata = parseMetadata(data.body);
}

const hashedMetadata = blake.blake2bHex(
Expand All @@ -49,7 +55,21 @@ export class AppService {
);

if (hashedMetadata !== hash) {
throw MetadataValidationStatus.INVALID_HASH;
// Optional support for the canonized data hash
// Validate canonized data hash
const canonizedMetadata = await jsonld.canonize(data, {
safe: false,
});

const hashedCanonizedMetadata = blake.blake2bHex(
canonizedMetadata,
undefined,
32,
);

if (hashedCanonizedMetadata !== hash) {
throw MetadataValidationStatus.INVALID_HASH;
}
}
} catch (error) {
Logger.error(LoggerMessage.METADATA_VALIDATION_ERROR, error);
Expand Down
7 changes: 0 additions & 7 deletions govtool/metadata-validation/src/dto/validateMetadata.dto.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
import { IsEnum } from 'class-validator';

import { MetadataStandard } from '@types';

export class ValidateMetadataDTO {
hash: string;

url: string;

@IsEnum(MetadataStandard, { message: 'Invalid metadata standard' })
standard?: MetadataStandard;
}
Loading

0 comments on commit 1a36035

Please sign in to comment.