diff --git a/src/v0.8/module/dataset/DatasetsChallenge.sol b/src/v0.8/module/dataset/DatasetsChallenge.sol index 7ef0c28e..d3ad9765 100644 --- a/src/v0.8/module/dataset/DatasetsChallenge.sol +++ b/src/v0.8/module/dataset/DatasetsChallenge.sol @@ -136,8 +136,6 @@ contract DatasetsChallenge is return; } - require(isWinner(_datasetId, msg.sender), "Not an election winner"); - DatasetType.DatasetChallengeProof storage datasetChallengeProof = datasetChallengeProofs[_datasetId]; require( @@ -147,6 +145,21 @@ contract DatasetsChallenge is .datasetRuleMaxChallengeProofsSubmitersPerDataset(), "exceeds maximum challenge submitters count of filplus" ); + + bytes32 seed = datasetChallengeProof.election._electSeed( + getAuditorElectionEndHeight(_datasetId) + ); + + require( + datasetChallengeProof.election._processCandidateTicketResult( + getAuditorElectionEndHeight(_datasetId), + msg.sender, + getChallengeSubmissionCount(_datasetId), + seed + ), + "Not an election winner" + ); + require( getDatasetChallengeProofsCount(_datasetId) < getChallengeSubmissionCount(_datasetId), @@ -378,20 +391,20 @@ contract DatasetsChallenge is function isWinner( uint64 _datasetId, address _account - ) public returns (bool) { - require( - uint64(block.number) >= getAuditorElectionEndHeight(_datasetId), - "auditor election not completed" - ); - + ) public view returns (bool) { DatasetType.DatasetChallengeProof storage datasetChallengeProof = datasetChallengeProofs[_datasetId]; + bytes32 _seed = datasetChallengeProof.election._getElectSeed( + getAuditorElectionEndHeight(_datasetId) + ); + return - datasetChallengeProof.election._processTicketResult( + datasetChallengeProof.election._processCandidateTicketResult( getAuditorElectionEndHeight(_datasetId), _account, - getChallengeSubmissionCount(_datasetId) + getChallengeSubmissionCount(_datasetId), + _seed ); } } diff --git a/src/v0.8/module/dataset/library/challenge/DatasetAuditorElectionLIB.sol b/src/v0.8/module/dataset/library/challenge/DatasetAuditorElectionLIB.sol index 4131db48..1e3a1e75 100644 --- a/src/v0.8/module/dataset/library/challenge/DatasetAuditorElectionLIB.sol +++ b/src/v0.8/module/dataset/library/challenge/DatasetAuditorElectionLIB.sol @@ -62,10 +62,24 @@ library DatasetAuditorElectionLIB { _hash = blockhash(uint32(_targetHeight)); } + /// Internal function to retrieve the election seed for dataset auditor election at a specific height. + /// @param self The storage reference to the dataset auditor election. + /// @param _height The height at which to retrieve the election seed. + /// @return The election seed for the specified height. + function _getElectSeed( + DatasetType.DatasetAuditorElection storage self, + uint64 _height + ) internal view returns (bytes32) { + if (self.seed == bytes32(0)) { + return _getBlockHashBaseHeight(_height); + } + return self.seed; + } + /// @dev Internal function to retrieve the block hash at a specified height. /// @param self The storage reference to the dataset auditor candidate. /// @param _height The target block height to retrieve the hash for. - /// @return blockHash The block hash at the specified height. + /// @return The election seed for the specified height. function _electSeed( DatasetType.DatasetAuditorElection storage self, uint64 _height @@ -78,21 +92,27 @@ library DatasetAuditorElectionLIB { /// @dev Internal function to process the ticket result. /// @param self The storage reference to the dataset auditor candidate. - /// @param _height The target block height. + /// @param _electionEndHeight The end height of the election. /// @param _account The account address. /// @param _numWinners The number of winners to be selected. + /// @param _seed The seed used for randomness in the election process. /// @return success A boolean indicating whether the ticket result is successfully processed. - function _processTicketResult( + function _processCandidateTicketResult( DatasetType.DatasetAuditorElection storage self, - uint64 _height, + uint64 _electionEndHeight, address _account, - uint256 _numWinners - ) internal returns (bool) { + uint256 _numWinners, + bytes32 _seed + ) internal view returns (bool) { require( _numWinners <= self.candidates.length, "The number of candidates is insufficient" ); - bytes32 _seed = _electSeed(self, _height); + + require( + uint64(block.number) >= _electionEndHeight, + "auditor election not completed" + ); bytes32[] memory weights = new bytes32[](self.candidates.length); diff --git a/test/v0.8/assertions/module/dataset/DatasetsAssertion.sol b/test/v0.8/assertions/module/dataset/DatasetsAssertion.sol index 2c3a76a0..410a43b5 100644 --- a/test/v0.8/assertions/module/dataset/DatasetsAssertion.sol +++ b/test/v0.8/assertions/module/dataset/DatasetsAssertion.sol @@ -795,7 +795,7 @@ contract DatasetsAssertion is for (uint64 i = 0; i < auditors.length; i++) { assertEq(auditors[i], _expectAuditors[i], "auditor not matched"); - (bytes32[] memory leaves, ,, ) = datasetsChallenge + (bytes32[] memory leaves, , , ) = datasetsChallenge .getDatasetChallengeProofs(_datasetId, auditors[i]); assertEq( leaves.length, @@ -857,7 +857,7 @@ contract DatasetsAssertion is } } - assertEq(randomSeed,_expectRandomSeed,"randomseed not matched"); + assertEq(randomSeed, _expectRandomSeed, "randomseed not matched"); } /// @notice Assertion function for getting dataset verification count. @@ -981,4 +981,20 @@ contract DatasetsAssertion is "challenge count not matched" ); } + + /// Checks whether an account is expected to be a winner for a dataset. + /// @param _datasetId The ID of the dataset. + /// @param _account The address of the account to check. + /// @param expectResult The expected result indicating whether the account is a winner. + function isWinnerAssersion( + uint64 _datasetId, + address _account, + bool expectResult + ) external { + assertEq( + datasetsChallenge.isWinner(_datasetId, _account), + expectResult, + "is winner not matched" + ); + } } diff --git a/test/v0.8/interfaces/assertions/module/IDatasetsAssertion.sol b/test/v0.8/interfaces/assertions/module/IDatasetsAssertion.sol index 476209d3..def43f84 100644 --- a/test/v0.8/interfaces/assertions/module/IDatasetsAssertion.sol +++ b/test/v0.8/interfaces/assertions/module/IDatasetsAssertion.sol @@ -256,4 +256,14 @@ interface IDatasetsAssertion is IStatisticsBaseAssertion { uint64 _datasetId, uint64 _expectCount ) external; + + /// Checks whether an account is expected to be a winner for a dataset. + /// @param _datasetId The ID of the dataset. + /// @param _account The address of the account to check. + /// @param expectResult The expected result indicating whether the account is a winner. + function isWinnerAssersion( + uint64 _datasetId, + address _account, + bool expectResult + ) external; } diff --git a/test/v0.8/testcases/module/dataset/SubmittChallengeProofsTestSuite.sol b/test/v0.8/testcases/module/dataset/SubmittChallengeProofsTestSuite.sol index 9cffd138..3c530104 100644 --- a/test/v0.8/testcases/module/dataset/SubmittChallengeProofsTestSuite.sol +++ b/test/v0.8/testcases/module/dataset/SubmittChallengeProofsTestSuite.sol @@ -65,6 +65,8 @@ contract SubmittChallengeProofsTestCaseWithSuccess is DatasetsTestBase { uint32[] memory paths = new uint32[](pointCount); uint64 randomSeed; + datasetsAssertion.isWinnerAssersion(_id, address(199), true); + (randomSeed, leaves, siblings, paths) = datasetsHelpers .generateVerification(pointCount);