Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multi: Add RFP proposal. #1054

Merged
merged 35 commits into from May 6, 2020
Merged

multi: Add RFP proposal. #1054

merged 35 commits into from May 6, 2020

Conversation

lukebp
Copy link
Member

@lukebp lukebp commented Nov 19, 2019

Closes #966

This diff adds a new type of proposal called a Request For Proposals
(RFP) and a new type of proposal vote called a runoff vote.

Overview of the RFP process

  1. Any politeia user can submit an RFP proposal. An RFP proposal must
    first be voted on and approved by the stakeholders before RFP
    submissions are allowed. The RFP proposal is essentially asking the
    stakeholders the question, "Do the stakeholders want to open up an
    RFP process and solicit proposals for this topic?"

  2. If approved, new proposal submissions are allowed to link to the RFP
    proposal. These linked proposals are considered to be RFP
    submissions. A link is not official until the RFP submission is made
    public, leaving this decision in the hands of the admins. A deadline
    exists for RFP submissions to be accepted. This deadline is set by
    the RFP author when they orginally submit the RFP and can be updated
    at any point before the start of the RFP proposal vote (step 1). Once
    the RFP proposal goes up for vote in step 1, this deadline becomes
    final. RFP submissions are not accepted once this deadline expires.

  3. Once the RFP submission deadline expires, an admin can start the
    voting process on the RFP submissions at any time. This is a new type
    of vote called a runoff vote. Whe an admin starts the runoff vote,
    the voting period on all public, non-abandoned RFP submissions will
    begin simultaneously. Unlike a normal proposal vote, no vote
    authorization is required from the submission author. Each submission
    is voted on like a normal proposal vote.

  4. The results of the runoff vote are calculated as follows:

    • Only one proposal can be approved.
    • The winning proposal is the proposal that meets the quorum %
      requirement, meets the pass % requirement, and that has the most
      net yes votes.
      Note: this means that it will be possible for a proposal to meet
      the quorum and pass requirements but still be rejected if it does
      not have the most net yes votes.
    • If no proposals meet the quorum and pass requirements then all of
      the proposals will be considered rejected.

Data changes

Added to the user defined ProposalMetdata:

  • LinkBy: A UNIX timestamp of the RFP submission deadline. We
    determine if a proposal is an RFP by checking if this field is set.
  • LinkTo: Censorship token of an existing public proposal to link to.
    This is only used for RFP submissions at the moment, but can be used
    for other types of links in the future such as proposal updates.

API changes

Routes added:

  • StartVoteRunoff: start the voting process on all public,
    non-abandoned RFP submissions simultaneously.

Routes with API changes:

  • VoteSummary: a Type field and a Approved field were added to the
    VoteSummaryReply. A runoff vote makes it much harder for the client
    to calculate the vote results, it needs the results from all of the
    proposals in the runoff vote to do so, so the backend now does it and
    returns whether the vote for any single proposal was approved.

Routes with code changes:

  • NewProposal
  • EditProposal
  • AuthorizeVote
  • StartVote
  • TokenInventory

Testing with piwww CLI

The following commands can be used to test this diff. Manually editing
the allowable quorum percentage, pass percentage, and minimum duration
in politeiad is required if you want to test this in a reasonable manner.

# Submit an RFP proposal, make it public, and start the voting process
# on it. The RFP must first pass a vote before RFP submissions can link
# to it. The following vote params are used for testing purposes:
# duration = 1 block
# quorum = 0%
# pass = 0%
$ piwww newproposal --random --rfp
$ piwww setproposalstatus [rfp_token] public
$ piwww authorizevote [rfp_token]
$ piwww startvote [rfp_token] 1 0 0

# Vote on the RFP proposal.
$ piwww vote [rfp_token] yes

# Wait for the vote to end...

# Submit four RFP submissions. Abandon one of them.
$ piwww newproposal --random --linkto=[rfp_token]
$ piwww setproposalstatus [submission1_token] public

$ piwww newproposal --random --linkto=[rfp_token]
$ piwww setproposalstatus [submission2_token] public

$ piwww newproposal --random --linkto=[rfp_token]
$ piwww setproposalstatus [submission3_token] public

$ piwww newproposal --random --linkto=[rfp_token]
$ piwww setproposalstatus [submission4_token] public
$ piwww setproposalstatus [submission4_token] abandoned

# Start the runoff vote on the RFP submissions. The same vote params are
# used as before.
$ piwww startvoterunoff [rfp_token] 1 0 0

# Vote on the submissions so that submission1 wins.
piwww vote [submission1_token] yes
piwww vote [submission2_token] no
piwww vote [submission3_token] no

# Wait for the vote to end...

# Fetch the token inventory so that the vote results get calculated and
# added to the cache.
piwww tokeninventory

