Last active
May 11, 2019 05:44
-
-
Save yuyasugano/e9ccf625679e75c97640e3707069cb1c to your computer and use it in GitHub Desktop.
SLCR Voting Commit and Reveal
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @notice Commits vote using hash of choice and secret salt to conceal vote until reveal | |
* @param _pollID Integer identifier associated with target poll | |
* @param _secretHash Commit keccak256 hash of voter's choice and salt | |
* @param _numTokens The number of tokens to be commited towards the target poll | |
* @param _prevPollID The ID of the poll that the user has voted the maximum number of | |
* tokens in which is still less than or equal to numTokens | |
*/ | |
// To commit a user must hold enough voting rights | |
require(voteTokenBalance[msg.sender] >= _numTokens, "Cannot commit because of shortage of ERC20 tokens"); | |
// Confirm if the commit period has not passed for the poll ID | |
require(commitPeriodActive(_pollID)); | |
require(!pollMap[_pollID].didCommit[msg.sender]); // prevent user from committing multiple times | |
require(!pollMap[_pollID].didReveal[msg.sender]); // prevent user from revealing multiple times | |
// prevent user from committing to zero node placeholder | |
require(_pollID != 0); | |
// prevent user from committing a secretHash of zero | |
require(_secretHash != 0); | |
// Check if _prevPollID exists in the user DLL or if _prevPollID is zero | |
require(_prevPollID == 0 || dllMap[msg.sender].contains(_prevPollID)); | |
// Determine the next poll ID | |
uint256 nextPollID = dllMap[msg.sender].getNext(_prevPollID); | |
// edge case: in-place update, which means current _pollID matches the next node | |
if (nextPollID == _pollID) { | |
nextPollID = dllMap[msg.sender].getNext(_pollID); | |
} | |
require(validPosition(_prevPollID, nextPollID, msg.sender, _numTokens)); | |
dllMap[msg.sender].insert(_prevPollID, _pollID, nextPollID); | |
// Generate an identifier which associates a user and a poll together | |
bytes32 UUID = attrUUID(msg.sender, _pollID); | |
// Set an attribute for numToken and commitHash | |
store.setAttribute(UUID, "numTokens", _numTokens); | |
store.setAttribute(UUID, "commitHash", uint256(_secretHash)); | |
// No partial lock, substruct _numTokens from the voting rights | |
voteTokenBalance[msg.sender] = voteTokenBalance[msg.sender].sub(_numTokens); | |
// This vote is commited to the poll | |
pollMap[_pollID].didCommit[msg.sender] = true; | |
emit _VoteCommitted(_pollID, _numTokens, msg.sender); | |
} | |
/** | |
* @notice Reveals vote with choice and secret salt used in generating commitHash to attribute commited tokens | |
* @param _pollID Integer identifier associated with target poll | |
* @param _voteOption Vote choice used to generate commitHash for associated poll | |
* @param _salt Secret number used to generate commitHash for associated poll | |
*/ | |
function revealVote(uint256 _pollID, uint256 _voteOption, uint256 _salt) public { | |
require(revealPeriodActive(_pollID)); // make sure the reveal period is active | |
require(pollMap[_pollID].didCommit[msg.sender]); // make sure user has commited a vote for this poll | |
require(!pollMap[_pollID].didReveal[msg.sender]); // prevent user from revealing multiple times | |
require(keccak256(abi.encodePacked(_voteOption, _salt)) == getCommitHash(msg.sender, _pollID)); // compare resultant hash from inputs to original commitHash, keccak256(abi.encodePacked(_voteOption, _salt)) is relevant to _secretHash | |
uint256 numTokens = getNumTokens(msg.sender, _pollID); | |
// Stake numTokens for votesFor and votesAgainst | |
if (_voteOption == 1) { // apply numTokens to appropriate poll choice | |
pollMap[_pollID].votesFor = pollMap[_pollID].votesFor.add(numTokens); | |
} else { | |
pollMap[_pollID].votesAgainst = pollMap[_pollID].votesAgainst.add(numTokens); | |
} | |
dllMap[msg.sender].remove(_pollID); // remove the node referring to this vote upon reveal | |
// No partial lock, add _numTokens back to the voting rights | |
// Tokens are now available to withdraw or for another vote | |
voteTokenBalance[msg.sender] = voteTokenBalance[msg.sender].add(numTokens); | |
pollMap[_pollID].didReveal[msg.sender] = true; | |
pollMap[_pollID].voteOptions[msg.sender] = _voteOption; | |
emit _VoteRevealed(_pollID, numTokens, pollMap[_pollID].votesFor, pollMap[_pollID].votesAgainst, _voteOption, msg.sender, _salt); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment