Betting Using Bitcoin Cash Smart Contracts
Betting on the outcome of events using smart contracts in bitcoin has been discussed for years. One proposed solution is to have an oracle sign messages describing the outcomes of events. In this article we describe a method of doing so that involves using a secure hashing algorithm for signing. Bitcoin Script have supported checking the hash of arbitrary data since the first release. This method can be used today.
Please don't assume that the method describe in this article is secure. What is described here is an idea that might work.
Before the event
Before the event the oracle will generate a secret key for each possible outcome. It will then calculate the sha256 sum of each outcome. The list of (outcome, sha256sum) pairs is then published.
Setting up the smart contract
Smart contracts for betting can now be made using the published sha256 sum. A normal pay-to-script-hash output looks like this:
- OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
A bet involving two persons betting on two different outcomes could be done like this:
- OP_DUP <outcomeAHash> OP_HASH256 OP_EQUAL
- OP_DUP OP_HASH160 <pubKeyHashPlayerA> OP_EQUALVERIFY OP_CHECKSIG
- OP_DUP <outcomeBHash> OP_HASH256 OP_EQUAL
- OP_DUP OP_HASH160 <pubKeyHashPlayerB> OP_EQUALVERIFY OP_CHECKSIG
After the event
The oracle publish the secret key corresponding to the outcome of the event. The other keys remains secret. The winner of the bet can now collect the prize, using an input like this: <sig> <pubKey> <publishedSecret>.
Large number of outcomes
This method requires that the oracle creates a hash and secret value for each possible outcome. Reducing the number of outcomes can always be done by splitting the message into smaller pieces. Example: The outcome is a number from 0 to 999,999. Instead of creating a key for each possible outcome, the oracle creates a key for each possible outcome for each of the six digits (first digit is 0, first digit is 1, ... , second digits is 0, ...). This reduces the number of keys from one million to 60. The smart contracts get slightly bigger, since they have to check six hashes instead of just one. On the other hand it becomes easier to check for ranges, e.g. by just checking the first five digits.
Comparison to OP_CHECKDATASIG
With the proposed new opcode OP_CHECKDATASIG smart contracts can check messages signed by the oracle using a ecdsa key-pair. This implies that the oracle can reuse it's key-pair and doesn't have to enumerate every possible message it plans to sign.
The ability to reuse key-pairs might not be that important. The oracle might want to use new key-pairs anyway, just like hd-wallets has become popular. Setting up a bet without checking that the public key of the oracle is still valid would be risky.
In order to setup reliable smart contracts depending on the messages signed be the oracle the format of these messages has to be known. The format might be described using regular expressions. This is in practice the same as listing all possible messages. Not listing all the matches is just an optimisation. This optimisation does however come with the huge risk that parsing of the messages in the smart contracts contains bugs. Listing the outcomes greatly reduces this risk. Misunderstandings and bugs is more likely to be discovered before the bet is done.
The secret key for each outcome can be derived from a master secret. For an event the oracle must create a master secret key and the syntax that describes every outcome. If using ecdsa signing the oracle has to calculate the public key and publish it along with the syntax. If using hashing the oracle has to produce all values that matches the syntax, derive a secret key for each value using the value and the master key (e.g. a HMAC), calculate the sha256 of the secret, and publish the list of value, sha256 sums. The oracle only need to store the master key and the syntax. Everything else can be derived from these values.
3 of 3 reviewers say it's worth paying for
0 of 3 reviewers say it's not worth paying for