Skip to content

Instantly share code, notes, and snippets.

@yuyasugano
Last active May 11, 2019 05:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yuyasugano/e9ccf625679e75c97640e3707069cb1c to your computer and use it in GitHub Desktop.
Save yuyasugano/e9ccf625679e75c97640e3707069cb1c to your computer and use it in GitHub Desktop.
SLCR Voting Commit and Reveal
/**
* @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