Implemented withdrawal rate limit in place of wihdrawal delay

This commit is contained in:
Vitalik Buterin 2018-11-05 07:37:07 -05:00
parent a6f8bdea66
commit eb1e8311c3
No known key found for this signature in database
GPG Key ID: A99D082A6179F987
1 changed files with 24 additions and 12 deletions

View File

@ -42,7 +42,9 @@ The primary source of load on the beacon chain are "attestations". Attestations
| `MIN_VALIDATOR_SET_CHANGE_INTERVAL` | 2**8 (= 256) | slots | ~1.1 hours | | `MIN_VALIDATOR_SET_CHANGE_INTERVAL` | 2**8 (= 256) | slots | ~1.1 hours |
| `RANDAO_SLOTS_PER_LAYER` | 2**12 (= 4096) | slots | ~18 hours | | `RANDAO_SLOTS_PER_LAYER` | 2**12 (= 4096) | slots | ~18 hours |
| `SQRT_E_DROP_TIME` | 2**16 (= 65,536) | slots | ~12 days | | `SQRT_E_DROP_TIME` | 2**16 (= 65,536) | slots | ~12 days |
| `WITHDRAWAL_PERIOD` | 2**19 (= 524,288) | slots | ~97 days | | `MIN_WITHDRAWAL_PERIOD` | 2**12 (= 4096) | slots | ~18 hours |
| `WITHDRAWALS_PER_CYCLE` | 8 | - | 4.3m ETH in ~6 months |
| `COLLECTIVE_PENALTY_CALCULATION_PERIOD` | 2**19 (= 524,288) | slots | ~3 months |
| `BASE_REWARD_QUOTIENT` | 2**15 (= 32,768) | — | | `BASE_REWARD_QUOTIENT` | 2**15 (= 32,768) | — |
| `MAX_VALIDATOR_CHURN_QUOTIENT` | 2**5 (= 32) | — | | `MAX_VALIDATOR_CHURN_QUOTIENT` | 2**5 (= 32) | — |
| `LOGOUT_MESSAGE` | `"LOGOUT"` | — | | `LOGOUT_MESSAGE` | `"LOGOUT"` | — |
@ -210,6 +212,8 @@ The `CrystallizedState` has the following fields:
'deposits_penalized_in_period': ['uint32'], 'deposits_penalized_in_period': ['uint32'],
# Hash chain of validator set changes (for light clients to easily track deltas) # Hash chain of validator set changes (for light clients to easily track deltas)
'validator_set_delta_hash_chain': 'hash32' 'validator_set_delta_hash_chain': 'hash32'
# Current sequence number for withdrawals
'current_exit_seq': 'uint64',
# Parameters relevant to hard forks / versioning. # Parameters relevant to hard forks / versioning.
# Should be updated only by hard forks. # Should be updated only by hard forks.
'pre_fork_version': 'uint32', 'pre_fork_version': 'uint32',
@ -238,6 +242,8 @@ A `ValidatorRecord` has the following fields:
'status': 'uint8', 'status': 'uint8',
# Slot when validator exited (or 0) # Slot when validator exited (or 0)
'exit_slot': 'uint64' 'exit_slot': 'uint64'
# Sequence number when validator exited (or 0)
'exit_seq': 'uint64'
} }
``` ```
@ -584,7 +590,8 @@ def add_validator(validators: List[ValidatorRecord],
randao_last_change=current_slot, randao_last_change=current_slot,
balance=DEPOSIT_SIZE * GWEI_PER_ETH, balance=DEPOSIT_SIZE * GWEI_PER_ETH,
status=status, status=status,
exit_slot=0 exit_slot=0,
exit_seq=0
) )
index = min_empty_validator(validators) index = min_empty_validator(validators)
if index is None: if index is None:
@ -601,9 +608,11 @@ def add_validator(validators: List[ValidatorRecord],
def exit_validator(index, crystallized_state, penalize, current_slot): def exit_validator(index, crystallized_state, penalize, current_slot):
validator = crystallized_state.validators[index] validator = crystallized_state.validators[index]
validator.exit_slot = current_slot validator.exit_slot = current_slot
validator.exit_seq = crystallized_state.current_exit_seq
crystallized_state.current_exit_seq += 1
if penalize: if penalize:
validator.status = PENALIZED validator.status = PENALIZED
crystallized_state.deposits_penalized_in_period[current_slot // WITHDRAWAL_PERIOD] += validator.balance crystallized_state.deposits_penalized_in_period[current_slot // COLLECTIVE_PENALTY_CALCULATION_PERIOD] += validator.balance
else: else:
validator.status = PENDING_EXIT validator.status = PENDING_EXIT
add_validator_set_change_record(crystallized_state, index, validator.pubkey, EXIT) add_validator_set_change_record(crystallized_state, index, validator.pubkey, EXIT)
@ -783,7 +792,7 @@ def change_validators(validators: List[ValidatorRecord]) -> None:
break 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 // WITHDRAWAL_PERIOD period_index = current_slot // COLLECTIVE_PENALTY_CALCULATION_PERIOD
total_penalties = ( total_penalties = (
(crystallized_state.deposits_penalized_in_period[period_index]) + (crystallized_state.deposits_penalized_in_period[period_index]) +
(crystallized_state.deposits_penalized_in_period[period_index - 1] if period_index >= 1 else 0) + (crystallized_state.deposits_penalized_in_period[period_index - 1] if period_index >= 1 else 0) +
@ -791,15 +800,18 @@ def change_validators(validators: List[ValidatorRecord]) -> None:
) )
# Separate loop to withdraw validators that have been logged out for long enough, and # Separate loop to withdraw validators that have been logged out for long enough, and
# calculate their penalties if they were slashed # calculate their penalties if they were slashed
for i in range(len(validators)):
if validators[i].status in (PENDING_WITHDRAW, PENALIZED) and current_slot >= validators[i].exit_slot + WITHDRAWAL_PERIOD:
if validators[i].status == PENALIZED:
validators[i].balance -= validators[i].balance * min(total_penalties * 3, total_balance) // total_balance
validators[i].status = WITHDRAWN
withdraw_amount = validators[i].balance def withdrawable(v):
... return v.status in (PENDING_WITHDRAW, PENALIZED) and current_slot >= v.exit_slot + MIN_WITHDRAWAL_PERIOD
# STUB: withdraw to shard chain
withdrawable_validators = sorted(filter(withdrawable, validators), key=lambda v: v.exit_seq)
for v in withdrawable_validators[:WITHDRAWALS_PER_CYCLE]:
if v.status == PENALIZED:
v.balance -= v.balance * min(total_penalties * 3, total_balance) // total_balance
v.status = WITHDRAWN
withdraw_amount = v.balance
...
# STUB: withdraw to shard chain
``` ```
Finally: Finally: