mirror of
https://github.com/status-im/eth2.0-specs.git
synced 2025-01-14 04:34:43 +00:00
commit
b0dd7c38dc
@ -128,7 +128,7 @@ def get_attestation_signature(spec, state, attestation_data, privkey, custody_bi
|
||||
)
|
||||
|
||||
|
||||
def fill_aggregate_attestation(spec, state, attestation):
|
||||
def fill_aggregate_attestation(spec, state, attestation, signed=False):
|
||||
crosslink_committee = spec.get_crosslink_committee(
|
||||
state,
|
||||
attestation.data.target.epoch,
|
||||
@ -137,10 +137,14 @@ def fill_aggregate_attestation(spec, state, attestation):
|
||||
for i in range(len(crosslink_committee)):
|
||||
attestation.aggregation_bits[i] = True
|
||||
|
||||
if signed:
|
||||
sign_attestation(spec, state, attestation)
|
||||
|
||||
def add_attestation_to_state(spec, state, attestation, slot):
|
||||
|
||||
def add_attestations_to_state(spec, state, attestations, slot):
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
block.slot = slot
|
||||
for attestation in attestations:
|
||||
block.body.attestations.append(attestation)
|
||||
spec.process_slots(state, block.slot)
|
||||
sign_block(spec, state, block)
|
||||
|
@ -7,11 +7,9 @@ from eth2spec.test.helpers.state import (
|
||||
)
|
||||
from eth2spec.test.helpers.block import apply_empty_block
|
||||
from eth2spec.test.helpers.attestations import (
|
||||
add_attestation_to_state,
|
||||
fill_aggregate_attestation,
|
||||
add_attestations_to_state,
|
||||
get_valid_attestation,
|
||||
sign_attestation,
|
||||
)
|
||||
sign_attestation)
|
||||
from eth2spec.test.phase_0.epoch_processing.run_epoch_process_base import run_epoch_processing_with
|
||||
|
||||
|
||||
@ -35,8 +33,7 @@ def test_single_crosslink_update_from_current_epoch(spec, state):
|
||||
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
|
||||
fill_aggregate_attestation(spec, state, attestation)
|
||||
add_attestation_to_state(spec, state, attestation, state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||
add_attestations_to_state(spec, state, [attestation], state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||
|
||||
assert len(state.current_epoch_attestations) == 1
|
||||
|
||||
@ -56,8 +53,7 @@ def test_single_crosslink_update_from_previous_epoch(spec, state):
|
||||
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
|
||||
fill_aggregate_attestation(spec, state, attestation)
|
||||
add_attestation_to_state(spec, state, attestation, state.slot + spec.SLOTS_PER_EPOCH)
|
||||
add_attestations_to_state(spec, state, [attestation], state.slot + spec.SLOTS_PER_EPOCH)
|
||||
|
||||
assert len(state.previous_epoch_attestations) == 1
|
||||
|
||||
@ -91,11 +87,10 @@ def test_double_late_crosslink(spec, state):
|
||||
state.slot += 4
|
||||
|
||||
attestation_1 = get_valid_attestation(spec, state, signed=True)
|
||||
fill_aggregate_attestation(spec, state, attestation_1)
|
||||
|
||||
# add attestation_1 to next epoch
|
||||
next_epoch(spec, state)
|
||||
add_attestation_to_state(spec, state, attestation_1, state.slot + 1)
|
||||
add_attestations_to_state(spec, state, [attestation_1], state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||
|
||||
for _ in range(spec.SLOTS_PER_EPOCH):
|
||||
attestation_2 = get_valid_attestation(spec, state)
|
||||
@ -105,12 +100,10 @@ def test_double_late_crosslink(spec, state):
|
||||
next_slot(spec, state)
|
||||
apply_empty_block(spec, state)
|
||||
|
||||
fill_aggregate_attestation(spec, state, attestation_2)
|
||||
|
||||
# add attestation_2 in the next epoch after attestation_1 has
|
||||
# already updated the relevant crosslink
|
||||
next_epoch(spec, state)
|
||||
add_attestation_to_state(spec, state, attestation_2, state.slot + 1)
|
||||
add_attestations_to_state(spec, state, [attestation_2], state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||
|
||||
assert len(state.previous_epoch_attestations) == 1
|
||||
assert len(state.current_epoch_attestations) == 0
|
||||
@ -130,3 +123,44 @@ def test_double_late_crosslink(spec, state):
|
||||
attestation_2.data.crosslink.shard):
|
||||
assert crosslink_deltas[0][index] == 0
|
||||
assert crosslink_deltas[1][index] > 0
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_tied_crosslink_between_epochs(spec, state):
|
||||
"""
|
||||
Addresses scenario found at Interop described by this test case
|
||||
https://github.com/djrtwo/interop-test-cases/tree/master/tests/night_one_16_crosslinks
|
||||
|
||||
Ensure that ties on crosslinks between epochs are broken by previous epoch.
|
||||
"""
|
||||
prev_attestation = get_valid_attestation(spec, state)
|
||||
sign_attestation(spec, state, prev_attestation)
|
||||
|
||||
# add attestation at start of next epoch
|
||||
next_epoch(spec, state)
|
||||
add_attestations_to_state(spec, state, [prev_attestation], state.slot)
|
||||
|
||||
# create attestation from current epoch for same shard
|
||||
for _ in range(spec.SLOTS_PER_EPOCH):
|
||||
cur_attestation = get_valid_attestation(spec, state)
|
||||
if cur_attestation.data.crosslink.shard == prev_attestation.data.crosslink.shard:
|
||||
sign_attestation(spec, state, cur_attestation)
|
||||
break
|
||||
next_slot(spec, state)
|
||||
|
||||
add_attestations_to_state(spec, state, [cur_attestation], state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY)
|
||||
|
||||
shard = prev_attestation.data.crosslink.shard
|
||||
pre_crosslink = deepcopy(state.current_crosslinks[shard])
|
||||
|
||||
assert prev_attestation.data.crosslink != cur_attestation.data.crosslink
|
||||
assert state.current_crosslinks[shard] == spec.Crosslink()
|
||||
assert len(state.previous_epoch_attestations) == 1
|
||||
assert len(state.current_epoch_attestations) == 1
|
||||
|
||||
yield from run_process_crosslinks(spec, state)
|
||||
|
||||
assert state.previous_crosslinks[shard] != state.current_crosslinks[shard]
|
||||
assert pre_crosslink != state.current_crosslinks[shard]
|
||||
assert state.current_crosslinks[shard] == prev_attestation.data.crosslink
|
||||
|
@ -0,0 +1,138 @@
|
||||
from copy import deepcopy
|
||||
|
||||
from eth2spec.test.context import spec_state_test, with_all_phases
|
||||
from eth2spec.test.helpers.state import (
|
||||
next_epoch,
|
||||
next_slot,
|
||||
)
|
||||
from eth2spec.test.helpers.attestations import (
|
||||
add_attestations_to_state,
|
||||
get_valid_attestation,
|
||||
)
|
||||
from eth2spec.test.phase_0.epoch_processing.run_epoch_process_base import run_epoch_processing_with
|
||||
|
||||
|
||||
def run_process_rewards_and_penalties(spec, state):
|
||||
yield from run_epoch_processing_with(spec, state, 'process_rewards_and_penalties')
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_genesis_epoch_no_attestations_no_penalties(spec, state):
|
||||
pre_state = deepcopy(state)
|
||||
|
||||
assert spec.compute_epoch_of_slot(state.slot) == spec.GENESIS_EPOCH
|
||||
|
||||
yield from run_process_rewards_and_penalties(spec, state)
|
||||
|
||||
for index in range(len(pre_state.validators)):
|
||||
assert state.balances[index] == pre_state.balances[index]
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_genesis_epoch_full_attestations_no_rewards(spec, state):
|
||||
attestations = []
|
||||
for slot in range(spec.SLOTS_PER_EPOCH - 1):
|
||||
# create an attestation for each slot
|
||||
if slot < spec.SLOTS_PER_EPOCH:
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
attestations.append(attestation)
|
||||
# fill each created slot in state after inclusion delay
|
||||
if slot - spec.MIN_ATTESTATION_INCLUSION_DELAY >= 0:
|
||||
include_att = attestations[slot - spec.MIN_ATTESTATION_INCLUSION_DELAY]
|
||||
add_attestations_to_state(spec, state, [include_att], state.slot)
|
||||
next_slot(spec, state)
|
||||
|
||||
# ensure has not cross the epoch boundary
|
||||
assert spec.compute_epoch_of_slot(state.slot) == spec.GENESIS_EPOCH
|
||||
|
||||
pre_state = deepcopy(state)
|
||||
|
||||
yield from run_process_rewards_and_penalties(spec, state)
|
||||
|
||||
for index in range(len(pre_state.validators)):
|
||||
assert state.balances[index] == pre_state.balances[index]
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_full_attestations(spec, state):
|
||||
attestations = []
|
||||
for slot in range(spec.SLOTS_PER_EPOCH + spec.MIN_ATTESTATION_INCLUSION_DELAY):
|
||||
# create an attestation for each slot in epoch
|
||||
if slot < spec.SLOTS_PER_EPOCH:
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
attestations.append(attestation)
|
||||
# fill each created slot in state after inclusion delay
|
||||
if slot - spec.MIN_ATTESTATION_INCLUSION_DELAY >= 0:
|
||||
include_att = attestations[slot - spec.MIN_ATTESTATION_INCLUSION_DELAY]
|
||||
add_attestations_to_state(spec, state, [include_att], state.slot)
|
||||
next_slot(spec, state)
|
||||
|
||||
assert spec.compute_epoch_of_slot(state.slot) == spec.GENESIS_EPOCH + 1
|
||||
assert len(state.previous_epoch_attestations) == spec.SLOTS_PER_EPOCH
|
||||
|
||||
pre_state = deepcopy(state)
|
||||
|
||||
yield from run_process_rewards_and_penalties(spec, state)
|
||||
|
||||
attesting_indices = spec.get_unslashed_attesting_indices(state, attestations)
|
||||
assert len(attesting_indices) > 0
|
||||
for index in range(len(pre_state.validators)):
|
||||
if index in attesting_indices:
|
||||
assert state.balances[index] > pre_state.balances[index]
|
||||
else:
|
||||
assert state.balances[index] < pre_state.balances[index]
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_no_attestations_all_penalties(spec, state):
|
||||
next_epoch(spec, state)
|
||||
pre_state = deepcopy(state)
|
||||
|
||||
assert spec.compute_epoch_of_slot(state.slot) == spec.GENESIS_EPOCH + 1
|
||||
|
||||
yield from run_process_rewards_and_penalties(spec, state)
|
||||
|
||||
for index in range(len(pre_state.validators)):
|
||||
assert state.balances[index] < pre_state.balances[index]
|
||||
|
||||
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_duplicate_attestation(spec, state):
|
||||
"""
|
||||
Although duplicate attestations can be included on-chain, they should only
|
||||
be rewarded for once.
|
||||
This test addresses this issue found at Interop
|
||||
https://github.com/djrtwo/interop-test-cases/tree/master/tests/prysm_16_duplicate_attestation_rewards
|
||||
"""
|
||||
attestation = get_valid_attestation(spec, state, signed=True)
|
||||
|
||||
indexed_attestation = spec.get_indexed_attestation(state, attestation)
|
||||
participants = indexed_attestation.custody_bit_0_indices + indexed_attestation.custody_bit_1_indices
|
||||
|
||||
assert len(participants) > 0
|
||||
|
||||
single_state = deepcopy(state)
|
||||
dup_state = deepcopy(state)
|
||||
|
||||
inclusion_slot = state.slot + spec.MIN_ATTESTATION_INCLUSION_DELAY
|
||||
add_attestations_to_state(spec, single_state, [attestation], inclusion_slot)
|
||||
add_attestations_to_state(spec, dup_state, [attestation, attestation], inclusion_slot)
|
||||
|
||||
next_epoch(spec, single_state)
|
||||
next_epoch(spec, dup_state)
|
||||
|
||||
# Run non-duplicate inclusion rewards for comparision. Do not yield test vectors
|
||||
for _ in run_process_rewards_and_penalties(spec, single_state):
|
||||
pass
|
||||
|
||||
# Output duplicate inclusion to test vectors
|
||||
yield from run_process_rewards_and_penalties(spec, dup_state)
|
||||
|
||||
for index in participants:
|
||||
assert state.balances[index] < single_state.balances[index]
|
||||
assert single_state.balances[index] == dup_state.balances[index]
|
Loading…
x
Reference in New Issue
Block a user