Skip to content

Commit

Permalink
Impove processAttestation for altair
Browse files Browse the repository at this point in the history
  • Loading branch information
dapplion committed Jun 3, 2021
1 parent f9d7db5 commit 8dea281
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 27 deletions.
22 changes: 18 additions & 4 deletions packages/beacon-state-transition/src/allForks/util/epochContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {computeEpochShuffling, IEpochShuffling} from "./epochShuffling";
import {MutableVector} from "@chainsafe/persistent-ts";
import {CachedValidatorList} from "./cachedValidatorList";
import {PROPOSER_WEIGHT, SYNC_REWARD_WEIGHT, WEIGHT_DENOMINATOR} from "../../altair/constants";
import {computeBaseRewardPerIncrement} from "../../altair/misc";

export type EpochContextOpts = {
pubkey2index?: PubkeyIndexMap;
Expand Down Expand Up @@ -106,11 +107,14 @@ export function createEpochContext(
? computeSyncCommitteeIndices(pubkey2index, state as altair.BeaconState, true)
: [];

const syncParticipantReward = onAltairFork ? computeSyncParticipantReward(config, state) : BigInt(0);
const totalActiveBalance = getTotalActiveBalance(config, state);
const syncParticipantReward = onAltairFork ? computeSyncParticipantReward(config, totalActiveBalance) : BigInt(0);
const syncProposerReward = onAltairFork
? (syncParticipantReward * PROPOSER_WEIGHT) / (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT)
: BigInt(0);

const baseRewardPerIncrement = onAltairFork ? computeBaseRewardPerIncrement(config, totalActiveBalance) : BigInt(0);

return new EpochContext({
config,
pubkey2index,
Expand All @@ -125,6 +129,7 @@ export function createEpochContext(
nextSyncComitteeValidatorIndexMap: computeSyncComitteeMap(nextSyncCommitteeIndexes),
syncParticipantReward,
syncProposerReward,
baseRewardPerIncrement,
});
}

Expand Down Expand Up @@ -222,9 +227,8 @@ export function computeSyncCommitteeIndices(
/**
* Same logic in https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.5/specs/altair/beacon-chain.md#sync-committee-processing
*/
export function computeSyncParticipantReward(config: IBeaconConfig, state: allForks.BeaconState): Gwei {
export function computeSyncParticipantReward(config: IBeaconConfig, totalActiveBalance: Gwei): Gwei {
const {EFFECTIVE_BALANCE_INCREMENT, BASE_REWARD_FACTOR, SLOTS_PER_EPOCH, SYNC_COMMITTEE_SIZE} = config.params;
const totalActiveBalance = getTotalActiveBalance(config, state);
const totalActiveIncrements = totalActiveBalance / EFFECTIVE_BALANCE_INCREMENT;
const baseRewardPerIncrement =
(EFFECTIVE_BALANCE_INCREMENT * BigInt(BASE_REWARD_FACTOR)) / bigIntSqrt(totalActiveBalance);
Expand Down Expand Up @@ -275,9 +279,12 @@ export function rotateEpochs(
}

if (currEpoch >= epochCtx.config.params.ALTAIR_FORK_EPOCH) {
epochCtx.syncParticipantReward = computeSyncParticipantReward(epochCtx.config, state);
const totalActiveBalance = getTotalActiveBalance(epochCtx.config, state);
epochCtx.syncParticipantReward = computeSyncParticipantReward(epochCtx.config, totalActiveBalance);
epochCtx.syncProposerReward =
(epochCtx.syncParticipantReward * PROPOSER_WEIGHT) / (WEIGHT_DENOMINATOR - PROPOSER_WEIGHT);

epochCtx.baseRewardPerIncrement = computeBaseRewardPerIncrement(epochCtx.config, totalActiveBalance);
}
}

Expand All @@ -296,6 +303,7 @@ interface IEpochContextData {
nextSyncComitteeValidatorIndexMap: SyncComitteeValidatorIndexMap;
syncParticipantReward: Gwei;
syncProposerReward: Gwei;
baseRewardPerIncrement: Gwei;
}

/**
Expand Down Expand Up @@ -332,6 +340,11 @@ export class EpochContext {
syncParticipantReward: phase0.Gwei;
syncProposerReward: phase0.Gwei;
config: IBeaconConfig;
/**
* Update freq: once per epoch after `process_effective_balance_updates()`
* Memory cost: 1 bigint
*/
baseRewardPerIncrement: Gwei;

constructor(data: IEpochContextData) {
this.config = data.config;
Expand All @@ -347,6 +360,7 @@ export class EpochContext {
this.nextSyncComitteeValidatorIndexMap = data.nextSyncComitteeValidatorIndexMap;
this.syncParticipantReward = data.syncParticipantReward;
this.syncProposerReward = data.syncProposerReward;
this.baseRewardPerIncrement = data.baseRewardPerIncrement;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
import {IEpochStakeSummary} from "./epochStakeSummary";
import {CachedBeaconState} from "./cachedBeaconState";
import {statusProcessEpoch} from "../../phase0/epoch/processPendingAttestations";
import {computeBaseRewardPerIncrement} from "../../altair/misc";

/**
* The AttesterStatus (and FlatValidator under status.validator) objects and
Expand All @@ -30,6 +31,8 @@ export interface IEpochProcess {
prevEpoch: Epoch;
currentEpoch: Epoch;
totalActiveStake: Gwei;
/** For altair */
baseRewardPerIncrement: Gwei;
prevEpochUnslashedStake: IEpochStakeSummary;
currEpochUnslashedTargetStake: Gwei;
indicesToSlash: ValidatorIndex[];
Expand All @@ -53,6 +56,7 @@ export function createIEpochProcess(): IEpochProcess {
prevEpoch: 0,
currentEpoch: 0,
totalActiveStake: BigInt(0),
baseRewardPerIncrement: BigInt(0),
prevEpochUnslashedStake: {
sourceStake: BigInt(0),
targetStake: BigInt(0),
Expand Down Expand Up @@ -139,6 +143,9 @@ export function prepareEpochProcessState<T extends allForks.BeaconState>(state:
out.totalActiveStake = EFFECTIVE_BALANCE_INCREMENT;
}

// SPEC: function getBaseRewardPerIncrement()
out.baseRewardPerIncrement = computeBaseRewardPerIncrement(config, out.totalActiveStake);

// order by sequence of activationEligibilityEpoch setting and then index
out.indicesToMaybeActivate.sort(
(a, b) => out.validators[a].activationEligibilityEpoch - out.validators[b].activationEligibilityEpoch || a - b
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {
WEIGHT_DENOMINATOR,
} from "../constants";

const PROPOSER_REWARD_DOMINATOR = ((WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * WEIGHT_DENOMINATOR) / PROPOSER_WEIGHT;

export function processAttestation(
state: CachedBeaconState<altair.BeaconState>,
attestation: phase0.Attestation,
Expand Down Expand Up @@ -87,7 +89,7 @@ export function processAttestation(

// For each participant, update their participation
// In epoch processing, this participation info is used to calculate balance updates
let proposerRewardNumerator = BigInt(0);
let totalBalancesWithWeight = BigInt(0);
for (const index of attestingIndices) {
const status = epochParticipation.getStatus(index) as IParticipationStatus;
const newStatus = {
Expand All @@ -96,16 +98,23 @@ export function processAttestation(
timelyHead: status.timelyHead || timelyHead,
};
epochParticipation.setStatus(index, newStatus);
// add proposer rewards for source/target/head that updated the state
proposerRewardNumerator +=
getBaseReward(state, index) *
(BigInt(!status.timelySource && timelySource) * TIMELY_SOURCE_WEIGHT +
BigInt(!status.timelyTarget && timelyTarget) * TIMELY_TARGET_WEIGHT +
BigInt(!status.timelyHead && timelyHead) * TIMELY_HEAD_WEIGHT);
/**
* Spec:
* baseReward = state.validators[index].effectiveBalance / EFFECTIVE_BALANCE_INCREMENT * baseRewardPerIncrement;
* proposerRewardNumerator += baseReward * totalWeight
*/
const totalWeight =
BigInt(!status.timelySource && timelySource) * TIMELY_SOURCE_WEIGHT +
BigInt(!status.timelyTarget && timelyTarget) * TIMELY_TARGET_WEIGHT +
BigInt(!status.timelyHead && timelyHead) * TIMELY_HEAD_WEIGHT;
if (totalWeight > 0) {
totalBalancesWithWeight += state.validators[index].effectiveBalance * totalWeight;
}
}

const proposerRewardDenominator = ((WEIGHT_DENOMINATOR - PROPOSER_WEIGHT) * WEIGHT_DENOMINATOR) / PROPOSER_WEIGHT;
const proposerReward = proposerRewardNumerator / proposerRewardDenominator;
const totalIncrements = totalBalancesWithWeight / config.params.EFFECTIVE_BALANCE_INCREMENT;
const proposerRewardNumerator = totalIncrements * state.baseRewardPerIncrement;
const proposerReward = proposerRewardNumerator / PROPOSER_REWARD_DOMINATOR;
increaseBalance(state, epochCtx.getBeaconProposer(state.slot), proposerReward);
}

Expand Down
14 changes: 1 addition & 13 deletions packages/beacon-state-transition/src/altair/epoch/balance.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {altair, Gwei, ValidatorIndex} from "@chainsafe/lodestar-types";
import {bigIntSqrt} from "@chainsafe/lodestar-utils";
import {PARTICIPATION_FLAG_WEIGHTS} from "../misc";
import * as phase0 from "../../phase0";
import {
Expand Down Expand Up @@ -100,23 +99,12 @@ export function getInactivityPenaltyDeltas(
return [rewards, penalties];
}

export function getBaseRewardPerIncrement(
state: CachedBeaconState<altair.BeaconState>,
process: IEpochProcess
): bigint {
const {config} = state;
return (
(config.params.EFFECTIVE_BALANCE_INCREMENT * BigInt(config.params.BASE_REWARD_FACTOR)) /
bigIntSqrt(process.totalActiveStake)
);
}

export function getBaseReward(
state: CachedBeaconState<altair.BeaconState>,
process: IEpochProcess,
index: ValidatorIndex
): bigint {
const {config} = state;
const increments = state.validators[index].effectiveBalance / config.params.EFFECTIVE_BALANCE_INCREMENT;
return increments * getBaseRewardPerIncrement(state, process);
return increments * process.baseRewardPerIncrement;
}
11 changes: 10 additions & 1 deletion packages/beacon-state-transition/src/altair/misc.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import {ParticipationFlags} from "@chainsafe/lodestar-types";
import {IBeaconConfig} from "@chainsafe/lodestar-config";
import {Gwei, ParticipationFlags} from "@chainsafe/lodestar-types";
import {bigIntSqrt} from "@chainsafe/lodestar-utils";
import {TIMELY_HEAD_WEIGHT, TIMELY_SOURCE_WEIGHT, TIMELY_TARGET_WEIGHT} from "./constants";

export const PARTICIPATION_FLAG_WEIGHTS = [TIMELY_SOURCE_WEIGHT, TIMELY_TARGET_WEIGHT, TIMELY_HEAD_WEIGHT];
Expand All @@ -11,3 +13,10 @@ export function hasFlag(flags: ParticipationFlags, flagIndex: number): boolean {
const flag = 2 ** flagIndex;
return (flags & flag) == flag;
}

export function computeBaseRewardPerIncrement(config: IBeaconConfig, totalActiveStake: Gwei): bigint {
return (
(config.params.EFFECTIVE_BALANCE_INCREMENT * BigInt(config.params.BASE_REWARD_FACTOR)) /
bigIntSqrt(totalActiveStake)
);
}

0 comments on commit 8dea281

Please sign in to comment.