Skip to content

Conversation

unknownunknown1
Copy link
Contributor

@unknownunknown1 unknownunknown1 commented Oct 14, 2025

PR-Codex overview

This PR focuses on updating the castCommitShutter function in the DisputeKitGatedShutter and DisputeKitShutter contracts to improve handling of justification and commitment hashes. It streamlines the parameters and updates the hash computation logic.

Detailed summary

  • Updated castCommitShutter parameters to include justificationHash and identity.
  • Removed _commit and changed _recoveryCommit to be used with the new justification approach.
  • Revised commitment construction to combine recoveryCommit and justificationHash.
  • Adjusted events emitted to reflect the new commitment structure.
  • Updated test cases to align with the new function signature and logic.

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

Summary by CodeRabbit

  • New Features

    • Commit flow now accepts an explicit justification and automatically derives the commit from recovery data + justification.
    • Vote hashing for non-jurors updated to hash the choice/salt pair combined with the justification hash.
  • Tests

    • Test suites updated to use the new recovery+justification commit flow and to validate the revised hashing and commit behavior.

Copy link

netlify bot commented Oct 14, 2025

Deploy Preview for kleros-v2-neo ready!

Name Link
🔨 Latest commit 5666931
🔍 Latest deploy log https://app.netlify.com/projects/kleros-v2-neo/deploys/68ee5ad081bd6500089ddc8a
😎 Deploy Preview https://deploy-preview-2175--kleros-v2-neo.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link

netlify bot commented Oct 14, 2025

Deploy Preview for kleros-v2-testnet-devtools failed. Why did it fail? →

Name Link
🔨 Latest commit 5666931
🔍 Latest deploy log https://app.netlify.com/projects/kleros-v2-testnet-devtools/deploys/68ee5ad0af0f88000868b093

Copy link

netlify bot commented Oct 14, 2025

Deploy Preview for kleros-v2-testnet ready!

Name Link
🔨 Latest commit 5666931
🔍 Latest deploy log https://app.netlify.com/projects/kleros-v2-testnet/deploys/68ee5ad07e3cc400084ac63f
😎 Deploy Preview https://deploy-preview-2175--kleros-v2-testnet.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Contributor

coderabbitai bot commented Oct 14, 2025

Walkthrough

Derive commit on-chain from recoveryCommit + justification (hash); castCommitShutter signatures changed to accept justification instead of an external commit; non-juror hashVote now hashes (choice,salt) first then combines with justification hash. Tests updated to match new commit/hash logic.

Changes

Cohort / File(s) Summary
Contracts: Shutter commit derivation & hashing
contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol, contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol
castCommitShutter signature changed: removed external _commit, added justification (string or bytes32 depending on file). Compute justificationHash = keccak256(bytes(_justification)) (or use provided _justificationHash), then commit = keccak256(abi.encode(_recoveryCommit, justificationHash)). Use computed commit in _castCommit and CommitCastShutter. Update non-juror hashVote to keccak256(abi.encode(keccak256(abi.encodePacked(_choice, _salt)), justificationHash)). Comments updated.
Tests: align commits & hashes
contracts/test/arbitration/dispute-kit-shutter.ts
Replace prior fullCommit usage with recoveryCommit + justification parameters in castCommitShutter calls. Update expected commit/hash computations and assertions to reflect abi.encode(recoveryCommit, justificationHash) and new non-juror hashVote behavior across normal and recovery flows.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Caller
  participant DK as DisputeKit(Shutter|Gated)
  participant Core as Core/_castCommit
  Note over Caller,DK: castCommitShutter(coreDisputeID, voteIDs, recoveryCommit, justification, identity, encryptedVote)

  Caller->>DK: castCommitShutter(...)
  DK->>DK: justificationHash = keccak256(bytes(justification))
  DK->>DK: commit = keccak256(abi.encode(recoveryCommit, justificationHash))
  DK->>Core: _castCommit(coreDisputeID, voteIDs, commit, identity, encryptedVote)
  Core-->>DK: result
  DK-->>Caller: emit CommitCastShutter(commit, recoveryCommit, ...)

  alt non-juror reveal/hash path
    Note over DK: voteHash = keccak256(abi.encode( keccak256(abi.encodePacked(choice, salt)), justificationHash ))
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

