[ncli_db] bugfix: take into account finalization delay in reward calc post Altair

This fixes a problem affecting Prater's epoch 64444.
This commit is contained in:
Zahary Karadjov 2022-01-27 18:37:30 +02:00 committed by zah
parent dcb671617c
commit 49b7daa39d
4 changed files with 39 additions and 19 deletions

View File

@ -466,11 +466,6 @@ func is_in_inactivity_leak(finality_delay: uint64): bool =
func get_finality_delay*(state: ForkyBeaconState): uint64 =
get_previous_epoch(state) - state.finalized_checkpoint.epoch
# https://github.com/ethereum/consensus-specs/blob/v1.1.8/specs/phase0/beacon-chain.md#rewards-and-penalties-1
func is_in_inactivity_leak(state: altair.BeaconState | bellatrix.BeaconState): bool =
# TODO remove this, see above
get_finality_delay(state) > MIN_EPOCHS_TO_INACTIVITY_PENALTY
func get_attestation_component_reward*(attesting_balance: Gwei,
total_balance: Gwei,
base_reward: uint64,
@ -636,8 +631,8 @@ func get_base_reward_increment*(
func get_flag_index_reward*(state: altair.BeaconState | bellatrix.BeaconState,
base_reward: Gwei, active_increments: Gwei,
unslashed_participating_increments: Gwei,
weight: uint64): Gwei =
if not is_in_inactivity_leak(state):
weight, finality_delay: uint64): Gwei =
if not is_in_inactivity_leak(finality_delay):
let reward_numerator =
base_reward * weight * unslashed_participating_increments
reward_numerator div (active_increments * WEIGHT_DENOMINATOR)
@ -657,7 +652,8 @@ func get_active_increments*(info: altair.EpochInfo): Gwei =
iterator get_flag_index_deltas*(
state: altair.BeaconState | bellatrix.BeaconState, flag_index: int,
base_reward_per_increment: Gwei,
info: var altair.EpochInfo):
info: var altair.EpochInfo,
finality_delay: uint64):
(ValidatorIndex, RewardDelta) =
## Return the deltas for a given ``flag_index`` by scanning through the
## participation flags.
@ -689,7 +685,7 @@ iterator get_flag_index_deltas*(
(vidx, RewardDelta(
rewards: get_flag_index_reward(
state, base_reward, active_increments,
unslashed_participating_increments, weight),
unslashed_participating_increments, weight, finality_delay),
penalties: 0.Gwei))
elif flag_index != TIMELY_HEAD_FLAG_INDEX:
(vidx, RewardDelta(
@ -780,11 +776,12 @@ func process_rewards_and_penalties(
total_active_balance = info.balances.current_epoch
base_reward_per_increment = get_base_reward_per_increment(
total_active_balance)
finality_delay = get_finality_delay(state)
doAssert state.validators.len() == info.validators.len()
for flag_index in 0 ..< PARTICIPATION_FLAG_WEIGHTS.len:
for validator_index, delta in get_flag_index_deltas(
state, flag_index, base_reward_per_increment, info):
state, flag_index, base_reward_per_increment, info, finality_delay):
info.validators[validator_index].delta.add(delta)
for validator_index, penalty in get_inactivity_penalty_deltas(
@ -1004,7 +1001,8 @@ func process_inactivity_updates*(
let
previous_epoch = get_previous_epoch(state) # get_eligible_validator_indices()
not_in_inactivity_leak = not is_in_inactivity_leak(state)
finality_delay = get_finality_delay(state)
not_in_inactivity_leak = not is_in_inactivity_leak(finality_delay)
for index in 0'u64 ..< state.validators.lenu64:
if not is_eligible_validator(info.validators[index]):

View File

@ -111,7 +111,10 @@ proc collectSlashings(
validator[].get_slashing_penalty(
adjusted_total_slashing_balance, total_balance).int64
proc getFinalizedCheckpoint(state: phase0.BeaconState, balances: TotalBalances):
proc getFinalizedCheckpoint(state: ForkyBeaconState,
total_active_balance,
previous_epoch_target_balance,
current_epoch_target_balance: Gwei):
Checkpoint =
if get_current_epoch(state) <= GENESIS_EPOCH + 1:
return state.finalized_checkpoint
@ -128,11 +131,10 @@ proc getFinalizedCheckpoint(state: phase0.BeaconState, balances: TotalBalances):
(uint8(state.justification_bits) shl 1) and
uint8((2^JUSTIFICATION_BITS_LENGTH) - 1))
let total_active_balance = balances.current_epoch
if balances.previous_epoch_target_attesters * 3 >= total_active_balance * 2:
if previous_epoch_target_balance * 3 >= total_active_balance * 2:
uint8(justification_bits).setBit 1
if balances.current_epoch_target_attesters * 3 >= total_active_balance * 2:
if current_epoch_target_balance * 3 >= total_active_balance * 2:
uint8(justification_bits).setBit 0
# Process finalizations
@ -164,6 +166,19 @@ proc getFinalizedCheckpoint(state: phase0.BeaconState, balances: TotalBalances):
return state.finalized_checkpoint
proc getFinalizedCheckpoint(state: phase0.BeaconState, balances: TotalBalances):
Checkpoint =
getFinalizedCheckpoint(state, balances.current_epoch,
balances.previous_epoch_target_attesters,
balances.current_epoch_target_attesters)
proc getFinalizedCheckpoint(
state: altair.BeaconState | bellatrix.BeaconState,
balances: UnslashedParticipatingBalances): Checkpoint =
getFinalizedCheckpoint(state, balances.current_epoch,
balances.previous_epoch[TIMELY_TARGET_FLAG_INDEX],
balances.current_epoch_TIMELY_TARGET)
func getFinalityDelay*(state: ForkyBeaconState,
finalizedCheckpoint: Checkpoint): uint64 =
state.get_previous_epoch - finalizedCheckpoint.epoch
@ -249,10 +264,12 @@ proc collectEpochRewardsAndPenalties*(
total_active_balance = info.balances.current_epoch
base_reward_per_increment = get_base_reward_per_increment(
total_active_balance)
finalized_checkpoint = state.getFinalizedCheckpoint(info.balances)
finality_delay = getFinalityDelay(state, finalized_checkpoint)
for flag_index in 0 ..< PARTICIPATION_FLAG_WEIGHTS.len:
for validator_index, delta in get_flag_index_deltas(
state, flag_index, base_reward_per_increment, info):
state, flag_index, base_reward_per_increment, info, finality_delay):
template rp: untyped = rewardsAndPenalties[validator_index]
let
@ -264,7 +281,8 @@ proc collectEpochRewardsAndPenalties*(
max_flag_index_reward = get_flag_index_reward(
state, base_reward, active_increments,
unslashed_participating_increment,
PARTICIPATION_FLAG_WEIGHTS[flag_index].uint64)
PARTICIPATION_FLAG_WEIGHTS[flag_index].uint64,
finalityDelay)
case flag_index
of TIMELY_SOURCE_FLAG_INDEX:

View File

@ -61,9 +61,11 @@ proc runTest(rewardsDir, identifier: string) =
Deltas.init(state[].validators.len)]
inactivityPenaltyDeltas2 = Deltas.init(state[].validators.len)
let finality_delay = get_finality_delay(state[])
for flag_index in 0 ..< PARTICIPATION_FLAG_WEIGHTS.len:
for validator_index, delta in get_flag_index_deltas(
state[], flag_index, base_reward_per_increment, info):
state[], flag_index, base_reward_per_increment, info, finality_delay):
if not is_eligible_validator(info.validators[validator_index]):
continue
flagDeltas2[flag_index].rewards[validator_index] = delta.rewards

View File

@ -61,9 +61,11 @@ proc runTest(rewardsDir, identifier: string) =
Deltas.init(state[].validators.len)]
inactivityPenaltyDeltas2 = Deltas.init(state[].validators.len)
let finality_delay = get_finality_delay(state[])
for flag_index in 0 ..< PARTICIPATION_FLAG_WEIGHTS.len:
for validator_index, delta in get_flag_index_deltas(
state[], flag_index, base_reward_per_increment, info):
state[], flag_index, base_reward_per_increment, info, finality_delay):
if not is_eligible_validator(info.validators[validator_index]):
continue
flagDeltas2[flag_index].rewards[validator_index] = delta.rewards