ethereum / ethereum/consensus-specs

Multiple fork transitions on same slot/epoch discard old `fork_version`s

Open
#2,902 6 comments 1 reaction 0 assignees View on GitHub
Dominant language
Python
Stars
4k
Forks
1.3k
Avg merge
1d 7h
Merged PRs (30d)
58

Description

The result is that certain messages across multiple-fork-transition-per-epoch boundaries might not be verifiable when received.

https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/fork.md#upgrading-the-state states that the fork of the upgraded state is
```python
fork=Fork(
previous_version=pre.fork.current_version,
current_version=ALTAIR_FORK_VERSION,
epoch=epoch,
),
```
https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/fork.md#upgrading-the-state states that for Bellatrix, it's:
```python
fork=Fork(
previous_version=pre.fork.current_version,
current_version=BELLATRIX_FORK_VERSION,
epoch=epoch,
),
```
And for https://github.com/ethereum/consensus-specs/blob/dev/specs/capella/fork.md#upgrading-the-state, it's
```python
fork=Fork(
previous_version=pre.fork.current_version,
current_version=CAPELLA_FORK_VERSION,
epoch=epoch,
),
```

That is, even if there was no observable beacon chain-time during which an `ALTAIR_FORK_EPOCH == BELLATRIX_FORK_EPOCH` or `BELLATRIX_FORK_EPOCH == CAPELLA_FORK_EPOCH` network existed in that intermediate fork, it will still show up as `state.fork.previous_version` of the fork to which it was upgraded, not necessarily the chronologically previous fork in question (e.g., the fork which might appear in the beacon API fork schedule).

This means that signatures of attestations, for example, from a slot or two before an `ALTAIR_FORK_EPOCH == BELLATRIX_FORK_EPOCH` or `BELLATRIX_FORK_EPOCH == CAPELLA_FORK_EPOCH` transition and then included in slots (which is supposed to be valid for up to 32 slots) cannot be verified afterward by a conforming client using https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#get_domain as written:
```python
def get_domain(state: BeaconState, domain_type: DomainType, epoch: Epoch=None) -> Domain:
...
fork_version = state.fork.previous_version if epoch < state.fork.epoch else state.fork.current_version
...
```
because `fork_version` cannot access an old enough version in `state` by then.

When fork transitions only occur on successive epochs, the attestations which trigger this are old enough to be invalid (`ATTESTATION_PROPAGATION_SLOT_RANGE == 32`), but in either the `minimal` preset or immediately-after-each-other fork transitions, there can be glitches around these fork boundaries.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.