CIP Proposal: Voting Meta Protocol through Broadcasts

With the lack of PoW ‘voting’ by miners there’s no good way to reach / poll for consensus on changes to the protocol that aren’t completely uncontroversial.
The Counterparty Devs should be able to initiate a vote to all XCP holders (for example for a protocol change).

Being able to let all XCP owners vote on a particular issue can be very useful to poll the consensus / desire of the community.

The votes done in this way is not part of this CIP and the initial intention is not to have any protocol changes activate automatically based on these votes, though that could be a future CIP if there’s a desire to do so.

As discussed previously here: counterpartytalk.org/t/cip-xcp-dividends-for-pos-voting/1895, to avoid making anyone have more power within the protocol, we won’t be using tokens but will instead use a meta protocol with messages encoded in broadcast messages.

This also makes this easily usable for other assets.

We’ll add the code to track votes to counterparty-lib/client so that anyone can easily track ongoing votes without requiring extra scripts. We’ll also add code to counterwallet to easily cast votes, this should cover a big part of the XCP holders.

Specification

There will be 2 types of ‘special’ broadcast messages that are used for this; INITVOTE and CASTVOTE.

INITVOTE <VOTENAME> <ASSET> <DURATION> OPTS <OPTION_1> <OPTION_N>

VOTENAME: any sequence of non-space characters used as label for the vote, must be unique across the network.
ASSET: the asset for which the olders can vote.
DURATION: the duration (in blocks) for the voting period (int) with max of 1 year.
OPTS, followed by 2+ options, ie; OPTS TRUE FALSE.
Once an INITVOTE is initiated a list of balances of ASSET will be stored which will be used to weight each vote.

CASTVOTE <VOTENAME> <VOTE> <OPTION>

VOTENAME: should match a VOTENAME that was initiated and has not expired it’s DURATION.
OPTION: one of the options from INITVOTE.
VOTE: int between 0 and 100 indicating percentage of vote.

Discussion Points

Should there be a max on DURATION? 1 year sounds like a good sanity check?
If a holder of a token has put a LOCK on his broadcast feed he won’t be able to vote, unless we’d ignore the LOCK (which can be done because broadcasts will still be stored with Status: invalid (locked feed))

The tables where the poll data is stored and any validation errors of poll broadcast messages are excluded from consensus hashes, to make sure this is optional and can be disabled.
I already wrote most of the code (hoping everyone will approve) and even added a --disablepolls flag so you can run your node without parsing these messages at all.

What’s to prevent someone from bloating the counterparty db by initiating many spam votes for assets with large amounts of holders?

Yea, that’s one remaining concern I have, because the data stored is considerably higher than that of any other message, gonna have a look how feasible it is to query for the balances when calculating the results instead

I’m a big proponent of not storing the same information twice if it’s not absolutely necessary.

Would the database entry size be enough to matter if no one responded to these spam polls? It is not free to make a broadcast, so there is an anti-spam measure already in place.

No, @loon3 is right, storing of the list of (for example XCP) holders is a considerably more than the amount of data stored for any other message.

@rubensayshi I haven’t looked at the code, but is there anything in place that prevents double voting during the time period?

In other words, can I vote with my 50 XCP, then transfer that XCP to another address, then vote again with that address?

that’s the point of storing the balances when the vote is initiated, that’s the ‘stake’ that you’re voting with.

Ahh. I understand now. That makes sense why the poll table entry size is so significant. It takes a snapshot of the balances of all holders of the asset at the time that the broadcast is confirmed.

To get the asset balances for a given address at block X, you would need to walk back from the balances at the current block and reverse every send, dividend, market action, etc. That is theoretically possible but problematic.

I think it will be virtually impossible after smart contracts land.

Crazy idea… How feasible is it to store a “diffs” table for all balances at each block? In other words, create a table that has a key of “block,address,asset” - and then have a balance change entry. That way you could easily query the database for the value of asset X at block Y stored in address Z.

(Maybe this is what you are already looking at).

afaik we have credit/debit table with that, gimme ~30min to look into it :wink:

@deweller CIP: XCP Dividends for PoS voting

You guys are way ahead of me… Cool.

sqlite> SELECT asset, COUNT(*) FROM debits GROUP BY asset ORDER BY COUNT(*) DESC LIMIT 50;
LTBCOIN|139453
XCP|94997
FLDC|66924
SJCX|21779
GEMZ|15539
BITCRYSTALS|9215
SELECT address, SUM(debits_sum), SUM(credits_sum), SUM(credits_sum) -SUM(debits_sum) AS balance FROM (
	SELECT 
		address, 
		SUM(quantity) AS debits_sum, 
		0 AS credits_sum 
	FROM debits 
	WHERE asset = 'XCP' 
	AND block_index <= 398215 
	GROUP BY address

	UNION

	SELECT 
		address, 
		0 AS debits_sum, 
		SUM(quantity) AS credits_sum 
	FROM credits 
	WHERE asset = 'XCP' 
	AND block_index <= 398215 
	GROUP BY address
)
GROUP BY address
;

takes ~0.5s to run, which is fine imo for when you want to list the results, we could add an index to those tables on asset + block_index instead of just asset, but doesn’t seem like it speeds up the query at this data set size (yet).

util.holders however normally takes into account balances that are in ‘escrow’ (for DEX and bets), which I think is correct, so this query above is insufficient.

okay, wasn’t too hard to make the required changes to no longer store the holders but instead query them when getting results.

I guess this also opens the door to add a FREEZEHEIGHT to the INITVOTE so you could choose to use the balances at a particular height in the past (or future if you feel like it) instead of at the current height of INITVOTE.

WIP: https://github.com/rubensayshi/counterparty-lib/pull/3

I like the FREEZEHEIGHT option quite a bit. Are you interested in including that in the proposal?

I would imagine it would have limits similar to DURATION.

yea, updated proposal and code

I don’t hold any XCP. Am I now disenfranchised?

I own 1000 assets. Am I without stake?

Should I buy, Buy, BUY, now?

Stick to coding. Less politicking.

I’m coding to others can have options do politics, and I personally think PoS based voting with XCP is probably one of the cleanest ways we could do it in CP and imo it would be a great feature for bitcoin to have too considering the latest year of dicussions about block size.

1 Like

Instead of <DURATION> in number of blocks, how about using a UNIX timestamp to set the deadline? The format would be: INITVOTE <VOTENAME> <ASSET> <DEADLINE> OPTS <OPTION_1> <OPTION_N>
The voting period will end with the first block with a timestamp greater than or equal to <DEADLINE>.

A separate idea is the option to reward voters. If a value >0 is broadcast at INITVOTE then escrow this amount of <ASSET>. At the end of the voting period this will be distributed proportionally to those who made a valid CASTVOTE.