Skip to content
This repository has been archived by the owner on Jun 11, 2024. It is now read-only.

Latest commit

 

History

History
134 lines (79 loc) · 26.3 KB

lip-0021.md

File metadata and controls

134 lines (79 loc) · 26.3 KB
LIP: 0021
Title: Change to one vote per account
Author: Jan Hackfeld <[email protected]>
Discussions-To: https://research.lisk.com/t/change-to-one-vote-per-account/18
Status: Withdrawn
Type: Standards Track
Created: 2018-10-30
Updated: 2021-09-07

Abstract

This LIP proposes a change of the voting system for the election of delegates in Lisk. We suggest to only allow one vote per account with a vote weight given by the balance of that account. The goal is to increase the decentralization of the network by disincentivizing coalitions between active delegates and creating a healthy competition for active delegate slots. Moreover, the proposed voting system is very simple and encourages a high participation of stakeholders.

Copyright

This LIP is licensed under the Creative Commons Zero 1.0 Universal.

Motivation

In the current voting system in Lisk, every account holder can vote for up to 101 delegates and the vote weight of the account is the balance of the account, also referred to as the stake of the account holder. The current voting system is based on approval voting and the idea is that the delegates approved by the highest proportion of stake are the most suitable to secure the Lisk network. In practice, this system suffers from several shortcomings, which also have been addressed by members of the Lisk community. First of all, there is a high incentive for delegates to form a coalition or pool by voting for each other as the vote weight is independent of the number of votes cast. The active delegates further typically share a certain fraction of their earnings via the block rewards with their voters. As many coalitions demand that stakeholders vote for all their members to receive any payouts from the block rewards, the coalitions can easily manifest their position in the top ranks. Secondly, there is a very high barrier for anybody to become an active delegate because many accounts that together represent a very large amount of stake (approximately 31,000,000 LSK as of 26/11/2018) need to change their votes. In particular, this means that a new delegate that manages to get support by a substantial part of total stake, such as 1%, has no chance to become an active delegate. The third problem, which is more of theoretical nature, is that it is possible to change all active delegates by owning 41 % of the total supply of Lisk tokens. This would allow to stop the chain, censor transactions or execute double spending attacks, for instance.

This LIP proposes to limit the number of votes to one vote per account. This voting system is based on the idea of proportional representation. This means that any delegate gathering support by a fraction of 1/101 of the total stake is guaranteed to be an active delegate (in other words, any interest group gathering support of approximately x % of the total stake will be able to obtain x delegate slots). In practice, the threshold to become an active delegate will be even lower as not all stakeholders are voting and some votes will also be cast for standby delegates. Having only one vote per account addresses all three issues mentioned above: First of all, delegates have no more incentive to form coalitions. Secondly, the threshold to become an active delegate is significantly lower as approximately 1 % of the total amount of Lisk tokens in all accounts that vote is sufficient to become an active delegate. Thirdly, even huge stakeholders will only be represented among the active delegates according to their proportion of the total supply of Lisk tokens.

Rationale

It is important to acknowledge that one perfect voting system for Delegated Proof of Stake does not exist. Nevertheless, the proposed change of the voting system is a great improvement of the current state and an important step in evolving the Lisk Delegated Proof of Stake system. In this section, we give our reasoning for favoring the proposed voting system and also discuss some alternative solutions, some of which were put forward by the community on GitHub. In general, the vote weight or rank of a delegate could depend on a lot of different factors, which we also discuss in the following.

Desired Properties

At first, we want to list the main desired properties of a voting system for Lisk:

  • Decentralization: In order to have a truly decentralized network, the delegates should act as independent entities and the voting system should give no incentive for delegates to form coalitions. Instead, it should foster high competition for the active delegate ranks.
  • Simplicity: Accessibility is one of the core values of Lisk, which should also be reflected in the Lisk voting system. This means that the voting system should be very easy to understand making the entry-barrier to participate low.
  • High participation: For a well-functioning Delegated Proof of Stake system a high participation of all stakeholders is crucial.

Another property that may be intuitively named is “fairness”. However, this property is very subjective and is hard to precisely define. Thus, it is not mentioned above.

Dependence on Stake

One of the first fundamental questions is how the voting power of an account should relate to the amount of stake in that account. A proposal that is often mentioned in this context is to somehow limit the power of very large stakeholders who have a large influence on the network. In a trustless, decentralized system it is however impossible to map accounts to people. In particular, it is impossible to distinguish if many small accounts are controlled by many people or just one big stakeholder. Therefore, any voting system that gives many small accounts more cumulative voting power than one large account can be easily circumvented by a large stakeholder by creating multiple accounts. In our proposal, the voting power is therefore linearly dependent on the amount of stake.

Dependence on Delegate Productivity

Another important factor to take into account for ranking the delegates is their productivity, i.e., the percentage of blocks successfully created as active delegate in the assigned forging slots and included in the blockchain. However, it is dangerous to directly punish lower productivity as it can create an incentive for delegates to have a competing delegate miss their slot by starting a denial-of-service attack, for instance. On the other hand, delegates that are offline for an extended period of time have a big negative effect on the productivity of the system. In a separate LIP, we therefore propose a very conservative approach of taking the delegate productivity into account and only punish active delegates after not forging for a long period of time. This way delegates cannot indefinitely harm the Lisk network in the case that they stop to maintain their server or lose their private key, for instance.

Changing the Maximum Number of Allowed Votes

A parameter that we propose to change in the current voting system is the maximum number of delegates an account can vote for. This parameter is currently 101. However, it does not necessarily need to coincide with the number of active delegates.

If we change the maximum number of votes to something larger than 101, we would be closer to actual approval voting which allows approval of an arbitrary number of delegates. This could potentially decrease the large gap in voting support that typically exists between the delegate on rank 101 and the delegates on lower ranks because then account holders could vote for all active delegates (to receive shared rewards) and also for additional standby delegates. However, the main issue of the current voting system, the high incentive to form coalitions between active delegates, would persist. Moreover, coalitions could possibly start to demand exclusive votes for them, which would again result in a cliff of voting support between active and standby delegates.

Another possibility would be to limit the maximum number of votes to a small number, let us say 10 for example. In this case, it would be still beneficial to form a coalition of 10 active delegates and require account holders to vote for all of them in order to receive any share of rewards. Moreover, larger coalitions may still develop a suitable scheme of having account holders distribute their votes evenly among all active delegates of the coalition. As long as the maximum number of votes is larger than 1, this issue persists and delegates campaigning as an independent entity have a big disadvantage over a coalition of delegates. Since decentralization is one of the key goals of the Lisk ecosystem, we want this desired property be reflected by the fact that the voting system encourages a diverse set of independent delegates. That is why we believe that allowing only one vote per account is a good choice for Delegated Proof of Stake.

Dependence on the Number of Votes Cast

