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

feat: assert indexer_result during preprocessing #439

Merged
merged 3 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions lib/evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,15 +267,6 @@ export const runFraudDetection = async ({
tasksAllowedForStations.size
)

//
// 0. Filter out measurements missing required fields.
//
for (const m of measurements) {
if (!m.indexerResult) {
m.fraudAssessment = 'IPNI_NOT_QUERIED'
}
}

//
// 1. Filter out measurements not belonging to any valid task in this round
NikolasHaimerl marked this conversation as resolved.
Show resolved Hide resolved
// or missing some of the required fields like `inet_group`
Expand Down
6 changes: 2 additions & 4 deletions lib/preprocess.js
Original file line number Diff line number Diff line change
Expand Up @@ -230,14 +230,15 @@ export const parseParticipantAddress = filWalletAddress => {
/**
* @param {Measurement} measurement
*/
const assertValidMeasurement = measurement => {
export const assertValidMeasurement = measurement => {
assert(
typeof measurement === 'object' && measurement !== null,
'object required'
)
assert(ethers.isAddress(measurement.participantAddress), 'valid participant address required')
assert(typeof measurement.inet_group === 'string', 'valid inet group required')
assert(typeof measurement.finished_at === 'number', 'field `finished_at` must be set to a number')
assert(measurement.indexerResult, 'field `indexerResult` must be set')
NikolasHaimerl marked this conversation as resolved.
Show resolved Hide resolved
if (measurement.stationId) {
assert(
typeof measurement.stationId === 'string' &&
Expand All @@ -256,9 +257,6 @@ export const getRetrievalResult = (measurement) => {
case 'OK':
case 'HTTP_NOT_ADVERTISED':
break
case undefined:
case null:
return 'IPNI_NOT_QUERIED'
default:
return `IPNI_${measurement.indexer_result}`
}
Expand Down
6 changes: 1 addition & 5 deletions lib/typings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ export type FraudAssesment =
| 'TASK_WRONG_NODE'
| 'DUP_INET_GROUP'
| 'TOO_MANY_TASKS'
| 'IPNI_NOT_QUERIED'
| CommitteeCheckError


Expand All @@ -58,7 +57,6 @@ export type RetrievalResult =
| 'CONTENT_VERIFICATION_FAILED'
| 'UNEXPECTED_CAR_BLOCK'
| 'CANNOT_PARSE_CAR_FILE'
| 'IPNI_NOT_QUERIED'
| 'IPNI_NO_VALID_ADVERTISEMENT'
| 'IPNI_ERROR_FETCH'
| `IPNI_ERROR_${number}`
Expand Down Expand Up @@ -97,9 +95,7 @@ export interface RawMeasurement {
| 'HTTP_NOT_ADVERTISED'
| 'NO_VALID_ADVERTISEMENT'
| 'ERROR_FETCH'
| `ERROR_${number}`
| undefined
| null;
| `ERROR_${number}`;
}

export type CreatePgClient = () => Promise<import('pg').Client>;
39 changes: 0 additions & 39 deletions test/evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -699,45 +699,6 @@ describe('fraud detection', function () {
)
})

it('rejects measurements missing indexer result', async () => {
/** @type {RoundDetails} */
const sparkRoundDetails = {
...SPARK_ROUND_DETAILS,
retrievalTasks: [
{
cid: VALID_MEASUREMENT.cid,
minerId: 'f1test'
}
]
}

const measurements = [
{
...VALID_MEASUREMENT,
inet_group: 'group1',
indexerResult: /** @type {const} */('OK')
},
{
...VALID_MEASUREMENT,
inet_group: 'group2',
indexerResult: undefined
}
]

await runFraudDetection({
roundIndex: 1n,
measurements,
sparkRoundDetails,
requiredCommitteeSize: 1,
logger
})

assert.deepStrictEqual(
measurements.map(m => m.fraudAssessment),
['OK', 'IPNI_NOT_QUERIED']
)
})

it('rejects tasks not allowed by the tasking algorithm', async () => {
/** @type {RoundDetails} */
const sparkRoundDetails = {
Expand Down
42 changes: 24 additions & 18 deletions test/preprocess.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { getRetrievalResult, parseParticipantAddress, preprocess, Measurement, parseMeasurements } from '../lib/preprocess.js'
import {
getRetrievalResult,
parseParticipantAddress,
preprocess,
Measurement,
parseMeasurements,
assertValidMeasurement
} from '../lib/preprocess.js'
import { Point } from '../lib/telemetry.js'
import assert from 'node:assert'
import createDebug from 'debug'
import { assertPointFieldValue, assertRecordedTelemetryPoint } from './helpers/assertions.js'
import { VALID_STATION_ID } from './helpers/test-data.js'
import { VALID_MEASUREMENT, VALID_STATION_ID } from './helpers/test-data.js'
import { RoundData } from '../lib/round.js'

const debug = createDebug('test')
Expand All @@ -27,6 +34,7 @@ describe('preprocess', () => {
station_id: VALID_STATION_ID,
spark_version: '1.2.3',
inet_group: 'ig1',
indexer_result: 'OK',
finished_at: '2023-11-01T09:00:00.000Z',
first_byte_at: '2023-11-01T09:00:01.000Z',
start_at: '2023-11-01T09:00:02.000Z',
Expand All @@ -46,6 +54,7 @@ describe('preprocess', () => {
station_id: VALID_STATION_ID,
spark_version: '1.2.3',
inet_group: 'ig1',
indexer_result: 'OK',
finished_at: '2023-11-01T09:00:00.000Z',
first_byte_at: '2023-11-01T09:00:01.000Z',
start_at: '2023-11-01T09:00:02.000Z',
Expand Down Expand Up @@ -207,22 +216,6 @@ describe('getRetrievalResult', () => {
assert.strictEqual(result, 'UNKNOWN_ERROR')
})

it('missing indexer result -> IPNI_NOT_QUERIED', () => {
const result = getRetrievalResult({
...SUCCESSFUL_RETRIEVAL,
indexer_result: undefined
})
assert.strictEqual(result, 'IPNI_NOT_QUERIED')
})

it('indexer result is null -> IPNI_NOT_QUERIED', () => {
const result = getRetrievalResult({
...SUCCESSFUL_RETRIEVAL,
indexer_result: null
})
assert.strictEqual(result, 'IPNI_NOT_QUERIED')
})

it('IPNI HTTP_NOT_ADVERTISED -> OK', () => {
const result = getRetrievalResult({
...SUCCESSFUL_RETRIEVAL,
Expand Down Expand Up @@ -305,3 +298,16 @@ describe('getRetrievalResult', () => {
assert.strictEqual(result, 'CANNOT_PARSE_CAR_FILE')
})
})

describe('assertValidMeasurement', () => {
it('rejects measurements where indexer_result is null', () => {
const m = {
...VALID_MEASUREMENT,
indexerResult: null
}
assert.throws(
() => assertValidMeasurement(m),
/field `indexerResult` must be set/
)
})
})
Loading