Repository navigation
Decision proposals: anyone opens a masternode yes/no vote for 0.5 Dash (5.1, protocol 15) #5679
Description
Summary
Let any identity open a decision proposal: a yes/no question that masternodes and evonodes vote on, with the result recorded on Platform. Proposals are signaling only: a passed proposal changes nothing on chain. Opening one costs 0.5 Dash, which pays for the votes. The proposer chooses the pass threshold, the minimum turnout and the end date, within protocol limits. Target: Platform 5.1 (protocol version 15).
This builds on yes/no vote polls (#4899, merged into v5.1-dev) and their client queries (#5651, in review).
Decisions (2026-10-30)
- Signaling only. Nothing acts on a result. The closed poll keeps the result and the tallies, which clients read with feat(platform): yes/no vote poll state and masternode answer queries #5651's queries.
- Anyone can open one, for 0.5 Dash.
- Ships in 5.1 (protocol version 15).
- The proposer chooses the rules, within limits.
- Three changes to the yes/no poll format merged in feat(platform)!: yes/no masternode vote poll kind with supermajority and minimum voting power #4899. They come first, because the format becomes permanent when protocol 15 ships (reasoning in feat(platform)!: yes/no masternode vote poll kind with supermajority and minimum voting power #4899 (comment)):
- A vote carries only the 32-byte poll id and its answer, not the whole poll (up to about 1 KB), so voters no longer rebuild the poll's exact bytes. The rule stays in the poll's stored info and cannot change after opening.
- A poll is identified by a typed purpose, for example
DecisionProposal { document_id }, matched exhaustively, instead of an opaque byte path. - PoSe-banned masternodes are left out of the network total that a fraction-of-network minimum is measured against.
What exists on v5.1-dev
- Polls:
VotePoll::YesNoVotePollcovers voting (aMasternodeVotecarrying aYesNoVote), tallying, closing at the end date, the stored result and the clean-up of the poll's fund. Voting power is 1 per masternode and 4 per evonode, and a masternode can vote up to 5 times per poll. Active from protocol version 15. - Opening:
Drive::open_yes_no_vote_poll[_operations]opens a poll and writes its end-date entry. It refuses bad parameters, an end date that is not after the opening block or is more than four weeks away, and a poll that already exists. Only tests call it today. The caller funds the poll. - Vote cost: each vote takes 0.00002 Dash from the poll's fund (
FEE_VERSION3). Once the fund is empty, further votes are refused. - Result hook:
on_yes_no_vote_poll_finishedv0 does nothing. Signaling proposals keep it that way. - Clients:
- rs-sdk
PutVotecasts yes/no votes. - wasm-sdk / js-evo-sdk
masternodeVotebuilds only contested-resource votes. - rs-sdk-ffi, Swift and Kotlin have nothing for yes/no votes.
- Dash Evo Tool has nothing for yes/no votes (
v1.0-dev).
- rs-sdk
Design
A system contract holds the proposals
Add a new system contract, DecisionProposals (SystemDataContract discriminant 11). Chains born at 15 register it at genesis, and transition_to_version_15 inserts it, as ModerationCharters is handled at 14. It has one document type, proposal, with:
title,descriptionand an optionalurl, each with a byte limit in the schema.- The rule:
supermajorityNumerator,supermajorityDenominator,minimumVotingPower(absolute, or a fraction of the network with a rounding, as inYesNoMinimumVotingPower) andendDatein milliseconds. - No updates and no deletion: masternodes vote on what the document said when it was created.
- Indexes for listing: by end date, by owner, and by creation time.
Creating a proposal document opens its poll
A proposal create in a batch does four things:
- Builds the poll with one rs-dpp function, shared by consensus and the SDKs. Its purpose is
DecisionProposal { document_id }, and it carries the proposer's rule. - Checks the rule against the limits below. The rule itself is checked in structure validation; the end date is checked against the block time in state validation.
- Requires a stated fund of exactly 0.5 Dash, as the moderation charter election already checks its own 0.5 Dash (
document_create_transition_action/advanced_structure_v1). - Opens the poll and credits the fund in the same batch:
open_yes_no_vote_poll_operations, given the batch's previous operations, plus the poll's fund credited under itsspecialized_balance_id.
Today the create transition's prefunded_voting_balance is a pair of contested index name and amount, and the create action carries a contested poll. Both need a yes/no case.
Limits the proposer works within
| Rule | Limit | Status |
|---|---|---|
Pass threshold n/d (yes > n/d of yes + no) |
0 < n < d |
exists |
at least a simple majority, n/d >= 1/2 |
proposed, new SystemLimits field |
|
| Minimum turnout | absolute: at most 2,000 voting power; fraction: at most 50% of the network | exists (SystemLimits) |
| End date | after the opening block, at most four weeks away | exists (SystemLimits) |
| at least one week away | proposed, new SystemLimits field |
|
| Text | byte limits on title, description, url |
in the contract schema |
Fund and fee
- The fee field: add
decision_proposal_fund_required_amount, 0.5 Dash, toVoteResolutionFundFees. It goes in a new fee schedule,FEE_VERSION4, selected by protocol version 15. Protocol 15 still usesFEE_VERSION3, which is protocol 14's schedule. - Enough for every vote: at 0.00002 Dash a vote, 0.5 Dash pays for 25,000 votes. Every masternode casting all five of its votes is about 3,000 × 5 = 15,000 votes, so the fund cannot run out before the poll closes at today's network size. For proposals, this settles open question 3 on feat(platform)!: yes/no masternode vote poll kind with supermajority and minimum voting power #4899 (answer changes draining the fund). Above about 5,000 masternodes, the fund would no longer cover every masternode's full allowance.
- The remainder goes to processing fees when the poll closes, as for DPNS contests.
- Create fees: the proposer also pays the normal document create fees.
Clients
- rs-dpp / rs-sdk: the proposal-to-poll function (the one consensus uses), a create helper that states the fund, and listing helpers.
- wasm-sdk / js-evo-sdk:
masternodeVoteaccepts a yes/no answer, plus aproposalsfacade with create, list, poll state (feat(platform): yes/no vote poll state and masternode answer queries #5651) and a masternode's answer (feat(platform): yes/no vote poll state and masternode answer queries #5651). - rs-sdk-ffi, Swift, Kotlin: cast a yes/no vote, and read proposals and their state.
- Dash Evo Tool (dashpay/dash-evo-tool): a list of proposals and voting for masternode operators.
- Release note: clients older than 5.1 fail any
getVotePollsByEndDatepage that contains a yes/no poll (accepted in feat(platform)!: yes/no masternode vote poll kind with supermajority and minimum voting power #4899). Proposals bring such entries to mainnet, so wallets, explorers and Dash Evo Tool need 5.1 SDKs by the time protocol 15 activates.
Still open
- The two proposed limits: a simple-majority floor (
n/d >= 1/2) and a one-week minimum length.
Question 4 on #4899 (acting on a result at the end of the block) does not apply to signaling proposals.
Build plan
- Poll format changes: the three format decisions above, on the merged yes/no poll code. Votes carry the poll id, polls carry a typed purpose, and banned masternodes leave the network total. Protocol 15 is unreleased, so its tables are edited in place. The client queries in feat(platform): yes/no vote poll state and masternode answer queries #5651 already name a poll by its id.
- Contract and rules: the
DecisionProposalssystem contract (schema, id, genesis andtransition_to_version_15), the rs-dpp proposal-to-poll function, the newSystemLimitsfields, andFEE_VERSION4with the fund field. - Opening: the document create path described above, new consensus errors (append-only) and tests. Needs step 2.
- Client queries: feat(platform): yes/no vote poll state and masternode answer queries #5651, in review.
- SDKs: rs-sdk and wasm-sdk / js-evo-sdk first, then rs-sdk-ffi, Swift and Kotlin. Needs steps 3 and 4.
- Dash Evo Tool: in its own repository. Needs step 5.
Tests
- At protocol 15, a
proposalcreate opens the poll, writes its end-date entry and funds it with 0.5 Dash. Before 15 the contract does not exist. - A wrong fund is refused (none, 0.5 Dash minus 1 credit, 0.5 Dash plus 1 credit).
- A rule outside each limit is refused, and a rule exactly at each limit is accepted. An end date too soon or too far away is refused.
- Two proposals with the same text from different owners open different polls.
- Full lifecycle with masternode and evonode votes:
- the close records the result and the tallies;
- the rest of the fund goes to processing fees;
- the document stays;
- feat(platform): yes/no vote poll state and masternode answer queries #5651's queries prove the result.
- A strategy test with many proposals and votes, on end dates shared with DPNS contests.
- A chain born at 15 and a chain upgraded from 14 to 15 end up with the same contract and trees.
Activity