Suggested labels

Type: Bug :bug:, Compatibility: ABI change 🗯, Package: Contracts

Suggested reviewers

  • jaybuidl
  • alcercu

Poem

I nibble on bytes and hum a small tune,
I stitch recovery with reasons at noon.
A hash here, a commit born anew,
No sneaky commits can slip past the view.
Thump-thump — consensus hops into view. 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly indicates a fix to the ShutterDK module by tying the commit logic to the recovery commit, directly reflecting the change to compute the commit from the recovery commit and justification hash.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/commit-fix

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8af1ba0 and 5666931.

📒 Files selected for processing (1)
  • contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-30T17:18:12.895Z
Learnt from: jaybuidl
PR: kleros/kleros-v2#2145
File: contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol:277-286
Timestamp: 2025-09-30T17:18:12.895Z
Learning: In DisputeKitClassicBase.sol's castCommit function, jurors are allowed to re-submit commits during the commit period. The implementation uses a commitCount variable to track only first-time commits (where commit == bytes32(0)) so that totalCommitted is not incremented when a juror updates their existing commit.

Applied to files:

  • contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (15)
  • GitHub Check: Redirect rules - kleros-v2-testnet
  • GitHub Check: Redirect rules - kleros-v2-testnet
  • GitHub Check: Redirect rules - kleros-v2-testnet-devtools
  • GitHub Check: Header rules - kleros-v2-testnet
  • GitHub Check: Header rules - kleros-v2-testnet
  • GitHub Check: Redirect rules - kleros-v2-neo
  • GitHub Check: Header rules - kleros-v2-testnet-devtools
  • GitHub Check: Pages changed - kleros-v2-testnet
  • GitHub Check: Pages changed - kleros-v2-testnet
  • GitHub Check: Header rules - kleros-v2-neo
  • GitHub Check: Pages changed - kleros-v2-testnet-devtools
  • GitHub Check: Pages changed - kleros-v2-neo
  • GitHub Check: SonarCloud
  • GitHub Check: Analyze (javascript)
  • GitHub Check: hardhat-tests
🔇 Additional comments (3)
contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol (3)

111-120: LGTM! Function signature updated correctly.

The signature change from accepting an external _commit parameter to accepting _justificationHash aligns with the PR objective of deriving the commit on-chain. The parameter type and documentation are correct.


130-134: LGTM! Commit derivation logic is correct.

The on-chain commit computation keccak256(abi.encode(_recoveryCommit, _justificationHash)) correctly combines the recovery commit with the justification hash. This aligns with the hashVote logic for non-jurors (line 182) and ensures consistency across the contract.

The event emission includes both commit and _recoveryCommit for transparency and verification.


176-183: LGTM! hashVote logic correctly handles both paths.

The hashVote function correctly implements two distinct paths:

  • Jurors (line 178): Returns keccak256(abi.encodePacked(_choice, _salt)) which matches the recoveryCommit
  • Non-jurors (line 182): Returns keccak256(abi.encode(keccak256(abi.encodePacked(_choice, _salt)), justificationHash)) which matches the full commit derived at line 131

This two-stage hashing maintains consistency with _getExpectedVoteHash (lines 196-200) and the commit computation logic.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol (1)

114-136: LGTM! On-chain commit derivation improves security.

The change to derive the commit on-chain from _recoveryCommit and _justification ensures that the commitment structure is always correctly formed. This prevents potential issues where an incorrectly constructed commit could be submitted.

