In the Update Mechanism research, we have managed to propose an update system that is capable of producing painless and almost seamless software updates as well as providing stakeholders with an option to vote for hard forks (backwards-incompatible protocol updates) without the necessity to introduce any non-protocol-level tools.
We propose to use stake for voting for soft and hard forks.
Update System Model
For CSL, we decided to add some support for protocol updates at the protocol layer itself. It introduces some overhead to blockchain processing, but has several important benefits:
- For each client implementing the protocol, its latest version from blockchain is known.
- There is no central entity responsible for maintaining or distributing updates, any such update is proposed under implicit or explicit agreement of the majority of stake and then distributed in a decentralized way.
- We do not rely upon clients updating the software on their PCs in time; this is done automatically, and updates are announced directly via the blockchain.
- If any security flaws are detected in some version of the CSL protocol or in some particular implementation, there would be a mechanism to distribute an update rapidly (and still under agreement of the majority of stake).
Application Update: Sign and Announce
Here we consider ways to update the application securely. Protocol updates are a separate issue which is covered in the relevant section of this document.
For an update to be applied, its proposal needs be approved first. Update proposal can be approved if at least one of two agreements is reached:
- Explicit agreement: it has positive votes from majority of total stake
(i. e. strictly greater than
- Implicit agreement: it has positive votes from more stake than negative
votes and it has been in blockchain for at least
This approach seems to fit naturally into the CSL model, as in a PoS cryptocurrency every stakeholder is responsible for maintaining the system proportionally to the relative size of their stake, and the blockchain is maintained via consensus among stakeholders.
Software updates are a part of this maintenance process too, so the stakeholders should agree on whether to consider this update trusted.
The fact that stakeholders are responsible for system updates does not restrict us to a system where every single update requires a signature from the majority of stake. We can introduce the concept of an implicit agreement.
An update has to have at least
T% of the stake signatures to be
published on the blockchain. It is not enough for stakeholders to sign
the update — they should vote either for or against it.
Incorporation of Alternative Clients
IOHK will maintain a single official client. But there is also room for third-party alternative clients maintained by the community. One requires enough collected signatures from stakeholders to publish their system update, which may be not an «update», but a different client developed from scratch, or a fork of the official client. As long as this update has enough signatures from stakeholders, the network considers it trusted, and it is updated via the same mechanisms as the official client.
Application Update: Deliver and Apply
А list of HTTP mirrors ran by IOHK shall be sufficient for a start.
In process of time, we plan to maintain a Bittorrent-based or Bittorrent-like solution to distribute updates. In general, P2P update distribution is a crucial business requirement due to legal concerns. It is to be decided which Bittorrent-like solution particular we will use.
Also, it’s interesting to note that the update itself does not require a secure and trusted channel to be used for delivery, as it is signed with some known in advance and trusted key (or set of keys).
First, we need to distinguish hard and soft protocol updates.
A soft fork proposes modifying blockchain consensus rules so that the new version blocks are still compatible with old version clients. A hard fork is one that doesn’t maintain backward compatibility with the previous version.
BIP-99 provides excellent criteria to distinguish between these two fork types:
- A soft fork introduces new rules, or restrictions, on blocks. That way, everything that was previously invalid remains invalid, while some blocks that would have been previously considered valid become invalid.
- A hard fork is a fork that makes previously invalid blocks valid.
Soft forks have some deployment advantages like backward compatibility, and they don’t require everyone’s consensus, as the stake majority of users can impose the new rules. By contrast, hard forks require all users to upgrade.
In theory, a hard fork may lead to a situation when a network splits into two parts, each maintaining a separate chain: one from the nodes that adopted the latest system update, and another from the nodes that rejected to do that. This means some blocks from the first part are considered invalid by the other part, and vice versa.
We define protocol version as a tuple
(Maj, Min, Alt):
- Major version (2 bytes): to be changed rarely, changes are not backward-compatible and would produce a hard fork.
- Minor version (2 bytes): integer to be adjusted for each update.
- Changes should be backward-compatible in a sense that a block generated by the new version shall be somehow accepted by old version.
- A particular block may contain addresses of unknown type. For each case like this, a concise workaround should be found in order not to affect stability and correctness of the system.
- Alt version (1 byte): integer to manage several simultaneous protocol update proposals.
The protocol version is to be announced in the application update, and is to be put later into each block created by updated software.
A major version change triggers a hard fork in the future.
A minor version change notifies the network that the subsequent application update modifies the protocol managed by a soft fork.
Alt version is a marker of new features. It allows independent developers to
introduce multiple changes to the protocol simultaneously. For example, if one
vendor decides to introduce feature X via a soft fork, and another proposes feature Y
(also via a soft fork), their software will be issuing blocks with versions
a.b.Y, which can coexist in the blockchain. However, only one will eventually
Soft Fork Updates
There is a thin line between what we can do within a soft fork and what we cannot:
- An old version of the client should always find recent blocks valid. (This is what BIP-99 calls “everything invalid remains invalid”).
- Some blocks issued by an old version of the client may be considered invalid by a newer version.
Obviously, imposing rule 2 as it is may cause the network to be split into two parts: a stakeholder with a stake large enough could update and maintain their own chain, rejecting blocks from others, but others would be still able to maintain their chain, rejecting blocks from this stakeholder (since he does not have a majority of stake, and therefore cannot catch up with the rest of the crowd, so his chain is shorter). A simple resolution rule could go like this: if 95% of the latest 2016 blocks have a newer block version, the blocks with the older version are rejected.
NOTE: block version here and later has the same meaning as the protocol version.
It may seem unclear why we would like to make some block version invalid at some moment. The key insight here is that a new feature is actually a restriction on what we had had previously. For example, currently we have plain old transactions which may contain either PublicKey-based addresses or Script-based ones. Then at some point we decide to include a third address type (no matter what its purpose is). Which strategy do we need for verifying a block with a transaction with an address of unknown type? Obviously the only option is not verifying this address.
Then imagine somebody proposing a transaction to this address, possibly doing that with an intention to secure funds from being spent until some conditions are met — and then watching them being spent in some other transaction in a block with version 1. This is the point. We cannot make use of a restriction without waiting for the network to start assuming the old version to be deprecated (since we can only start rejecting blocks when their version is deprecated).
We also cannot bluntly accept all blocks with a version that is higher than the one
currenlty adopted, since in our implementation every block has a field called
which is used for storing auxiliary information. An attacker can claim she
uses a higher version of the protocol and generate a block whose
are polluted with meaningless keys. If we accept it, it will bloat
This is the motivation for the logic described below.
In our implementation, a block version can exist in the following states:
- Adopted, when the soft fork resolution rule (see below) for a confirmed block version is triggered.
- Confirmed, when there is an update proposal that contains a confirmed
version of the software and this block version. Note that “confirmed version of the software”
is a technical term defined elsewhere.
If there are multiple block
versions where corresponding software is confirmed, but these versions
aren’t adopted, we call them competing. For instance, there might be
1.1.2, with the last adopted version being
1.1.3. In this case the versions that are competing are
1.2.1. The older versions
1.1.2aren’t competing, because
1.1.3is already adopted.
- Everything else. For example, a new block version is proposed, but the software version isn’t confirmed yet. There is no special name for this state.
The soft fork resolution rule works as follows:
- Informally, a block version becomes adopted when a certain percentage of
stake (75% in the current implementation, but this may be different in the
mainnet) creates a block with version
- Formally, we do the following. First, recall that by design, our system does
not allow rollbacks of blockchain deeper than a certain fixed global threshold
k, which allows to define stable stake for each stakeholder as their stake
kblocks ago. When we process genesis block for epoch
e, we compute the stable stake of all leaders of all slots from the very beginning of the network’s existence. For each block with version
Xthat is currently competing, we take all created stable blocks with version
X, take set of all leaders of these blocks and accumulate their stakes. If one of versions has ≥ 75%, it gets adopted. If more than one version has ≥ 75%, we take one of them deterministically.
Note that adopted block version can’t be changed during epoch (only between epochs), so all blocks in an epoch are verified according to the same rules (because rules are defined by adopted block version). But it’s wrong to assume that all blocks in an epoch have the same block version. After block version is adopted, another block version can become competing and some nodes may create blocks with this new version.
So, gathering everything up:
- Once the update is confirmed, the protocol version (say
0.5.0) can be used.
- Behavior of nodes that have been updated (i.e. can issue and validate blocks with the newer version):
- Before the soft fork is resolved (i.e. before the resolution rule is triggered),
issue blocks with the new version
0.5.0, but do not include any new
attributes(if there are any). Treat and validate blocks of version
0.5.0as blocks of version
- Once the soft fork is resolved, issue and validate blocks per version
0.5.0, including the new
- Before the soft fork is resolved (i.e. before the resolution rule is triggered), issue blocks with the new version
- Behavior of nodes that have not been updated (i.e. cannot issue and validate blocks with the newer version):
- Before the soft fork is resolved, issue and validate blocks per version
0.4.0. Among other things, a block is not accepted if it contains unknown
- Once the soft fork is resolved, start accepting all blocks with version
0.5.0, including the ones with unknown
attributes. Keep validating them as version
- Before the soft fork is resolved, issue and validate blocks per version
Hard Fork Updates
Hard forks are resolved using Modified Proof of Burn. As it is not implemented yet, we omit this section from this document and will publish it as a separate document.