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_IF

OP_DROP

OP_DUP OP_HASH160 <pubKeyHashPlayerA> OP_EQUALVERIFY OP_CHECKSIG

OP_ENDIF

OP_DUP <outcomeBHash> OP_HASH256 OP_EQUAL

OP_IF

OP_DROP

OP_DUP OP_HASH160 <pubKeyHashPlayerB> OP_EQUALVERIFY OP_CHECKSIG

OP_ENDIF

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.