Skip to content

Polls RFC 69 #320

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

Closed
wants to merge 0 commits into from
Closed

Conversation

toadlyBroodle
Copy link

@toadlyBroodle toadlyBroodle commented Mar 3, 2023

Request for Comment on new Poll event (kind #6969)
-Poll notes are paid poll events on nostr used to conduct quantitative opinion polls that users can vote on with zaps

Copy link
Contributor

@Semisol Semisol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks great, but needs some changes. also, in the future, we may need polls that count people that fall under specific criteria, having a NIP-05, 2 degrees of separation from the user that does the poll, ... but that can be left for later

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented Mar 5, 2023

I would break poll by value and by amount into separate event kinds. In that way:

  • specs for each method is well defined and won't change
  • new nips can create new talling methods
  • clients can declare full compliance to a specific kind and avoid open-ended specs.

@toadlyBroodle
Copy link
Author

toadlyBroodle commented Mar 5, 2023

There have been some concerns raised during private conversations that I think are important to be part of the public review process here. They may be largely summarized as pointing to two different attack vectors for potential poll manipulations: 1) single whale votes discrediting many shrimp participants' votes 2) fake/bot accounts swaying outcomes via vote flooding.

To address both attack vectors, I have eliminated the tally_method tag altogether and replaced its value and count attributes with optional value_minimum and value_maximum tags for specifying satoshi value limits on zaps to be included in tallies. Imposing upper limits on satoshi values of tallied zaps should decrease the likelihood of whales swamping shrimps, while imposing lower limits should make fake vote flooding attacks prohibitively expensive.

Additionally this resolves @vitorpamplona's suggestion, while significantly simplifying the standard, and allowing for the maximum freedom in poll design.

I've included further details in the revised specification and added the relevant poll_option tag to the zap event specification and README tag index.

@alltheseas
Copy link
Contributor

alltheseas commented Mar 6, 2023

Should there be a max number of choices (in zap polls for Damus story I suggested four (4) max; this is the expected pattern from cagedbird)? I can imagine e.g. 100 choices being unwieldy for a mobile client. Is ten (10) too many? Is five (5)?

"_ MAY include a consensus_threshold (0-100), representing a percentage threshold for any single vote option to achieve poll consensus_"
Is this variable consensus_threshold grouped with a minimum number of votes? If one (1) user votes, is consensus reached - i.e. does voting end prematurely with consensus_threshold surpassee, or is this evaluated after the poll closes?

"MAY specify a value_minimum satoshi value for zapped votes to be included in the tally"

Is there a minimum hard-coded for value_minimum at 1 sat? Are free polls possible with this NIP? Are combined free + zap polls possible?

If poll votes take place with zaps, is there a list of voters displayed?

Is there an option for a non-zap poll vote?

@toadlyBroodle
Copy link
Author

toadlyBroodle commented Mar 6, 2023

Should there be a max number of choices (in zap polls for Damus story I suggested four (4) max; this is the expected pattern from cagedbird)? I can imagine e.g. 100 choices being unwieldy for a mobile client. Is ten (10) too many? Is five (5)?

@alltheseas I've attempted to specify the least restrictive rule set here to ensure polling functions correctly and fairly, while allowing devs the greatest freedom to implement other non-critical details as they see fit. A large number of poll_options does not break anything inherent to the polling process, so I think the responsibility is on clients to impose such limits individually, if they choose.

Is this variable consensus_threshold grouped with a minimum number of votes? If one (1) user votes, is consensus reached - i.e. does voting end prematurely with consensus_threshold surpassee, or is this evaluated after the poll closes?

consensus_threshold is the minimum percentage for any single poll_option's percentage of the total tally to attain poll consensus status. It's intended as a simple 'measuring bar' and has no effect on prematurely closing polls. If only one person votes in a poll, then consensus is sure to be attained, when specified: how meaningful it is, depends on other statistical measures. It should probably be publicly visible before closing. Maybe this should be elaborated on in the spec?

Is there a minimum hard-coded for value_minimum at 1 sat? Are free polls possible with this NIP? Are combined free + zap polls possible?

Lightning wallets impose their own limits on minimum payment amounts. Don't think it's necessary to re-iterate here that values need be a 'positive decimal integer', as anything else will fail to be sent by wallets. By definition, zaps are not free. Certainly free polls are possible, but this NIP defines paid polls.

If poll votes take place with zaps, is there a list of voters displayed?

Clients can display any additional event information they choose.

Is there an option for a non-zap poll vote?

No.

@toadlyBroodle
Copy link
Author

this looks great, but needs some changes. also, in the future, we may need polls that count people that fall under specific criteria, having a NIP-05, 2 degrees of separation from the user that does the poll, ... but that can be left for later

Thanks @Semisol. Do the changes since your last review adequately address your concerns?

I think specifying value_minimum and value_maximum amounts for inclusion in tallies will allow for flexible poll designs that can successfully deter certain undesired participants. But definitely it would be nice to include options for more specific voter filters in the future.

@fernandolguevara
Copy link
Contributor

@toadlyBroodle

here is a draft for surveys/polls #111 that defines a survey/poll by using tags instead of a new kind

Why don't we decorate kind 1 with tags indicating that we want to start a survey/poll?

@toadlyBroodle
Copy link
Author

Why don't we decorate kind 1 with tags indicating that we want to start a survey/poll?

@fernandolguevara zap poll events are a significant departure from kind 1, particularly in how clients must handle them. Pretty sure they warrant their own 'kind' designation, if only to allow clients to query relays specifically for poll events.

@alltheseas
Copy link
Contributor

Thanks @toadlyBroodle, you answered my questions.

One more question for you: does the current structure of zap polls as you have written it preclude an anonymous zap from a poll taker?

@staab
Copy link
Member

staab commented Mar 6, 2023

My two cents is that I'd like to see a way to vote "other" with a custom value. It's already commonly done, and when it's not, polls almost always shoehorn you into a false dichotomy.

I like zaps for polls, and given the choice between zap-only and non-zap-only polls I'd prefer the former. But a solution that accepts both based on a required level of participation set by the poll author might be a good thing.

@vitorpamplona
Copy link
Collaborator

To think about:

  1. Poll should specify a relay to collect&tally votes. Client applications should send votes there. In that way, there will be no result inconsistency between users that are using different relay sets

  2. Shouldn't it require tallying clients only to count if zap votes were sent to the author? Otherwise fake Zaps can easily take over. How do we protect participants against the author faking their own zaps?

  3. "Received" time (MUST NOT tally late votes received after closed_at time) is irrelevant. Most clients will download these events after pools close. The receiving time should never be used in Nostr.

  4. Clients can create events in the past, adding votes after the closed_at date by creation time. Zappers can also send zaps in the past, especially if the zapper is controlled by the author or a party interested in certain results. Maybe this is a good use for NIP-03

@toadlyBroodle
Copy link
Author

My two cents is that I'd like to see a way to vote "other" with a custom value. It's already commonly done, and when it's not, polls almost always shoehorn you into a false dichotomy.

@staab Poll makers are free to include an 'other' poll_option, users may include comments in zap 'content' field, and clients can choose how to render these comments.

@toadlyBroodle
Copy link
Author

@vitorpamplona excellent feedback on some key omissions!

1. Poll should specify a relay to collect&tally votes. Client applications should send votes there. In that way, there will be no result inconsistency between users that are using different relay sets

Great point, added requirement for primary relay inclusion.

2. Shouldn't it require tallying clients only to count if zap votes were sent to the author? Otherwise fake Zaps can easily take over. How do we protect participants against the author faking their own zaps?

Absolutely! This got me thinking of how to solve both problems at once: allowing for distribution of funds across predetermined public-keys. This way pollers can design more authentic/legitimate polls by allowing voters a choice for where they send their funds. This also addresses @alltheseas's last question, and enables distribution of funds functionality that was of importance to @StackSats.IO.

3. "Received" time (`MUST NOT tally late votes received after closed_at time`) is irrelevant. Most clients will download these events after pools close. The receiving time should never be used in Nostr. 
4. Clients can create events in the past, adding votes after the `closed_at` date by creation time. Zappers can also send zaps in the past, especially if the zapper is controlled by the author or a party interested in certain results. Maybe this is a good use for NIP-03

Great catch of a glaring omission on my part and excellent suggestion for a fix. Added requirement for ots when closed_at time is specified.

Copy link
Author

@toadlyBroodle toadlyBroodle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these changes resolve your review @Semisol?

@braydonf
Copy link
Contributor

braydonf commented Apr 4, 2023

Considering that a zap receipt is not a proof of payment, the poll results can be manipulated to achieve any preferred poll result.

From NIP-57:

"The zap receipt is not a proof of payment, all it proves is that some nostr user fetched an invoice. The existence of the zap receipt implies the invoice as paid, but it could be a lie given a rogue implementation."
https://github.com/nostr-protocol/nips/blob/master/57.md#appendix-e-zap-receipt-event

@v0l v0l mentioned this pull request Apr 5, 2023
@toadlyBroodle
Copy link
Author

toadlyBroodle commented Apr 6, 2023

Considering that a zap receipt is not a proof of payment, the poll results can be manipulated to achieve any preferred poll result.

Yes, this is a known issue that applies to all zaps, not just polls. A solution will hopefully emerge soon.

Copy link
Author

@toadlyBroodle toadlyBroodle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved poll_options tag from 9735->9734

@fiatjaf
Copy link
Member

fiatjaf commented Apr 6, 2023

Is this implemented somewhere? I saw some poll things on Amethyst. Is it ready to merge?

Can we rename it to "Zap Polls" or something like that? Just to differentiate it from non-paid polls that could be done in some other NIP later?

@toadlyBroodle
Copy link
Author

Is this implemented somewhere? I saw some poll things on Amethyst. Is it ready to merge?

Yes, it's already released in Amethyst v0.32+

Can we rename it to "Zap Polls" or something like that? Just to differentiate it from non-paid polls that could be done in some other NIP later?

Yeah absolutely.

@fiatjaf
Copy link
Member

fiatjaf commented Apr 6, 2023

Can you fix the conflicts?

@v0l
Copy link
Member

v0l commented Apr 6, 2023

I don't think we implement this spec as described though, there is some reference to e/p tags and that was just ignored, idk if you want to update the NIP to reflect this or we should discuss with @vitorpamplona why he implemented it like this

@toadlyBroodle
Copy link
Author

I don't think we implement this spec as described though, there is some reference to e/p tags and that was just ignored, idk if you want to update the NIP to reflect this or we should discuss with @vitorpamplona why he implemented it like this

Most of the spec is implemented as described (except additional recipients and ots), however @vitorpamplona wanted to disable all optional features for first release. Once it's proven stable, I'm sure we'll start rolling out the extra features: min/max values, consensus, closing time, etc.

e/p tags are same as kind 1, additional p tags will probably be implemented as additional recipients, but I'm waiting on possible wallet splits to add this feature. e tag in kind 9734 reference the original poll note, while p is the zap recipient.

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented Apr 6, 2023

IMHO min/max values, consensus, and closing time are too complicated for an average user that just want to do a weak poll. We will probably have a default setting for them and some semi-hidden way to customize: a fixed zap amount for the communists out there (lol), closing time of 24 hours (similar to Twitter to simplify), and a default consensus number based on the number of options.

@braydonf
Copy link
Contributor

braydonf commented Apr 6, 2023

I don't think Zaps are solving the Sybil-attack issue, even if it was a proof-of-payment; though it certainly doesn't help.

I think a solution to that is to only consider poll results from those that you follow, everything else is ignored. This could be done with another Poll specification or with this one. If kept with zaps, I agree with @fiatjaf to rename to "Zap Polls".

@fiatjaf
Copy link
Member

fiatjaf commented Apr 6, 2023

I agree with @braydonf that zaps don't provide sibyl-resistance, my preference is to only trust poll votes from relays that offer sibyl-resistance, but I didn't want to disrupt this NIP.

@toadlyBroodle
Copy link
Author

toadlyBroodle commented Apr 29, 2023

I suspect that even perfect proof of payment would not be Sibyl resistant. An attacker could spin up any number of voter npubs and have them “pay” invoices that the attacker receives.

Recent addition of zap forwarding should help mitigate poll authors' ability to self-zap.

I suspect the only way to truly prevent fake voting is to make the payment irrecoverable via proof-of-work, as described for example in NIP13.

Yes this may eventually be needed.

@toadlyBroodle
Copy link
Author

toadlyBroodle commented Apr 29, 2023

