Skip to content

Commit

Permalink
fix dominance size (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
onmax authored Nov 19, 2024
1 parent f46eea7 commit 0b94890
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 27 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
</a>

<p align="center">
Details of validators in the Nimiq Blockchain and their scores, calculated using Nimiq's VTS algorithm.
Details of validators in the Nimiq Blockchain and their scores, calculated using Nimiq's VTS algorithm.
<p>

[![Sync Mainnet](https://github.com/nimiq/validators-api/actions/workflows/sync-mainnet.yml/badge.svg)](https://github.com/nimiq/validators-api/actions/workflows/sync-mainnet.yml)
Expand Down
4 changes: 2 additions & 2 deletions app/components/ScorePie.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const strokeColor = computed(() => {
<template>
<div grid="~ cols-1 rows-1 place-content-center *:row-span-full *:col-span-full">
<template v-if="score !== null">
<div font-bold dominance-full grid="~ place-content-center">
<div font-bold size-full grid="~ place-content-center">
{{ (score * 100).toFixed(0) }}
</div>
<svg
Expand All @@ -50,7 +50,7 @@ const strokeColor = computed(() => {
</svg>
</template>
<template v-else>
<div font-bold dominance-full grid="~ place-content-center">
<div font-bold size-full grid="~ place-content-center">
NA
</div>
<svg
Expand Down
23 changes: 6 additions & 17 deletions packages/nimiq-validators-trustscore/src/score.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { ScoreParams, ScoreValues } from './types'
import { defu } from 'defu'

export function getDominance({ threshold, steepness, dominanceRatio }: ScoreParams['dominance']) {
export function getDominance({ threshold = 0.15, steepness = 7.5, dominanceRatio }: ScoreParams['dominance']) {
if (!threshold || !steepness || !dominanceRatio)
throw new Error('Balance, threshold, steepness, or total balance is not set')
if (dominanceRatio < 0 || dominanceRatio > 1)
Expand All @@ -10,7 +9,7 @@ export function getDominance({ threshold, steepness, dominanceRatio }: ScorePara
return s
}

export function getAvailability({ activeEpochStates, weightFactor }: ScoreParams['availability']) {
export function getAvailability({ activeEpochStates, weightFactor = 0.5 }: ScoreParams['availability']) {
if (!activeEpochStates || !weightFactor || activeEpochStates.length === 0)
throw new Error(`Invalid availability params: ${JSON.stringify({ activeEpochStates, weightFactor })}`)

Expand All @@ -32,7 +31,7 @@ export function getAvailability({ activeEpochStates, weightFactor }: ScoreParams
return availability
}

export function getReliability({ inherentsPerEpoch, weightFactor, curveCenter }: ScoreParams['reliability']) {
export function getReliability({ inherentsPerEpoch, weightFactor = 0.5, curveCenter = 0.16 }: ScoreParams['reliability']) {
if (!inherentsPerEpoch || !weightFactor || !curveCenter)
throw new Error(`Invalid reliability params: ${JSON.stringify({ inherentsPerEpoch, weightFactor, curveCenter })}`)

Expand Down Expand Up @@ -68,20 +67,10 @@ export function getReliability({ inherentsPerEpoch, weightFactor, curveCenter }:
return Math.max(-curveCenter + 1 - Math.sqrt(discriminant), 1)
}

// The default values for the computeScore function
// Negative values and empty arrays are used to indicate that the user must provide the values or an error will be thrown
const defaultScoreParams: ScoreParams = {
dominance: { threshold: 0.25, steepness: 4, dominanceRatio: -1 },
availability: { weightFactor: 0.5, activeEpochStates: [] },
reliability: { weightFactor: 0.5, curveCenter: -0.16, inherentsPerEpoch: new Map() },
}

export function computeScore(params: ScoreParams) {
const computeScoreParams = defu(params, defaultScoreParams)

const dominance = getDominance(computeScoreParams.dominance)
const availability = getAvailability(computeScoreParams.availability)
const reliability = getReliability(computeScoreParams.reliability)
const dominance = getDominance(params.dominance)
const availability = getAvailability(params.availability)
const reliability = getReliability(params.reliability)

const total = dominance * availability * reliability
const score: ScoreValues = { dominance, availability, reliability, total }
Expand Down
21 changes: 14 additions & 7 deletions server/utils/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { readdir, readFile } from 'node:fs/promises'
import path from 'node:path'
import { consola } from 'consola'
import { desc, inArray, isNotNull } from 'drizzle-orm'
import { getDominance } from 'nimiq-validators-trustscore'
import { getBrandingParameters } from './branding'
import { defaultValidatorJSON, validatorSchema } from './schemas'

Expand Down Expand Up @@ -126,7 +127,8 @@ export type FetchValidatorsOptions = Zod.infer<typeof mainQuerySchema> & { addre
type FetchedValidator = Omit<Validator, 'logo' | 'contact'> & {
logo?: string
score?: Score
dominanceRatio?: number
dominanceRatioViaBalance?: number
dominanceRatioViaSlots?: number
}

export async function fetchValidators(params: FetchValidatorsOptions): Result<FetchedValidator[]> {
Expand Down Expand Up @@ -161,11 +163,8 @@ export async function fetchValidators(params: FetchValidatorsOptions): Result<Fe
availability: tables.scores.availability,
reliability: tables.scores.reliability,
},
dominanceRatio: sql<number>`
COALESCE(
NULLIF(${tables.activity.dominanceRatioViaBalance}, -1),
NULLIF(${tables.activity.dominanceRatioViaSlots}, -1)
)`,
dominanceRatioViaBalance: tables.activity.dominanceRatioViaBalance,
dominanceRatioViaSlots: tables.activity.dominanceRatioViaSlots,
})
.from(tables.validators)
.where(and(...filters))
Expand All @@ -192,10 +191,18 @@ export async function fetchValidators(params: FetchValidatorsOptions): Result<Fe

const nullScore = { total: null, dominance: null, availability: null, reliability: null }
validators.forEach((v) => {
const dominance = v.score?.dominance
// @ts-expect-error The wallet expects a score object, but until these values are stable, we will use null
v.score = nullScore
if (dominance)
// @ts-expect-error The wallet expects a score object, but until these values are stable, we will use null
v.score.dominance = dominance
else if (v.dominanceRatioViaBalance !== -1)
// @ts-expect-error The wallet expects a score object, but until these values are stable, we will use null
v.score.dominance = v.dominanceRatio
v.score = { ...nullScore, dominance: getDominance({ dominanceRatio: v.dominanceRatioViaBalance }) }
else if (v.dominanceRatioViaSlots !== -1)
// @ts-expect-error The wallet expects a score object, but until these values are stable, we will use null
v.score = { ...nullScore, dominance: getDominance({ dominanceRatio: v.dominanceRatioViaSlots }) }
})

return { data: validators, error: undefined }
Expand Down

0 comments on commit 0b94890

Please sign in to comment.