@@ -18,8 +18,8 @@ contract DisputeKitShutter is DisputeKitClassicBase {
1818 // * Storage * //
1919 // ************************************* //
2020
21- mapping (uint256 localDisputeID = > mapping (uint256 localRoundID = > mapping (uint256 voteID = > bytes32 recoveryCommitment )))
22- public recoveryCommitments ;
21+ mapping (uint256 localDisputeID = > mapping (uint256 localRoundID = > mapping (uint256 voteID = > bytes32 justificationCommitment )))
22+ public justificationCommitments ;
2323
2424 // ************************************* //
2525 // * Transient Storage * //
@@ -34,15 +34,15 @@ contract DisputeKitShutter is DisputeKitClassicBase {
3434 /// @notice Emitted when a vote is cast.
3535 /// @param _coreDisputeID The identifier of the dispute in the Arbitrator contract.
3636 /// @param _juror The address of the juror casting the vote commitment.
37- /// @param _commit The commitment hash.
38- /// @param _recoveryCommit The commitment hash without the justification.
37+ /// @param _choiceCommit The commitment hash without the justification .
38+ /// @param _justificationCommit The commitment hash for the justification.
3939 /// @param _identity The Shutter identity used for encryption.
4040 /// @param _encryptedVote The Shutter encrypted vote.
4141 event CommitCastShutter (
4242 uint256 indexed _coreDisputeID ,
4343 address indexed _juror ,
44- bytes32 indexed _commit ,
45- bytes32 _recoveryCommit ,
44+ bytes32 indexed _choiceCommit ,
45+ bytes32 _justificationCommit ,
4646 bytes32 _identity ,
4747 bytes _encryptedVote
4848 );
@@ -91,30 +91,37 @@ contract DisputeKitShutter is DisputeKitClassicBase {
9191 ///
9292 /// @param _coreDisputeID The ID of the dispute in Kleros Core.
9393 /// @param _voteIDs The IDs of the votes.
94- /// @param _commit The commitment hash including the justification.
95- /// @param _recoveryCommit The commitment hash without the justification.
94+ /// @param _choiceCommit The commitment hash without the justification.
95+ /// @param _justificationCommit The commitment hash for justification.
9696 /// @param _identity The Shutter identity used for encryption.
9797 /// @param _encryptedVote The Shutter encrypted vote.
9898 function castCommitShutter (
9999 uint256 _coreDisputeID ,
100100 uint256 [] calldata _voteIDs ,
101- bytes32 _commit ,
102- bytes32 _recoveryCommit ,
101+ bytes32 _choiceCommit ,
102+ bytes32 _justificationCommit ,
103103 bytes32 _identity ,
104104 bytes calldata _encryptedVote
105105 ) external {
106- if (_recoveryCommit == bytes32 (0 )) revert EmptyRecoveryCommit ();
106+ if (_justificationCommit == bytes32 (0 )) revert EmptyJustificationCommit ();
107107
108108 uint256 localDisputeID = coreDisputeIDToLocal[_coreDisputeID];
109109 Dispute storage dispute = disputes[localDisputeID];
110110 uint256 localRoundID = dispute.rounds.length - 1 ;
111111 for (uint256 i = 0 ; i < _voteIDs.length ; i++ ) {
112- recoveryCommitments [localDisputeID][localRoundID][_voteIDs[i]] = _recoveryCommit ;
112+ justificationCommitments [localDisputeID][localRoundID][_voteIDs[i]] = _justificationCommit ;
113113 }
114114
115115 // `_castCommit()` ensures that the caller owns the vote and that dispute is active
116- _castCommit (_coreDisputeID, _voteIDs, _commit);
117- emit CommitCastShutter (_coreDisputeID, msg .sender , _commit, _recoveryCommit, _identity, _encryptedVote);
116+ _castCommit (_coreDisputeID, _voteIDs, _choiceCommit);
117+ emit CommitCastShutter (
118+ _coreDisputeID,
119+ msg .sender ,
120+ _choiceCommit,
121+ _justificationCommit,
122+ _identity,
123+ _encryptedVote
124+ );
118125 }
119126
120127 /// @notice Version of `castVote` function designed specifically for Shutter.
@@ -146,50 +153,43 @@ contract DisputeKitShutter is DisputeKitClassicBase {
146153 // * Public Views * //
147154 // ************************************* //
148155
149- /// @notice Computes the hash of a vote using ABI encoding
150- /// @param _choice The choice being voted for
156+ /// @notice Computes the hash of a justification using ABI encoding
151157 /// @param _salt A random salt for commitment
152158 /// @param _justification The justification for the vote
153- /// @return bytes32 The hash of the encoded vote parameters
154- function hashVote (
155- uint256 _choice ,
156- uint256 _salt ,
157- string memory _justification
158- ) public view override returns (bytes32 ) {
159- if (callerIsJuror) {
160- // Caller is the juror, hash without `_justification` to facilitate recovery.
161- return keccak256 (abi.encodePacked (_choice, _salt));
162- } else {
163- // Caller is not the juror, hash with `_justification`.
164- bytes32 justificationHash = keccak256 (bytes (_justification));
165- return keccak256 (abi.encode (_choice, _salt, justificationHash));
166- }
159+ /// @return bytes32 The hash of the encoded justification
160+ function hashJustification (uint256 _salt , string memory _justification ) public pure returns (bytes32 ) {
161+ return keccak256 (abi.encode (_salt, keccak256 (bytes (_justification))));
167162 }
168163
169164 // ************************************* //
170165 // * Internal * //
171166 // ************************************* //
172167
173- /// @notice Returns the expected vote hash for a given vote.
174- /// @param _localDisputeID The ID of the dispute in the Dispute Kit.
175- /// @param _localRoundID The ID of the round in the Dispute Kit.
176- /// @param _voteID The ID of the vote.
177- /// @return The expected vote hash.
178- function _getExpectedVoteHash (
168+ /// @inheritdoc DisputeKitClassicBase
169+ function _verifyHiddenVoteCommitments (
179170 uint256 _localDisputeID ,
180171 uint256 _localRoundID ,
181- uint256 _voteID
182- ) internal view override returns (bytes32 ) {
183- if (callerIsJuror) {
184- return recoveryCommitments[_localDisputeID][_localRoundID][_voteID];
185- } else {
186- return disputes[_localDisputeID].rounds[_localRoundID].votes[_voteID].commit;
172+ uint256 [] calldata _voteIDs ,
173+ uint256 _choice ,
174+ string memory _justification ,
175+ uint256 _salt
176+ ) internal view override {
177+ super ._verifyHiddenVoteCommitments (_localDisputeID, _localRoundID, _voteIDs, _choice, _justification, _salt);
178+
179+ // The juror is allowed to reveal without verifying the justification commitment for recovery purposes.
180+ if (callerIsJuror) return ;
181+
182+ bytes32 actualJustificationHash = hashJustification (_salt, _justification);
183+ for (uint256 i = 0 ; i < _voteIDs.length ; i++ ) {
184+ if (justificationCommitments[_localDisputeID][_localRoundID][_voteIDs[i]] != actualJustificationHash)
185+ revert JustificationCommitmentMismatch ();
187186 }
188187 }
189188
190189 // ************************************* //
191190 // * Errors * //
192191 // ************************************* //
193192
194- error EmptyRecoveryCommit ();
193+ error EmptyJustificationCommit ();
194+ error JustificationCommitmentMismatch ();
195195}
0 commit comments