Address Justin's #1

This commit is contained in:
vbuterin 2018-11-25 06:33:05 -05:00 committed by GitHub
parent 117b7b6953
commit 99d7f5c1b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 22 additions and 15 deletions

View File

@ -543,6 +543,13 @@ def get_attestation_participants(state: State,
We define another set of helpers to be used throughout: `bytes1(x): return x.to_bytes(1, 'big')`, `bytes2(x): return x.to_bytes(2, 'big')`, and so on for all integers, particularly 1, 2, 3, 4, 8, 32. We define another set of helpers to be used throughout: `bytes1(x): return x.to_bytes(1, 'big')`, `bytes2(x): return x.to_bytes(2, 'big')`, and so on for all integers, particularly 1, 2, 3, 4, 8, 32.
We define a function to determine the balance of a validator used for determining punishments and calculating stake:
```python
def balance_at_stake(validator):
return min(validator.balance, DEPOSIT_SIZE)
```
We define a function to "add a link" to the validator hash chain, used when a validator is added or removed: We define a function to "add a link" to the validator hash chain, used when a validator is added or removed:
```python ```python
@ -771,7 +778,7 @@ def exit_validator(index, state, block, penalize, current_slot):
whistleblower_xfer_amount = validator.deposit // SLASHING_WHISTLEBLOWER_REWARD_DENOMINATOR whistleblower_xfer_amount = validator.deposit // SLASHING_WHISTLEBLOWER_REWARD_DENOMINATOR
validator.deposit -= whistleblower_xfer_amount validator.deposit -= whistleblower_xfer_amount
get_beacon_proposer(state, block.slot).deposit += whistleblower_xfer_amount get_beacon_proposer(state, block.slot).deposit += whistleblower_xfer_amount
state.deposits_penalized_in_period[current_slot // COLLECTIVE_PENALTY_CALCULATION_PERIOD] += validator.balance state.deposits_penalized_in_period[current_slot // COLLECTIVE_PENALTY_CALCULATION_PERIOD] += balance_at_stake(validator)
else: else:
validator.status = PENDING_EXIT validator.status = PENDING_EXIT
add_validator_set_change_record(state, index, validator.pubkey, EXIT) add_validator_set_change_record(state, index, validator.pubkey, EXIT)
@ -937,21 +944,21 @@ _Note: `last_state_recalculation_slot` will always be a multiple of `CYCLE_LENGT
#### Precomputation #### Precomputation
* Let `active_validators = [state.validators[i] for i in get_active_validator_indices(state.validators)]` * Let `active_validators = [state.validators[i] for i in get_active_validator_indices(state.validators)]`
* Let `total_balance = sum([v.balance for v in active_validators])` * Let `total_balance = sum([balance_at_stake(v) for v in active_validators])`
* Let `this_cycle_attestations = [a for a in state.pending_attestations if s <= a.slot < s + CYCLE_LENGTH]` (note: this is the set of attestations _of slots in the cycle `s...s+CYCLE_LENGTH-1`_, not attestations _that got included in the chain during the cycle `s...s+CYCLE_LENGTH-1`_) * Let `this_cycle_attestations = [a for a in state.pending_attestations if s <= a.slot < s + CYCLE_LENGTH]` (note: this is the set of attestations _of slots in the cycle `s...s+CYCLE_LENGTH-1`_, not attestations _that got included in the chain during the cycle `s...s+CYCLE_LENGTH-1`_)
* Let `prev_cycle_attestations = [a for a in state.pending_attestations if s - CYCLE_LENGTH <= a.slot < s]` * Let `prev_cycle_attestations = [a for a in state.pending_attestations if s - CYCLE_LENGTH <= a.slot < s]`
* Let `this_cycle_s_attestations = [a for a in this_cycle_attestations if get_block_hash(state, block, s) in a.parent_hashes and a.justified_slot == state.justification_source]` * Let `this_cycle_s_attestations = [a for a in this_cycle_attestations if get_block_hash(state, block, s) in a.parent_hashes and a.justified_slot == state.justification_source]`
* Let `prev_s_attestations = [a for a in this_cycle_attestations + prev_cycle_attestations if get_block_hash(state, block, s - CYCLE_LENGTH) in a.parent_hashes and a.justified_slot == state.prev_cycle_justification_source]` * Let `prev_s_attestations = [a for a in this_cycle_attestations + prev_cycle_attestations if get_block_hash(state, block, s - CYCLE_LENGTH) in a.parent_hashes and a.justified_slot == state.prev_cycle_justification_source]`
* Let `s_attesters` be the union of the validator index sets given by `[get_attestation_participants(state, a) for a in this_cycle_s_attestations]` * Let `s_attesters` be the union of the validator index sets given by `[get_attestation_participants(state, a) for a in this_cycle_s_attestations]`
* Let `prev_s_attesters` be the union of the validator index sets given by `[get_attestation_participants(state, a) for a in prev_s_attestations]` * Let `prev_s_attesters` be the union of the validator index sets given by `[get_attestation_participants(state, a) for a in prev_s_attestations]`
* Let `total_balance_attesting_at_s = sum([v.balance for v in s_attesters])` * Let `total_balance_attesting_at_s = sum([balance_at_stake(v) for v in s_attesters])`
* Let `total_balance_attesting_at_prev_s = sum([v.balance for v in prev_s_attesters])` * Let `total_balance_attesting_at_prev_s = sum([balance_at_stake(v) for v in prev_s_attesters])`
* For every `ShardAndCommittee` object `obj` in `shard_and_committee_for_slots`, let: * For every `ShardAndCommittee` object `obj` in `shard_and_committee_for_slots`, let:
* `attesting_validators(obj, shard_block_hash)` be the union of the validator index sets given by `[get_attestation_participants(state, a) for a in this_cycle_attestations + prev_cycle_attestations if a.shard == obj.shard and a.shard_block_hash == shard_block_hash]` * `attesting_validators(obj, shard_block_hash)` be the union of the validator index sets given by `[get_attestation_participants(state, a) for a in this_cycle_attestations + prev_cycle_attestations if a.shard == obj.shard and a.shard_block_hash == shard_block_hash]`
* `attesting_validators(obj)` be equal to `attesting_validators(obj, shard_block_hash)` for the value of `shard_block_hash` such that `sum([v.balance for v in attesting_validators(obj, shard_block_hash)])` is maximized (ties broken by favoring lower `shard_block_hash` values) * `attesting_validators(obj)` be equal to `attesting_validators(obj, shard_block_hash)` for the value of `shard_block_hash` such that `sum([balance_at_stake(v) for v in attesting_validators(obj, shard_block_hash)])` is maximized (ties broken by favoring lower `shard_block_hash` values)
* `total_attesting_balance(obj)` be the maximal sum balance * `total_attesting_balance(obj)` be the maximal sum balance
* `winning_hash(obj)` be the winning `shard_block_hash` value * `winning_hash(obj)` be the winning `shard_block_hash` value
* `total_balance(obj) = sum([v.balance for v in obj.committee])` * `total_balance(obj) = sum([balance_at_stake(v) for v in obj.committee])`
Let `inclusion_slot(a)` equal the slot in which attestation `a` was included, and `inclusion_distance(a) = inclusion_slot(a) - a.slot`. Let `inclusion_slot(v)` equal `inclusion_distance(a)` for the attestation `a` where `v` is in `get_attestation_participants(state, a)`, and define `inclusion_distance(v)` similarly. We define a function `adjust_for_inclusion_distance(magnitude, dist)` which adjusts the reward of an attestation based on how long it took to get included (the longer, the lower the reward). Returns a value between 0 and `magnitude` Let `inclusion_slot(a)` equal the slot in which attestation `a` was included, and `inclusion_distance(a) = inclusion_slot(a) - a.slot`. Let `inclusion_slot(v)` equal `inclusion_distance(a)` for the attestation `a` where `v` is in `get_attestation_participants(state, a)`, and define `inclusion_distance(v)` similarly. We define a function `adjust_for_inclusion_distance(magnitude, dist)` which adjusts the reward of an attestation based on how long it took to get included (the longer, the lower the reward). Returns a value between 0 and `magnitude`
@ -985,22 +992,22 @@ Note: When applying penalties in the following balance recalculations implemente
Case 1: `time_since_finality <= 4 * CYCLE_LENGTH`: Case 1: `time_since_finality <= 4 * CYCLE_LENGTH`:
* Any validator `V` in `prev_s_attesters` gains `adjust_for_inclusion_distance(V.balance // reward_quotient * (prev_s_attesters - total_balance) // total_balance, inclusion_distance(V))``. * Any validator `V` in `prev_s_attesters` gains `adjust_for_inclusion_distance(balance_at_stake(V) // reward_quotient * (prev_s_attesters - total_balance) // total_balance, inclusion_distance(V))``.
* All other active validators lose `V.balance // reward_quotient`. * Any active validator `V` not in `prev_s_attesters` loses `balance_at_stake(V) // reward_quotient`.
Case 2: `time_since_finality > 4 * CYCLE_LENGTH`: Case 2: `time_since_finality > 4 * CYCLE_LENGTH`:
* Any validator in `prev_s_attesters` sees their balance unchanged. * Any validator in `prev_s_attesters` sees their balance unchanged.
* All other active validators, and validators with `status == PENALIZED`, lose `V.balance // reward_quotient + V.balance * time_since_finality // quadratic_penalty_quotient`. * Any active validator `V` not in `prev_s_attesters`, and any validator with `status == PENALIZED`, loses `balance_at_stake(V) // reward_quotient + balance_at_stake(V) * time_since_finality // quadratic_penalty_quotient`.
For each `V` in `prev_s_attesters`, the validator `proposer = get_beacon_proposer(state, inclusion_slot(V))` gains `proposer.balance // INCLUDER_REWARD_QUOTIENT`. For each `V` in `prev_s_attesters`, the validator `proposer = get_beacon_proposer(state, inclusion_slot(V))` gains `balance_at_stake(proposer) // INCLUDER_REWARD_QUOTIENT`.
#### Balance recalculations related to crosslink rewards #### Balance recalculations related to crosslink rewards
For every `ShardAndCommittee` object `obj` in `shard_and_committee_for_slots[:CYCLE_LENGTH]` (ie. the objects corresponding to the slot before the current one), for each `v in obj.committee`, where `V = state.validators[b]` adjust balances as follows: For every `ShardAndCommittee` object `obj` in `shard_and_committee_for_slots[:CYCLE_LENGTH]` (ie. the objects corresponding to the slot before the current one), for each `v in obj.committee`, where `V = state.validators[b]` adjust balances as follows:
* If `v in attesting_validators(obj)`, `V.balance += adjust_for_inclusion_distance(V.balance // reward_quotient * total_attesting_balance(obj) // total_balance(obj)), inclusion_distance(V))`. * If `v in attesting_validators(obj)`, `V.balance += adjust_for_inclusion_distance(balance_at_stake(V) // reward_quotient * total_attesting_balance(obj) // total_balance(obj)), inclusion_distance(V))`.
* If `v not in attesting_validators(obj)`, `V.balance -= V.balance // reward_quotient`. * If `v not in attesting_validators(obj)`, `V.balance -= balance_at_stake(V) // reward_quotient`.
#### PoW chain related rules #### PoW chain related rules
@ -1053,7 +1060,7 @@ def change_validators(validators: List[ValidatorRecord], current_slot: int) -> N
# The active validator set # The active validator set
active_validators = get_active_validator_indices(validators) active_validators = get_active_validator_indices(validators)
# The total balance of active validators # The total balance of active validators
total_balance = sum([v.balance for i, v in enumerate(validators) if i in active_validators]) total_balance = sum([balance_at_stake(v) for i, v in enumerate(validators) if i in active_validators])
# The maximum total wei that can deposit+withdraw # The maximum total wei that can deposit+withdraw
max_allowable_change = max( max_allowable_change = max(
2 * DEPOSIT_SIZE * GWEI_PER_ETH, 2 * DEPOSIT_SIZE * GWEI_PER_ETH,
@ -1074,7 +1081,7 @@ def change_validators(validators: List[ValidatorRecord], current_slot: int) -> N
if validators[i].status == PENDING_EXIT: if validators[i].status == PENDING_EXIT:
validators[i].status = PENDING_WITHDRAW validators[i].status = PENDING_WITHDRAW
validators[i].exit_slot = current_slot validators[i].exit_slot = current_slot
total_changed += validators[i].balance total_changed += balance_at_stake(validators[i])
add_validator_set_change_record( add_validator_set_change_record(
state=state, state=state,
index=i, index=i,
@ -1100,7 +1107,7 @@ def change_validators(validators: List[ValidatorRecord], current_slot: int) -> N
withdrawable_validators = sorted(filter(withdrawable, validators), key=lambda v: v.exit_seq) withdrawable_validators = sorted(filter(withdrawable, validators), key=lambda v: v.exit_seq)
for v in withdrawable_validators[:WITHDRAWALS_PER_CYCLE]: for v in withdrawable_validators[:WITHDRAWALS_PER_CYCLE]:
if v.status == PENALIZED: if v.status == PENALIZED:
v.balance -= v.balance * min(total_penalties * 3, total_balance) // total_balance v.balance -= balance_at_stake(v) * min(total_penalties * 3, total_balance) // total_balance
v.status = WITHDRAWN v.status = WITHDRAWN
v.exit_slot = current_slot v.exit_slot = current_slot