Repository navigation
Implement commit-reveal voting for cast_vote to prevent juror vote-copying #59
Description
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)thenreveal_vote(escrow_id, juror, vote_for_depositor, salt), each with its own deadline - Replace the current plaintext
JurorVotestorage write incast_votewith 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_disputeonly 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
Opulencechuks commentedon Aug 16, 2026
I am confident that I can implement this issue having worked on something similar in the past
rhemy-arc commentedon Aug 16, 2026
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:
commit_vote(escrow_id, juror, commitment_hash)to store a cryptographic commitment rather than the actual vote.reveal_vote(escrow_id, juror, vote_for_depositor, salt)to verify the revealed vote and salt against the original commitment.resolve_disputeso that only successfully verified reveals contribute to the final tally.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:
I would also review the existing
cast_voteandresolve_disputeimplementation 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.
grantfox-oss commentedon Aug 16, 2026
🦊 GrantFox — @rhemy-arc has been assigned to this issue as part of the Third Campaign campaign!
Next steps:
Closes #59)Good luck! Track your progress on GrantFox.
grantfox-oss commentedon Aug 20, 2026
🎉 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.