# [Response] Forks/Upgrades (to prestonvanloon)
First of all, agreed that the core of this is managing a fork schedule wrt to epochs. (Note: epoch boundary is the natural place to put it imo rather than with slot granularity).
Although the intention is to generally update the fork-version to isolate domains at forks and would probably be the default functionality, it is not in fact _requisite_. There might be reasons to avoid bumping a fork version in an upgrade/fix so I would consider updating a fork in state as one of the many things you might do conditioned on an EPOCH, rather than something that's certainly updated and then everything conditioned upon fork version.
Just for context, you can only (potentially) slash across the current and previous fork. So a rapid two fork upgrade (with two changes in fork version) would reduce the slashable epoch range to that of the two recent forks. In early forks, this is probably totally fine as we expect all validators/nodes to be online during such a fork and for new nodes to sync from these recent forks so long-range attacks aren't really a concern. But still, I would be hesitant to bake that forced fork version bump into the client and instead center the logic conditioning on epochs.
(_slashing across forks is actually a hard problem if attestations modify at all across forks! having functions handle mixed-types is likely a pain not worth implementing in early eth2 forks and instead having a strong coordination of nodes on taht epoch and WSS served after the fork is a much saner path_)
Another complication in early forks (e.g. Phase 1) is that we expect types to have to modified/upgraded. A BeaconState in Phase 1 has additional and modified fields and so is not really the same as a phase 0 BeaconState. Depending on the language of the client, this will have to be handled carefully. and sharing logic across forks may be more of less of a pain. For most of these languages, this has been addressed in eth1 clients to a certain extent and instead of premising changes on epoch, it's been on block height. I encourage an investigation of the mirrored language eth1 impl to see how they handle typing/logic changes.
The things we'll have to handle in forks are:
* upgrading/modifying types
* irregular state change
* conditional logic changes
Each will be code paths conditioned on an epoch number and the complexity of exactly how each is managed will be pretty language dependent.
For type upgrades and irregular state transitions, _in the spec_ we'll probably write adhoc functions (e.g. phase1 fork upgrade) that handle such upgrades rather than trying to embed the functions in say `process_epoch`. This is because in the spec, we are managing logic on a per-fork basis. You'll see in the testing that we have a notion of a `spec` and each `spec` has within it embedded the functions for that spec. So `phase0_spec.process_epoch` is different than `phase1_spec.process_epoch`, and on some fork boundary, we'll (1) upgrade types and make irregular state trnasiitons and then (2) use a new "spec" for state transition processing. This is the cleanest path for the python/spec impl but I do not make a claim that this is the cleanest path for a client or other language.
The first planned fork is a modification of a few of the slashing/inactivity-leak penalty constants. This will manifest (at some layer) as a conditional on a few constants. e.g. `Before PENALTY_FORK, use initial constants for calcs, after PENALTY_FORK use penalty fork constants for calcs`. This is probably the easiest type of fork in early beacon chain operations. I would suspect that modifying types (e.g. adding a new field to `BeaconState`) would be much more complex depending on the language and I would recommend playing with how this will look. The dummy field I would consider adding is `BeaconState.epoch` that just tracked the epoch number in addition to slot. Very trivial change but will highlight where typing and logic changes might become a pain in your codebase.
nitpick -- Fork.version is bytes so there is no `>` operator defined. Another reason fork-epoch is the natural conditional.