Implementation of the update system can be found in the Pos.Update family of modules. The general approach to implementation is the same as in other subsystems of CSL, such as Txp, Ssc and Delegation. The update system has the global state, stored in the database. The global state can be unambiguously derived from the information that is in the blockchain. The local state, sometimes referred to as “mempool”, is stored in the memory. The mempool is used for data transfer and inclusion of transferred data into blocks. The network protocol (built with standard Inv/Req/Data pattern) is described in Application-level document with the binary protocol described in Binary protocols document.
Currently, everything is ready to add hard fork functionality via software update and then perform a hard fork as described in research section; soft forks (or software updates) are fully implemented.
Fields Updatable with a Soft Fork
fields for changing some parameters used by Cardano SL (for instance, slot
upBlockVersion is used to signify that a proposal
performs such changes; if
upBlockVersion is greater than the last used
block version, the changes from
upBlockVersionData will be applied.
upBlockVersionData has the type
Its fields are described below:
bvdScriptVersion– a script language version used to validate script transactions. If the proposal increases
upBlockVersion, it must also increase
bvdScriptVersionby 1 (and can’t leave it unchanged).
bvdSlotDuration– slot duration (in milliseconds).
bvdMaxBlockSize– block size limit (in bytes). A proposal can’t increase the block size limit more than twofold compared to the previous limit.
The checks described above are made in verifyNextBVData. In addition, there are some fields that are unused right now, but will be used in the future. Their meaning is briefly described below:
bvdMpcThd– eligibility threshold for MPC.
bvdHeavyDelThd– threshold for heavyweight delegation.
bvdUpdateVoteThd– portion of total stake necessary to vote for or against an update.
bvdUpdateProposalThd– portion of total stake such that block containing
UpdateProposalmust contain positive votes for this proposal from stakeholders owning at least this amount of stake.
bvdUpdateImplicit– number of slots after which an update is implicitly approved (unless it has more negative votes than positive).
bvdUpdateSoftforkThd– portion of total stake such that if total stake of issuers of blocks with some block version is bigger than this portion, this block version is adopted.
MemPool consists of votes and proposals. Apart from that
MemState contains tip,
PollModifier corresponding to
MemPool (and to current
GState, i. e.
to application of
GState). No matter whether a change in
proposal state comes from the network/mempool, or from loading
modification of global state which will be made if one applies mempool.
Updating the Mempool
MemPool is updated in three cases:
- When a new proposal/vote is received. In this case, one of the
functions is called, which in turn calls
and then updates current
- When a new slot starts. In this case some data in
MemPoolmay become invalid. In fact, it happens only when epoch changes. That can happen because stable stake distribution changes and some votes may have not enough stake for inclusion. It’s done in the processNewSlot function.
GStateis updated. It is called usNormalize. Some data may become invalid as a result of block(s) application or rollback. For instance, we have a proposal in memory, apply block with this proposal and it becomes invalid (because it’s already in block). We should drop such proposals. Or we have a vote for proposal from some block, then rollback of this block happens and vote is no longer valid. It is implemented by applying all local data to empty state, ignoring all data which is no longer valid.
Proposal and Votes Accumulation
To vote for a proposal, nodes should send their votes. Proposals and votes are stored in mempool (even if proposals don’t have enough votes for inclusion into blocks, this way votes can be collected automatically) or gathered from the blockchain in order to figure out which proposal is adopted.
Interaction With the Database
In order to verify update system data, we have to get this data from the global state (database). To provide such interface, a well-documented type class MonadPollRead is presented. This type class is used not only for DB interaction, but also to take mempool into account when the data received from the network are processed. It is important that its implementation relies on functions found in Pos.Update.DB.
Core types are mentioned in the Binary protocols document. Those types reflect the concepts from the research section in a straightforward way. Please refer to the core types module for more information.
Update Proposal Approval
A very important part of implementation of the update mechanism is the part that works with genesis blocks for epochs. This logic resides in this well-documented function. The terminology related to this process is explained below.
Suppose there is a block version
X. And there are blocks with version
created in slots
S is a set of slots). If total relative stake of
leaders of all slots in
S is ≥
(referred to as «threshold» in the code), then
X becomes adopted.
See the more detailed description in research overview.
Update proposal can be in one of the states described below.
It means that update proposal is contained in
one of the blocks, but it doesn’t have
50% votes for/against it (here
50% means total
stake of voters who are for/against proposal relative to total stake of all stakeholders
in system) and implicit agreement rule hasn’t been triggered yet.
It means that proposal has more than
50% votes for it or it was added to block long ago
(according to implicit agreement rule) and it has more positive votes than negative
(comparison by stake of course).
A proposal is called rejected if that proposal has more than
50% votes against it or
it was added to block long ago (according to implicit agreement rule) and it has more
negative votes than positive (again, comparison by stake).
An approved proposal is called confirmed if at least
k blocks ago proposal
became Approved. At this point we can be sure that proposal won’t become rejected,
because rollbacks with depth more than
k aren’t possible.
A rejected proposal is called discarded, if at least
k blocks ago that proposal
became Rejected. At this point we can be sure that proposal won’t be approved,
because rollbacks with depth more than
k aren’t possible.
Download New Version
Download Confirmed Update
To download a confirmed update, we extract the update hash from
ConfirmedProposalState. It is extracted depending on whether or not we’re
using an installer on given platform. If the update hash is extracted
successfully, the “Download Update by Hash” algorithm is invoked to download and save the confirmed update.
Download Update by Hash
To download an update by hash, we loop through known update servers trying
to download the update with given hash using
httpLBS from HTTP. It’s simple: in
the end, we will either have the update completely downloaded or server list
exhausted and an error reported.