ICON Workshop — Voting DAPP

2infiniti (Justin Hsiao)
4 min readNov 5, 2018

--

ibriz inc prepared another workshop item that was not presented at the ICON workshop during SF blockchain week. Unfortunately there’s no presentation available, but if you had done all previous tutorials part 1, part 2, and part3, this one should be fairly easy to implement.

It is a simple voting DAPP using ICONex wallet, one vote per wallet, and the results are displayed on a webpage. Let’s go over the code in this tutorial, first get the project files from their gitlab repository,

$ git clone https://gitlab.com/ibriz/icon-polling.git

SCORE

Take a quick glance as our SCORE polling.py,

I’ve made some additional comments to the source file, the SCORE is really simple. It takes a contract call vote to receive votes, checks to see if the sender has voted, then log the results, that’s about it.

You can test locally first, we’ll skip this and deploy directly to testnet.

You need to fix tbears_cli_config_testnet.json as it is using some deprecated code,

config/tbears_cli_config_testnet.json
{
"uri": "https://bicon.net.solidwallet.io/api/v3",
"nid": "0x3",
"keyStore": null,
"from": "hxe9d75191906ccc604fc1e45a9f3c59fb856c215f",
"to": "cx0000000000000000000000000000000000000000",
"deploy": {
"stepLimit": "0x5a000000",
"contentType": "zip",
"mode": "install",
"scoreParams": {
}
},
"txresult": {},
"transfer": {}
}

then deploy directly to testnet,

$ tbears deploy polling -k keystores/keystore1.json -c config/tbears_cli_config_testnet.json# password p@ssword1

Check the result as usual,

$ tbears txresult 0x3948fbf6ca67dd04801283c47123064e54d7324a358add345c8c4fd05fa1d385 -u https://bicon.net.solidwa
llet.io/api/v3

keep scoreAddress somewhere, we’ll need to paste the address in a few places,

"scoreAddress": "cx4e739b203b92498b6b6fb6d205f1cb62a6d4f88d"

Edit webapp/main.py and change default_score to our new SCORE address, also enable localhost on port 5000.

# webapp/main.py
default_score = "cx4e739b203b92498b6b6fb6d205f1cb62a6d4f88d"
# Last line
app.run(debug=True, host='localhost', port=5000)

Test run it and visit http://localhost:5000

$ python main.py
# Visit http://localhost:5000

You should see an empty page without any votes

Replace keystore2.json and keystore3.json with your keystore files from testnet wallets, we’ll use iconkeystore3 and iconkeystore4. Copy these files from earlier tutorials into keystores/ folder. You can also use any wallets with some balance on the testnet.

Change the password under wallets in line 23 of webapp/main.py accordingly.

# webapp/main.pywallets = {
'wallet1': KeyWallet.load("../keystores/keystore1.json", "p@ssword1"),
'wallet2': KeyWallet.load("../keystores/iconkeystore3", "@icon333"),
'wallet3': KeyWallet.load("../keystores/iconkeystore4", "@icon444"),
}

Now cast our first vote with keystore1.json (wallet1), "_vote": "0x1" = yes, "_vote": "0x2" = no. In this example, we’re voting yes.

# testcmd/send.json
{
"jsonrpc": "2.0",
"method": "icx_sendTransaction",
"params": {
"version": "0x3",
"from": "hxe9d75191906ccc604fc1e45a9f3c59fb856c215f",
"value": "0x0",
"stepLimit": "0x200000",
"nid": "0x3",
"nonce": "0x2",
"to": "cx4e739b203b92498b6b6fb6d205f1cb62a6d4f88d",
"dataType": "call",
"data": {
"method": "vote",
"params": {
"_vote": "0x1"
}
}
},
"id": 1
}

execute it,

$ tbears sendtx -k keystores/keystore1.json testcmdline/send.json -u https://bicon.net.solidwallet.io/api/v3

then check the txresult,

$ tbears txresult 0xad6e8058a8f992f6b7312848853437c9639280e436e5391dd6254d8593d637ec -u https://bicon.net.solidwallet.io/api/v3

Visit our webpage http://localhost:5000 again, you should see wallet1 voted yes.

You cannot repeat votes from the same wallet, for wallets that haven’t voted (iconkeystore3, iconkeystore4), you can vote via JSON RPC like we did for wallet1, or you can simply vote through the webapp.

You can also check the tally results from T-Bears by calling our get_vote_talley from SCORE.

# testcmdline/call.json
{
"jsonrpc": "2.0",
"method": "icx_call",
"params": {
"from": "hxe9d75191906ccc604fc1e45a9f3c59fb856c215f",
"to": "cx4e739b203b92498b6b6fb6d205f1cb62a6d4f88d",
"dataType": "call",
"data": {
"method": "get_vote_talley"
}
},
"id": 1
}

Execute,

$ tbears call testcmdline/call.json -u https://bicon.net.solidwallet.io/api/v3

you should see the same result

response : {
"jsonrpc": "2.0",
"result": {
"yes": "0x2",
"no": "0x1"
},
"id": 1
}

Web App

The main.py has some unused and irrelevant code, don’t worry about those. The main flow is basically getAllVotesIcon from polling-script.js, which routes to result/<wallet> calling votingResults on our main.py then draw the chart. The main function vote in our webapp would create a signed transaction and call our SCORE’s vote method to cast the vote.

Optionally you can deploy the app to a production server, follow the steps from the previous tutorial

Demo: https://dapps.icon.support/icon-polling

That’s it for this voting DAPP, this demonstrates another great use case for blockchain decentralized applications. Paper ballots have been used in voting since the Roman Empire and results are counted by hand till this day. Online voting in a centralized application has a few fundamental flaws that are usually overcome by higher security standards, but votes stored in a centralized database can be breached and altered. Application code can also change, meaning election rules can change. Blockchains enhance voting integrity with secure transactions and traceability, so every vote can be vetted and records are permanent, transparent and immutable. It’s time to evolve.

Follow me on Twitter for most up-to-date ICON related content: https://www.twitter.com/2infiniti

--

--