fix(governance): validators display fixes (#4547)

This commit is contained in:
Sam Keen 2023-08-16 22:58:14 +01:00 committed by GitHub
parent 35e25d9a8f
commit cae1fc67a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 47 additions and 23 deletions

View File

@ -626,7 +626,8 @@
"status-tendermint": "Consensus", "status-tendermint": "Consensus",
"status-ersatz": "Standby", "status-ersatz": "Standby",
"status-pending": "Candidate", "status-pending": "Candidate",
"ersatzDescription": "To be promoted, a standby validator must have more than the lowest consensus stake, plus a bonus given to existing validators. This currently requires a minimum of {{stakeNeededForPromotion}} stake assuming no penalties. Only one validator per epoch can be promoted.", "ersatzDescription1": "To be promoted, a standby validator must have more than the lowest consensus stake, plus a bonus given to existing validators, and only one standby validator can be promoted per epoch. Currently this requires a minimum of",
"ersatzDescription2": "stake assuming no performance penalty incurred.",
"pendingDescription1": "Anyone can", "pendingDescription1": "Anyone can",
"pendingDescriptionLinkText": "set up and run a node on Vega", "pendingDescriptionLinkText": "set up and run a node on Vega",
"pendingDescription2": ". A node can move from being a candidate into standby based on how much nomination it attracts, assuming it has proven reliability by sending heartbeats to the network.", "pendingDescription2": ". A node can move from being a candidate into standby based on how much nomination it attracts, assuming it has proven reliability by sending heartbeats to the network.",
@ -784,6 +785,7 @@
"PerformancePenaltyDescription": "Performance score is a measure of how often a validator proposed blocks in the last epoch relative to how many they should be expected to propose based on their voting power. Performance penalty is applied for having a performance score of less than 1", "PerformancePenaltyDescription": "Performance score is a measure of how often a validator proposed blocks in the last epoch relative to how many they should be expected to propose based on their voting power. Performance penalty is applied for having a performance score of less than 1",
"UnnormalisedVotingPowerDescription": "The voting power of the validator based on their final validator score after all penalties have been applied", "UnnormalisedVotingPowerDescription": "The voting power of the validator based on their final validator score after all penalties have been applied",
"NormalisedVotingPowerDescription": "The voting power of the validator, adjusted to ensure all validator scores sum to 1, used for distribution of rewards", "NormalisedVotingPowerDescription": "The voting power of the validator, adjusted to ensure all validator scores sum to 1, used for distribution of rewards",
"NonConsensusVotingPowerDescription": "The voting power of the validator. Only consensus validators have voting power",
"Score": "Score", "Score": "Score",
"performancePenalty": "Performance penalty", "performancePenalty": "Performance penalty",
"overstaked": "Overstaked", "overstaked": "Overstaked",

View File

@ -389,10 +389,10 @@ export const ConsensusValidatorsTable = ({
}, },
{ {
field: ValidatorFields.NORMALISED_VOTING_POWER, field: ValidatorFields.NORMALISED_VOTING_POWER,
headerName: t(ValidatorFields.NORMALISED_VOTING_POWER).toString(), headerName: t('votingPower').toString(),
headerTooltip: t('NormalisedVotingPowerDescription').toString(), headerTooltip: t('NormalisedVotingPowerDescription').toString(),
cellRenderer: VotingPowerRenderer, cellRenderer: VotingPowerRenderer,
width: 200, width: 120,
}, },
{ {
field: ValidatorFields.TOTAL_PENALTIES, field: ValidatorFields.TOTAL_PENALTIES,

View File

@ -20,6 +20,7 @@ import {
TotalStakeRenderer, TotalStakeRenderer,
StakeShareRenderer, StakeShareRenderer,
PendingStakeRenderer, PendingStakeRenderer,
VotingPowerRenderer,
} from './shared'; } from './shared';
import type { AgGridReact } from 'ag-grid-react'; import type { AgGridReact } from 'ag-grid-react';
import type { ColDef } from 'ag-grid-community'; import type { ColDef } from 'ag-grid-community';
@ -39,7 +40,6 @@ interface StandbyPendingValidatorsTableProps extends ValidatorsTableProps {
export const StandbyPendingValidatorsTable = ({ export const StandbyPendingValidatorsTable = ({
data, data,
previousEpochData, previousEpochData,
totalStake,
stakeNeededForPromotion, stakeNeededForPromotion,
stakeNeededForPromotionDescription, stakeNeededForPromotionDescription,
validatorsView, validatorsView,
@ -132,6 +132,8 @@ export const StandbyPendingValidatorsTable = ({
name, name,
}, },
[ValidatorFields.STAKE]: stakedTotal, [ValidatorFields.STAKE]: stakedTotal,
[ValidatorFields.NORMALISED_VOTING_POWER]: '0%',
[ValidatorFields.UNNORMALISED_VOTING_POWER]: '0%',
[ValidatorFields.STAKE_NEEDED_FOR_PROMOTION]: [ValidatorFields.STAKE_NEEDED_FOR_PROMOTION]:
individualStakeNeededForPromotion || null, individualStakeNeededForPromotion || null,
[ValidatorFields.STAKE_NEEDED_FOR_PROMOTION_DESCRIPTION]: [ValidatorFields.STAKE_NEEDED_FOR_PROMOTION_DESCRIPTION]:
@ -223,7 +225,14 @@ export const StandbyPendingValidatorsTable = ({
headerName: t(ValidatorFields.STAKE_SHARE).toString(), headerName: t(ValidatorFields.STAKE_SHARE).toString(),
headerTooltip: t('StakeShareDescription').toString(), headerTooltip: t('StakeShareDescription').toString(),
cellRenderer: StakeShareRenderer, cellRenderer: StakeShareRenderer,
width: 100, width: 120,
},
{
field: ValidatorFields.NORMALISED_VOTING_POWER,
headerName: t('votingPower').toString(),
headerTooltip: t('NonConsensusVotingPowerDescription').toString(),
cellRenderer: VotingPowerRenderer,
width: 120,
}, },
// { // {
// field: ValidatorFields.STAKE_NEEDED_FOR_PROMOTION, // field: ValidatorFields.STAKE_NEEDED_FOR_PROMOTION,

View File

@ -17,6 +17,10 @@ import type { PreviousEpochQuery } from '../../__generated__/PreviousEpoch';
import type { StakingQuery } from '../../__generated__/Staking'; import type { StakingQuery } from '../../__generated__/Staking';
import type { StakingDelegationFieldsFragment } from '../../__generated__/Staking'; import type { StakingDelegationFieldsFragment } from '../../__generated__/Staking';
import type { ValidatorWithUserData } from './shared'; import type { ValidatorWithUserData } from './shared';
import {
NetworkParams,
useNetworkParams,
} from '@vegaprotocol/network-parameters';
export interface ValidatorsTableProps { export interface ValidatorsTableProps {
nodesData: NodesQuery | undefined; nodesData: NodesQuery | undefined;
@ -41,6 +45,9 @@ export const ValidatorTables = ({
const { const {
appState: { decimals }, appState: { decimals },
} = useAppState(); } = useAppState();
const { params } = useNetworkParams([
NetworkParams.network_validators_incumbentBonus,
]);
const [validatorsView, setValidatorsView] = useState<ValidatorsView>('all'); const [validatorsView, setValidatorsView] = useState<ValidatorsView>('all');
const totalStake = useMemo( const totalStake = useMemo(
@ -52,6 +59,10 @@ export const ValidatorTables = ({
() => userStakingData?.party?.stakingSummary.currentStakeAvailable || '0', () => userStakingData?.party?.stakingSummary.currentStakeAvailable || '0',
[userStakingData?.party?.stakingSummary.currentStakeAvailable] [userStakingData?.party?.stakingSummary.currentStakeAvailable]
); );
const incumbentBonus = useMemo(
() => new BigNumber(params?.network_validators_incumbentBonus),
[params?.network_validators_incumbentBonus]
);
let stakeNeededForPromotion = undefined; let stakeNeededForPromotion = undefined;
let delegations: StakingDelegationFieldsFragment[] | undefined = undefined; let delegations: StakingDelegationFieldsFragment[] | undefined = undefined;
@ -126,28 +137,23 @@ export const ValidatorTables = ({
consensusValidators.length && consensusValidators.length &&
(standbyValidators.length || pendingValidators.length) (standbyValidators.length || pendingValidators.length)
) { ) {
const lowestRankingConsensusScore = consensusValidators.reduce( const lowestConsensusStake = consensusValidators.reduce(
(lowest: ValidatorWithUserData, validator: ValidatorWithUserData) => { (lowest: ValidatorWithUserData, validator: ValidatorWithUserData) => {
if ( if (Number(validator.stakedTotal) < Number(lowest.stakedTotal)) {
Number(validator.rankingScore.rankingScore) <
Number(lowest.rankingScore.rankingScore)
) {
lowest = validator; lowest = validator;
} }
return lowest; return lowest;
} }
).rankingScore.rankingScore; ).stakedTotal;
const lowestRankingBigNum = toBigNum(lowestRankingConsensusScore, 0); const lowestRankingBigNum = toBigNum(lowestConsensusStake, decimals);
const consensusStakedTotal = consensusValidators.reduce((acc, cur) => {
return acc.plus(toBigNum(cur.stakedTotal, decimals));
}, new BigNumber(0));
stakeNeededForPromotion = formatNumber( stakeNeededForPromotion = formatNumber(
lowestRankingBigNum.times(consensusStakedTotal), lowestRankingBigNum.multipliedBy(incumbentBonus.plus(1)),
2 2
).toString(); ).toString();
} }
return ( return (
<section data-testid="validator-tables"> <section data-testid="validator-tables">
<div className="grid w-full justify-end"> <div className="grid w-full justify-end">
@ -187,12 +193,18 @@ export const ValidatorTables = ({
<div className="mb-10"> <div className="mb-10">
<SubHeading title={t('status-ersatz')} /> <SubHeading title={t('status-ersatz')} />
<p> <p>
<Trans <span>
i18nKey="ersatzDescription" <Trans i18nKey="ersatzDescription1" />
values={{ </span>
stakeNeededForPromotion,
}} <span className="text-white font-bold">
/> {' '}
{stakeNeededForPromotion}{' '}
</span>
<span>
<Trans i18nKey="ersatzDescription2" />
</span>
</p> </p>
<StandbyPendingValidatorsTable <StandbyPendingValidatorsTable
data={standbyValidators} data={standbyValidators}

View File

@ -68,7 +68,7 @@ export const calculateOverstakedPenalty = (nodeId: string, nodes: Node[]) => {
} }
const penalty = new BigNumber(1) const penalty = new BigNumber(1)
.minus( .minus(
new BigNumber(node.rewardScore?.rawValidatorScore || 0).dividedBy(tts) new BigNumber(node.rewardScore?.rawValidatorScore || 1).dividedBy(tts)
) )
.times(100); .times(100);
return penalty.isLessThan(0) ? new BigNumber(0) : penalty; return penalty.isLessThan(0) ? new BigNumber(0) : penalty;

View File

@ -107,6 +107,7 @@ export const NetworkParams = {
market_liquidity_targetstake_triggering_ratio: market_liquidity_targetstake_triggering_ratio:
'market_liquidity_targetstake_triggering_ratio', 'market_liquidity_targetstake_triggering_ratio',
transfer_fee_factor: 'transfer_fee_factor', transfer_fee_factor: 'transfer_fee_factor',
network_validators_incumbentBonus: 'network_validators_incumbentBonus',
} as const; } as const;
type Params = typeof NetworkParams; type Params = typeof NetworkParams;