mdstream/mdstream.go Outdated Show resolved Hide resolved
mdstream/mdstream.go Outdated Show resolved Hide resolved
politeiad/backend/gitbe/decred.go Outdated Show resolved Hide resolved
politeiad/backend/gitbe/decred.go Show resolved Hide resolved
politeiad/backend/gitbe/decred.go Outdated Show resolved Hide resolved
@lukebp
Copy link
Member Author

lukebp commented Dec 2, 2019

This PR has been put on hold temporarily. During the process of writing the RFP code I discovered issues with two of the mdstreams, the StartVote metadata and the ProposalStatusChange metadata. Fixing the the mdstream issues is going to require bumping the versions of those two mdstreams. Since we're bumping the version of the StartVote metadata it makes sense to also add the VoteType from this PR to the StartVote mdstream at the same time. This means the mdstream fixes will need to go in before this PR can go in. I'm working on those changes now.

@xaur
Copy link

xaur commented Dec 3, 2019

This diff adds a new type of proposal called a Request For Proposals

Is the base entity called "proposal" and not something more abstract like "post" or "message"?

RFP proposal

This is "Request for Proposals proposal". I suggest to use just "RFP".

A link is not official until the RFP submission is made public

What "official" means here?

Unlike a normal proposal vote, no vote authorization is required from the submission author.

This has implications.

Unlike normal proposals, author no longer controls the time of discussion and Pi admins become the ones to decide it. "Submission deadline" only refers to submissions, not discussions. Imagine that late submissions are posted right before the deadline. A few days/weeks of comments may be required after the deadline but before the runoff vote starts.

Which leads to a related issue: once the initial RFP vote ends, the discussion under the RFP gets locked, while new submissions may arrive (until the deadline) and get discussed. If any questions or comments about the RFP in general (not about specific submissions) appear, they are forced to go into one of the submissions or even get duplicated across all of them, as we have observed in the market makers RFP. Or worse - spill over to chats or Reddit. What do you think about leaving the RFP discussion unlocked until the runoff vote finishes?

Can RFP submission proposals be edited after the RFP submission deadline?

  • Intuitively it should be "yes" because "submission deadline" only requires to submit by certain date, while comments and edits in response to feedback can continue past that deadline.
  • The challenges with "yes" is that
    • Pi admins need to decide whether the feedback and editing is over.
    • There can be a legit dynamic where authors edit their submissions to compete with others, either proactively or in response to edits by others. Such interaction may arbitrarily extend the discussion phase.
    • A "delay attack" is possible where submission authors delay the collective runoff vote by editing their submissions and keeping the discussion alive.

Based on the above I wonder what you think about

  • adding back vote authorization by the submission author,
  • and/or adding another deadline to limit how long submissions can be commented and edited. After that deadline the Pi admins can start the vote at any time.

@xaur
Copy link

xaur commented Dec 3, 2019

Re data model, revising my comment in #966,

LinkBy: A UNIX timestamp of the RFP submission deadline. We determine if a proposal is an RFP by checking if this field is set.

if p.LinkBy != nil ... // this is an RFP looks awkward, how about an explicit IsRfp flag or at least a more specific RfpLinkBy?

LinkTo: This is only used for RFP submissions at the moment, but can be used for other types of links in the future such as proposal updates.

  • LinkTo is too abstract. How about LinkToken?
  • Cramming multiple purposes ("member of this RFP", "update for this proposal", etc) into a single field might not be a good idea. How about making it a more specific RfpLinkToken and adding fields for other purposes (like UpdateFor for updates) as needed?

LinkedFrom: List of censorship tokens of all public proposals that have linked to this proposal.

Why is this needed? It breaks "single source of truth" and requires error-prone data consistency. Also, this will need to be updated even after the RFP vote finishes if new submissions arrive.

Decred Designated Market Maker
linkby:1574026984

This adds even more ad-hoc-iness to already ad-hoccy "first line is the title" format. How about standard YAML enclosed in ---'s like adopted by popular static site generators?

---
title: Decred Designated Market Maker
linkby: 1574026984
---

Body begins here...

This allows embedding of any structured metadata in proposal header (even with lists and maps).

@amass01
Copy link
Member

amass01 commented Feb 26, 2020

@lukebp Do we want to provide proposal types as well in our policy api call ?

According to the specs we gonna have a dropdown in proposal create page, so maybe we should fetch proposal types from BE as well ?

@lukebp
Copy link
Member Author

lukebp commented Mar 13, 2020

I force push this because #1088 and #1110 changed this PR enough that is became harder to rebase than to just start fresh on a new cut of master and copy/paste over certain changes. A large part of the PR was re-written based on changes over the past 2 months. The notable changes were:

  • Instead of including fields such as LinkBy in and LinkTo in the proposal markdown file, we now attach a json file as part of the proposal files bundle with these fields in them.
  • multi: Add v2 StartVote. #1088 added a vote type field to the VoteV2 struct, simplifying this PR a good bit.
  • [cms] Add CMS Users Request #1100 broke the ProposalGeneral mdstream out into its own cache table. This allows us to use the cache to query the links between proposals which also simplified this PR a good bit.

The original commit message has been updated to reflect these changes.

This diff adds a new type of proposal called a Request For Proposals
(RFP) and a new type of proposal vote called a runoff vote.

1. Any politeia user can submit an RFP proposal. An RFP proposal must
   first be voted on and approved by the stakeholders before RFP
   submissions are allowed. The RFP proposal is essentially asking the
   stakeholders the question, "Do the stakeholders want to open up an
   RFP process and solicit proposals for this topic?"

2. If approved, new proposal submissions are allowed to link to the RFP
   proposal. These linked proposals are considered to be RFP
   submissions. A link is not official until the RFP submission is made
   public, leaving this decision in the hands of the admins. A deadline
   exists for RFP submissions to be accepted. This deadline is set by
   the RFP author when they orginally submit the RFP and can be updated
   at any point before the start of the RFP proposal vote (step 1). Once
   the RFP proposal goes up for vote in step 1, this deadline becomes
   final. RFP submissions are not accepted once this deadline expires.

3. Once the RFP submission deadline expires, an admin can start the
   voting process on the RFP submissions at any time. This is a new type
   of vote called a runoff vote. Whe an admin starts the runoff vote,
   the voting period on all public, non-abandoned RFP submissions will
   begin simultaneously. Unlike a normal proposal vote, no vote
   authorization is required from the submission author. Each submission
   is voted on like a normal proposal vote.

4. The results of the runoff vote are calculated as follows:
   - Only one proposal can be approved.
   - The winning proposal is the proposal that meets the quorum %
     requirement, meets the pass % requirement, and that has the most
     net yes votes.
     Note: this means that it will be possible for a proposal to meet
     the quorum and pass requirements but still be rejected if it does
     not have the most net yes votes.
   - If no proposals meet the quorum and pass requirements then all of
     the proposals will be considered rejected.

Added to the `ProposalGeneral` mdstream:
- `LinkBy`: A UNIX timestamp of the RFP submission deadline. We
  determine if a proposal is an RFP by checking if this field is set.
- `LinkTo`: Censorship token of an existing public proposal to link to.
  This is only used for RFP submissions at the moment, but can be used
	for other types of links in the future such as proposal updates.

This proposal creates the concept of a proposal data.json file. The
data.json file is part of the proposal files bundle and includes fields
that are specified by the user and that needed by politeiawww, such as
the LinkTo and LinkBy fields. They are included in a seperate json file
instead of the index markdown file to make parsing easier.

Routes added:
- `StartVoteRunoff`: start the voting process on all public,
  non-abandoned RFP submissions simultaneously.

Routes with API changes:
- `VoteSummary`: a `Type` field and a `Approved` field were added to the
  `VoteSummaryReply`. A runoff vote makes it much harder for the client
  to calculate the vote results, it needs the results from all of the
  proposals in the runoff vote to do so, so the backend now does it and
  returns whether the vote for any single proposal was approved.

Routes with code changes:
- `NewProposal`
- `EditProposal`
- `AuthorizeVote`
- `StartVote`
- `TokenInventory`

The following commands can be used to test this diff. Manually editing
the allowable quorum percentage, pass percentage, and minimum duration
in politeiad is required if you want to test this in a reasonable manner.

```bash
$ piwww newproposal --random --rfp
$ piwww setproposalstatus [rfp_token] public
$ piwww authorizevote [rfp_token]
$ piwww startvote [rfp_token] 1 0 0

$ piwww vote [rfp_token] yes

$ piwww newproposal --random --linkto=[rfp_token]
$ piwww setproposalstatus [submission1_token] public

$ piwww newproposal --random --linkto=[rfp_token]
$ piwww setproposalstatus [submission2_token] public

$ piwww newproposal --random --linkto=[rfp_token]
$ piwww setproposalstatus [submission3_token] public

$ piwww newproposal --random --linkto=[rfp_token]
$ piwww setproposalstatus [submission4_token] public
$ piwww setproposalstatus [submission4_token] abandoned

$ piwww startvoterunoff [rfp_token] 1 0 0

piwww vote [submission1_token] yes
piwww vote [submission2_token] no
piwww vote [submission3_token] no

piwww tokeninventory
```
politeiawww/proposals.go Outdated Show resolved Hide resolved
@marcopeereboom
Copy link
Member

This is a huge PR and I'd lie if I don't think this will have a couple of buglets still hiding in it. I do think we need to move ahead and get this into master so that we can test it on testnet. There is no way we can get more eyes on it before it is deployed to testnet.

@lukebp lukebp merged commit 798ca09 into decred:master May 6, 2020
@lukebp lukebp deleted the rfp branch June 16, 2020 23:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[gui/www/d] Add multiple choice mechanism to select competing proposals
4 participants