Alexander Chepurnoy

The Web of Mind

Voting System Guide for Developers & Experienced Users

| Comments

This blogpost describes voting system presented in NRS(Nxt Reference Software) 1.5 for application developers & experienced users. For simple use cases, wallet’s UI is self-explanatory and enough.

Features

  • Different voting models supported: voting by account(1 account = 1 vote), balance(1 Nqt = 1 vote), asset balance(1 Qnt = 1 vote), or Monetary System token balance(1 currency unit = 1 vote)

  • Voting has finite predefined duration(finish block height, to say precisely)

  • Poll has minimum and maximum number of options to provide opinion for. E.g. choose from 2 to 5 options out of 8

  • Range is the vote parameter. E.g. give a rate from 0 to 10.

  • By combining number of options & range a lot of specific poll types could be done. E.g. binary poll is poll where range is from 0 to 1 (i.e. no or yes). UI can handles some ranges in such a meaningful way.

  • Anonymous voting ( https://bitbucket.org/JeanLucPicard/nxt/issue/176/private-polls ) is not implemented. It could be implemented with e.g. Blind signatures(https://en.wikipedia.org/wiki/Blind_signature) but it’s not known how to implement that on top of the blockchain. So it seems an anonymous voting could be implemented by trusted 3rd party services only.

Parameters

Voting models

Four voting models exist:

  • By account, 1 account = 1 Vote

  • By balance, 1 Nqt = 1 Vote (nqt, not nxt!)

  • By asset, 1 Asset Qnt = 1 Vote

  • By Monetary System token, 1 curency unit = 1 Vote

All the models could be enhanced by additional parameter, describing min balance in units(nqt/qnt/currency units).

Counting

Counting happens at the finish block height set during poll creation. And a vote being counted only if it satisfies poll parameters(min balance etc) at that finish height. Please note, a voter could vote with balance < min balance needed to vote(at height where vote has been sent), and that’s valid, but a vote will be counted only if balance >= threshold balance at poll finish height.

Mandatory Parameters

name - a poll’s title, no more than 100 characters

description - detailed poll description, no more than 1000 characters

options - possible options titles to choose from and give a rate to. Minimum one option, maximum 100.

votingModel - four possible values for by-account, by-balance, by-asset, by-token voting

finishHeight - block height in future poll is finishing and counting taking at. Minimum 1 block since inclusion height(so set current height + 2 at least), maximum 14*1440 blocks = 20160 blocks since inclusion height

minNumberOfOptions , maxNumberOfOptions - minimum and maximum number of options a voter can choose

minRangeValue , maxRangeValue - a vote’s value is within this range

minBalance - 0 by default. A vote is counted only if account balance @ finishing height (in nqts/qnts/MS tokens) >= minBalance. Mandatory for by-account voting (i.e. should be more than 0 in case of by-account voting)

minBalanceModel - used in by-account voting to distinguish which kind of units used for minbalance, nqt balance / assets / currency units. For last two options holdingId parameter is also required

Optional parameters

  • holdingId - for voting by assets or MS tokens, also used for minBalance in by-account voting

Notes

  • Voting by asset could be started by anyone, not just asset/currency issuer or even owner

HTTP API

  • Create poll

Use POST request to createPoll API call to create a new poll. Example with curl:

1
curl -d 'name=cryptos&description=rate+cryptos+you+like&finishHeight=300000&votingModel=1&minNumberOfOptions=1&maxNumberOfOptions=2&minRangeValue=-5&maxRangeValue=5&secretPhrase=very+secret+phrase&deadline=1000&feeNQT=1000000000&option00=nxt&option01=btc' http://localhost:6876/nxt?requestType=createPoll

Parameters:

name - mandatory - poll title, not longer than 100 chars

description - mandatory - detailed poll description, max 1000 chars

finishHeight - mandatory - height of block when voting will be finished i.e. counted(should be > current one)

votingModel - mandatory - by-asset, by-account, or by-balance. see corresponding numeric value below

minBalance - mandatory for by-account voting, optional for other types - min amount of money or assets to vote, in nxt or qnt. by default 0(if skipped)

minBalanceModel - mandatory for by-account voting - what kind of tokens to use for vote threshold, nqt/qnt/ms token. See below for possible field values.

minNumberOfOptions - mandatory - min number of options to choose

maxNumberOfOptions - mandatory - max number of options to choose

minRangeValue - mandatory - min vote value possible, no more than 100

maxRangeValue - mandatory - max vote value possible, no less than -100

holdingId - mandatory in case of by-asset voting, could be also usedin addition with minBalance in by-account voting - asset or ms token id in unsigned form

option00,option01,option02,option03,…option99 - titles of corresponding options, please note parameter is always with two digits, starting with 00

Use following numerical values to set voting model:

1
2
3
4
VotingModel.ACCOUNT = 0;
VotingModel.NQT = 1;
VotingModel.ASSET = 2;
VotingModel.CURRENCY = 3;   //MS Token

Use following numerical values to set voting minBalanceModel:

1
2
3
4
MinBalanceModel.NONE = 0;
MinBalanceModel.NQT = 1;
MinBalanceModel.ASSET = 2;
MinBalanceModel.CURRENCY = 3; //MS Token
  • Vote casting

Use POST request to castVote API call to send your vote to the NRS. Example:

1
curl -d 'poll=12528572507118413418&secretPhrase=secret+phrase&deadline=1000&feeNQT=100000000&vote00=1&vote00=0' http://localhost:6876/nxt?requestType=castVote

Parameters are pretty straightforward. Use poll’s transaction id as poll parameter value, use vote00..vote99 to provide weights for option00..option99 options.

Please note, poll should be included into the blockchain to vote on it.

  • Get poll data

Use GET request getPoll to get poll data, e.g.

1
http://localhost:6876/nxt?requestType=getPoll&poll=12528572507118413418 

could returns something like

1
{"minRangeValue":-5,"votingModel":1,"description":"rate cryptos you like","finished":false,"poll":"4555214309048629195","requestProcessingTime":1,"minNumberOfOptions":1,"minBalance":"0","accountRS":"NXT-DV37-DD8K-3Q74-8LE2W","name":"cryptos","options":["nxt","btc"],"finishHeight":300000,"maxNumberOfOptions":2,"minBalanceModel":1,"account":"7926777737834261541","maxRangeValue":5,"timestamp":45731391}
  • Get poll results

Use GET request getPollResult to get poll results, e.g.

1
http://localhost:6876/nxt?requestType=getPollResult&poll=12528572507118413418

example result:

1
{"votingModel":1,"minBalance":"0","options":["nxt","btc"],"finished":false,"poll":"4555214309048629195","requestProcessingTime":1,"minBalanceModel":1,"results":[{"result":"1942320000000","weight":"1942320000000"},{"result":"","weight":"0"}]}

“finished” value is false, so voting still happens!

The request accepts some interesting parameters: votingModel , holding , minBalance , minBalanceModel - you can play with these parameters to see how results could be different depending on polls' input parameters(with the same set of voters).

  • Get polls

Use POST request to getPolls :

1
curl -d 'account=7926777737834261541&firstIndex=0&lastIndex=5&includeFinished=true'  http://localhost:6876/nxt?requestType=getPolls

There’s additional includeFinished parameter(self-explanatory). If account=0, all limited by indexes polls in the chain (active only if includeFinished=false) will be returned.

  • Get vote(s) details

There’re two API calls to get vote details, getPollVote & getPollVotes . First one accepts poll & account parameters, while second accepts just poll (& firstIndex, lastIndex).

  • Search polls

Use searchPoll to find relevant polls by text query. Example query with all the four parameters possible.

curl -d ‘query=cryptos&firstIndex=0&lastIndex=5&includeFinished=true’ http://localhost:6876/nxt?requestType=searchPolls

Fees

If poll contains less than 20 options, fee for it’s creation is 10 Nxt, otherwise each additional option costs 1 Nxt as well.

Vote fee is 1 Nxt.

Settings

There’s only one setting at the moment which could be overriden in nxt.properties:

1
2
3
# If disabled, polls are not processed at finish height and results are not stored in the database.
# When requested, poll results will be calculated on-the-fly, if the votes are still available.
nxt.processPolls=true

Set the value to false if you run a lean node & don’t need for results of all the polls in the chain to be calculated & stored.

Use Cases & Application Ideas

Out of the scope of simple voting, there are a lot of possibilities Voting System provides:

  • Distributed shareholders meetings (using assets as voting rights)
  • Publicly verifiable community decisions (using e.g. Monetary System tokens as community currency)
  • Building consensus protocols on top of the blockchain with strong evidence of a consensus

  • (to be continued)

Internal details (for developers)

This section is for developers working with core, studying the NRS code, or writing apps working closely with the core(so using low-level Java API not HTTP, though that way isn’t recommended unless a developer knows why he’s doing that).

Attachments

There are two kinds of attachments related to voting system: MessagingPollCreation & MessagingVoteCasting. Also please take a look PollBuilder helper implementing Builder pattern to create MessagingPollCreation objects:

1
2
3
4
5
6
7
8
9
10
11
12
val pb = new PollBuilder(question, desc, options, finishBlockHeight, votingModel,
      minNumberOfChoices, maxNumberOfChoices, minRangeValue, maxRangeValue)

minBalanceOpt.map { mb =>
    minBalanceModelOpt match {
      case Some(minBalanceModel) => pb.minBalance(minBalanceModel, mb)
      case None => pb.minBalance(mb)
    }
}
holdingIdOpt.map(hi => pb.holdingId(hi))

issueTx(phrase, pb.build())

Transaction types

There are two transaction types related to VS: Messaging.POLL_CREATION and Messaging.VOTE_CASTING.

Getting data

Take a look to static methods of the Poll class to get data you want. E.g. getPoll(long id) returns poll by its id, getPollsByAccount returns polls created by an account specified etc.

Comments