diff --git a/specs/lightclient/beacon-chain.md b/specs/lightclient/beacon-chain.md index bb00a5c59..bcb90f756 100644 --- a/specs/lightclient/beacon-chain.md +++ b/specs/lightclient/beacon-chain.md @@ -374,7 +374,7 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None: # Participation flags participation_flags = [] - if is_matching_head and state.slot <= data.slot + MIN_ATTESTATION_INCLUSION_DELAY: + if is_matching_head and is_matching_target and state.slot <= data.slot + MIN_ATTESTATION_INCLUSION_DELAY: participation_flags.append(TIMELY_HEAD_FLAG) if is_matching_source and state.slot <= data.slot + integer_squareroot(SLOTS_PER_EPOCH): participation_flags.append(TIMELY_SOURCE_FLAG) diff --git a/tests/core/pyspec/eth2spec/test/helpers/rewards.py b/tests/core/pyspec/eth2spec/test/helpers/rewards.py index 770519384..81eb1f955 100644 --- a/tests/core/pyspec/eth2spec/test/helpers/rewards.py +++ b/tests/core/pyspec/eth2spec/test/helpers/rewards.py @@ -517,11 +517,18 @@ def run_test_full_random(spec, state, rng=Random(8020)): pending_attestation.inclusion_delay = rng.randint(1, spec.SLOTS_PER_EPOCH) else: for index in range(len(state.validators)): - # ~1/3 have bad target - state.previous_epoch_participation[index][spec.TIMELY_TARGET_FLAG] = rng.randint(0, 2) != 0 - # ~1/3 have bad head - state.previous_epoch_participation[index][spec.TIMELY_HEAD_FLAG] = rng.randint(0, 2) != 0 - # ~50% participation - state.previous_epoch_participation[index][spec.TIMELY_SOURCE_FLAG] = rng.choice([True, False]) + # ~1/3 have bad head or bad target or not timely enough + is_timely_correct_head = rng.randint(0, 2) != 0 + state.previous_epoch_participation[index][spec.TIMELY_HEAD_FLAG] = is_timely_correct_head + if is_timely_correct_head: + # If timely head, then must be timely target + state.previous_epoch_participation[index][spec.TIMELY_TARGET_FLAG] = True + # If timely head, then must be timely source + state.previous_epoch_participation[index][spec.TIMELY_SOURCE_FLAG] = True + else: + # ~50% of remaining have bad target or not timely enough + state.previous_epoch_participation[index][spec.TIMELY_TARGET_FLAG] = rng.choice([True, False]) + # ~50% of remaining have bad source or not timely enough + state.previous_epoch_participation[index][spec.TIMELY_SOURCE_FLAG] = rng.choice([True, False]) yield from run_deltas(spec, state) diff --git a/tests/core/pyspec/eth2spec/test/phase0/rewards/test_random.py b/tests/core/pyspec/eth2spec/test/phase0/rewards/test_random.py index 83c7f7905..ae44c6640 100644 --- a/tests/core/pyspec/eth2spec/test/phase0/rewards/test_random.py +++ b/tests/core/pyspec/eth2spec/test/phase0/rewards/test_random.py @@ -29,6 +29,12 @@ def test_full_random_2(spec, state): yield from rewards_helpers.run_test_full_random(spec, state, rng=Random(3030)) +@with_all_phases +@spec_state_test +def test_full_random_3(spec, state): + yield from rewards_helpers.run_test_full_random(spec, state, rng=Random(4040)) + + @with_all_phases @with_custom_state(balances_fn=low_balances, threshold_fn=lambda spec: spec.EJECTION_BALANCE) @spec_test