Commit Reveal Pattern
As data in a blockchain is public, it is impossible to store them secretly.
This creates some challenges for many applications where data needs to remain unknown to the caller at the time of transaction.
The commit-reveal-scheme provides a solution to this problem.
Scaffold Eth Challenge
Checks | Done | Notes |
---|---|---|
SC: Create a Commit Function | X | |
SC: Create a Reveal Function | X | |
SC: Extend Reveal to show how Random Number can be generated | X | |
App: Enable interaction through UI | X | |
App: Improve UI UX | - | |
App: Deploy Smart Contract to a Testnet | - | |
App: Deploy Web App | - |
Commit
Enable a user to send in a secret word converted into bytes.
Save that hash in a mapping by user's address
Return to user a hash of that in combination with their address.
function getHash(bytes32 data) public view returns(bytes32) {
return keccak256(abi.encodePacked(address(this), data));
}
function commit(bytes32 dataHash, uint64 block_number) public {
require(block_number > block.number,"CommitReveal::reveal: Already revealed");
commits[msg.sender].commit = dataHash;
commits[msg.sender].block = block_number;
commits[msg.sender].revealed = false;
console.log(block.number, block_number);
emit CommitHash(msg.sender,commits[msg.sender].commit,commits[msg.sender].block);
}
Reveal
Recieve the hash of the secret from a user then check if it matches the hash of the secret word for the sender's address.
function reveal(bytes32 revealHash) public {
require(commits[msg.sender].revealed==false,"CommitReveal::reveal: Already revealed");
require(revealHash==commits[msg.sender].commit,"CommitReveal::reveal: Revealed hash does not match commit");
commits[msg.sender].revealed=true;
bytes32 blockHash = blockhash(commits[msg.sender].block);
}
Generate a Random Number
function reveal(bytes32 revealHash) public {
require(commits[msg.sender].revealed==false,"CommitReveal::reveal: Already revealed");
//require(getHash(revealHash)==commits[msg.sender].commit,"CommitReveal::reveal: Revealed hash does not match commit");
require(revealHash==commits[msg.sender].commit,"CommitReveal::reveal: Revealed hash does not match commit");
commits[msg.sender].revealed=true;
bytes32 blockHash = blockhash(commits[msg.sender].block);
uint8 random = uint8(uint(keccak256(abi.encodePacked(blockHash,revealHash))))%max;
emit RevealHash(msg.sender,revealHash,random);
console.log("Random: ", random);
}
React App UI Flow
See the happy path
- User enters a secret word
- Copies hash of secret word into input clicks on commit
- Success: Event is logged
- Copies hash of secret word into input clicks on reveal
Deploy
TODO: deploy this contract.
See web3 deployment best practices