All BSIPs
.md

BSIP-6

Votes

The format and signing of upvotes and downvotes on Bitsocial comments, and how communities count them.

draftCore
On this page

Abstract

A vote is an author-signed upvote, downvote, or vote cancellation on a comment. Votes are published to a community like any other publication (BSIP-4); the community counts them and reflects the totals in the comment’s update (BSIP-5). This BSIP defines the vote format, the rules a community applies when accepting a vote, and how votes are counted.

Motivation

Voting is the simplest publication type, but clients still need to agree on its exact shape — which comment it targets, the allowed values, and which fields are signed — and communities need to count votes the same way, so that vote counts mean the same thing across implementations.

Specification

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.

Fields

A vote is a JSON object with the common publication fields and two vote-specific fields:

  • commentCid — REQUIRED. The CID of the comment being voted on.
  • vote — REQUIRED. One of 1 (upvote), -1 (downvote), or 0 (cancel the author’s previous vote).

Votes are published inside a CHALLENGEREQUEST under the vote key (BSIP-4). Unlike comments, accepted votes are not published individually; only their totals are.

Example vote:

{
  "commentCid": "QmQwin4X1VAmELE5KsDHBfz3ZhaLiN8NcH663nvBJNMqUm",
  "vote": -1,
  "communityPublicKey": "12D3KooWBexQF4qDvyaxDgK4r2qPNk5z8s9b1eU5z2bnR6dExamPLe",
  "communityName": "jokes.bso",
  "author": { "name": "john.bso" },
  "timestamp": 1728174027,
  "protocolVersion": "1.0.0",
  "signature": {
    "type": "ed25519",
    "signature": "<base64>",
    "publicKey": "<base64, 32 bytes>",
    "signedPropertyNames": ["author", "communityPublicKey", "communityName", "protocolVersion", "timestamp", "commentCid", "vote"]
  }
}

Signing

A vote is signed by its author following BSIP-2, Signatures. Every field of the vote except signature MUST be listed in signedPropertyNames. The convenience field communityAddress is never signed and never appears on the wire.

Acceptance

In addition to the rules for every publication (BSIP-4), which reject votes on comments that do not exist, were removed or deleted, are pending approval or disapproved, or sit in an archived or locked thread, a community MUST reject a vote that:

  • has vote 0 when the same author has no effective vote on that comment;
  • is disallowed by the community’s features (BSIP-3): noUpvotes, noDownvotes, or, for a post (depth 0) or a reply, noPostUpvotes, noPostDownvotes, noReplyUpvotes, or noReplyDownvotes.

Votes in a locked thread are rejected for everyone, moderators included.

Counting

An author is identified for counting by the IPNS name of the vote’s signature.publicKey. A community MUST count at most one effective vote per author per comment: each accepted vote replaces that author’s previous vote on the comment, and a vote of 0 leaves the author with no effective vote. The comment update’s upvoteCount and downvoteCount (BSIP-5) are the numbers of effective 1 and -1 votes. An author’s postScore and replyScore in the community (BSIP-5) are the sums of upvotes minus downvotes on their posts and replies.

Rationale

  • A single vote field with values 1/0/-1 keeps voting minimal and makes cancellation explicit rather than requiring a separate message type.
  • Author-signed votes, community-counted totals keep the trust model consistent: each vote is attributable to an author key, while the community is the authority on the aggregate it publishes.
  • Not publishing individual votes keeps comment updates small and avoids exposing who voted for what.

Security Considerations

  • One effective vote per author. Counting MUST be idempotent per author per comment, or an author could inflate a tally by republishing.
  • Sybil resistance is the community’s job. A vote only proves that some keypair voted, and keypairs are free. Resistance to vote manipulation comes from the community’s anti-spam challenges and exclusion policy (BSIP-3), not from the vote format.
  • Target binding. commentCid is signed, so a vote cannot be moved to a different comment.
  • Replays. Within the five-minute timestamp window, resending an author’s earlier signed vote would replace their current one. A community SHOULD reject a vote whose signature it has already accepted (BSIP-4).
  • Unverifiable totals. Because individual votes are not published, readers cannot audit a community’s counts; they are as trustworthy as the community that signs them.

Copyright and related rights waived via CC0.