Handle activations and exits separately for balance churn (#230)

This change is to avoid deposits from fully consuming the allowable balance churn, preventing exits from being processed. And vice versa with deposits/exits swapped.

A bunch of cleanups and bug fixes were made along the way.
This commit is contained in:
Justin 2018-12-04 19:49:26 +00:00 committed by GitHub
parent b40a7c5ad6
commit a4722faf12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 25 additions and 11 deletions

View File

@ -1446,38 +1446,52 @@ def get_changed_validators(validators: List[ValidatorRecord],
""" """
# The active validators # The active validators
active_validator_indices = get_active_validator_indices(validators) active_validator_indices = get_active_validator_indices(validators)
# The total balance of active validators # The total effective balance of active validators
total_balance = sum([get_effective_balance(v) for i, v in enumerate(validators) if i in active_validator_indices]) total_balance = sum([get_effective_balance(v) for i, v in enumerate(validators) if i in active_validator_indices])
# The maximum total Gwei that can be deposited and withdrawn
max_allowable_change = max( # The maximum balance churn in Gwei (for deposits and exits separately)
2 * MAX_DEPOSIT * GWEI_PER_ETH, max_balance_churn = max(
total_balance // MAX_BALANCE_CHURN_QUOTIENT MAX_DEPOSIT * GWEI_PER_ETH,
total_balance // (2 * MAX_BALANCE_CHURN_QUOTIENT)
) )
# Go through the list start to end, depositing and withdrawing as many as possible
total_changed = 0 # Activate validators within the allowable balance churn
balance_churn = 0
for i in range(len(validators)): for i in range(len(validators)):
if validators[i].status == PENDING_ACTIVATION and validators[i].balance >= MAX_DEPOSIT: if validators[i].status == PENDING_ACTIVATION and validators[i].balance >= MAX_DEPOSIT:
# Check the balance churn would be within the allowance
balance_churn += get_effective_balance(validators[i])
if balance_churn > max_balance_churn:
break
# Activate validator
validators[i].status = ACTIVE validators[i].status = ACTIVE
validators[i].latest_status_change_slot = current_slot validators[i].latest_status_change_slot = current_slot
total_changed += get_effective_balance(validators[i])
validator_registry_delta_chain_tip = get_new_validator_registry_delta_chain_tip( validator_registry_delta_chain_tip = get_new_validator_registry_delta_chain_tip(
validator_registry_delta_chain_tip=validator_registry_delta_chain_tip, validator_registry_delta_chain_tip=validator_registry_delta_chain_tip,
index=i, index=i,
pubkey=validators[i].pubkey, pubkey=validators[i].pubkey,
flag=ACTIVATION, flag=ACTIVATION,
) )
# Exit validators within the allowable balance churn
balance_churn = 0
for i in range(len(validators)):
if validators[i].status == ACTIVE_PENDING_EXIT: if validators[i].status == ACTIVE_PENDING_EXIT:
# Check the balance churn would be within the allowance
balance_churn += get_effective_balance(validators[i])
if balance_churn > max_balance_churn:
break
# Exit validator
validators[i].status = EXITED_WITHOUT_PENALTY validators[i].status = EXITED_WITHOUT_PENALTY
validators[i].latest_status_change_slot = current_slot validators[i].latest_status_change_slot = current_slot
total_changed += get_effective_balance(validators[i])
validator_registry_delta_chain_tip = get_new_validator_registry_delta_chain_tip( validator_registry_delta_chain_tip = get_new_validator_registry_delta_chain_tip(
validator_registry_delta_chain_tip=validator_registry_delta_chain_tip, validator_registry_delta_chain_tip=validator_registry_delta_chain_tip,
index=i, index=i,
pubkey=validators[i].pubkey, pubkey=validators[i].pubkey,
flag=EXIT, flag=EXIT,
) )
if total_changed >= max_allowable_change:
break
# Calculate the total ETH that has been penalized in the last ~2-3 withdrawal periods # Calculate the total ETH that has been penalized in the last ~2-3 withdrawal periods
period_index = current_slot // COLLECTIVE_PENALTY_CALCULATION_PERIOD period_index = current_slot // COLLECTIVE_PENALTY_CALCULATION_PERIOD