@Semisol @v0l @cameri @jimbojw just merged Zap Polls with recent changes and removed last TODOs.
As both Snort and Amethyst have now implemented required aspects of NIP69, can we get this merged into protocol?

@fiatjaf
Copy link
Member

fiatjaf commented Apr 29, 2023

Yes, but why is this PR editing 22 files?

@Semisol
Copy link
Contributor

Semisol commented Apr 29, 2023

Yes, but why is this PR editing 22 files?

CRLF probably. Fucking Windows.

@toadlyBroodle
Copy link
Author

ah good ol' CRLF, sorry, didn't catch that.

Copy link
Author

@toadlyBroodle toadlyBroodle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted unnecessarily changed files with CRLFs, added poll_option references to 57.md examples

@fiatjaf fiatjaf changed the title Polls RFC #69 Polls RFC 69 May 5, 2023
@vitorpamplona
Copy link
Collaborator

Can we merge this? Amethyst and Snort implement this NIP and has been working well.

@fiatjaf
Copy link
Member

fiatjaf commented Jul 6, 2023

I haven't merged it yet because it is breaking the README and I haven't had time for or remembered fixing it myself.

@staab
Copy link
Member

staab commented Jul 6, 2023

I realize this ship has already sailed, but NACK on making zaps a hard dependency of other nostr features. Payment proof should be open ended and optional.

@alexgleason
Copy link
Member

Agreed @staab. We will need a different type of poll to bridge polls from ActivityPub.

@vitorpamplona
Copy link
Collaborator

@staab @alexgleason I don't see this as the only poll implementation in Nostr and I generally agree that the dependency on zaps is not good. However, I do think for those using zaps, this is already good enough.

@fernandolguevara
Copy link
Contributor

@staab @alexgleason I don't see this as the only poll implementation in Nostr and I generally agree that the dependency on zaps is not good. However, I do think for those using zaps, this is already good enough.

I think we can make this better, Dependency on zaps sucks...
We need a better way to make this use case over the network ...
#111

@toadlyBroodle
Copy link
Author

I haven't merged it yet because it is breaking the README and I haven't had time for or remembered fixing it myself.

Fixed

@vitorpamplona
Copy link
Collaborator

I am coming here again asking to merge this. Let's move on.

@staab
Copy link
Member

staab commented Aug 8, 2023

Consensus seems to be that dependency on zaps is bad. I vote against this PR.

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented Aug 8, 2023

Consensus seems to be that dependency on zaps is bad. I vote against this PR.

Can't we merge and if somebody has a good non-zap implementation they can just update this NIP? By not merging, we are essentially blocking all potential changes from the community.

@staab
Copy link
Member

staab commented Aug 8, 2023

There have been 3-4 other poll implementations. We could vote on those or someone could make a new NIP. I'd rather not merge for no reason and make a bad idea a standard. Do we have a tally of how many implementations each one has? We've had polls in various places for over a year, I remember some in branle.

@vitorpamplona
Copy link
Collaborator

make a bad idea a standard

That's a bit too much. Not having a non-zap version doesn't make this a bad idea. The procedure is sound as a polling option. If people want to offer polls with zaps, this is it. We can tweak things around to make it better, but it works well.

Then somebody else will need to create a different procedure for polling without zaps that hopefully have similar protections against spam.

@toadlyBroodle
Copy link
Author

toadlyBroodle commented Aug 11, 2023

There have been 3-4 other poll implementations.

I've yet to see a single other NIP that comes anywhere close to as comprehensive as this one. Afterall, NIP69 was paid out @NVK and @StackSatsIO bounty.

Copy link
Contributor

@Semisol Semisol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll review this more later.

57.md Outdated
@@ -37,6 +37,7 @@ In addition, the event MAY include the following tags:

- `e` is an optional hex-encoded event id. Clients MUST include this if zapping an event rather than a person.
- `a` is an optional NIP-33 event coordinate that allows tipping parameterized replaceable events such as NIP-23 long-form notes.
- `poll_option` is a tag used for voting by [zap poll events](69.md).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No reason to modify NIP-57 for this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is under optional MAY conditional list, for documentation purposes. It is a required field for zap-poll event zap requests: which is why it's included here. Still want it removed?

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.