Skip to content

Implement commit-reveal voting for cast_vote to prevent juror vote-copying #59

Description

@meshackyaro

Description

cast_vote (contracts/trustflow/src/lib.rs, ~line 364) writes each juror's vote directly and in plaintext: env.storage().persistent().set(&DataKey::JurorVote(vote_key), &vote_for_depositor). Contract storage is publicly readable, so any juror (or bot) can observe the running tally in real time before casting their own vote. Since resolve_dispute slashes every juror whose vote disagrees with the majority, a rational juror's dominant strategy is to simply copy whatever the current majority is rather than vote their honest independent assessment of the dispute — which undermines the entire economic incentive the slashing mechanism is supposed to create.

This needs a commit-reveal scheme: jurors submit a hash of their vote (+ a secret salt) during a commit phase, then reveal the actual vote (+ salt) during a separate reveal phase after commits close, so nobody can see how anyone voted until it's too late to copy them.

Component

Contract

Difficulty

🔴 Hard

Tasks

  • Design the two-phase flow: commit_vote(escrow_id, juror, commitment_hash) then reveal_vote(escrow_id, juror, vote_for_depositor, salt), each with its own deadline
  • Replace the current plaintext JurorVote storage write in cast_vote with a commitment hash during the commit phase
  • Add reveal-phase verification: recompute the hash from the revealed vote + salt and reject mismatches
  • Decide the penalty for a juror who commits but never reveals (should probably be treated as slashable, similar to a wrong vote, to prevent jurors from committing then reveal-sniping based on other reveals)
  • Update resolve_dispute's tally logic to only count successfully revealed votes
  • Add contract tests: honest reveal, mismatched reveal (hash doesn't match commitment), commit-without-reveal, and a scenario proving a late "voter" can no longer copy the majority since votes are hidden until reveal

Acceptance Criteria

  • Votes are not readable by other jurors (or anyone else) during the commit phase — verified by a test asserting JurorVote/commitment storage doesn't leak the boolean vote before reveal
  • A juror who commits but fails to reveal before the reveal deadline is penalized (slashed or explicitly excluded per the design decision above) rather than silently ignored
  • resolve_dispute only tallies verified reveals, and rejects/handles reveals that don't match their commitment
  • Full existing dispute/slashing test suite still passes with the new two-phase flow

Estimated Time

3-5 days

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions