@lodestar/beacon-node
Version:
A Typescript implementation of the beacon chain
37 lines • 1.9 kB
JavaScript
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