add baseline get_target_deltas tests
This commit is contained in:
parent
4a086fba5c
commit
5f18dd778c
|
@ -1341,6 +1341,8 @@ def process_justification_and_finalization(state: BeaconState) -> None:
|
||||||
|
|
||||||
#### Rewards and penalties
|
#### Rewards and penalties
|
||||||
|
|
||||||
|
##### Helpers
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_base_reward(state: BeaconState, index: ValidatorIndex) -> Gwei:
|
def get_base_reward(state: BeaconState, index: ValidatorIndex) -> Gwei:
|
||||||
total_balance = get_total_active_balance(state)
|
total_balance = get_total_active_balance(state)
|
||||||
|
@ -1376,20 +1378,31 @@ def compute_attestation_component_deltas(state: BeaconState,
|
||||||
return rewards, penalties
|
return rewards, penalties
|
||||||
```
|
```
|
||||||
|
|
||||||
|
##### Components of attestation deltas
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_source_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
|
def get_source_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
|
||||||
|
"""
|
||||||
|
Return attester micro-rewards/penalties for source-vote for each validator.
|
||||||
|
"""
|
||||||
matching_source_attestations = get_matching_source_attestations(state, get_previous_epoch(state))
|
matching_source_attestations = get_matching_source_attestations(state, get_previous_epoch(state))
|
||||||
return compute_attestation_component_deltas(state, matching_source_attestations)
|
return compute_attestation_component_deltas(state, matching_source_attestations)
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_target_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
|
def get_target_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
|
||||||
|
"""
|
||||||
|
Return attester micro-rewards/penalties for target-vote for each validator.
|
||||||
|
"""
|
||||||
matching_target_attestations = get_matching_target_attestations(state, get_previous_epoch(state))
|
matching_target_attestations = get_matching_target_attestations(state, get_previous_epoch(state))
|
||||||
return compute_attestation_component_deltas(state, matching_target_attestations)
|
return compute_attestation_component_deltas(state, matching_target_attestations)
|
||||||
```
|
```
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_head_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
|
def get_head_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
|
||||||
|
"""
|
||||||
|
Return attester micro-rewards/penalties for head-vote for each validator.
|
||||||
|
"""
|
||||||
matching_head_attestations = get_matching_source_attestations(state, get_previous_epoch(state))
|
matching_head_attestations = get_matching_source_attestations(state, get_previous_epoch(state))
|
||||||
return compute_attestation_component_deltas(state, matching_head_attestations)
|
return compute_attestation_component_deltas(state, matching_head_attestations)
|
||||||
```
|
```
|
||||||
|
@ -1397,7 +1410,7 @@ def get_head_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]
|
||||||
```python
|
```python
|
||||||
def get_inclusion_delay_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
|
def get_inclusion_delay_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
|
||||||
"""
|
"""
|
||||||
Return proposer and inclusion delay micro-rewards.
|
Return proposer and inclusion delay micro-rewards/penalties for each validator.
|
||||||
"""
|
"""
|
||||||
rewards = [Gwei(0) for _ in range(len(state.validators))]
|
rewards = [Gwei(0) for _ in range(len(state.validators))]
|
||||||
penalties = [Gwei(0) for _ in range(len(state.validators))]
|
penalties = [Gwei(0) for _ in range(len(state.validators))]
|
||||||
|
@ -1417,7 +1430,7 @@ def get_inclusion_delay_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequ
|
||||||
```python
|
```python
|
||||||
def get_inactivity_penalty_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
|
def get_inactivity_penalty_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
|
||||||
"""
|
"""
|
||||||
Return inactivity penalty.
|
Return inactivity reward/penalty deltas for each validator.
|
||||||
"""
|
"""
|
||||||
rewards = [Gwei(0) for _ in range(len(state.validators))]
|
rewards = [Gwei(0) for _ in range(len(state.validators))]
|
||||||
penalties = [Gwei(0) for _ in range(len(state.validators))]
|
penalties = [Gwei(0) for _ in range(len(state.validators))]
|
||||||
|
@ -1434,8 +1447,13 @@ def get_inactivity_penalty_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], S
|
||||||
return rewards, penalties
|
return rewards, penalties
|
||||||
```
|
```
|
||||||
|
|
||||||
|
##### `get_attestation_deltas`
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def get_attestation_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
|
def get_attestation_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence[Gwei]]:
|
||||||
|
"""
|
||||||
|
Return attestation reward/penalty deltas for each validator.
|
||||||
|
"""
|
||||||
source_rewards, source_penalties = get_source_deltas(state)
|
source_rewards, source_penalties = get_source_deltas(state)
|
||||||
target_rewards, target_penalties = get_target_deltas(state)
|
target_rewards, target_penalties = get_target_deltas(state)
|
||||||
head_rewards, head_penalties = get_head_deltas(state)
|
head_rewards, head_penalties = get_head_deltas(state)
|
||||||
|
@ -1461,6 +1479,8 @@ def get_attestation_deltas(state: BeaconState) -> Tuple[Sequence[Gwei], Sequence
|
||||||
return rewards, penalties
|
return rewards, penalties
|
||||||
```
|
```
|
||||||
|
|
||||||
|
##### `process_rewards_and_penalties`
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def process_rewards_and_penalties(state: BeaconState) -> None:
|
def process_rewards_and_penalties(state: BeaconState) -> None:
|
||||||
if get_current_epoch(state) == GENESIS_EPOCH:
|
if get_current_epoch(state) == GENESIS_EPOCH:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from eth2spec.test.context import expect_assertion_error, PHASE0
|
from eth2spec.test.context import expect_assertion_error, PHASE0
|
||||||
from eth2spec.test.helpers.state import state_transition_and_sign_block
|
from eth2spec.test.helpers.state import state_transition_and_sign_block, next_epoch, next_slot
|
||||||
from eth2spec.test.helpers.block import build_empty_block_for_next_slot
|
from eth2spec.test.helpers.block import build_empty_block_for_next_slot
|
||||||
from eth2spec.test.helpers.keys import privkeys
|
from eth2spec.test.helpers.keys import privkeys
|
||||||
from eth2spec.utils import bls
|
from eth2spec.utils import bls
|
||||||
|
@ -278,3 +278,34 @@ def next_epoch_with_attestations(spec,
|
||||||
signed_blocks.append(signed_block)
|
signed_blocks.append(signed_block)
|
||||||
|
|
||||||
return state, signed_blocks, post_state
|
return state, signed_blocks, post_state
|
||||||
|
|
||||||
|
|
||||||
|
def prepare_state_with_full_attestations(spec, state, empty=False):
|
||||||
|
"""
|
||||||
|
Fill ``state`` with maximally full attestations.
|
||||||
|
Move to the start of the next epoch to ensure full epoch worth.
|
||||||
|
"""
|
||||||
|
# Go to start of next epoch to ensure can have full participation
|
||||||
|
next_epoch(spec, state)
|
||||||
|
|
||||||
|
start_slot = state.slot
|
||||||
|
start_epoch = spec.get_current_epoch(state)
|
||||||
|
next_epoch_start_slot = spec.compute_start_slot_at_epoch(start_epoch + 1)
|
||||||
|
attestations = []
|
||||||
|
for _ in range(spec.SLOTS_PER_EPOCH + spec.MIN_ATTESTATION_INCLUSION_DELAY):
|
||||||
|
# create an attestation for each index in each slot in epoch
|
||||||
|
if state.slot < next_epoch_start_slot:
|
||||||
|
for committee_index in range(spec.get_committee_count_at_slot(state, state.slot)):
|
||||||
|
attestation = get_valid_attestation(spec, state, index=committee_index, empty=empty, signed=True)
|
||||||
|
attestations.append(attestation)
|
||||||
|
# fill each created slot in state after inclusion delay
|
||||||
|
if state.slot >= start_slot + spec.MIN_ATTESTATION_INCLUSION_DELAY:
|
||||||
|
inclusion_slot = state.slot - spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||||
|
include_attestations = [att for att in attestations if att.data.slot == inclusion_slot]
|
||||||
|
add_attestations_to_state(spec, state, include_attestations, state.slot)
|
||||||
|
next_slot(spec, state)
|
||||||
|
|
||||||
|
assert state.slot == next_epoch_start_slot + spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||||
|
assert len(state.previous_epoch_attestations) == len(attestations)
|
||||||
|
|
||||||
|
return attestations
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
from eth2spec.test.context import with_all_phases, spec_state_test
|
||||||
|
from eth2spec.test.helpers.attestations import prepare_state_with_full_attestations
|
||||||
|
|
||||||
|
|
||||||
|
def run_get_target_deltas(spec, state):
|
||||||
|
"""
|
||||||
|
Run ``process_block_header``, yielding:
|
||||||
|
- pre-state ('pre')
|
||||||
|
- rewards ('rewards')
|
||||||
|
- penalties ('penalties')
|
||||||
|
"""
|
||||||
|
yield 'pre', state
|
||||||
|
|
||||||
|
rewards, penalties = spec.get_target_deltas(state)
|
||||||
|
|
||||||
|
yield 'rewards', rewards
|
||||||
|
yield 'penalties', penalties
|
||||||
|
|
||||||
|
matching_target_attestations = spec.get_matching_target_attestations(state, spec.get_previous_epoch(state))
|
||||||
|
matching_target_indices = spec.get_unslashed_attesting_indices(state, matching_target_attestations)
|
||||||
|
for index in spec.get_eligible_validator_indices(state):
|
||||||
|
if index in matching_target_indices and not state.validators[index].slashed:
|
||||||
|
assert rewards[index] > 0
|
||||||
|
assert penalties[index] == 0
|
||||||
|
else:
|
||||||
|
assert rewards[index] == 0
|
||||||
|
assert penalties[index] > 0
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_empty(spec, state):
|
||||||
|
# Do not add any attestations to state
|
||||||
|
|
||||||
|
yield from run_get_target_deltas(spec, state)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_full_all_correct(spec, state):
|
||||||
|
prepare_state_with_full_attestations(spec, state)
|
||||||
|
|
||||||
|
yield from run_get_target_deltas(spec, state)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_full_half_correct(spec, state):
|
||||||
|
prepare_state_with_full_attestations(spec, state)
|
||||||
|
|
||||||
|
# Make half of pending attestations have bad target
|
||||||
|
for pending_attestation in state.previous_epoch_attestations[:len(state.previous_epoch_attestations) // 2]:
|
||||||
|
pending_attestation.data.target.root = b'\x66'*32
|
||||||
|
|
||||||
|
yield from run_get_target_deltas(spec, state)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_half_full(spec, state):
|
||||||
|
prepare_state_with_full_attestations(spec, state)
|
||||||
|
|
||||||
|
# Remove half of attestations
|
||||||
|
state.previous_epoch_attestations = state.previous_epoch_attestations[:len(state.previous_epoch_attestations) // 2]
|
||||||
|
|
||||||
|
yield from run_get_target_deltas(spec, state)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_one_correct(spec, state):
|
||||||
|
prepare_state_with_full_attestations(spec, state)
|
||||||
|
|
||||||
|
# Remove half of attestations
|
||||||
|
state.previous_epoch_attestations = state.previous_epoch_attestations[:1]
|
||||||
|
|
||||||
|
yield from run_get_target_deltas(spec, state)
|
||||||
|
|
||||||
|
|
||||||
|
@with_all_phases
|
||||||
|
@spec_state_test
|
||||||
|
def test_with_slashed_validators(spec, state):
|
||||||
|
prepare_state_with_full_attestations(spec, state)
|
||||||
|
|
||||||
|
# Slash half of validators
|
||||||
|
for validator in state.validators:
|
||||||
|
validator.slashed = True
|
||||||
|
|
||||||
|
yield from run_get_target_deltas(spec, state)
|
||||||
|
|
||||||
|
def test_some_zero_balances(spec, state):
|
||||||
|
|
|
@ -12,6 +12,7 @@ from eth2spec.test.helpers.state import (
|
||||||
from eth2spec.test.helpers.attestations import (
|
from eth2spec.test.helpers.attestations import (
|
||||||
add_attestations_to_state,
|
add_attestations_to_state,
|
||||||
get_valid_attestation,
|
get_valid_attestation,
|
||||||
|
prepare_state_with_full_attestations,
|
||||||
)
|
)
|
||||||
from eth2spec.test.helpers.attester_slashings import get_indexed_attestation_participants
|
from eth2spec.test.helpers.attester_slashings import get_indexed_attestation_participants
|
||||||
from eth2spec.test.phase_0.epoch_processing.run_epoch_process_base import run_epoch_processing_with
|
from eth2spec.test.phase_0.epoch_processing.run_epoch_process_base import run_epoch_processing_with
|
||||||
|
@ -21,33 +22,6 @@ def run_process_rewards_and_penalties(spec, state):
|
||||||
yield from run_epoch_processing_with(spec, state, 'process_rewards_and_penalties')
|
yield from run_epoch_processing_with(spec, state, 'process_rewards_and_penalties')
|
||||||
|
|
||||||
|
|
||||||
def prepare_state_with_full_attestations(spec, state, empty=False):
|
|
||||||
# Go to start of next epoch to ensure can have full participation
|
|
||||||
next_epoch(spec, state)
|
|
||||||
|
|
||||||
start_slot = state.slot
|
|
||||||
start_epoch = spec.get_current_epoch(state)
|
|
||||||
next_epoch_start_slot = spec.compute_start_slot_at_epoch(start_epoch + 1)
|
|
||||||
attestations = []
|
|
||||||
for _ in range(spec.SLOTS_PER_EPOCH + spec.MIN_ATTESTATION_INCLUSION_DELAY):
|
|
||||||
# create an attestation for each index in each slot in epoch
|
|
||||||
if state.slot < next_epoch_start_slot:
|
|
||||||
for committee_index in range(spec.get_committee_count_at_slot(state, state.slot)):
|
|
||||||
attestation = get_valid_attestation(spec, state, index=committee_index, empty=empty, signed=True)
|
|
||||||
attestations.append(attestation)
|
|
||||||
# fill each created slot in state after inclusion delay
|
|
||||||
if state.slot >= start_slot + spec.MIN_ATTESTATION_INCLUSION_DELAY:
|
|
||||||
inclusion_slot = state.slot - spec.MIN_ATTESTATION_INCLUSION_DELAY
|
|
||||||
include_attestations = [att for att in attestations if att.data.slot == inclusion_slot]
|
|
||||||
add_attestations_to_state(spec, state, include_attestations, state.slot)
|
|
||||||
next_slot(spec, state)
|
|
||||||
|
|
||||||
assert state.slot == next_epoch_start_slot + spec.MIN_ATTESTATION_INCLUSION_DELAY
|
|
||||||
assert len(state.previous_epoch_attestations) == len(attestations)
|
|
||||||
|
|
||||||
return attestations
|
|
||||||
|
|
||||||
|
|
||||||
@with_phases(['phase0'])
|
@with_phases(['phase0'])
|
||||||
@spec_state_test
|
@spec_state_test
|
||||||
def test_genesis_epoch_no_attestations_no_penalties(spec, state):
|
def test_genesis_epoch_no_attestations_no_penalties(spec, state):
|
||||||
|
|
Loading…
Reference in New Issue