remove global quotient penalties from fork spec [temp]
This commit is contained in:
parent
9c75c3819d
commit
b8d3589b46
|
@ -49,7 +49,8 @@
|
||||||
This is a patch implementing the first hard fork to the beacon chain, tentatively named HF1 pending a permanent name. It has three main features:
|
This is a patch implementing the first hard fork to the beacon chain, tentatively named HF1 pending a permanent name. It has three main features:
|
||||||
|
|
||||||
* Light client support via sync committees
|
* Light client support via sync committees
|
||||||
* Incentive accounting reforms, reducing spec complexity and reducing the cost of processing chains that have very little or zero participation for a long span of epochs
|
* Incentive accounting reforms, reducing spec complexity
|
||||||
|
and [TODO] reducing the cost of processing chains that have very little or zero participation for a long span of epochs
|
||||||
* Fork choice rule changes to address weaknesses recently discovered in the existing fork choice
|
* Fork choice rule changes to address weaknesses recently discovered in the existing fork choice
|
||||||
|
|
||||||
## Constants
|
## Constants
|
||||||
|
@ -78,9 +79,7 @@ The reward fractions add up to 7/8, leaving the remaining 1/8 for proposer rewar
|
||||||
| Name | Value |
|
| Name | Value |
|
||||||
| - | - |
|
| - | - |
|
||||||
| `PARTICIPATION_FLAGS_LENGTH` | `8` |
|
| `PARTICIPATION_FLAGS_LENGTH` | `8` |
|
||||||
| `FLAGS_AND_NUMERATORS` | `((TIMELY_HEAD_FLAG, TIMELY_HEAD_NUMERATOR), (TIMELY_SOURCE_FLAG, TIMELY_SOURCE_NUMERATOR), (TIMELY_TARGET_FLAG, TIMELY_TARGET_NUMERATOR))` |
|
|
||||||
| `G2_POINT_AT_INFINITY` | `BLSSignature(b'\xc0' + b'\x00' * 95)` |
|
| `G2_POINT_AT_INFINITY` | `BLSSignature(b'\xc0' + b'\x00' * 95)` |
|
||||||
| `GWEI_PER_ETH` | `10**9` |
|
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -155,8 +154,6 @@ class BeaconState(Container):
|
||||||
# Light client sync committees
|
# Light client sync committees
|
||||||
current_sync_committee: SyncCommittee
|
current_sync_committee: SyncCommittee
|
||||||
next_sync_committee: SyncCommittee
|
next_sync_committee: SyncCommittee
|
||||||
# Denominator to real-time-updated balances (NOT effective balances!)
|
|
||||||
balance_denominator: uint64
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### New containers
|
### New containers
|
||||||
|
@ -173,23 +170,6 @@ class SyncCommittee(Container):
|
||||||
|
|
||||||
### `Predicates`
|
### `Predicates`
|
||||||
|
|
||||||
#### `get_base_reward`
|
|
||||||
|
|
||||||
*Note*: The function `get_base_reward` is modified with the removal of `BASE_REWARDS_PER_EPOCH`. Additionally, it is split into `get_base_reward_per_eth` to allow penalties to be computed to the denominator.
|
|
||||||
|
|
||||||
```python
|
|
||||||
def get_base_reward(state: BeaconState, index: ValidatorIndex) -> Gwei:
|
|
||||||
return get_base_reward_per_eth(state) * state.validators[index].effective_balance // GWEI_PER_ETH
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `get_base_reward_per_eth`
|
|
||||||
|
|
||||||
```python
|
|
||||||
def get_base_reward_per_eth(state: BeaconState) -> Gwei:
|
|
||||||
total_balance = get_total_active_balance(state)
|
|
||||||
return Gwei(GWEI_PER_ETH * BASE_REWARD_FACTOR // integer_squareroot(total_balance))
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `eth2_fast_aggregate_verify`
|
#### `eth2_fast_aggregate_verify`
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
@ -202,6 +182,21 @@ def eth2_fast_aggregate_verify(pubkeys: Sequence[BLSPubkey], message: Bytes32, s
|
||||||
return bls.FastAggregateVerify(pubkeys, message, signature)
|
return bls.FastAggregateVerify(pubkeys, message, signature)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Misc
|
||||||
|
|
||||||
|
#### `flags_and_numerators`
|
||||||
|
|
||||||
|
```python
|
||||||
|
def get_flags_and_numerators() -> Sequence[Tuple[int, int]]:
|
||||||
|
return (
|
||||||
|
(TIMELY_HEAD_FLAG, TIMELY_HEAD_NUMERATOR),
|
||||||
|
(TIMELY_SOURCE_FLAG, TIMELY_SOURCE_NUMERATOR),
|
||||||
|
(TIMELY_TARGET_FLAG, TIMELY_TARGET_NUMERATOR)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Beacon state accessors
|
### Beacon state accessors
|
||||||
|
|
||||||
#### `get_sync_committee_indices`
|
#### `get_sync_committee_indices`
|
||||||
|
@ -246,6 +241,17 @@ def get_sync_committee(state: BeaconState, epoch: Epoch) -> SyncCommittee:
|
||||||
return SyncCommittee(pubkeys=pubkeys, pubkey_aggregates=aggregates)
|
return SyncCommittee(pubkeys=pubkeys, pubkey_aggregates=aggregates)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### `get_base_reward`
|
||||||
|
|
||||||
|
*Note*: The function `get_base_reward` is modified with the removal of `BASE_REWARDS_PER_EPOCH`.
|
||||||
|
|
||||||
|
```python
|
||||||
|
def get_base_reward(state: BeaconState, index: ValidatorIndex) -> Gwei:
|
||||||
|
total_balance = get_total_active_balance(state)
|
||||||
|
effective_balance = state.validators[index].effective_balance
|
||||||
|
return Gwei(effective_balance * BASE_REWARD_FACTOR // integer_squareroot(total_balance))
|
||||||
|
```
|
||||||
|
|
||||||
#### `get_unslashed_participating_indices`
|
#### `get_unslashed_participating_indices`
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
@ -255,20 +261,24 @@ def get_unslashed_participating_indices(state: BeaconState, flag: uint8, epoch:
|
||||||
epoch_participation = state.current_epoch_participation
|
epoch_participation = state.current_epoch_participation
|
||||||
else:
|
else:
|
||||||
epoch_participation = state.previous_epoch_participation
|
epoch_participation = state.previous_epoch_participation
|
||||||
participating_indices = [index for index in get_active_validator_indices(state, epoch)
|
participating_indices = [
|
||||||
if epoch_participation[index][flag]]
|
index for index in get_active_validator_indices(state, epoch)
|
||||||
|
if epoch_participation[index][flag]
|
||||||
|
]
|
||||||
return set(filter(lambda index: not state.validators[index].slashed, participating_indices))
|
return set(filter(lambda index: not state.validators[index].slashed, participating_indices))
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `get_flag_deltas`
|
#### `get_flag_deltas`
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_flag_deltas(state: BeaconState, flag: uint8, numerator: uint64) -> Tuple[Sequence[Gwei], Gwei]:
|
def get_flag_deltas(state: BeaconState, flag: uint8, numerator: uint64) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
|
||||||
"""
|
"""
|
||||||
Computes the rewards and penalties associated with a particular duty, by scanning through the participation
|
Computes the rewards and penalties associated with a particular duty, by scanning through the participation
|
||||||
flags to determine who participated and who did not and assigning them the appropriate rewards and penalties.
|
flags to determine who participated and who did not and assigning them the appropriate rewards and penalties.
|
||||||
"""
|
"""
|
||||||
rewards = [Gwei(0)] * len(state.validators)
|
rewards = [Gwei(0)] * len(state.validators)
|
||||||
|
penalties = [Gwei(0)] * len(state.validators)
|
||||||
|
|
||||||
unslashed_participating_indices = get_unslashed_participating_indices(state, flag, get_previous_epoch(state))
|
unslashed_participating_indices = get_unslashed_participating_indices(state, flag, get_previous_epoch(state))
|
||||||
increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from balances to avoid uint64 overflow
|
increment = EFFECTIVE_BALANCE_INCREMENT # Factored out from balances to avoid uint64 overflow
|
||||||
unslashed_participating_increments = get_total_balance(state, unslashed_participating_indices) // increment
|
unslashed_participating_increments = get_total_balance(state, unslashed_participating_indices) // increment
|
||||||
|
@ -281,10 +291,12 @@ def get_flag_deltas(state: BeaconState, flag: uint8, numerator: uint64) -> Tuple
|
||||||
rewards[index] = base_reward * numerator // REWARD_DENOMINATOR
|
rewards[index] = base_reward * numerator // REWARD_DENOMINATOR
|
||||||
else:
|
else:
|
||||||
rewards[index] = (
|
rewards[index] = (
|
||||||
(base_reward * unslashed_participating_increments // active_increments + base_reward)
|
(base_reward * numerator * unslashed_participating_increments)
|
||||||
* numerator // REWARD_DENOMINATOR
|
// (active_increments * REWARD_DENOMINATOR)
|
||||||
)
|
)
|
||||||
return rewards, get_base_reward_per_eth(state) * numerator // REWARD_DENOMINATOR
|
else:
|
||||||
|
penalties[index] = base_reward * numerator // REWARD_DENOMINATOR
|
||||||
|
return rewards, penalties
|
||||||
```
|
```
|
||||||
|
|
||||||
##### `get_inactivity_penalty_deltas`
|
##### `get_inactivity_penalty_deltas`
|
||||||
|
@ -298,17 +310,21 @@ def get_inactivity_penalty_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], S
|
||||||
flags to determine who participated and who did not, applying the leak penalty globally and applying
|
flags to determine who participated and who did not, applying the leak penalty globally and applying
|
||||||
compensatory rewards to participants.
|
compensatory rewards to participants.
|
||||||
"""
|
"""
|
||||||
rewards = [Gwei(0) for _ in range(len(state.validators))]
|
penalties = [Gwei(0) for _ in range(len(state.validators))]
|
||||||
if is_in_inactivity_leak(state):
|
if is_in_inactivity_leak(state):
|
||||||
reward_numerator_sum = sum(numerator for (_, numerator) in FLAGS_AND_NUMERATORS)
|
reward_numerator_sum = sum(numerator for (_, numerator) in get_flags_and_numerators())
|
||||||
matching_target_attesting_indices = get_unslashed_participating_indices(
|
matching_target_attesting_indices = get_unslashed_participating_indices(
|
||||||
state, TIMELY_TARGET_FLAG, get_previous_epoch(state)
|
state, TIMELY_TARGET_FLAG, get_previous_epoch(state)
|
||||||
)
|
)
|
||||||
for index in get_eligible_validator_indices(state):
|
for index in get_eligible_validator_indices(state):
|
||||||
if index in matching_target_attesting_indices:
|
# If validator is performing optimally this cancels all attestation rewards for a neutral balance
|
||||||
|
penalties[index] += Gwei(get_base_reward(state, index) * reward_numerator_sum // REWARD_DENOMINATOR)
|
||||||
|
if index not in matching_target_attesting_indices:
|
||||||
effective_balance = state.validators[index].effective_balance
|
effective_balance = state.validators[index].effective_balance
|
||||||
rewards[index] += Gwei(effective_balance * get_finality_delay(state) // INACTIVITY_PENALTY_QUOTIENT)
|
penalties[index] += Gwei(effective_balance * get_finality_delay(state) // INACTIVITY_PENALTY_QUOTIENT)
|
||||||
return rewards, Gwei(GWEI_PER_ETH * get_finality_delay(state) // INACTIVITY_PENALTY_QUOTIENT)
|
|
||||||
|
rewards = [Gwei(0) for _ in range(len(state.validators))]
|
||||||
|
return rewards, penalties
|
||||||
```
|
```
|
||||||
|
|
||||||
### Block processing
|
### Block processing
|
||||||
|
@ -334,19 +350,26 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None:
|
||||||
assert data.target.epoch == compute_epoch_at_slot(data.slot)
|
assert data.target.epoch == compute_epoch_at_slot(data.slot)
|
||||||
assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= data.slot + SLOTS_PER_EPOCH
|
assert data.slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= data.slot + SLOTS_PER_EPOCH
|
||||||
assert data.index < get_committee_count_per_slot(state, data.target.epoch)
|
assert data.index < get_committee_count_per_slot(state, data.target.epoch)
|
||||||
|
|
||||||
committee = get_beacon_committee(state, data.slot, data.index)
|
committee = get_beacon_committee(state, data.slot, data.index)
|
||||||
assert len(attestation.aggregation_bits) == len(committee)
|
assert len(attestation.aggregation_bits) == len(committee)
|
||||||
|
|
||||||
if data.target.epoch == get_current_epoch(state):
|
if data.target.epoch == get_current_epoch(state):
|
||||||
epoch_participation = state.current_epoch_participation
|
epoch_participation = state.current_epoch_participation
|
||||||
justified_checkpoint = state.current_justified_checkpoint
|
justified_checkpoint = state.current_justified_checkpoint
|
||||||
else:
|
else:
|
||||||
epoch_participation = state.previous_epoch_participation
|
epoch_participation = state.previous_epoch_participation
|
||||||
justified_checkpoint = state.previous_justified_checkpoint
|
justified_checkpoint = state.previous_justified_checkpoint
|
||||||
|
|
||||||
# Matching roots
|
# Matching roots
|
||||||
is_matching_head = data.beacon_block_root == get_block_root_at_slot(state, data.slot)
|
is_matching_head = data.beacon_block_root == get_block_root_at_slot(state, data.slot)
|
||||||
is_matching_source = data.source == justified_checkpoint
|
is_matching_source = data.source == justified_checkpoint
|
||||||
is_matching_target = data.target.root == get_block_root(state, data.target.epoch)
|
is_matching_target = data.target.root == get_block_root(state, data.target.epoch)
|
||||||
assert is_matching_source
|
assert is_matching_source
|
||||||
|
|
||||||
|
# Verify signature
|
||||||
|
assert is_valid_indexed_attestation(state, get_indexed_attestation(state, attestation))
|
||||||
|
|
||||||
# Participation flags
|
# Participation flags
|
||||||
participation_flags = []
|
participation_flags = []
|
||||||
if is_matching_head and state.slot <= data.slot + MIN_ATTESTATION_INCLUSION_DELAY:
|
if is_matching_head and state.slot <= data.slot + MIN_ATTESTATION_INCLUSION_DELAY:
|
||||||
|
@ -355,18 +378,18 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None:
|
||||||
participation_flags.append(TIMELY_SOURCE_FLAG)
|
participation_flags.append(TIMELY_SOURCE_FLAG)
|
||||||
if is_matching_target and state.slot <= data.slot + SLOTS_PER_EPOCH:
|
if is_matching_target and state.slot <= data.slot + SLOTS_PER_EPOCH:
|
||||||
participation_flags.append(TIMELY_TARGET_FLAG)
|
participation_flags.append(TIMELY_TARGET_FLAG)
|
||||||
|
|
||||||
# Update epoch participation flags
|
# Update epoch participation flags
|
||||||
proposer_reward_numerator = 0
|
proposer_reward_numerator = 0
|
||||||
for index in get_attesting_indices(state, data, attestation.aggregation_bits):
|
for index in get_attesting_indices(state, data, attestation.aggregation_bits):
|
||||||
for flag, numerator in FLAGS_AND_NUMERATORS:
|
for flag, numerator in get_flags_and_numerators():
|
||||||
if flag in participation_flags and not epoch_participation[index][flag]:
|
if flag in participation_flags and not epoch_participation[index][flag]:
|
||||||
epoch_participation[index][flag] = True
|
epoch_participation[index][flag] = True
|
||||||
proposer_reward_numerator += get_base_reward(state, index) * numerator
|
proposer_reward_numerator += get_base_reward(state, index) * numerator
|
||||||
|
|
||||||
# Reward proposer
|
# Reward proposer
|
||||||
proposer_reward = Gwei(proposer_reward_numerator // (REWARD_DENOMINATOR * PROPOSER_REWARD_QUOTIENT))
|
proposer_reward = Gwei(proposer_reward_numerator // (REWARD_DENOMINATOR * PROPOSER_REWARD_QUOTIENT))
|
||||||
increase_balance(state, get_beacon_proposer_index(state), proposer_reward)
|
increase_balance(state, get_beacon_proposer_index(state), proposer_reward)
|
||||||
# Verify signature
|
|
||||||
assert is_valid_indexed_attestation(state, get_indexed_attestation(state, attestation))
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -406,6 +429,7 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None:
|
||||||
# Add validator and balance entries
|
# Add validator and balance entries
|
||||||
state.validators.append(get_validator_from_deposit(state, deposit))
|
state.validators.append(get_validator_from_deposit(state, deposit))
|
||||||
state.balances.append(amount)
|
state.balances.append(amount)
|
||||||
|
# [Added in hf-1] Initialize empty participation flags for new validator
|
||||||
state.previous_epoch_participation.append(Bitvector[PARTICIPATION_FLAGS_LENGTH]())
|
state.previous_epoch_participation.append(Bitvector[PARTICIPATION_FLAGS_LENGTH]())
|
||||||
state.current_epoch_participation.append(Bitvector[PARTICIPATION_FLAGS_LENGTH]())
|
state.current_epoch_participation.append(Bitvector[PARTICIPATION_FLAGS_LENGTH]())
|
||||||
else:
|
else:
|
||||||
|
@ -458,6 +482,7 @@ def process_justification_and_finalization(state: BeaconState) -> None:
|
||||||
current_epoch = get_current_epoch(state)
|
current_epoch = get_current_epoch(state)
|
||||||
old_previous_justified_checkpoint = state.previous_justified_checkpoint
|
old_previous_justified_checkpoint = state.previous_justified_checkpoint
|
||||||
old_current_justified_checkpoint = state.current_justified_checkpoint
|
old_current_justified_checkpoint = state.current_justified_checkpoint
|
||||||
|
|
||||||
# Process justifications
|
# Process justifications
|
||||||
state.previous_justified_checkpoint = state.current_justified_checkpoint
|
state.previous_justified_checkpoint = state.current_justified_checkpoint
|
||||||
state.justification_bits[1:] = state.justification_bits[:JUSTIFICATION_BITS_LENGTH - 1]
|
state.justification_bits[1:] = state.justification_bits[:JUSTIFICATION_BITS_LENGTH - 1]
|
||||||
|
@ -472,6 +497,7 @@ def process_justification_and_finalization(state: BeaconState) -> None:
|
||||||
state.current_justified_checkpoint = Checkpoint(epoch=current_epoch,
|
state.current_justified_checkpoint = Checkpoint(epoch=current_epoch,
|
||||||
root=get_block_root(state, current_epoch))
|
root=get_block_root(state, current_epoch))
|
||||||
state.justification_bits[0] = 0b1
|
state.justification_bits[0] = 0b1
|
||||||
|
|
||||||
# Process finalizations
|
# Process finalizations
|
||||||
bits = state.justification_bits
|
bits = state.justification_bits
|
||||||
# The 2nd/3rd/4th most recent epochs are justified, the 2nd using the 4th as source
|
# The 2nd/3rd/4th most recent epochs are justified, the 2nd using the 4th as source
|
||||||
|
@ -497,22 +523,17 @@ def process_rewards_and_penalties(state: BeaconState) -> None:
|
||||||
# No rewards are applied at the end of `GENESIS_EPOCH` because rewards are for work done in the previous epoch
|
# No rewards are applied at the end of `GENESIS_EPOCH` because rewards are for work done in the previous epoch
|
||||||
if get_current_epoch(state) == GENESIS_EPOCH:
|
if get_current_epoch(state) == GENESIS_EPOCH:
|
||||||
return
|
return
|
||||||
flag_deltas = [get_flag_deltas(state, flag, numerator) for (flag, numerator) in FLAGS_AND_NUMERATORS]
|
flag_deltas = [get_flag_deltas(state, flag, numerator) for (flag, numerator) in get_flags_and_numerators()]
|
||||||
deltas = flag_deltas + [get_inactivity_penalty_deltas(state)]
|
deltas = flag_deltas + [get_inactivity_penalty_deltas(state)]
|
||||||
for (rewards, penalty) in deltas:
|
for (rewards, penalties) in deltas:
|
||||||
for index in range(len(state.validators)):
|
for index in range(len(state.validators)):
|
||||||
increase_balance(state, ValidatorIndex(index), rewards[index])
|
increase_balance(state, ValidatorIndex(index), rewards[index])
|
||||||
# Bounds-friendly expansion for `denom *= (1 + penalty // GWEI_PER_ETH)`
|
decrease_balance(state, ValidatorIndex(index), penalties[index])
|
||||||
state.balance_denominator = (
|
|
||||||
state.balance_denominator +
|
|
||||||
penalty +
|
|
||||||
(state.balance_denominator - GWEI_PER_ETH) * penalty // GWEI_PER_ETH
|
|
||||||
)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Final updates
|
#### Final updates
|
||||||
|
|
||||||
*Note*: The function `process_final_updates` is modified to handle sync committee updates, replacement of `PendingAttestation`s with participation flags, and a sliding-denominator-aware hysteresis mechanism.
|
*Note*: The function `process_final_updates` is modified to handle sync committee updates and with the replacement of `PendingAttestation`s with participation flags.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def process_final_updates(state: BeaconState) -> None:
|
def process_final_updates(state: BeaconState) -> None:
|
||||||
|
@ -521,23 +542,21 @@ def process_final_updates(state: BeaconState) -> None:
|
||||||
# Reset eth1 data votes
|
# Reset eth1 data votes
|
||||||
if next_epoch % EPOCHS_PER_ETH1_VOTING_PERIOD == 0:
|
if next_epoch % EPOCHS_PER_ETH1_VOTING_PERIOD == 0:
|
||||||
state.eth1_data_votes = []
|
state.eth1_data_votes = []
|
||||||
# Update sync committees
|
# [Added in hf-1] Update sync committees
|
||||||
if next_epoch % EPOCHS_PER_SYNC_COMMITTEE_PERIOD == 0:
|
if next_epoch % EPOCHS_PER_SYNC_COMMITTEE_PERIOD == 0:
|
||||||
state.current_sync_committee = state.next_sync_committee
|
state.current_sync_committee = state.next_sync_committee
|
||||||
state.next_sync_committee = get_sync_committee(state, next_epoch + EPOCHS_PER_SYNC_COMMITTEE_PERIOD)
|
state.next_sync_committee = get_sync_committee(state, next_epoch + EPOCHS_PER_SYNC_COMMITTEE_PERIOD)
|
||||||
# Update effective balances with hysteresis
|
# Update effective balances with hysteresis
|
||||||
for index, validator in enumerate(state.validators):
|
for index, validator in enumerate(state.validators):
|
||||||
balance_increments = state.balances[index] * HYSTERESIS_QUOTIENT // state.balance_denominator
|
balance = state.balances[index]
|
||||||
effective_increments = validator.effective_balance // GWEI_PER_ETH * HYSTERESIS_QUOTIENT
|
HYSTERESIS_INCREMENT = uint64(EFFECTIVE_BALANCE_INCREMENT // HYSTERESIS_QUOTIENT)
|
||||||
|
DOWNWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_DOWNWARD_MULTIPLIER
|
||||||
|
UPWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_UPWARD_MULTIPLIER
|
||||||
if (
|
if (
|
||||||
balance_increments + HYSTERESIS_DOWNWARD_MULTIPLIER < effective_increments
|
balance + DOWNWARD_THRESHOLD < validator.effective_balance
|
||||||
or effective_increments + HYSTERESIS_UPWARD_MULTIPLIER < balance_increments
|
or validator.effective_balance + UPWARD_THRESHOLD < balance
|
||||||
or get_current_epoch(state) == validator.withdrawable_epoch
|
|
||||||
):
|
):
|
||||||
validator.effective_balance = (state.balances[index] // state.balance_denominator) * GWEI_PER_ETH
|
validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
|
||||||
if state.balance_denominator >= 2 * GWEI_PER_ETH:
|
|
||||||
state.balances = [x // 2 for x in state.balances]
|
|
||||||
state.balance_denominator //= 2
|
|
||||||
# Reset slashings
|
# Reset slashings
|
||||||
state.slashings[next_epoch % EPOCHS_PER_SLASHINGS_VECTOR] = Gwei(0)
|
state.slashings[next_epoch % EPOCHS_PER_SLASHINGS_VECTOR] = Gwei(0)
|
||||||
# Set randao mix
|
# Set randao mix
|
||||||
|
@ -546,6 +565,8 @@ def process_final_updates(state: BeaconState) -> None:
|
||||||
if next_epoch % (SLOTS_PER_HISTORICAL_ROOT // SLOTS_PER_EPOCH) == 0:
|
if next_epoch % (SLOTS_PER_HISTORICAL_ROOT // SLOTS_PER_EPOCH) == 0:
|
||||||
historical_batch = HistoricalBatch(block_roots=state.block_roots, state_roots=state.state_roots)
|
historical_batch = HistoricalBatch(block_roots=state.block_roots, state_roots=state.state_roots)
|
||||||
state.historical_roots.append(hash_tree_root(historical_batch))
|
state.historical_roots.append(hash_tree_root(historical_batch))
|
||||||
# Rotate current/previous epoch participation flags
|
# [Added in hf-1] Rotate current/previous epoch participation flags
|
||||||
state.previous_epoch_participation = state.current_epoch_participation
|
state.previous_epoch_participation = state.current_epoch_participation
|
||||||
state.current_epoch_participation = [Bitvector[PARTICIPATION_FLAGS_LENGTH]() for _ in range(len(state.validators))]
|
state.current_epoch_participation = [Bitvector[PARTICIPATION_FLAGS_LENGTH]() for _ in range(len(state.validators))]
|
||||||
|
# [Removed in hf-1] Rotate current/previous epoch attestations
|
||||||
|
```
|
||||||
|
|
|
@ -74,7 +74,6 @@ def upgrade_to_lightclient_patch(pre: phase0.BeaconState) -> BeaconState:
|
||||||
previous_justified_checkpoint=pre.previous_justified_checkpoint,
|
previous_justified_checkpoint=pre.previous_justified_checkpoint,
|
||||||
current_justified_checkpoint=pre.current_justified_checkpoint,
|
current_justified_checkpoint=pre.current_justified_checkpoint,
|
||||||
finalized_checkpoint=pre.finalized_checkpoint,
|
finalized_checkpoint=pre.finalized_checkpoint,
|
||||||
balance_denominator=GWEI_PER_ETH,
|
|
||||||
)
|
)
|
||||||
# Fill in sync committees
|
# Fill in sync committees
|
||||||
post.current_sync_committee = get_sync_committee(post, get_current_epoch(post))
|
post.current_sync_committee = get_sync_committee(post, get_current_epoch(post))
|
||||||
|
|
Loading…
Reference in New Issue