Skip to content

Commit 17d7a81

Browse files
unknownunknown1jaybuidl
authored andcommitted
fix(KlerosCore): drawing iterations don't repeat
1 parent 73782d9 commit 17d7a81

File tree

6 files changed

+20
-14
lines changed

6 files changed

+20
-14
lines changed

Diff for: contracts/src/arbitration/KlerosCore.sol

+6-5
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ contract KlerosCore is IArbitratorV2 {
6464
uint256 sumFeeRewardPaid; // Total sum of arbitration fees paid to coherent jurors as a reward in this round.
6565
uint256 sumPnkRewardPaid; // Total sum of PNK paid to coherent jurors as a reward in this round.
6666
IERC20 feeToken; // The token used for paying fees in this round.
67+
uint256 drawIterations; // The number of iterations passed drawing the jurors for this round.
6768
}
6869

6970
struct Juror {
@@ -609,11 +610,10 @@ contract KlerosCore is IArbitratorV2 {
609610

610611
IDisputeKit disputeKit = disputeKitNodes[round.disputeKitID].disputeKit;
611612

612-
uint256 startIndex = round.drawnJurors.length;
613-
uint256 endIndex = startIndex + _iterations <= round.nbVotes ? startIndex + _iterations : round.nbVotes;
614-
615-
for (uint256 i = startIndex; i < endIndex; i++) {
616-
address drawnAddress = disputeKit.draw(_disputeID);
613+
uint256 startIndex = round.drawIterations;
614+
// TODO: cap the iterations?
615+
for (uint256 i = startIndex; i < startIndex + _iterations; i++) {
616+
address drawnAddress = disputeKit.draw(_disputeID, i);
617617
if (drawnAddress != address(0)) {
618618
jurors[drawnAddress].lockedPnk += round.pnkAtStakePerJuror;
619619
emit Draw(drawnAddress, _disputeID, currentRound, round.drawnJurors.length);
@@ -624,6 +624,7 @@ contract KlerosCore is IArbitratorV2 {
624624
}
625625
}
626626
}
627+
round.drawIterations += _iterations;
627628
}
628629

629630
/// @dev Appeals the ruling of a specified dispute.

Diff for: contracts/src/arbitration/SortitionModule.sol

+3-3
Original file line numberDiff line numberDiff line change
@@ -268,15 +268,15 @@ contract SortitionModule is ISortitionModule {
268268
/// Note that this function reverts if the sum of all values in the tree is 0.
269269
/// @param _key The key of the tree.
270270
/// @param _coreDisputeID Index of the dispute in Kleros Core.
271-
/// @param _voteID ID of the voter.
271+
/// @param _nonce Nonce to hash with random number.
272272
/// @return drawnAddress The drawn address.
273273
/// `O(k * log_k(n))` where
274274
/// `k` is the maximum number of children per node in the tree,
275275
/// and `n` is the maximum number of nodes ever appended.
276276
function draw(
277277
bytes32 _key,
278278
uint256 _coreDisputeID,
279-
uint256 _voteID
279+
uint256 _nonce
280280
) public view override returns (address drawnAddress) {
281281
require(phase == Phase.drawing, "Wrong phase.");
282282
SortitionSumTree storage tree = sortitionSumTrees[_key];
@@ -285,7 +285,7 @@ contract SortitionModule is ISortitionModule {
285285
return address(0); // No jurors staked.
286286
}
287287

288-
uint256 currentDrawnNumber = uint256(keccak256(abi.encodePacked(randomNumber, _coreDisputeID, _voteID))) %
288+
uint256 currentDrawnNumber = uint256(keccak256(abi.encodePacked(randomNumber, _coreDisputeID, _nonce))) %
289289
tree.nodes[0];
290290

291291
// While it still has children

Diff for: contracts/src/arbitration/dispute-kits/DisputeKitClassic.sol

+4-2
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,11 @@ contract DisputeKitClassic is BaseDisputeKit, IEvidence {
181181
/// @dev Draws the juror from the sortition tree. The drawn address is picked up by Kleros Core.
182182
/// Note: Access restricted to Kleros Core only.
183183
/// @param _coreDisputeID The ID of the dispute in Kleros Core.
184+
/// @param _nonce Nonce of the drawing iteration.
184185
/// @return drawnAddress The drawn address.
185186
function draw(
186-
uint256 _coreDisputeID
187+
uint256 _coreDisputeID,
188+
uint256 _nonce
187189
) external override onlyByCore notJumped(_coreDisputeID) returns (address drawnAddress) {
188190
Dispute storage dispute = disputes[coreDisputeIDToLocal[_coreDisputeID]];
189191
Round storage round = dispute.rounds[dispute.rounds.length - 1];
@@ -193,7 +195,7 @@ contract DisputeKitClassic is BaseDisputeKit, IEvidence {
193195
bytes32 key = bytes32(uint256(courtID)); // Get the ID of the tree.
194196

195197
// TODO: Handle the situation when no one has staked yet.
196-
drawnAddress = sortitionModule.draw(key, _coreDisputeID, round.votes.length);
198+
drawnAddress = sortitionModule.draw(key, _coreDisputeID, _nonce);
197199

198200
if (_postDrawCheck(_coreDisputeID, drawnAddress)) {
199201
round.votes.push(Vote({account: drawnAddress, commit: bytes32(0), choice: 0, voted: false}));

Diff for: contracts/src/arbitration/dispute-kits/DisputeKitSybilResistant.sol

+4-2
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,11 @@ contract DisputeKitSybilResistant is BaseDisputeKit, IEvidence {
200200
/// @dev Draws the juror from the sortition tree. The drawn address is picked up by Kleros Core.
201201
/// Note: Access restricted to Kleros Core only.
202202
/// @param _coreDisputeID The ID of the dispute in Kleros Core.
203+
/// @param _nonce Nonce of the drawing iteration.
203204
/// @return drawnAddress The drawn address.
204205
function draw(
205-
uint256 _coreDisputeID
206+
uint256 _coreDisputeID,
207+
uint256 _nonce
206208
) external override onlyByCore notJumped(_coreDisputeID) returns (address drawnAddress) {
207209
Dispute storage dispute = disputes[coreDisputeIDToLocal[_coreDisputeID]];
208210
Round storage round = dispute.rounds[dispute.rounds.length - 1];
@@ -212,7 +214,7 @@ contract DisputeKitSybilResistant is BaseDisputeKit, IEvidence {
212214
bytes32 key = bytes32(uint256(courtID)); // Get the ID of the tree.
213215

214216
// TODO: Handle the situation when no one has staked yet.
215-
drawnAddress = sortitionModule.draw(key, _coreDisputeID, round.votes.length);
217+
drawnAddress = sortitionModule.draw(key, _coreDisputeID, _nonce);
216218

217219
if (_postDrawCheck(_coreDisputeID, drawnAddress) && !round.alreadyDrawn[drawnAddress]) {
218220
round.votes.push(Vote({account: drawnAddress, commit: bytes32(0), choice: 0, voted: false}));

Diff for: contracts/src/arbitration/interfaces/IDisputeKit.sol

+2-1
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ interface IDisputeKit {
5151
/// @dev Draws the juror from the sortition tree. The drawn address is picked up by Kleros Core.
5252
/// Note: Access restricted to Kleros Core only.
5353
/// @param _coreDisputeID The ID of the dispute in Kleros Core, not in the Dispute Kit.
54+
/// @param _nonce Nonce.
5455
/// @return drawnAddress The drawn address.
55-
function draw(uint256 _coreDisputeID) external returns (address drawnAddress);
56+
function draw(uint256 _coreDisputeID, uint256 _nonce) external returns (address drawnAddress);
5657

5758
// ************************************* //
5859
// * Public Views * //

Diff for: contracts/src/arbitration/interfaces/ISortitionModule.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ interface ISortitionModule {
2424

2525
function notifyRandomNumber(uint256 _drawnNumber) external;
2626

27-
function draw(bytes32 _court, uint256 _coreDisputeID, uint256 _voteID) external view returns (address);
27+
function draw(bytes32 _court, uint256 _coreDisputeID, uint256 _nonce) external view returns (address);
2828

2929
function preStakeHook(address _account, uint96 _courtID, uint256 _stake) external returns (preStakeHookResult);
3030

0 commit comments

Comments
 (0)