Exploring Commit-Reveal Schemes on Ethereum – The Startup
For example, in a traditional game of rock-paper-scissors, both players pick secret values, and they share their values to see who wins. The difficulty with this approach on the blockchain is that both players can’t share their values at the same time, and the player who goes first must publicly broadcast their value, meaning their opponent can act accordingly. Luckily for us, commitment schemes are an excellent solution.
A commitment scheme is a cryptographic algorithm used to allow someone to commit to a value while keeping it hidden from others with the ability to reveal it later. The values in a commitment scheme are binding, meaning that no one can change them once committed. The scheme has two phases: a commit phase in which a value is chosen and specified, and a reveal phase in which the value is revealed and checked.
To get a better understanding, consider this simplified visualization. Imagine Alice, the sender, placing a message in a locked box and handing it to Bob, the receiver. Bob can’t access the message because it’s locked in the box, and Alice can’t change the message because it’s in Bob’s possession, but when Alice wants to reveal the message, she can unlock the box and show the message to Bob.
Let’s take a look at how we can properly build a game of rock paper scissors on Ethereum using a commitment scheme.
Let’s start with our constructor and initialization values. We will need choices for the players to select — rock, paper, and scissors. We’ll also have stages so that functions can only run in their respective phases. Finally, we’ll create a struct to represent the player commitments, as well as some initialization values that will be set in the constructor, some state variables, and events.
Next, we’ll put together a commit function, starting with checks. First, we’ll
require the function to only run during one of the two commit stages. Next, we can ensure that the proper value was sent along with the transaction, and send back any additional funds. Once we’ve done our checks, we can store the commitment, emit the
Commit event, and move on to the next stage.
Now let’s move on to the reveal function, again starting with checks. We’ll
require that this function only runs during one of the reveal stages, and only accepts valid choices. Then we’ll find the player’s data so we can check their commitment hash to determine if it is valid. If their hash is valid, we’ll store it, fire the
Reveal event, and move on to the next stage.
Lastly, we have the distribute function, where we’ll determine the winner and pay them out. As always, we’ll
require that the function only runs if we are in the distribute stage, or the reveal stage has run out of time. Next, we’ll calculate the payouts and determine the winner by examining all possible outcomes. Once we’ve determined the winner, we will transfer the funds to their address, emit the
Payout event, and reset the state for the next game.
Now that we’ve completed our contract, let’s take a look at it in full.
Commitment schemes are an excellent way to hide a value on Ethereum while maintaining proof of its commitment. To learn more about commitment schemes, see this example of a blind auction in the Solidity docs, or read this excellent article by Austin Thomas Griffith.