Skip to main content

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

Instructions

ChecksDoneNotes
SC: Create a Commit FunctionX
SC: Create a Reveal FunctionX
SC: Extend Reveal to show how Random Number can be generatedX
App: Enable interaction through UIX
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

  1. User enters a secret word
  2. Copies hash of secret word into input clicks on commit
  • Success: Event is logged
  1. Copies hash of secret word into input clicks on reveal

Deploy

TODO: deploy this contract.

See web3 deployment best practices