fix: improve error handling for forbidden countries list mismatch (#494)

* Update SelfBackendVerifier.ts

* Update constants.ts

* Update formatInputs.ts

* Update formatCallData.ts
This commit is contained in:
crStiv
2025-04-18 16:18:06 +03:00
committed by GitHub
parent 91d86b6fdb
commit 28ec407e49
4 changed files with 77 additions and 3 deletions

View File

@@ -31,6 +31,12 @@ export const DEFAULT_MAJORITY = '18';
export const hashAlgos = ['sha512', 'sha384', 'sha256', 'sha224', 'sha1'];
export const saltLengths = [64, 48, 32];
/**
* Maximum number of countries in the forbidden countries list.
*
* IMPORTANT: This value must match in both backend and frontend SDK.
* Any mismatch will result in an INVALID_FORBIDDEN_COUNTRIES error.
*/
export const MAX_FORBIDDEN_COUNTRIES_LIST_LENGTH = 40;
export const DEPLOYED_CIRCUITS_REGISTER = [

View File

@@ -1,9 +1,39 @@
import { MAX_FORBIDDEN_COUNTRIES_LIST_LENGTH } from "../../constants/constants";
import { commonNames } from "../../constants/countries";
/**
* Formats the list of country codes for use in verification circuits.
* Important: this list must exactly match the list in the backend.
*
* @param countries Array of three-letter country codes
* @returns Formatted byte array representing country codes
* @throws Error if the maximum list length is exceeded or if country codes are invalid
*/
export function formatCountriesList(countries: string[]) {
// Check maximum list length
if (countries.length > MAX_FORBIDDEN_COUNTRIES_LIST_LENGTH) {
throw new Error(`Countries list must be inferior or equals to ${MAX_FORBIDDEN_COUNTRIES_LIST_LENGTH}`);
}
// Validate country codes
for (const country of countries) {
if (!country || country.length !== 3) {
throw new Error(`Invalid country code: "${country}". Country codes must be exactly 3 characters long.`);
}
// Optional check for the country code existence in the list of valid codes
// This code can be uncommented if strict validation of country codes is needed
/*
const isValidCountry = Object.values(commonNames).some(
name => name === country || country in commonNames
);
if (!isValidCountry) {
throw new Error(`Unknown country code: "${country}". Please use valid 3-letter ISO country codes.`);
}
*/
}
const paddedCountries = countries.concat(Array(MAX_FORBIDDEN_COUNTRIES_LIST_LENGTH - countries.length).fill(''));
const result = paddedCountries.flatMap((country) => {
const chars = country
@@ -37,4 +67,4 @@ export function reverseCountryBytes(input: string): string {
}
return '0x' + reversedGroups.join('') + remainder;
}
}

View File

@@ -46,6 +46,13 @@ export function packForbiddenCountriesList(forbiddenCountries: string[]): string
const REQUIRED_CHUNKS = 4;
const bytes: number[] = [];
// Validate all country codes (3 characters)
for (const country of forbiddenCountries) {
if (!country || country.length !== 3) {
throw new Error(`Invalid country code: "${country}". Country codes must be exactly 3 characters long.`);
}
}
// Convert countries to bytes
for (const country of forbiddenCountries) {
const countryCode = country.padEnd(3, ' ').slice(0, 3);

View File

@@ -138,7 +138,13 @@ export class SelfBackendVerifier {
let result: any;
try {
result = await this.verifyAllContract.verifyAll(timestamp, vcAndDiscloseHubProof, types);
} catch (error) {
} catch (error: any) {
let errorMessage = error instanceof Error ? error.message : 'Unknown error';
if (error && typeof error === 'object' && error.message && error.message.includes('INVALID_FORBIDDEN_COUNTRIES')) {
errorMessage = 'The forbidden countries list in the backend does not match the list provided in the frontend SDK. Please ensure both lists are identical.';
}
return {
isValid: false,
isValidDetails: {
@@ -157,7 +163,7 @@ export class SelfBackendVerifier {
publicSignals: publicSignals,
},
},
error: error,
error: errorMessage,
};
}
@@ -224,10 +230,35 @@ export class SelfBackendVerifier {
return this;
}
/**
* Sets the list of countries to be excluded in the verification.
* This list must exactly match the list configured in the backend.
*
* @param countries Array of 3-letter country codes to exclude
* @returns This instance for method chaining
* @throws Error if more than 40 countries are provided or if any country code is invalid
*/
excludeCountries(...countries: Country3LetterCode[]): this {
if (countries.length > 40) {
throw new Error('Number of excluded countries cannot exceed 40');
}
// Validate country codes
for (const country of countries) {
if (!country || country.length !== 3) {
throw new Error(`Invalid country code: "${country}". Country codes must be exactly 3 characters long.`);
}
// Check if the country code exists in the list of valid codes (additional check)
const isValidCountry = Object.values(commonNames).some(
name => name === country || country in commonNames
);
if (!isValidCountry) {
throw new Error(`Unknown country code: "${country}". Please use valid 3-letter ISO country codes.`);
}
}
this.excludedCountries = { enabled: true, value: countries };
return this;
}