UNPKG

@lodestar/beacon-node

Version:

A Typescript implementation of the beacon chain

37 lines 1.9 kB
import { ForkName, SYNC_COMMITTEE_SIZE } from "@lodestar/params"; export async function computeSyncCommitteeRewards(block, preState, validatorIds = []) { const fork = preState.config.getForkName(block.slot); if (fork === ForkName.phase0) { throw Error("Cannot get sync rewards as phase0 block does not have sync committee"); } const altairBlock = block; const preStateAltair = preState; const { index2pubkey } = preStateAltair.epochCtx; // Bound committeeIndices in case it goes beyond SYNC_COMMITTEE_SIZE just to be safe const committeeIndices = preStateAltair.epochCtx.currentSyncCommitteeIndexed.validatorIndices.slice(0, SYNC_COMMITTEE_SIZE); const { syncParticipantReward } = preStateAltair.epochCtx; const { syncCommitteeBits } = altairBlock.body.syncAggregate; // Use balance of each committee as starting point such that we cap the penalty to avoid balance dropping below 0 const balances = new Map(); for (const i of committeeIndices) { balances.set(i, { val: preStateAltair.balances.get(i) }); } for (const i of committeeIndices) { const balanceRecord = balances.get(i); if (syncCommitteeBits.get(i)) { // Positive rewards for participants balanceRecord.val += syncParticipantReward; } else { // Negative rewards for non participants balanceRecord.val = Math.max(0, balanceRecord.val - syncParticipantReward); } } const rewards = Array.from(balances, ([validatorIndex, v]) => ({ validatorIndex, reward: v.val })); if (validatorIds.length) { const filtersSet = new Set(validatorIds); return rewards.filter((reward) => filtersSet.has(reward.validatorIndex) || filtersSet.has(index2pubkey[reward.validatorIndex].toHex())); } return rewards; } //# sourceMappingURL=syncCommitteeRewards.js.map