Consider using string calldata _justification instead of string memory for better gas efficiency:

     function castCommitShutter(
         uint256 _coreDisputeID,
         uint256[] calldata _voteIDs,
         bytes32 _recoveryCommit,
-        string memory _justification,
+        string calldata _justification,
         bytes32 _identity,
         bytes calldata _encryptedVote
     ) external notJumped(_coreDisputeID) {

While the conversion to bytes(_justification) for hashing will copy to memory anyway, using calldata signals intent and may provide minor gas savings in some scenarios.

contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol (1)

98-120: LGTM! On-chain commit derivation improves security.

The change to derive the commit on-chain from _recoveryCommit and _justification ensures that the commitment structure is always correctly formed. This prevents potential issues where an incorrectly constructed commit could be submitted.

Consider using string calldata _justification instead of string memory for better gas efficiency:

     function castCommitShutter(
         uint256 _coreDisputeID,
         uint256[] calldata _voteIDs,
         bytes32 _recoveryCommit,
-        string memory _justification,
+        string calldata _justification,
         bytes32 _identity,
         bytes calldata _encryptedVote
     ) external notJumped(_coreDisputeID) {

While the conversion to bytes(_justification) for hashing will copy to memory anyway, using calldata signals intent and may provide minor gas savings in some scenarios.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between decd3e7 and 8af1ba0.

📒 Files selected for processing (3)
  • contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol (3 hunks)
  • contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol (3 hunks)
  • contracts/test/arbitration/dispute-kit-shutter.ts (22 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: jaybuidl
PR: kleros/kleros-v2#2145
File: contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol:277-286
Timestamp: 2025-09-30T17:18:12.895Z
Learning: In DisputeKitClassicBase.sol's castCommit function, jurors are allowed to re-submit commits during the commit period. The implementation uses a commitCount variable to track only first-time commits (where commit == bytes32(0)) so that totalCommitted is not incremented when a juror updates their existing commit.
📚 Learning: 2025-09-30T17:18:12.895Z
Learnt from: jaybuidl
PR: kleros/kleros-v2#2145
File: contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol:277-286
Timestamp: 2025-09-30T17:18:12.895Z
Learning: In DisputeKitClassicBase.sol's castCommit function, jurors are allowed to re-submit commits during the commit period. The implementation uses a commitCount variable to track only first-time commits (where commit == bytes32(0)) so that totalCommitted is not incremented when a juror updates their existing commit.

Applied to files:

  • contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol
  • contracts/test/arbitration/dispute-kit-shutter.ts
  • contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: Redirect rules - kleros-v2-testnet
  • GitHub Check: Redirect rules - kleros-v2-testnet
  • GitHub Check: Header rules - kleros-v2-testnet
  • GitHub Check: Header rules - kleros-v2-testnet
  • GitHub Check: Redirect rules - kleros-v2-testnet-devtools
  • GitHub Check: Pages changed - kleros-v2-testnet
  • GitHub Check: Pages changed - kleros-v2-testnet
  • GitHub Check: Header rules - kleros-v2-testnet-devtools
  • GitHub Check: Redirect rules - kleros-v2-neo
  • GitHub Check: Pages changed - kleros-v2-testnet-devtools
  • GitHub Check: Header rules - kleros-v2-neo
  • GitHub Check: Pages changed - kleros-v2-neo
  • GitHub Check: Analyze (javascript)
  • GitHub Check: hardhat-tests
🔇 Additional comments (4)
contracts/src/arbitration/dispute-kits/DisputeKitGatedShutter.sol (1)

172-185: LGTM! Hash logic aligns with on-chain commit construction.

The updated hash logic for non-jurors now correctly mirrors the commit structure by first hashing (choice, salt) to produce the recovery commit, then encoding it with the justification hash. This ensures consistency between commit construction in castCommitShutter and vote validation in castVoteShutter.

contracts/test/arbitration/dispute-kit-shutter.ts (2)

95-108: LGTM! Test helper correctly reflects on-chain commit structure.

The generateCommitments helper now properly constructs the full commit by encoding the recovery commit and justification hash as two separate bytes32 values. This aligns with the contract's on-chain commit derivation logic.


623-637: LGTM! Hash computation test validates the new structure.

The test correctly verifies that hashVote for non-jurors produces a hash matching the commit structure: keccak256(abi.encode(recoveryCommit, justificationHash)) where recoveryCommit = keccak256(abi.encode([choice, salt])).

contracts/src/arbitration/dispute-kits/DisputeKitShutter.sol (1)

156-169: LGTM! Hash logic aligns with on-chain commit construction.

The updated hash logic for non-jurors now correctly mirrors the commit structure by first hashing (choice, salt) to produce the recovery commit, then encoding it with the justification hash. This ensures consistency between commit construction in castCommitShutter and vote validation in castVoteShutter.

coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 14, 2025
Copy link

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hidden votes recovery: prevent the juror from exploiting the recovery hash to vote strategically

1 participant