Abstractly we could describe a voting system depending on the number of votes and linearly on the stake of an account as follows: The vote weight of an account is given by vote weight = f(# votes cast) * account balance in LSK for a function f. The delegate weight is then the sum of all vote weights of accounts voting for that delegate. The top 101 delegates by delegate weight are the active delegates securing the Lisk network. Currently, the vote weight of an account is independent of the number of votes cast, i.e., f(# votes cast)=1. One approach to disincentivize coalitions between active delegates is to decrease the vote weight for every vote cast. This means that f is a monotonically decreasing function in the number of votes cast by the account. In principle, it could make sense to set f(# votes cast) to any value in the interval from 1/(#votes cast) to 1.

Let us first consider the case f(# votes cast)=1/(#votes cast). Assume two delegates A and B with equal balances both vote for each other and also for themselves. As the vote weight is divided by the number of votes cast, the delegates could also both just vote for themselves with the same result. In general, this means that there is zero incentive in the voting system for delegates to form coalitions as their stake is split by the number of votes cast. Now, consider an account holder that votes for delegate A and delegate B. Equivalently, the account holder could also split its stake into two accounts with equal balances and with the first account vote for A and the second account vote for B. The delegate weights would be exactly the same in both cases. In general, this choice of f is equivalent to allowing only one vote per account, as multiple votes can just be simulated by account holders by splitting their stake into multiple accounts. That is the reason why we prefer the simpler voting system of only one vote per account over changing the vote weight of an account by setting f(# votes cast)=1/(#votes cast).

In the community, other variants in between the extremes f(# votes cast)=1/(#votes cast) and f(# votes cast)=1 have been discussed. One example is f(# votes cast)=1- # votes cast*0.005. For this suggested dependence on the number of votes, the incentive to form coalitions is still very high. This becomes especially clear if you compare one delegate with significant stake campaigning independently to, for example, 20 delegates with significant stake all voting for each other and campaigning together. In general, any choice for the function f that is not already very close to f(# votes cast)=1/(#votes casted) will have exactly this shortcoming. Hence, we believe that splitting the stake by the number of votes would be the best option and, as argued above, we can simplify our voting system to one vote per account in this case.

Vote Expiration or Vote Decay

In order to encourage a dynamic voting environment and stakeholders to regularly re-evaluate their votes, a mechanism of vote expiration or vote decay have been discussed. Vote expiration means that a vote is only valid for a certain period of time and has to be renewed to be still taken into account. In contrast to that, vote decay means that the weight of a vote gradually decreases over time instead of expiring. While a dynamic voting environment is desirable, both proposals have some shortcomings. First of all, it adds additional complexity to the voting system, in particular for users. Secondly, regularly casting a vote transaction can be easily automated by a voting bot, which would circumvent both mechanisms. In particular, it would be possible to sign a large number of vote transactions at once, each with different timestamps, and have a bot broadcast them automatically at specific times. Thirdly, requiring stakeholders to vote regularly increases the total cost for participating in the voting system giving a disadvantage especially to small stakeholders. The two mechanism may, nevertheless, be re-evaluated for future improvements of Delegated Proof of Stake in Lisk along other possibilities such as proxy voting, which also encourage a more dynamic voting environment.

Ranked Voting

Ranked voting systems have nice theoretical properties and implementations such as single transferable vote are endorsed by NGOs such as FairVote. The complexity of ranked voting, however, has disadvantages in the context of the Lisk blockchain. Most importantly, as votes are changing dynamically all the time, it is essential that Lisk nodes can efficiently recompute a ranking of the delegates and decide which active delegates are securing the system. First of all, computing the outcome of a ranked voting is far more complex and takes substantially longer than for the system of simply having one vote per account. Moreover, even if only a small number of votes change, it is unclear if it is possible to recompute the results much faster than computing the outcome from scratch considering all votes. Another disadvantage in terms of usability is that the number of delegates is large and requiring a ranking of only a subset of delegates involves a much more complex decision by stakeholders than simply voting for one delegate.

Score Voting

Score voting means that voters can score each candidate and the candidate with the highest total score is elected. This voting system can be seen as a generalization of approval voting for which the possible scores are only 0 and 1. As such it suffers the same shortcoming as approval voting. That is, coalitions are highly incentivized by the voting system and the barrier for somebody to become an active delegate would be very high. Voters are also likely to only use the extreme scores, i.e. either the maximal or minimal score, so that there is very little benefit for the intermediate scores. It is possible to consider a form of score voting which only allows voters to score a small limited number of delegates. But also in this case the same issues as discussed in the section “Changing the Maximum Number of Allowed Votes” persist. That is why we believe score voting would not be a good choice for Delegated Proof of Stake.

Impact on Security

In this subsection, we want to discuss the security implications of the proposed voting system. In the current voting system, a delegate needs to be approved by a very large percentage of stake to become an active delegate (approx. 24 % as of 26/11/2018). For the proposed voting system of one vote per account, the barrier will be substantially lower (around 0,44 % or around 560,000 LSK if the same accounts abstain from voting). This has the benefit that it is much easier for independent entities and small minorities to be represented among the delegates. But it also makes it a lot easier for a malicious entity to secure a delegate slot.

At this point, it is important to be very clear what a malicious active delegate can and cannot do. First of all, no Lisk node ever accepts any block with invalid transactions. Thus, even the delegates cannot add invalid transactions to the blockchain or manipulate account balances. The only way a single delegate can harm the system is hence by not accepting certain transactions or by regularly not forging a block and therefore lowering the productivity of the system. However, both actions lead to a financial loss for the delegate because the delegate forfeits the block rewards or transactions fees. From an economic perspective, it makes little sense for a stakeholder to invest into a large amount of Lisk tokens, secure a small number of delegates slots and then try to harm the system by not forging blocks or rejecting transactions. Moreover, for the case of only one or very few delegate slots the negative impact on the Lisk blockchain is still rather small and could be further mitigated by adopting a more active punishment of delegates with low productivity in terms of the voting system.

A large number of malicious delegates can, however, become a problem for the security of the Lisk blockchain. A majority of 51 malicious delegates could for example not accept any blocks from all other delegates and their chain would always be the longest chain. This way, they could censor transactions and reject any vote transactions. Moreover, by secretly forging an alternative fork they could attempt double spending attacks. Note that Lisk nodes currently never revert more than 201 blocks without manual intervention so that also the possibility of double spending attacks is limited. A malicious group could either own a huge amount of Lisk tokens to be able to vote 51 delegates into the top 101 ranks or attempt to bribe 51 of the current active delegates directly. We discuss both of these scenarios below.

In the following, we argue that the difficulty of securing 51 active delegates in the new proposed voting system is similar to securing 51 active delegates in the current voting system and thus would require a huge amount of economic resources. If we assume that all active delegates in the new voting system have the support by exactly the same amount of Lisk tokens, all account holders vote and they only vote for active delegates, then more than 50 % of all Lisk tokens are required to secure 51 active delegate slots. In the current voting system, more than 50 % of all Lisk tokens are sufficient to secure all active delegate slots, not only a majority. In practice, these thresholds will be lower as the vote distribution among the active delegates will not be even and account holders also vote for standby delegates or abstain from voting.

In the current voting system, we can observe that the highest ranked delegate has an approval by 41 % of the total supply of Lisk tokens and the overall balance of account holders participating in voting is around 44 % (as of 26/11/2018). This means that among the voting accounts a group of account holders representing around 22 % of the total supply of Lisk tokens could change all active delegates. Furthermore, buying around 37 % (approval of the delegate on rank 51) of the supply of currently non-voting Lisk tokens in order to change 51 of the active delegates is rather unrealistic because this would lead to a dramatic decrease in liquidity and large increase in price of the Lisk token.

For the new voting system, it is of course hard to make any exact predictions. If we assume that the same account holders participate in voting and most votes will be cast approximately equally for active delegates, then every active delegate would receive votes by around 0,44 % (or 560,000 LSK) of the supply of Lisk tokens. If we consider a group of voting account holders, which overall vote with approximately 0,22 % of the supply of Lisk for 51 distinct active delegates, then they could change their votes to put 51 new active delegates into place. Then again, a rather unrealistic possibility is that a malicious entity would buy around 22 % of the non-voting Lisk tokens to secure 51 active delegate slots. It is important to note, however, that the voting system is dynamic and accounts voting for down-voted delegates may change their votes to other delegates thereby increasing the threshold for an attacker to maintain 51 active delegate slots.

In the proposed new voting system, the competition for active delegate slots is higher and delegates would likely share a larger fraction of the block rewards with their voters. In theory, this would make active delegates more susceptible to direct bribes as they have less future income to lose when participating in an attack on the network. Nevertheless, it would be very difficult for an attacker to convince and coordinate 51 different delegates for participation in an attack. Moreover, in the case of such an attack, there will be an honest minority chain as long as there is at least one honest delegate. In this minority chain, all malicious delegates can be down-voted so that eventually the minority chain will have a lot of honest active delegates and progress fast. Most Lisk nodes are likely to switch to the honest chain by manual intervention. So the network would soon recover and the malicious delegates would lose their income as active delegates.

Overall, the outlined attacks in this section require huge financial resources or the coordination of many different entities with significant stake in the system. Moreover, the stakeholders participating in such an attack would themselves suffer a substantial financial loss because of the devaluation of the Lisk token in the case of such an attack. We therefore believe that for economic reasons these attacks are highly unlikely.

Vote Transaction Object

In the current vote transaction JSON object, public keys are used to reference specific delegates for voting and unvoting. We propose to use delegate account addresses instead of public keys. The security guarantees are the same for both alternatives. Addresses are, however, optimized to be used by humans, e.g., they are shorter than public keys and provide a human-friendly encoding. This is also the main reason the recipient is referenced by address in balance transfer transactions. We therefore propose to use the same approach for vote transaction and use addresses to reference delegates in this case.

Specification

New Vote Transaction

Every account holder can cast a vote for at most one registered delegate. Therefore, it is possible to simplify the vote transaction JSON object to only contain the following properties:

  • id: the id of the transaction,
  • senderPublicKey: the public key of the transaction sender,
  • timestamp: a valid timestamp,
  • type: the transaction type, i.e., 3,
  • fee: the fee for the transaction,
  • asset.delegateAddress: the Lisk ID of the delegate (delegate account address) that the transaction sender votes for, this property is contained in the nested asset object,
  • signature: the transaction signature.

We propose to let new votes automatically overwrite the old votes so that the property asset.delegateAddress is simply the new Lisk ID of the delegate an account votes for. This way it is not necessary to undo past votes. Additionally, it is possible for an account holder to abstain from voting again after casting a vote by sending a vote transaction with the value none in the asset.delegateAddress property.

Computation of Active Delegates

Let the vote weight of an account be its balance in LSK. The delegate weight is then the sum of all vote weights of accounts voting for that delegate. At the end of every round, the top 101 delegates by delegate weight are computed by one of the methods described below. If there is a tie, the delegate with smaller Lisk ID is ranked higher. These top 101 delegate accounts are then the active delegates for the next round.

For an efficient implementation of the computation of the active delegates, the following three alternatives can be considered and compared via benchmarking. We propose to adopt the second alternative if it is sufficiently fast, as it is the simplest approach and does not require additional tables or data structures. Otherwise, we would suggest to use the third alternative because it allows the highest performance as the delegate weight changes are computed in memory.

  • Keep using the PostgreSQL table mem_round storing the delegate weight for every delegate. Update the delegate weights in this table for every transaction. This approach has the advantage that the delegate weight can possibly already be updated during the round while processing the transactions.
  • Introduce a column delegateAddressVoted in the mem_accounts table containing the Lisk ID of the delegate the account voted for. Then the top 101 delegates by delegate weight can be obtained via a single SQL query, which is executed once per round, as follows: SELECT delegateAddressVoted, SUM (balance) as delegate_weight FROM mem_accounts GROUP BY delegateAddressVoted ORDER BY delegate_weight DESC, delegateAddressVoted ASC;
  • Consider moving the computation of active delegates into main memory. A simple approach would be to store the delegate weight for every delegate in a dictionary with delegateAddress as key and delegate weight as value. This way any updates can be performed in constant time. The dictionary can be initialized using the delegate weight obtained via the second alternative. For obtaining the active delegates for a round, the dictionary entries are moved to an array while possibly pruning low delegate weight accounts. The array is sorted in memory to obtain the top 101 active delegates.

Backwards Compatibility

The changes will introduce a hard fork as the vote transactions would change and the top 101 delegates would be decided based on a different voting system. For migrating from the old voting system to the new voting system we propose to perform the migration in two steps. In the first step, we would introduce the new vote transaction while the old vote transaction is still active and the active delegates are elected via the old voting system. This first step has to last for a suitable amount of time so that account holders have enough time to cast votes in the new voting system. As a second step, the delegates would then be elected via the new voting system starting from a defined block height. Moreover, the old vote transaction would then be deactivated.

Reference Implementation

TBD