Skip to content

Commit

Permalink
Altair: carry-over prev epoch participation
Browse files Browse the repository at this point in the history
Closes #2314
  • Loading branch information
michaelsproul committed May 3, 2021
1 parent 2af585b commit 2f6a796
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 21 deletions.
59 changes: 38 additions & 21 deletions specs/altair/beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,37 @@ def get_unslashed_participating_indices(state: BeaconState, flag_index: int, epo
return set(filter(lambda index: not state.validators[index].slashed, participating_indices))
```

#### `get_attestation_participation_flags`

```python
def get_attestation_participation_flag_indices(state: BeaconState,
data: AttestationData,
inclusion_delay: uint64) -> Sequence[int]:
"""
Return the flag indices that are satisfied by an attestation.
"""
if data.target.epoch == get_current_epoch(state):
justified_checkpoint = state.current_justified_checkpoint
else:
justified_checkpoint = state.previous_justified_checkpoint

# Matching roots
is_matching_head = data.beacon_block_root == get_block_root_at_slot(state, data.slot)
is_matching_source = data.source == justified_checkpoint
is_matching_target = data.target.root == get_block_root(state, data.target.epoch)
assert is_matching_source

participation_flag_indices = []
if is_matching_head and is_matching_target and inclusion_delay == MIN_ATTESTATION_INCLUSION_DELAY:
participation_flag_indices.append(TIMELY_HEAD_FLAG_INDEX)
if is_matching_source and inclusion_delay <= integer_squareroot(SLOTS_PER_EPOCH):
participation_flag_indices.append(TIMELY_SOURCE_FLAG_INDEX)
if is_matching_target and inclusion_delay <= SLOTS_PER_EPOCH:
participation_flag_indices.append(TIMELY_TARGET_FLAG_INDEX)

return participation_flag_indices
```

#### `get_flag_index_deltas`

```python
Expand Down Expand Up @@ -446,32 +477,18 @@ def process_attestation(state: BeaconState, attestation: Attestation) -> None:
committee = get_beacon_committee(state, data.slot, data.index)
assert len(attestation.aggregation_bits) == len(committee)

if data.target.epoch == get_current_epoch(state):
epoch_participation = state.current_epoch_participation
justified_checkpoint = state.current_justified_checkpoint
else:
epoch_participation = state.previous_epoch_participation
justified_checkpoint = state.previous_justified_checkpoint

# Matching roots
is_matching_head = data.beacon_block_root == get_block_root_at_slot(state, data.slot)
is_matching_source = data.source == justified_checkpoint
is_matching_target = data.target.root == get_block_root(state, data.target.epoch)
assert is_matching_source
# Participation flag indices
participation_flag_indices = get_attestation_participation_flag_indices(state, data, state.slot - data.slot)

# Verify signature
assert is_valid_indexed_attestation(state, get_indexed_attestation(state, attestation))

# Participation flag indices
participation_flag_indices = []
if is_matching_head and is_matching_target and state.slot == data.slot + MIN_ATTESTATION_INCLUSION_DELAY:
participation_flag_indices.append(TIMELY_HEAD_FLAG_INDEX)
if is_matching_source and state.slot <= data.slot + integer_squareroot(SLOTS_PER_EPOCH):
participation_flag_indices.append(TIMELY_SOURCE_FLAG_INDEX)
if is_matching_target and state.slot <= data.slot + SLOTS_PER_EPOCH:
participation_flag_indices.append(TIMELY_TARGET_FLAG_INDEX)

# Update epoch participation flags
if data.target.epoch == get_current_epoch(state):
epoch_participation = state.current_epoch_participation
else:
epoch_participation = state.previous_epoch_participation

proposer_reward_numerator = 0
for index in get_attesting_indices(state, data, attestation.aggregation_bits):
for flag_index, weight in get_flag_indices_and_weights():
Expand Down
14 changes: 14 additions & 0 deletions specs/altair/fork.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ Note that for the pure Altair networks, we don't apply `upgrade_to_altair` since
After `process_slots` of Phase 0 finishes, if `state.slot % SLOTS_PER_EPOCH == 0` and `compute_epoch_at_slot(state.slot) == ALTAIR_FORK_EPOCH`, an irregular state change is made to upgrade to Altair.

```python
def translate_participation(pending_attestations: Sequence[PendingAttestation], post: BeaconState):
for attestation in pending_attestations:
# Translate attestation inclusion info to flag indices
participation_flag_indices = get_attestation_participation_flag_indices(post, attestation.data, attestation.inclusion_delay)

# Apply flags to all attesting validators
epoch_participation = post.previous_epoch_participation
for index in get_attesting_indices(post, data, pending_attestation.aggregation_bits):
for flag_index, weight in get_flag_indices_and_weights():
if flag_index in participation_flag_indices and not has_flag(epoch_participation[index], flag_index):
epoch_participation[index] = add_flag(epoch_participation[index], flag_index)

def upgrade_to_altair(pre: phase0.BeaconState) -> BeaconState:
epoch = phase0.get_current_epoch(pre)
post = BeaconState(
Expand Down Expand Up @@ -80,6 +92,8 @@ def upgrade_to_altair(pre: phase0.BeaconState) -> BeaconState:
# Inactivity
inactivity_scores=[uint64(0) for _ in range(len(pre.validators))],
)
# Fill in previous epoch participation from the pre state's pending attestations
translate_participation(pre.previous_epoch_attestations, post)
# Fill in sync committees
post.current_sync_committee = get_sync_committee(post, get_current_epoch(post))
post.next_sync_committee = get_sync_committee(post, get_current_epoch(post) + EPOCHS_PER_SYNC_COMMITTEE_PERIOD)
Expand Down

0 comments on commit 2f6a796

Please sign in to comment.