Skip to content

Commit

Permalink
Add processNetExcessPenalties
Browse files Browse the repository at this point in the history
  • Loading branch information
ensi321 committed Jun 3, 2024
1 parent b8c5f3d commit 0cad664
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 38 deletions.
2 changes: 1 addition & 1 deletion packages/config/src/chainConfig/configs/mainnet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const chainConfig: ChainConfig = {
// Deneb
DENEB_FORK_VERSION: b("0x04000000"),
DENEB_FORK_EPOCH: 269568, // March 13, 2024, 01:55:35pm UTC

// EIP-7716
EIP7716_FORK_VERSION: b("0x05000000"),
EIP7716_FORK_EPOCH: Infinity,
Expand Down
6 changes: 3 additions & 3 deletions packages/config/src/chainConfig/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ export type ChainConfig = {
MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS: number;

// EIP-7716
PENALTY_ADJUSTMENT_FACTOR: number,
MAX_PENALTY_FACTOR: number,
PENALTY_RECOVERY_RATE: number,
PENALTY_ADJUSTMENT_FACTOR: number;
MAX_PENALTY_FACTOR: number;
PENALTY_RECOVERY_RATE: number;
};

export const chainConfigTypes: SpecTypes<ChainConfig> = {
Expand Down
4 changes: 2 additions & 2 deletions packages/state-transition/src/epoch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
EpochTransitionCache,
} from "../types.js";
import {BeaconStateTransitionMetrics} from "../metrics.js";
import {CachedBeaconStateEIP7716} from "../cache/stateCache.js";
import {processEffectiveBalanceUpdates} from "./processEffectiveBalanceUpdates.js";
import {processEth1DataReset} from "./processEth1DataReset.js";
import {processHistoricalRootsUpdate} from "./processHistoricalRootsUpdate.js";
Expand All @@ -27,8 +28,7 @@ import {processRewardsAndPenalties} from "./processRewardsAndPenalties.js";
import {processSlashings} from "./processSlashings.js";
import {processSlashingsReset} from "./processSlashingsReset.js";
import {processSyncCommitteeUpdates} from "./processSyncCommitteeUpdates.js";
import { processNetExcessPenalties } from "./processNetExcessPenalties.js";
import { CachedBeaconStateEIP7716 } from "../cache/stateCache.js";
import {processNetExcessPenalties} from "./processNetExcessPenalties.js";

// For spec tests
export {getRewardsAndPenalties} from "./processRewardsAndPenalties.js";
Expand Down
22 changes: 10 additions & 12 deletions packages/state-transition/src/epoch/processNetExcessPenalties.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import {
EFFECTIVE_BALANCE_INCREMENT,
ForkSeq,
HYSTERESIS_DOWNWARD_MULTIPLIER,
HYSTERESIS_QUOTIENT,
HYSTERESIS_UPWARD_MULTIPLIER,
MAX_EFFECTIVE_BALANCE,
TIMELY_TARGET_FLAG_INDEX,
} from "@lodestar/params";
import {EpochTransitionCache, CachedBeaconStateAllForks, BeaconStateAltair} from "../types.js";
import {PARTICIPATION_FLAG_WEIGHTS, SLOTS_PER_EPOCH} from "@lodestar/params";
import {CachedBeaconStateEIP7716} from "../types.js";
import {getPreviousEpoch} from "../util/epoch.js";
import {computePenaltyFactor} from "../util/eip7716.js";

export function processNetExcessPenalties(state: CachedBeaconStateAllForks): void {
// TODO
export function processNetExcessPenalties(state: CachedBeaconStateEIP7716): void {
const lastSlotPrevEpoch = getPreviousEpoch(state) + SLOTS_PER_EPOCH - 1;
for (let flagIndex = 0; flagIndex < PARTICIPATION_FLAG_WEIGHTS.length; flagIndex++) {
const {netExcessPenalty} = computePenaltyFactor(state, lastSlotPrevEpoch, flagIndex);
state.netExcessPenalties.set(flagIndex, netExcessPenalty);
}
}
2 changes: 2 additions & 0 deletions packages/state-transition/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type {
CachedBeaconStateBellatrix,
CachedBeaconStateCapella,
CachedBeaconStateDeneb,
CachedBeaconStateEIP7716,
} from "./cache/stateCache.js";

export type {
Expand All @@ -19,4 +20,5 @@ export type {
BeaconStateBellatrix,
BeaconStateCapella,
BeaconStateDeneb,
BeaconStateEip7716,
} from "./cache/types.js";
78 changes: 66 additions & 12 deletions packages/state-transition/src/util/eip7716.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,79 @@
import {digest} from "@chainsafe/as-sha256";
import {BLSSignature} from "@lodestar/types";
import {intDiv, bytesToBigInt} from "@lodestar/utils";
import {Epoch, Slot, ValidatorIndex} from "@lodestar/types";
import {
TARGET_AGGREGATORS_PER_COMMITTEE,
SYNC_COMMITTEE_SIZE,
SYNC_COMMITTEE_SUBNET_COUNT,
TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE,
SLOTS_PER_EPOCH,
} from "@lodestar/params";
import {CachedBeaconStateEIP7716} from "../types.js";
import {computeEpochAtSlot, computeStartSlotAtEpoch} from "./epoch.js";

export function computePenaltyFactor() {
export function computePenaltyFactor(
state: CachedBeaconStateEIP7716,
atSlot: Slot,
flagIndex: number
): {penaltyFactor: number; netExcessPenalty: number} {
let netExcessPenalty = state.netExcessPenalties.get(flagIndex);
const epoch = computeEpochAtSlot(atSlot);
const {PENALTY_ADJUSTMENT_FACTOR, MAX_PENALTY_FACTOR, PENALTY_RECOVERY_RATE} = state.config;
let penaltyFactor = 1;

for (let slot = computeStartSlotAtEpoch(epoch); slot < atSlot; slot++) {
const totalBalance = getSlotCommitteeBalance(state, slot);
const participatingBalance = participatingBalanceSlot(state, slot, flagIndex);
penaltyFactor = Math.min(
Math.floor(
((totalBalance - participatingBalance) * PENALTY_ADJUSTMENT_FACTOR) / (netExcessPenalty * totalBalance + 1)
),
MAX_PENALTY_FACTOR
);
netExcessPenalty = Math.max(PENALTY_RECOVERY_RATE, netExcessPenalty + penaltyFactor) - PENALTY_RECOVERY_RATE;
}

return {penaltyFactor, netExcessPenalty};
}

export function committeeSlotOfValidator(state: CachedBeaconStateEIP7716, index: ValidatorIndex, epoch: Epoch) {
for (let slot = epoch * SLOTS_PER_EPOCH; slot < (epoch + 1) * SLOTS_PER_EPOCH; slot++) {
if (index in getSlotCommittees(state, slot)) {
return slot;
}
}
throw new Error(`Validator with index ${index} is not active`);
}

export function committeeSlotOfValidator() {
export function participatingBalanceSlot(state: CachedBeaconStateEIP7716, slot: Slot, flagIndex: number) {
const inCurrentEpoch = computeEpochAtSlot(slot) === state.epochCtx.epoch;
const epochParticipation = inCurrentEpoch ? state.currentEpochParticipation : state.previousEpochParticipation;

const flagBit = 1 << flagIndex;
const participatingIndices = getSlotCommittees(state, slot).filter(
(index) => (epochParticipation.get(index) & flagBit) === flagBit
);

return participatingIndices
.map((participatingIndex) => state.balances.get(participatingIndex))
.reduce((total, balance) => total + balance, 0);
}

export function participatingBalanceSlot() {
export function getSlotCommittees(state: CachedBeaconStateEIP7716, slot: Slot): Uint32Array {
const committees = state.epochCtx.getShufflingAtSlot(slot).committees[slot % SLOTS_PER_EPOCH].flat();
// Create a new Uint32Array to flatten `committees`
const totalLength = committees.reduce((acc, curr) => acc + curr.length, 0);
const result = new Uint32Array(totalLength);

let offset = 0;
for (const committee of committees) {
result.set(committee, offset);
offset += committee.length;
}

return result;
}

export function getSlotCommittees() {
export function getSlotCommitteeBalance(state: CachedBeaconStateEIP7716, slot: Slot): number {
const validatorIndices = getSlotCommittees(state, slot);

}
// 32eth * 1mil / 32 is still within number range
// WIth maxEB = 2048, total max balance could be 2^46
return validatorIndices
.map((validatorIndex) => state.balances.get(validatorIndex))
.reduce((total, balance) => total + balance, 0);
}
5 changes: 5 additions & 0 deletions packages/types/src/allForks/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {ssz as altairSsz} from "../altair/index.js";
import {ssz as bellatrixSsz} from "../bellatrix/index.js";
import {ssz as capellaSsz} from "../capella/index.js";
import {ssz as denebSsz} from "../deneb/index.js";
import {ssz as eip7716Ssz} from "../eip7716/index.js";

// Re-export union types for types that are _known_ to differ

Expand Down Expand Up @@ -178,27 +179,31 @@ export type AllForksSSZTypes = {
| typeof bellatrixSsz.BeaconBlockBody
| typeof capellaSsz.BeaconBlockBody
| typeof denebSsz.BeaconBlockBody
| typeof eip7716Ssz.BeaconBlockBody
>;
BeaconBlock: AllForksTypeOf<
| typeof phase0Ssz.BeaconBlock
| typeof altairSsz.BeaconBlock
| typeof bellatrixSsz.BeaconBlock
| typeof capellaSsz.BeaconBlock
| typeof denebSsz.BeaconBlock
| typeof eip7716Ssz.BeaconBlock
>;
SignedBeaconBlock: AllForksTypeOf<
| typeof phase0Ssz.SignedBeaconBlock
| typeof altairSsz.SignedBeaconBlock
| typeof bellatrixSsz.SignedBeaconBlock
| typeof capellaSsz.SignedBeaconBlock
| typeof denebSsz.SignedBeaconBlock
| typeof eip7716Ssz.SignedBeaconBlock
>;
BeaconState: AllForksTypeOf<
| typeof phase0Ssz.BeaconState
| typeof altairSsz.BeaconState
| typeof bellatrixSsz.BeaconState
| typeof capellaSsz.BeaconState
| typeof denebSsz.BeaconState
| typeof eip7716Ssz.BeaconState
>;
Metadata: AllForksTypeOf<typeof phase0Ssz.Metadata | typeof altairSsz.Metadata>;
};
Expand Down
11 changes: 4 additions & 7 deletions packages/types/src/eip7716/sszTypes.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
import {ContainerType, VectorBasicType} from "@chainsafe/ssz";
import {
TIMELY_HEAD_FLAG_INDEX,
} from "@lodestar/params";
import {TIMELY_HEAD_FLAG_INDEX} from "@lodestar/params";
import {ssz as primitiveSsz} from "../primitive/index.js";
import {ssz as denebSsz} from "../capella/index.js";

const {UintNum64} =
primitiveSsz;
const {UintNum64} = primitiveSsz;

export const BeaconState = new ContainerType(
{
...denebSsz.BeaconState.fields,
netExcessPenalties: new VectorBasicType(UintNum64, TIMELY_HEAD_FLAG_INDEX)
netExcessPenalties: new VectorBasicType(UintNum64, TIMELY_HEAD_FLAG_INDEX),
},
{typeName: "BeaconState", jsonCase: "eth2"}
);

export const SignedBeaconBlock = denebSsz.SignedBeaconBlock;
export const BeaconBlock = denebSsz.BeaconBlock;
export const BeaconBlockBody = denebSsz.BeaconBlockBody;
export const ExecutionPayload = denebSsz.ExecutionPayload;
export const ExecutionPayload = denebSsz.ExecutionPayload;
2 changes: 1 addition & 1 deletion packages/types/src/eip7716/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ export type BeaconState = ValueOf<typeof ssz.BeaconState>;
export type SignedBeaconBlock = ValueOf<typeof ssz.SignedBeaconBlock>;
export type BeaconBlock = ValueOf<typeof ssz.BeaconBlock>;
export type BeaconBlockBody = ValueOf<typeof ssz.BeaconBlockBody>;
export type ExecutionPayload = ValueOf<typeof ssz.ExecutionPayload>;
export type ExecutionPayload = ValueOf<typeof ssz.ExecutionPayload>;

0 comments on commit 0cad664

Please sign in to comment.