|
| 1 | +# Hard Forks in Cardano |
| 2 | + |
| 3 | +## Introduction |
| 4 | + |
| 5 | +This document details how the Cardano node handles a [hard fork](https://en.wikipedia.org/wiki/Fork_(blockchain)#Hard_fork). |
| 6 | + |
| 7 | +Cardano mainnet is intended to hard fork when and only when the major component of the [`protocol version` protocol parameter](https://github.com/IntersectMBO/cardano-ledger/blob/2ff5fa4e8c6b773748799981ef44ef6a62cd5c92/libs/cardano-ledger-core/src/Cardano/Ledger/Core/PParams.hs#L350) changes. |
| 8 | +As an updatable protocol parameter, the protocol version can only change due to on-chain governance [^updatable-protocol-parameters], and in practice the major protocol version should only increase by one when it changes and the lesser components should be reset to zero. |
| 9 | + |
| 10 | +- The requirement that a major protocol version change implies a hard fork and that it only ever increments by one and resets the lessers is merely the traditional semantics of the major component of a version, ie _backwards-incompatibility_ (aka _breaking_ change). |
| 11 | + |
| 12 | +- The requirement of on-chain governance for each hard fork means that --- as of the arrival of decentralized governance to the Cardano mainnet chain --- it's the community that decides when to transition to the next iteration of the protocol rules and/or ledger rules, ie when to abandon any nodes that have not yet updated their software in preparation for the hard fork. |
| 13 | + |
| 14 | +There are other Cardano networks besides mainnet, notably the testnets. |
| 15 | +By their essential nature, though, testnets should also use mainnet's mapping between each major protocol version number and the corresponding pair of protocol rules and ledger rules. |
| 16 | +On the other hand, these other networks must be able to hard fork at different times than mainnet does --- the testnets should have hard forked successfully before mainnet hard forks! |
| 17 | +Since the testnet governance and mainnet governance are independent, the determination of the hard fork timing via on-chain governance immediately enables it to vary on different networks' chains. |
| 18 | + |
| 19 | +## Eras |
| 20 | + |
| 21 | +A hard fork is the result of the nodes' developers introducing backwards-incompatible changes [^change-decisions] and the community ultimately choosing to adopt them by increasing the major protocol version parameter via on-chain governance [^frame-rule]. |
| 22 | +When those developers design and implement such changes, they determine whether the changes are easy to maintain as variations within the existing code. |
| 23 | +If so, then the hard fork is ultimately toggling some conditionals within the code. |
| 24 | +If the changes are not so simple, the Cardano developers instead introduce a new _era_ within the code [^roadmap-disambiguation]. |
| 25 | + |
| 26 | +Each era defines some new types and rules that are independent within the code from the existing eras. |
| 27 | +For example, the [Conway era introduces](https://docs.cardano.org/about-cardano/evolution/upgrades/chang) many new parts of the ledger state, transaction types, corresponding rules, etc that the preceding era does not have, and so the architects decided to explicitly separate the Conway code from the old code as a new era. |
| 28 | +The Ledger and Consensus infrastructure code is defined so that each era can flexibly reuse whichever of the older eras' features it does not supersede. |
| 29 | +Several eras coexist sequentially on the Cardano chain; a hard fork that takes one step within that sequence is called an _era transition_. |
| 30 | + |
| 31 | +Every hard fork is either an era transition or an _intra-era hard fork_ [^accidentals]. |
| 32 | +Intra-era hard forks only introduce changes with a small effect on the code, eg a few easy-to-maintain conditionals. |
| 33 | +Some have been bugfixes that were small by chance, and others have been changes that were only small because they had been anticipated and intentionally deferred when the era was originally designed. |
| 34 | + |
| 35 | +Eras are a straight-forward mechanism that enables node developers to separate the concerns arising from features that are added to Cardano over time. |
| 36 | +The separation amongst eras inherently simplifies the development of the new features, and it also helps ensure that the Cardano node can sync the entire historical chain [^mithril] --- as well as refuse invalid alternative histories. |
| 37 | + |
| 38 | +### Which changes require a new era? |
| 39 | + |
| 40 | +It's ultimately the judgment of the node developers whether some changes should be achieved with an era transition rather than an intra-era hard fork. |
| 41 | + |
| 42 | +The Cardano developers have so far used very expressive static typing. |
| 43 | +It's plausible that an implementation that instead used dynamic types could more frequently use intra-era hard forks rather than era transitions. |
| 44 | +However, we strongly believe that overall development and assurance would degrade without the benefits of such precise types. |
| 45 | + |
| 46 | +The first era transition (from Byron to Shelley) is a notable example. |
| 47 | +It was the first era transition we experienced, and no subsequent transition changes nearly so much. |
| 48 | +The two code bases are drastically different, so it's hard to argue this should have been an intra-era hard fork. |
| 49 | +In particular, this is the only era transition that changed the duration of slots and the number of slots in an epoch. |
| 50 | +In the current codebase, any hard fork that changes those per-era constants must be an era transition, since the Consensus infrastructure was explicitly designed with that restriction as a simplifying assumption. |
| 51 | +A different design might relax that constraint, but it is has not been restrictive so far: a second change to these constants has been discussed only rarely and never actually proposed, and deferring them until whatever justifies the next era transition wouldn't obviously be prohibitively disruptive. |
| 52 | + |
| 53 | +### How wide-reaching are eras? |
| 54 | + |
| 55 | +Eras are ultimately an implementation detail of the node, a consequence of architectural trade-offs. |
| 56 | +The node's behaviors currently reflects the eras in only two ways. |
| 57 | + |
| 58 | +Specifically, the node must be able to forecast the data necessary to validate a useful prefix of some header chain from the intersection of that header chain and the node's current selection, including whether each header arrived too early. |
| 59 | + |
| 60 | +- The familiar and intuitive notion of era is useful for organization in general, and so the eras' names might appear within parameter names in configuration files, specification documents, announcements, etc. |
| 61 | + |
| 62 | + However, the era transitions themselves should generally be considered as "just a big hard fork". |
| 63 | + The foundational data is instead the protocol version, especially because not all hard forks are era transitions. |
| 64 | + (See [this GitHub comment](https://github.com/IntersectMBO/ouroboros-consensus/issues/416#issuecomment-2669347315) for the details of how this lesson was learned.) |
| 65 | + |
| 66 | +- Some codecs reflect Cardano's specific era structure. |
| 67 | + That's not strictly necessary, but a tagged union approach has made it trivial to combine the era-specific codecs into a full Cardano codec. |
| 68 | + Specifically, top-level codecs fundamentally branch on a simple number located near the beginning of the bytestring and dispatch accordingly to the corresponding era's codecs. |
| 69 | + |
| 70 | +- (TODO Confirm whether these tags dont affect any hashes. If they do, to what extent does it actually matter?) |
| 71 | + |
| 72 | +## Forecasting, forewarning |
| 73 | + |
| 74 | +Hard forks can affect the validity of block headers, and so must be sufficiently forecastable. |
| 75 | +For this reason, hard forks must not happen less than 36 hr (on mainnet) after the voting deadline, ie hard forks must have at least 36 hrs of forewarning --- just like other protocol parameter updates that affect headers (eg maximum block size). |
| 76 | + |
| 77 | +TODO how to argue that hard forks or era transitions needs more than that? |
| 78 | + |
| 79 | +[^updatable-protocol-parameters]: *Reference*. |
| 80 | + See Section 5 "Protocol Parameters" of the "A Formal Specification of the Cardano Ledger, Deliverable SL-D5" document for more details. |
| 81 | + Its latest revision can be accessed via the hyperlink in the "Formal Specification" column of the "Shelley" row of the documentation table at the top of the [README](https://github.com/IntersectMBO/cardano-ledger/blob/master/README.md) of the [`cardano-ledger` repository](https://github.com/IntersectMBO/cardano-ledger). |
| 82 | + |
| 83 | +[^change-decisions]: *Reference*. |
| 84 | + Nowadays, these are almost always going to be (possibly indirectly) related to a Cardano Improvement Proposal (aka [CIP](https://cips.cardano.org/)). |
| 85 | + |
| 86 | +[^frame-rule]: *Clarification*. |
| 87 | + There's no other technical reason for the community to increment the major protocol version. |
| 88 | + |
| 89 | +[^roadmap-disambiguation]: *Disambiguation*. |
| 90 | + The [Cardano Roadmap](https://roadmap.cardano.org/en/) also defines some very broad "eras": Byron, Shelley, Goguen, Basho, and Voltaire. |
| 91 | + These are more general than the eras that divide the actual evolution of the protocol rules and ledger rules within the node. |
| 92 | + [CIP-0059](https://github.com/cardano-foundation/CIPs/blob/master/CIP-0059/feature-table.md) maintains a table showing the correspondence; it lists roadmap eras in the "Phase" column. |
| 93 | + |
| 94 | +[^accidentals]: *Clarification*. |
| 95 | + Accidental hard forks would necessarily be intra-era hard forks. |
| 96 | + |
| 97 | +[^mithril]: *Clarification*. |
| 98 | + Mechanisms such as [Mithril](https://github.com/input-output-hk/mithril) would provide alternatives to the node, but the node itself should always be able to revalidate (or merely reapply) all the blocks if needed/desired. |
0 commit comments