Skip to content

Commit 5e987c4

Browse files
authored
Merge pull request #2100 from kleros/feat/shutter-recovery-hash
Support for recovery hash in Shutter DK
2 parents 068df77 + fb6ca6a commit 5e987c4

File tree

8 files changed

+1023
-98
lines changed

8 files changed

+1023
-98
lines changed

.github/workflows/contracts-testing.yml

Lines changed: 121 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -15,73 +15,129 @@ on:
1515
pull_request:
1616
branches:
1717
- "*"
18-
19-
permissions: # added using https://github.com/step-security/secure-workflows
18+
19+
permissions: # added using https://github.com/step-security/secure-workflows
2020
contents: read
2121

2222
jobs:
23-
contracts-testing:
23+
# *********************************************************************************** #
24+
# ******************************* Hardhat Tests ************************************* #
25+
# *********************************************************************************** #
26+
hardhat-tests:
2427
runs-on: ubuntu-latest
2528
steps:
26-
- name: Harden Runner
27-
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
28-
with:
29-
disable-sudo: false
30-
egress-policy: block
31-
allowed-endpoints: >
32-
binaries.soliditylang.org:443
33-
classic.yarnpkg.com:443
34-
github.com:443
35-
nightly.yarnpkg.com:443
36-
nodejs.org:443
37-
objects.githubusercontent.com:443
38-
registry.yarnpkg.com:443
39-
registry.npmjs.org:443
40-
54.185.253.63:443
41-
42-
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
43-
with:
44-
submodules: recursive
45-
46-
- name: Set up corepack (for yarn)
47-
run: |
48-
corepack enable
49-
corepack prepare yarn@4.9.2 --activate
50-
yarn set version 4.9.2
51-
52-
- name: Setup Node.js environment
53-
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
54-
with:
55-
node-version: 20.x
56-
cache: yarn
57-
58-
- name: Cache node modules
59-
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
60-
env:
61-
cache-name: cache-node-modules
62-
with:
63-
path: |
64-
~/.npm
65-
**/node_modules
66-
key: ${{ runner.os }}-build-${{ secrets.CACHE_VERSION }}-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}
67-
restore-keys: |
68-
${{ runner.os }}-build-${{ secrets.CACHE_VERSION }}-${{ env.cache-name }}-
69-
70-
- name: Install contracts dependencies
71-
run: yarn workspace @kleros/kleros-v2-contracts install
72-
73-
- name: Install Foundry
74-
uses: foundry-rs/foundry-toolchain@de808b1eea699e761c404bda44ba8f21aba30b2c # v1.3.1
75-
76-
- name: Install lcov
77-
run: sudo apt-get install -y lcov
78-
79-
- name: Run Hardhat and Foundry tests with coverage
80-
run: yarn coverage
81-
working-directory: contracts
82-
83-
- name: Upload a build artifact
84-
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
85-
with:
86-
name: code-coverage-report
87-
path: contracts/coverage
29+
- name: Harden Runner
30+
uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
31+
with:
32+
disable-sudo: false
33+
egress-policy: block
34+
allowed-endpoints: >
35+
binaries.soliditylang.org:443
36+
classic.yarnpkg.com:443
37+
github.com:443
38+
nightly.yarnpkg.com:443
39+
nodejs.org:443
40+
objects.githubusercontent.com:443
41+
registry.yarnpkg.com:443
42+
registry.npmjs.org:443
43+
54.185.253.63:443
44+
45+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
46+
with:
47+
submodules: recursive
48+
49+
- name: Set up corepack (for yarn)
50+
run: |
51+
corepack enable
52+
corepack prepare yarn@4.9.2 --activate
53+
yarn set version 4.9.2
54+
55+
- name: Setup Node.js environment
56+
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
57+
with:
58+
node-version: 20.x
59+
cache: yarn
60+
61+
- name: Cache node modules
62+
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
63+
env:
64+
cache-name: cache-node-modules
65+
with:
66+
path: |
67+
~/.npm
68+
**/node_modules
69+
key: ${{ runner.os }}-build-${{ secrets.CACHE_VERSION }}-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}
70+
restore-keys: |
71+
${{ runner.os }}-build-${{ secrets.CACHE_VERSION }}-${{ env.cache-name }}-
72+
73+
- name: Install contracts dependencies
74+
run: yarn workspace @kleros/kleros-v2-contracts install
75+
76+
- name: Run Hardhat tests
77+
run: yarn test
78+
working-directory: contracts
79+
80+
# *********************************************************************************** #
81+
# ******************************* Foundry Tests ************************************* #
82+
# *********************************************************************************** #
83+
# COMPILATION FAILS 🤬
84+
# foundry-tests:
85+
# runs-on: ubuntu-latest
86+
# steps:
87+
# - name: Harden Runner
88+
# uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0
89+
# with:
90+
# disable-sudo: false
91+
# egress-policy: block
92+
# allowed-endpoints: >
93+
# binaries.soliditylang.org:443
94+
# classic.yarnpkg.com:443
95+
# github.com:443
96+
# nightly.yarnpkg.com:443
97+
# nodejs.org:443
98+
# objects.githubusercontent.com:443
99+
# registry.yarnpkg.com:443
100+
# registry.npmjs.org:443
101+
# 54.185.253.63:443
102+
103+
# - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
104+
# with:
105+
# submodules: recursive
106+
107+
# - name: Set up corepack (for yarn)
108+
# run: |
109+
# corepack enable
110+
# corepack prepare yarn@4.9.2 --activate
111+
# yarn set version 4.9.2
112+
113+
# - name: Setup Node.js environment
114+
# uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
115+
# with:
116+
# node-version: 20.x
117+
# cache: yarn
118+
119+
# - name: Cache node modules
120+
# uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
121+
# env:
122+
# cache-name: cache-node-modules
123+
# with:
124+
# path: |
125+
# ~/.npm
126+
# **/node_modules
127+
# key: ${{ runner.os }}-build-${{ secrets.CACHE_VERSION }}-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}
128+
# restore-keys: |
129+
# ${{ runner.os }}-build-${{ secrets.CACHE_VERSION }}-${{ env.cache-name }}-
130+
131+
# # - name: Install contracts dependencies
132+
# # run: yarn workspace @kleros/kleros-v2-contracts install
133+
134+
# - name: Install Foundry
135+
# uses: foundry-rs/foundry-toolchain@82dee4ba654bd2146511f85f0d013af94670c4de # v1.4.0
136+
137+
# - name: Run Foundry tests
138+
# run: forge test --config-path ./foundry.toml
139+
# working-directory: contracts
140+
141+
# - name: Run snapshot
142+
# run: NO_COLOR=1 forge snapshot >> $GITHUB_STEP_SUMMARY
143+
# working-directory: contracts

