Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate reserved parameters #1574

Open
aTeoke opened this issue Dec 1, 2022 · 3 comments
Open

Validate reserved parameters #1574

aTeoke opened this issue Dec 1, 2022 · 3 comments

Comments

@aTeoke
Copy link

aTeoke commented Dec 1, 2022

Context: #620 (comment) and see the discussion below the ticket (some comments are outdated though). See the documentation for reserved parameters: https://docs.api3.org/ois/v1.0.0/reserved-parameters.html#type

We should verify that the reserved parameters configuration is valid. This means:

  • Ensure the “_type“ is supported (e.g. prevent mistake like “unit256” instead of “uint256“) , “_times“ is a valid number and “_path“ is a valid path
  • The validation needs to support multiple parameters
  • The validation is currently performed at run time in and validation of the values from config.json should be moved to validator
@aTeoke
Copy link
Author

aTeoke commented Dec 1, 2022

Comments:
Burak Benligiray
2 June 2022 at 12:38
Could be removed from 0.7.0 similar to the other new OIS validation rules

Emanuel Tesař
14 February 2022 at 13:21
Removed from 0.6 as it’s blocked by the validator being refactored.

Emanuel Tesař
5 January 2022 at 13:56
Edited
Not really specific to _type . The problem with validator is that it’s difficult (or impossible) to validate some values (e.g. the _type) - because the validation is really specific/dynamic. If you would like to validator to be able to do it, you would be basically creating a new programming language, which is a bit how validator works now.

I’d argue that it might be easier/maintainable to implement some checks directly in TypeScript as part of validator logic. I could also imagine validator being completely rewritten to TS.

Burak Benligiray
5 January 2022 at 12:24
Is this strictly for validating _type? Note that we encountered a similar issue in Function signature doesn't get verified · Issue #263 · api3dao/api3-dao-dashboard

Emanuel Tesař
16 November 2021 at 09:25

I did some research and GitHub - colinhacks/zod: TypeScript-first schema validation with static type inference is exactly what we want - it allows us to easily build composable validations which in turn parse the unknown input (user defined config.json) and returns TypeSafe parse result.

The most useful thing (and the purpose of this ticket) is refine function GitHub - colinhacks/zod: TypeScript-first schema validation with static type inference function in which we can implement arbitrary business logic validation.

@dcroote
Copy link
Contributor

dcroote commented Dec 1, 2022

Partially overlaps with: api3dao/ois#15

@dcroote
Copy link
Contributor

dcroote commented Dec 11, 2022

Currently some checking happens in airnode-adapter as shown below, but more comprehensive validation should happen upfront in https://github.com/api3dao/ois.

export function splitReservedParameters(parameters: ReservedParameters): ReservedParameters[] {
const splitByDelimeter = (name: keyof ReservedParameters) => {
return {
name,
splitResult: parameters[name] ? escapeAwareSplit(parameters[name]!, MULTIPLE_PARAMETERS_DELIMETER) : undefined,
};
};
const types = splitByDelimeter('_type');
const paths = splitByDelimeter('_path');
const timeses = splitByDelimeter('_times');
// Check that all of the parsed arrays have the same length or are undefined
const splitParams = [types, paths, timeses] as const;
const typesLength = types.splitResult!.length;
splitParams.forEach((split) => {
if (split.splitResult && split.splitResult.length !== typesLength) {
throw new Error(
`Unexpected number of parsed reserved parameters. Number of "_types" parameters = ${typesLength}, but "${split.name}" has only ${split.splitResult.length}`
);
}
});
const reservedParameters: ReservedParameters[] = range(typesLength).map((i) =>
splitParams.reduce((acc, param) => {
if (!param.splitResult) return acc;
return { ...acc, [param.name]: param.splitResult[i] };
}, {} as any as ReservedParameters)
);
return reservedParameters;
}
function extractSingleResponse(data: unknown, parameters: ReservedParameters) {
const parsedArrayType = parseArrayType(parameters._type);
const type = parsedArrayType?.baseType ?? parameters._type;
if (!isNumericType(type) && parameters._times) {
throw new Error(`Parameter "_times" can only be used with numeric types, but "_type" was "${type}"`);
}
if (type === 'timestamp' && parameters._path) {
throw new Error(
`Parameter "_path" must be empty string or undefined when "_type" is "timestamp", but it was "${parameters._path}"`
);
}
const extracted = extractValue(data, parameters._path);
const value = castValue(extracted, parameters._type);
if (isNumericType(type)) {
const multipledValue = parsedArrayType
? (applyToArrayRecursively(value, parsedArrayType, (num: number) =>
multiplyValue(num.toString(), parameters._times)
) as ValueType)
: multiplyValue(value.toString(), parameters._times);
return multipledValue;
}
return value;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants