[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:
parent
dcb671617c
commit
49b7daa39d
|
@ -466,11 +466,6 @@ func is_in_inactivity_leak(finality_delay: uint64): bool =
|
||||||
func get_finality_delay*(state: ForkyBeaconState): uint64 =
|
func get_finality_delay*(state: ForkyBeaconState): uint64 =
|
||||||
get_previous_epoch(state) - state.finalized_checkpoint.epoch
|
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,
|
func get_attestation_component_reward*(attesting_balance: Gwei,
|
||||||
total_balance: Gwei,
|
total_balance: Gwei,
|
||||||
base_reward: uint64,
|
base_reward: uint64,
|
||||||
|
@ -636,8 +631,8 @@ func get_base_reward_increment*(
|
||||||
func get_flag_index_reward*(state: altair.BeaconState | bellatrix.BeaconState,
|
func get_flag_index_reward*(state: altair.BeaconState | bellatrix.BeaconState,
|
||||||
base_reward: Gwei, active_increments: Gwei,
|
base_reward: Gwei, active_increments: Gwei,
|
||||||
unslashed_participating_increments: Gwei,
|
unslashed_participating_increments: Gwei,
|
||||||
weight: uint64): Gwei =
|
weight, finality_delay: uint64): Gwei =
|
||||||
if not is_in_inactivity_leak(state):
|
if not is_in_inactivity_leak(finality_delay):
|
||||||
let reward_numerator =
|
let reward_numerator =
|
||||||
base_reward * weight * unslashed_participating_increments
|
base_reward * weight * unslashed_participating_increments
|
||||||
reward_numerator div (active_increments * WEIGHT_DENOMINATOR)
|
reward_numerator div (active_increments * WEIGHT_DENOMINATOR)
|
||||||
|
@ -657,7 +652,8 @@ func get_active_increments*(info: altair.EpochInfo): Gwei =
|
||||||
iterator get_flag_index_deltas*(
|
iterator get_flag_index_deltas*(
|
||||||
state: altair.BeaconState | bellatrix.BeaconState, flag_index: int,
|
state: altair.BeaconState | bellatrix.BeaconState, flag_index: int,
|
||||||
base_reward_per_increment: Gwei,
|
base_reward_per_increment: Gwei,
|
||||||
info: var altair.EpochInfo):
|
info: var altair.EpochInfo,
|
||||||
|
finality_delay: uint64):
|
||||||
(ValidatorIndex, RewardDelta) =
|
(ValidatorIndex, RewardDelta) =
|
||||||
## Return the deltas for a given ``flag_index`` by scanning through the
|
## Return the deltas for a given ``flag_index`` by scanning through the
|
||||||
## participation flags.
|
## participation flags.
|
||||||
|
@ -689,7 +685,7 @@ iterator get_flag_index_deltas*(
|
||||||
(vidx, RewardDelta(
|
(vidx, RewardDelta(
|
||||||
rewards: get_flag_index_reward(
|
rewards: get_flag_index_reward(
|
||||||
state, base_reward, active_increments,
|
state, base_reward, active_increments,
|
||||||
unslashed_participating_increments, weight),
|
unslashed_participating_increments, weight, finality_delay),
|
||||||
penalties: 0.Gwei))
|
penalties: 0.Gwei))
|
||||||
elif flag_index != TIMELY_HEAD_FLAG_INDEX:
|
elif flag_index != TIMELY_HEAD_FLAG_INDEX:
|
||||||
(vidx, RewardDelta(
|
(vidx, RewardDelta(
|
||||||
|
@ -780,11 +776,12 @@ func process_rewards_and_penalties(
|
||||||
total_active_balance = info.balances.current_epoch
|
total_active_balance = info.balances.current_epoch
|
||||||
base_reward_per_increment = get_base_reward_per_increment(
|
base_reward_per_increment = get_base_reward_per_increment(
|
||||||
total_active_balance)
|
total_active_balance)
|
||||||
|
finality_delay = get_finality_delay(state)
|
||||||
|
|
||||||
doAssert state.validators.len() == info.validators.len()
|
doAssert state.validators.len() == info.validators.len()
|
||||||
for flag_index in 0 ..< PARTICIPATION_FLAG_WEIGHTS.len:
|
for flag_index in 0 ..< PARTICIPATION_FLAG_WEIGHTS.len:
|
||||||
for validator_index, delta in get_flag_index_deltas(
|
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)
|
info.validators[validator_index].delta.add(delta)
|
||||||
|
|
||||||
for validator_index, penalty in get_inactivity_penalty_deltas(
|
for validator_index, penalty in get_inactivity_penalty_deltas(
|
||||||
|
@ -1004,7 +1001,8 @@ func process_inactivity_updates*(
|
||||||
|
|
||||||
let
|
let
|
||||||
previous_epoch = get_previous_epoch(state) # get_eligible_validator_indices()
|
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:
|
for index in 0'u64 ..< state.validators.lenu64:
|
||||||
if not is_eligible_validator(info.validators[index]):
|
if not is_eligible_validator(info.validators[index]):
|
||||||
|
|
|
@ -111,7 +111,10 @@ proc collectSlashings(
|
||||||
validator[].get_slashing_penalty(
|
validator[].get_slashing_penalty(
|
||||||
adjusted_total_slashing_balance, total_balance).int64
|
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 =
|
Checkpoint =
|
||||||
if get_current_epoch(state) <= GENESIS_EPOCH + 1:
|
if get_current_epoch(state) <= GENESIS_EPOCH + 1:
|
||||||
return state.finalized_checkpoint
|
return state.finalized_checkpoint
|
||||||
|
@ -128,11 +131,10 @@ proc getFinalizedCheckpoint(state: phase0.BeaconState, balances: TotalBalances):
|
||||||
(uint8(state.justification_bits) shl 1) and
|
(uint8(state.justification_bits) shl 1) and
|
||||||
uint8((2^JUSTIFICATION_BITS_LENGTH) - 1))
|
uint8((2^JUSTIFICATION_BITS_LENGTH) - 1))
|
||||||
|
|
||||||
let total_active_balance = balances.current_epoch
|
if previous_epoch_target_balance * 3 >= total_active_balance * 2:
|
||||||
if balances.previous_epoch_target_attesters * 3 >= total_active_balance * 2:
|
|
||||||
uint8(justification_bits).setBit 1
|
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
|
uint8(justification_bits).setBit 0
|
||||||
|
|
||||||
# Process finalizations
|
# Process finalizations
|
||||||
|
@ -164,6 +166,19 @@ proc getFinalizedCheckpoint(state: phase0.BeaconState, balances: TotalBalances):
|
||||||
|
|
||||||
return state.finalized_checkpoint
|
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,
|
func getFinalityDelay*(state: ForkyBeaconState,
|
||||||
finalizedCheckpoint: Checkpoint): uint64 =
|
finalizedCheckpoint: Checkpoint): uint64 =
|
||||||
state.get_previous_epoch - finalizedCheckpoint.epoch
|
state.get_previous_epoch - finalizedCheckpoint.epoch
|
||||||
|
@ -249,10 +264,12 @@ proc collectEpochRewardsAndPenalties*(
|
||||||
total_active_balance = info.balances.current_epoch
|
total_active_balance = info.balances.current_epoch
|
||||||
base_reward_per_increment = get_base_reward_per_increment(
|
base_reward_per_increment = get_base_reward_per_increment(
|
||||||
total_active_balance)
|
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 flag_index in 0 ..< PARTICIPATION_FLAG_WEIGHTS.len:
|
||||||
for validator_index, delta in get_flag_index_deltas(
|
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]
|
template rp: untyped = rewardsAndPenalties[validator_index]
|
||||||
|
|
||||||
let
|
let
|
||||||
|
@ -264,7 +281,8 @@ proc collectEpochRewardsAndPenalties*(
|
||||||
max_flag_index_reward = get_flag_index_reward(
|
max_flag_index_reward = get_flag_index_reward(
|
||||||
state, base_reward, active_increments,
|
state, base_reward, active_increments,
|
||||||
unslashed_participating_increment,
|
unslashed_participating_increment,
|
||||||
PARTICIPATION_FLAG_WEIGHTS[flag_index].uint64)
|
PARTICIPATION_FLAG_WEIGHTS[flag_index].uint64,
|
||||||
|
finalityDelay)
|
||||||
|
|
||||||
case flag_index
|
case flag_index
|
||||||
of TIMELY_SOURCE_FLAG_INDEX:
|
of TIMELY_SOURCE_FLAG_INDEX:
|
||||||
|
|
|
@ -61,9 +61,11 @@ proc runTest(rewardsDir, identifier: string) =
|
||||||
Deltas.init(state[].validators.len)]
|
Deltas.init(state[].validators.len)]
|
||||||
inactivityPenaltyDeltas2 = 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 flag_index in 0 ..< PARTICIPATION_FLAG_WEIGHTS.len:
|
||||||
for validator_index, delta in get_flag_index_deltas(
|
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]):
|
if not is_eligible_validator(info.validators[validator_index]):
|
||||||
continue
|
continue
|
||||||
flagDeltas2[flag_index].rewards[validator_index] = delta.rewards
|
flagDeltas2[flag_index].rewards[validator_index] = delta.rewards
|
||||||
|
|
|
@ -61,9 +61,11 @@ proc runTest(rewardsDir, identifier: string) =
|
||||||
Deltas.init(state[].validators.len)]
|
Deltas.init(state[].validators.len)]
|
||||||
inactivityPenaltyDeltas2 = 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 flag_index in 0 ..< PARTICIPATION_FLAG_WEIGHTS.len:
|
||||||
for validator_index, delta in get_flag_index_deltas(
|
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]):
|
if not is_eligible_validator(info.validators[validator_index]):
|
||||||
continue
|
continue
|
||||||
flagDeltas2[flag_index].rewards[validator_index] = delta.rewards
|
flagDeltas2[flag_index].rewards[validator_index] = delta.rewards
|
||||||
|
|
Loading…
Reference in New Issue