contracts/CHANGELOG.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,31 @@ The format is based on [Common Changelog](https://common-changelog.org/).
1515
- **Breaking:** Rename `governor` to `owner` in order to comply with the lightweight ownership standard [ERC-5313](https://eipsinsight.com/ercs/erc-5313) ([#2112](https://github.com/kleros/kleros-v2/issues/2112))
1616
- **Breaking:** Apply the penalties to the stakes in the Sortition Tree ([#2107](https://github.com/kleros/kleros-v2/issues/2107))
1717
- **Breaking:** Make `SortitionModule.getJurorBalance().stakedInCourt` include the penalties ([#2107](https://github.com/kleros/kleros-v2/issues/2107))
18-
- **Breaking:** Add a new field `drawnJurorFromCourtIDs` to the `Round` struct in `KlerosCoreBase` and `KlerosCoreUniversity` ([#2107](https://github.com/kleros/kleros-v2/issues/2107))
19-
- **Breaking:** Add a new state variable `jumpDisputeKitID` to the `DisputeKitClassicBase` contract ([#2114](https://github.com/kleros/kleros-v2/issues/2114))
2018
- Make `IDisputeKit.draw()` and `ISortitionModule.draw()` return the court ID from which the juror was drawn ([#2107](https://github.com/kleros/kleros-v2/issues/2107))
2119
- Rename `SortitionModule.setJurorInactive()` to `SortitionModule.forcedUnstakeAllCourts()` ([#2107](https://github.com/kleros/kleros-v2/issues/2107))
22-
- Allow stake changes to by-pass delayed stakes when initiated by the SortitionModule by setting the `_noDelay` parameter to `true` in `SortitionModule.validateStake()` ([#2107](https://github.com/kleros/kleros-v2/issues/2107))
2320
- Make the primary VRF-based RNG fall back to `BlockhashRNG` if the VRF request is not fulfilled within a timeout ([#2054](https://github.com/kleros/kleros-v2/issues/2054))
2421
- Authenticate the calls to the RNGs to prevent 3rd parties from depleting the Chainlink VRF subscription funds ([#2054](https://github.com/kleros/kleros-v2/issues/2054))
2522
- Use `block.timestamp` rather than `block.number` for `BlockhashRNG` for better reliability on Arbitrum as block production is sporadic depending on network conditions. ([#2054](https://github.com/kleros/kleros-v2/issues/2054))
2623
- Replace the `bytes32 _key` parameter in `SortitionTrees.createTree()` and `SortitionTrees.draw()` by `uint96 courtID` ([#2113](https://github.com/kleros/kleros-v2/issues/2113))
2724
- Extract the sortition sum trees logic into a library `SortitionTrees` ([#2113](https://github.com/kleros/kleros-v2/issues/2113))
25+
- Make `IDisputeKit.getDegreeOfCoherenceReward()` multi-dimensional so different calculations may be applied to PNK rewards, fee rewards and PNK penalties (future-proofing) ([#2090](https://github.com/kleros/kleros-v2/issues/2090))
26+
- Consolidate the constant `ALPHA_DIVISOR` with `ONE_BASIS_POINTS` ([#2090](https://github.com/kleros/kleros-v2/issues/2090))
2827
- Set the Hardhat Solidity version to v0.8.30 and enable the IR pipeline ([#2069](https://github.com/kleros/kleros-v2/issues/2069))
2928
- Set the Foundry Solidity version to v0.8.30 and enable the IR pipeline ([#2073](https://github.com/kleros/kleros-v2/issues/2073))
3029
- Widen the allowed solc version to any v0.8.x for the interfaces only ([#2083](https://github.com/kleros/kleros-v2/issues/2083))
31-
- Make `IDisputeKit.getDegreeOfCoherenceReward()` multi-dimensional so different calculations may be applied to PNK rewards, fee rewards and PNK penalties (future-proofing) ([#2090](https://github.com/kleros/kleros-v2/issues/2090))
32-
- Consolidate the constant `ALPHA_DIVISOR` with `ONE_BASIS_POINTS` ([#2090](https://github.com/kleros/kleros-v2/issues/2090))
3330
- Bump `hardhat` to v2.26.2 ([#2069](https://github.com/kleros/kleros-v2/issues/2069))
3431
- Bump `@kleros/vea-contracts` to v0.7.0 ([#2073](https://github.com/kleros/kleros-v2/issues/2073))
3532

3633
### Added
3734

35+
- **Breaking:** Add a new field `drawnJurorFromCourtIDs` to the `Round` struct in `KlerosCoreBase` and `KlerosCoreUniversity` ([#2107](https://github.com/kleros/kleros-v2/issues/2107))
36+
- **Breaking:** Add a new state variable `jumpDisputeKitID` to the `DisputeKitClassicBase` contract ([#2114](https://github.com/kleros/kleros-v2/issues/2114))
37+
- **Breaking:** Add a parameter `_recoveryCommit` to the event `DisputeKitShutter.CommitCastShutter` ([#2100](https://github.com/kleros/kleros-v2/issues/2100))
38+
- **Breaking:** Add a storage variable `recoveryCommitments` to `DisputeKitShutter` ([#2100](https://github.com/kleros/kleros-v2/issues/2100))
39+
- Allow the Shutter commitment to be recovered by the juror using only the salt and the choice, without having to provide the justification ([#2100](https://github.com/kleros/kleros-v2/issues/2100))
3840
- Allow the dispute kits to force an early court jump and to override the number of votes after an appeal (future-proofing) ([#2110](https://github.com/kleros/kleros-v2/issues/2110))
3941
- Allow the dispute kits to specify which new dispute kit to use when a court jump occurs ([#2114](https://github.com/kleros/kleros-v2/issues/2114))
42+
- Allow stake changes to by-pass delayed stakes when initiated by the SortitionModule by setting the `_noDelay` parameter to `true` in `SortitionModule.validateStake()` ([#2107](https://github.com/kleros/kleros-v2/issues/2107))
4043

4144
### Fixed
4245

contracts/foundry.toml

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
11

22
[profile.default]
33
solc = "0.8.30"
4+
evm_version = "cancun"
45
via_ir = true
56
optimizer = true
6-
optimizer_runs = 500
7-
optimizer_details = { yulDetails = { stackAllocation = true } }
8-
additional_compiler_profiles = [
9-
{ name = "tests", via_ir = false }
10-
]
11-
compilation_restrictions = [
12-
{ paths = "test/foundry/KlerosCore.t.sol", via_ir = false },
13-
]
7+
optimizer_runs = 10000
8+
149
src = 'src'
1510
out = 'out'
1611
libs = ['../node_modules', 'lib']

contracts/hardhat.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const config: HardhatUserConfig = {
2828
{
2929
version: "0.8.30",
3030
settings: {
31+
evmVersion: "cancun",
3132
viaIR: process.env.VIA_IR !== "false", // Defaults to true
3233
optimizer: {
3334
enabled: true,

contracts/src/arbitration/dispute-kits/DisputeKitClassicBase.sol

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -318,19 +318,21 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi
318318
if (_voteIDs.length == 0) revert EmptyVoteIDs();
319319
if (!coreDisputeIDToActive[_coreDisputeID]) revert NotActiveForCoreDisputeID();
320320

321-
Dispute storage dispute = disputes[coreDisputeIDToLocal[_coreDisputeID]];
321+
uint256 localDisputeID = coreDisputeIDToLocal[_coreDisputeID];
322+
Dispute storage dispute = disputes[localDisputeID];
322323
if (_choice > dispute.numberOfChoices) revert ChoiceOutOfBounds();
323324

324-
Round storage round = dispute.rounds[dispute.rounds.length - 1];
325+
uint256 localRoundID = dispute.rounds.length - 1;
326+
Round storage round = dispute.rounds[localRoundID];
325327
{
326328
(uint96 courtID, , , , ) = core.disputes(_coreDisputeID);
327329
(, bool hiddenVotes, , , , , ) = core.courts(courtID);
328-
bytes32 voteHash = hashVote(_choice, _salt, _justification);
330+
bytes32 actualVoteHash = hashVote(_choice, _salt, _justification);
329331

330332
// Save the votes.
331333
for (uint256 i = 0; i < _voteIDs.length; i++) {
332334
if (round.votes[_voteIDs[i]].account != _juror) revert JurorHasToOwnTheVote();
333-
if (hiddenVotes && round.votes[_voteIDs[i]].commit != voteHash)
335+
if (hiddenVotes && _getExpectedVoteHash(localDisputeID, localRoundID, _voteIDs[i]) != actualVoteHash)
334336
revert HashDoesNotMatchHiddenVoteCommitment();
335337
if (round.votes[_voteIDs[i]].voted) revert VoteAlreadyCast();
336338
round.votes[_voteIDs[i]].choice = _choice;
@@ -484,15 +486,14 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi
484486
* @dev Computes the hash of a vote using ABI encoding
485487
* @dev The unused parameters may be used by overriding contracts.
486488
* @param _choice The choice being voted for
487-
* @param _justification The justification for the vote
488489
* @param _salt A random salt for commitment
489490
* @return bytes32 The hash of the encoded vote parameters
490491
*/
491492
function hashVote(
492493
uint256 _choice,
493494
uint256 _salt,
494-
string memory _justification
495-
) public pure virtual returns (bytes32) {
495+
string memory /*_justification*/
496+
) public view virtual returns (bytes32) {
496497
return keccak256(abi.encodePacked(_choice, _salt));
497498
}
498499

@@ -738,17 +739,29 @@ abstract contract DisputeKitClassicBase is IDisputeKit, Initializable, UUPSProxi
738739
// * Internal * //
739740
// ************************************* //
740741

742+
/// @dev Returns the expected vote hash for a given vote.
743+
/// @param _localDisputeID The ID of the dispute in the Dispute Kit.
744+
/// @param _localRoundID The ID of the round in the Dispute Kit.
745+
/// @param _voteID The ID of the vote.
746+
/// @return The expected vote hash.
747+
function _getExpectedVoteHash(
748+
uint256 _localDisputeID,
749+
uint256 _localRoundID,
750+
uint256 _voteID
751+
) internal view virtual returns (bytes32) {
752+
return disputes[_localDisputeID].rounds[_localRoundID].votes[_voteID].commit;
753+
}
754+
741755
/// @dev Checks that the chosen address satisfies certain conditions for being drawn.
742756
/// Note that we don't check the minStake requirement here because of the implicit staking in parent courts.
743757
/// minStake is checked directly during staking process however it's possible for the juror to get drawn
744758
/// while having < minStake if it is later increased by governance.
745759
/// This issue is expected and harmless.
746-
/// @param _round The round in which the juror is being drawn.
747760
/// @param _coreDisputeID ID of the dispute in the core contract.
748761
/// @param _juror Chosen address.
749762
/// @return result Whether the address passes the check or not.
750763
function _postDrawCheck(
751-
Round storage _round,
764+
Round storage /*_round*/,
752765
uint256 _coreDisputeID,
753766
address _juror
754767
) internal view virtual returns (bool result) {

0 commit comments

Comments
 (0)