This is part 2 of a series on the new voting system for the PKT Network Steward. If you didn’t read the first installment, check it out first https://thegoodwork.substack.com/p/the-democratization-of-pkt and everything here will make more sense.
In 2023 I began thinking about how to design a new voting system. Clearly we needed to stop requiring a fixed percentage of PKT coins to call an election, because as the community evolves, whatever number we pick eventually becomes too high. It also offered a great opportunity to dispatch with the awkward voting process where coins needed to be placed in “voting transactions”.
But I didn’t want to just fix the obvious flaws of the original system, I wanted to create the great voting system. I wanted a voting system which would empower voters more than the traditional first-past-the-post election process.
The problem with first-past-the-post voting is that it only really represents the will of the people when there are 2 options. When there are more than 2 choices, people have to vote for what they consider the lesser evil among the two choices most likely to win. Doing otherwise is "throwing your vote away".
Nobody ever sits down and asks themselves who is most fit to manage the affairs of the nation, the first-past-the-post system has deleted that question right out of people’s minds. Instead people argue over whether it’s going to be the blue guy or the red guy, and they think that’s democracy. It’s quite possible that the entire partisan landscape as we know it is an artifact of this flawed voting system.
It’s quite possible that the entire partisan landscape as we know it is an artifact of this flawed voting system.
There exist systems like Single transferable vote, Ranked-choice voting and Approval voting which aim to offer more agency to the voters, but these systems are conceived from the same limited mindset. In particular, they come from the perspective of the third party candidate.
The dream of the third party candidate is that if enough people would vote for him, he would no longer be “third party”. But to get there, he needs to somehow overcome the objection that voting for him means losing a chance to vote against The Bad Guy. Even the third party candidate does not ask the voter who is most fit to rule!
If we could just cast all the politics and partisanship aside and get to the real heart of the question, everybody’s answer would probably be different. We’d most likely have a beautiful patchwork of nominations including businessmen, professors, soldiers, clergy, and other people of distinction.
Now you might wonder what good that does if we still have no consensus on who it is that will actually lead. But at this point everybody who has been nominated could be considered a representative. So what if we simply delegated the votes to the representatives? If they don’t win, the votes would be passed along to whoever they voted for.
What if we simply delegated the votes to the representatives? If they don’t win, the votes would be passed along to whoever they voted for.
You might wonder what happens if you want to vote for somebody, but you don’t like who they would vote for. Well you can’t have it both ways, either you trust their judgment or you don’t, and the beauty of this system is that it forces you to reconcile that.
You also don’t get to evade moral responsibility by choosing a lovable candidate who's guaranteed to lose. The question before you is who is most fit to lead, and you cannot vote without answering it. If you do vote, it is highly likely that your vote will somehow help elect the final winner.
The Electorium algorithm
This computation of delegated votes is not as simple as it might seem. If Alice votes for Bob, and Bob votes for Alice, it is not immediately obvious who should win. Not only that, it is important that the counting process be fast, so it doesn’t impose significant performance penalty on the PKT FullNodes and mining pools.
To address this, I created a new vote counting algorithm which I call Electorium. It is in essence a search algorithm, it finds the candidate who cannot be beaten by anyone else, if we were to pretend that neither they, nor their challenger, voted for each other. So in the case of Alice and Bob, we pretend Alice is not voting for Bob, and Bob is not voting for Alice and we can easily find the winner.
There is also another case where perhaps Alice votes for Bob, but Bob does not vote for Alice. It might seem that Bob is the clear winner, but if the majority of his votes have been received from or through Alice, then by these rules Alice still wins. However, if there is another candidate who receives more votes than Alice but less than Bob, Bob becomes the winner because Alice loses and is forced to delegate her votes.
In Electorium you can vote for anyone, but no one is required to be a candidate. If you vote for someone who’s does not wish to be a candidate, your vote is simply delegated to whoever they vote for.
Everyone who chooses to be a candidate automatically votes for themselves. If they vote for someone else, that vote is secondary to their implied vote for themselves. To put it differently, voting as a candidate will never cause you to lose.
If a candidate explicitly votes for himself, his explicit vote is meaningless. It is the same as indicating his candidacy without voting at all.
The Electorium algorithm has been implemented in Rust and Golang both and has received extensive fuzz testing to verify correctness. If you are interested in how it works, you can learn more about it here:
https://github.com/cjdelisle/Electorium
https://github.com/cjdelisle/Electorium_go
Connecting Electorium to PKT
As with the old voting system, the new one values each vote by the amount of PKT the voter holds. This is of course unlike a standard national election where every citizen gets an equal vote. But like almost all blockchains, PKT has nothing analogous to the concept of the citizen.
One person can trivially pretend to be thousands, or even millions, of unique individuals. So PKT must by necessity adopt the model used in public corporations, where votes are weighted based on how much of the coin is held.
This idea of weighting the vote based on skin in the game actually makes some sense as well. In a national election, every citizen could be considered to have the equal skin in the game, it is their life and family that is at stake. But in the case of a project or online community, a person with little investment can easily walk away, so they cannot be expected to make decisions with the same level of care as someone whose involvement is greater.
Another limitation that would be carried over from the old system is that voting cannot be done anonymously. The right to vote one’s conscience without fear of repercussion is a fundamental part of the modern democratic process. But anonymous voting on a blockchain is largely uncharted territory, so it is not clear how, or even if, this could be achieved.
In any case, there is one advantage to public voting, and that is public voting of the delegates. When you choose who is to represent you, you certainly should know what decisions they make. Secret voting, while important for the general public, is abhorrent when done in the senate chamber.
In the Electorium system everyone is a potential senator, and everyone’s vote is a matter of public record.
As with the old system, the votes would be based on transactions, but rather than changing the transaction in any non-compatible way, the far easier solution was to simply make a payment of zero PKT to a special address. Like the Ordinals stored in Bitcoin, votes are not seen by FullNodes as anything other than strange but completely valid payments.
This means you no longer need to make sure all of your coins are in “voting transactions”, you simply cast one vote with your address and the entire balance of that address is then considered to be voting. Of course what simplifies the usage complicates the code, and this necessary change required implementing new logic to track the balance of each address - including non-voting addresses which might vote in the future.
And to get rid of the broken rule that 50% of all coins must call an election for one to occur, the new implementation uses the obvious choice - an election once per week. The choice of a fixed time period also has a technical benefit because it means there will never be two elections in rapid succession. Therefore it is allowable for the counting of the votes to take a longer time, so it can be done in the background without interrupting the all important processing of blocks.
You only need to vote once, and your vote counts in every election with whatever balance you have at the time of the election, until you either change it, or it expires. On the advice of a community member, I implemented an expiration time of 1 year so that lost wallets will not affect the outcome of elections forever.
The code for voting has been completed and is sitting in the unreleased PKT-Lightning-Wallet so you can be one of the first people to vote!
Casting a vote
To cast a vote, you need to install PKT-Lightning-Wallet on your computer.
git clone https://github.com/cjdelisle/PKT-Lightning-Wallet
cd PKT-Lightning-Wallet
./do
Then you can create a new wallet to test the voting system:
./bin/pld --create --wallet=voting_test_jan24_2024
Once you have created it, start pld using:
./bin/pld --wallet=voting_test
After it is running, open another window, navigate to the same folder, and make a new address:
./bin/pldctl wallet/address/create
Once you have the new address, send yourself a few PKT in order to vote with it. You can check your balance using:
./bin/pldctl wallet/address/balances
Before you can vote, you will first need to unlock the wallet:
./bin/pldctl unlock
And after you have unlocked the wallet using the password you configured earlier, you can finally cast your vote:
./bin/pldctl wallet/transaction/sendvote \
--from_address=<your wallet address> \
—-vote_for=pkt1q2yt8djdlykf2d9ukmw0q5z5tur05xm674tq6y8
If all goes well, you should see a transaction ID as the result, and within a few minutes you will be able to look up that transaction on any of the block explorers.
Here is a vote which I created while writing this document: 57d29c6662c7b12d96551418738f2bee77631266d8a1dfdd8982d467e11f5b88
You can see it takes 100 PKT (it will use the smallest amount it has available), and it cycles all of the PKT back to itself as change (excluding the minuscule transaction fee). It paid exactly 0 PKT to an address identified by the explorer as “Custom Script”. It did not even pay 1 nano-PKT, it is actually zero.
A few words of caution: If you use the CLI pktwallet
, PKT-Lightning-Wallet will open your same wallet.db
file and it responds the same way to the --wallet
flag. PKT-Lightning-Wallet is still in development do not use it to open a large wallet yet!
To be continued…
In the next installment, I will explain the address balance and vote counting logic, and show you how you can look at the address balances and winners using the unreleased code in PKT-FullNode. Make sure you subscribe so you will receive that as soon as it comes out.
In the mean time, check out all of the other features that PKT-Lightning-Wallet has using:
./bin/pldctl help
You can also learn how to become a candidate by reading:
./bin/pldctl help wallet/transaction/sendvote