Skip to content

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

Closed

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

Activity

  1. Opulencechuks commented on Aug 16, 2026

    @Opulencechuks

    I am confident that I can implement this issue having worked on something similar in the past

  2. rhemy-arc commented on Aug 16, 2026

    @rhemy-arc
    Contributor

    Application to Work on Commit-Reveal Voting for Dispute Resolution

    I am interested in contributing to this issue because it addresses an important security and incentive problem in the dispute-resolution mechanism. Storing juror votes in plaintext allows subsequent jurors to observe the current vote distribution and simply follow the majority, which undermines the purpose of independent juror assessment and the existing slashing mechanism.

    I understand that the appropriate solution is a two-phase commit-reveal voting system where a juror first commits to a vote without revealing its value, and only reveals the vote after the commitment period has ended.

    My proposed approach would be to:

    • Design separate commit and reveal phases with clearly defined deadlines.
    • Implement commit_vote(escrow_id, juror, commitment_hash) to store a cryptographic commitment rather than the actual vote.
    • Implement reveal_vote(escrow_id, juror, vote_for_depositor, salt) to verify the revealed vote and salt against the original commitment.
    • Ensure that a reveal with an incorrect vote or salt is rejected.
    • Ensure that the underlying vote cannot be derived from the commitment during the commit phase.
    • Define and implement the appropriate behavior for jurors who commit but fail to reveal before the reveal deadline.
    • Update resolve_dispute so that only successfully verified reveals contribute to the final tally.
    • Preserve the existing slashing behavior while adapting it to the new voting lifecycle.

    I would pay particular attention to the commitment format and domain separation so that a commitment cannot be reused or interpreted incorrectly across different disputes. The escrow/dispute identifier and juror identity should also be considered when designing the commitment scheme to prevent replay or cross-dispute attacks.

    For testing, I would create contract-level tests covering:

    • A juror successfully committing and revealing an honest vote.
    • A reveal with an incorrect salt or vote being rejected.
    • A juror committing but failing to reveal before the deadline.
    • Verification that the committed storage does not expose the underlying boolean vote.
    • Multiple jurors committing before the reveal phase and subsequently revealing their votes.
    • A late juror being unable to observe and copy the majority during the commit phase.
    • Resolution using only valid, successfully revealed votes.
    • Existing dispute and slashing behavior continuing to work correctly after the change.

    I would also review the existing cast_vote and resolve_dispute implementation carefully before making the migration, ensuring that the new state transitions do not introduce edge cases around deadlines, repeated commits, repeated reveals, or dispute resolution.

    My goal would be to implement the commit-reveal mechanism in a way that preserves the contract's existing economic incentives while ensuring that jurors must make independent decisions rather than simply copying an observable majority.

    I would be glad to contribute to the contract design, implementation, security-focused testing, and integration with the existing dispute/slashing logic.

  3. grantfox-oss commented on Aug 16, 2026

    @grantfox-oss

    🦊 GrantFox — @rhemy-arc has been assigned to this issue as part of the Third Campaign campaign!

    Next steps:

    1. Open a Pull Request referencing this issue (e.g., Closes #59)
    2. Your PR will be reviewed by the trustflow-protocol maintainers

    Good luck! Track your progress on GrantFox.

  4. grantfox-oss commented on Aug 20, 2026

    @grantfox-oss

    🎉 This issue has been marked as completed on GrantFox as part of the Third Campaign campaign!

    @rhemy-arc's PR #60 was approved and merged by @meshackyaro.

    🏆 @rhemy-arc: You earned 35 FoxPoints for this contribution! Your current tier: Explorer (414 total points). Track your full progress on GrantFox.

    👏 Great work, @rhemy-arc! Keep contributing to trustflow-protocol.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions