I was intrigued by Mike Hearn's idea for
Oracle Contracts and wanted to begin implementation. I was able to prototype quite a bit, but wanted to get feedback to see if there was anything I was overlooking or anything that could be improved.
Oracle ContractsAn Oracle Contract is a set of Bitcoin transactions that allows multiple parties to enter an agreement based on the outcome of an event with minimal trust. The multiple parties each spend Bitcoins that are combined into a single output. This output can only be redeemed by a subset of the parties based on the outcome of the event. For example, two parties might want to wager if the Royal Baby will be a boy or a girl. Each bet 1 Bitcoin. If the baby is born a boy, then the first party will get the output (2 Bitcoins minus fees), and if the baby is a girl, then the second party will get the output. A third party, called an oracle, is responsible for deciding the outcome of the event and allowing the winning party to redeem the transaction.
Basic Bitcoin Transaction OverviewTransactions are the basis of the Bitcoin ledger. A transaction consists of a set of inputs and outputs. The outputs must add up to less than or equal to the inputs. Each input is an output of a previous transaction. Each output is a script that takes a set of data as inputs. When you spend Bitcoins, you must give data that correctly executes the script. Typically, the script requires that you prove you have access to a private key. However, the script can have many other formats that are considered non-standard.
DefinitionsEvent - Something that occurs in the future with many possible outcomes.
Contract Transaction - A transaction that contains inputs that come from some or all of the parties involved in the contract. The transaction contains a single output that describes what conditions will allow redemption by the parties involved.
Redemption Transaction - a transaction that spends the Contract Transaction’s input.
Oracle - A third party that agrees to decide whether an event occurs or not. The oracle will allow the Redemption Contract to be created.
Refund Transaction - a transaction that will automatically refund the output of the Contract Transaction in the event that the Oracle cannot be contacted by a specified date.
Event Expression - a string that contains defines what event determines the payout for an event, along with who should get the payout for each outcome.
Change - when an input is provided that is larger than the intended output, an additional output is added to receive “change”. For example, if you are spending a 1 BTC input, and wish to send .75 BTC to an address, you will want to receive .25 BTC back as change. This is done by creating an additional output to an address you control and adding a value of .25 BTC to it.
Basic OverviewTwo parties wish to be paid based on the outcome of an event. If the event occurs with Outcome A, then party 1 should be paid. If the event occurs with Outcome B, then party 2 should be paid. To determine the outcome of the event, a third party, called the Oracle, is enlisted. An oracle simply determines if an event has occurred and what the outcome is. If the outcome is A, then he will allow Party 1 to be paid. If the outcome is B, then he will allow Party 2 to be paid. If the event did not occur yet, then neither party can be paid.
Preparing for the ContractAn oracle creates a set of events it is willing to adjudicate. An event is something that will happen in the future and each event will have a set of outcomes. Here are some examples of events and outcomes:
- England 2016 World Cup
- England Will Win
- England Will Not Win
- 2016 World Cup Winner
- England Will Win
- France Will Win
- Brazil Will Win
- Anyone Else will win
- 2016 World Cup Qualifier USA vs. Costa Rica
- United States Will Win
- Costa Rica Will Win
- Draw
- At Least One Country will Leave the EU by Jan 1, 2015
The simplest type of event is a binary event. While other types of contracts are possible, the initial implementation of contracts will focus on these binary events. In the above examples, “England winning the 2016 World Cup” and “At Least One Country Will Leave the EU”. For the rest of this document, only binary contracts are considered.
Once an oracle publishes a list of events and outcomes it will adjudicate, two parties must agree to take opposite sides of the event outcomes. Parties must negotiate the price each are willing to pay and the total amount of the bet. This matching can occur manually (I want to make a contract with a friend), or could even be automated through a matching service (each party submits to a willingness to pay a certain amount for one outcome of an event, and if any two parties could create a matching bet, a contract is generated and given to the parties to sign).
Matching services could be run by the oracle or be separate and handle multiple oracles. Matching services could also be run as a P2P service where oracles and users could register with the network.
Funding the ContractOnce a contract is ready to be created, it must be funded. This process can be done in multiple ways, such as the following:
Each party can add an input to a contract transaction and an output for change
Each party can submit funds to a trusted entity who keeps a balance for each account, then the trusted party will fund the contract’s inputs.
A shared address can be used, such that each party can submit a payment that can only be spent if both parties agree.
This document focuses on the third method - using a shared address. Here is an example transaction where Party 1 has a 2 BTC unspent output and wishes to contribute 1.5 BTC to the contract, and Party 2 has a 3 BTC unspent output and wishes to contribute 0.5 BTC. At the end of this set of transactions, there are 2 BTC ready to fund the contract.
There are still issues with this type of funding. Both parties have no guarantee that the other will fund their transaction. Similarly, once the funds arrive, there is no guarantee that the other party won’t hold the Bitcoins hostage, since both parties must agree to spend them out of the shared address. There are less sinister problems that could exist, such as the other party losing their private key to the shared address or just becoming unreachable.
One way to avoid this is to have a chained transaction that will automatically spend the outputs of the shared address before funding. The Micropayments Channel implementation does this similar type of chaining. While it is vulnerable to transaction malleability, this problem is not likely to occur with the current network as such changes are non-standard and will not be relayed.
The most obvious solution to this is to have both parties share a hash of their funding transactions such that the contract can be generated. However, this is still vulnerable to another exploit where one party refuses to submit their funding transaction after the other submits, making the contract transaction invalid and leaving the coins unspendable (the inputs will contain a transaction that does not exist).
To avoid this, a refund transaction containing each input should be created to return to the address that funded it. That transaction will contain an input sequence value of 0 so that it could be replaced at a later time, and a lock time some small amount of time in the future, such the contract can be created after both parties have funded the shared address.
A contract transaction is also generated with a higher sequence value (1) that spends both inputs with a single output. That output is spendable when two of the three parties involved (the oracle and the two funding the transaction) agree the conditions have been met to spend it.
In this scenario, if the contract transaction is not created within 30 minutes, the refund transactions may be published to the blockchain. If a contract transaction is created and signed, it will replace the refund transaction and be added to the blockchain. Both parties are protected from each other and do not have to trust the other will comply and are only at risk for the transaction fee for the refund. It is also possible to set the lock time to be after the event, such that the contract transaction need not be published until after the event, thus the oracle cannot know if the transaction is real or not.
Contract Transaction Output StructureThe contract will consist of the inputs from the shared address and a single output. The contents of the script for this output are as follows for a two party contract:
<expression hash> OP_DROP 2 <OraclePubKey> <Party1PubKey> <Party2PubKey> 3 OP_CHECKMULTISIG
The expression hash is the hash160(x) of the expression string. The expression is a string in the following format: “<EVENTID>?<Outcome1Address>:<Outcome2Address>”. The <EVENTID> parameter is a string identifier representing an event that the oracle knows about.
It is possible to have a different expression language that supports more complicated contracts. For contracts with multiple parties, a different syntax would have to be used. The script would also have to be modified since an N of M multisignature check would no longer work, since the parties who lose could collaborate against the winner. In this case, it would require a script that requires the oracle plus the winner to sign. It also is possible to have contracts that require N of M oracles to agree before it can be paid out, but a different script would be needed.
It is possible the oracle may not be available to adjudicate the event, may refuse to sign a transaction, or may hold the funds hostage. In this case, a refund transaction can be created on the contract output to return funds. The lock time can be set to a few days after the event should be completed, and the sequence of the input set to 0. When the event occurs, a new transaction can be created with a sequence of 1 on the input and a lock time of final.
There are two possible redemption contracts, one for each outcome of the event. Since the oracle will only sign one of these, only one can be valid, and published to the block chain.
Possible ProblemsThe main exploit that exists is that there is no guarantee that an oracle will also take positions in contracts, and always side with himself for those transactions. The reputation of the oracle will still be important and oracle transactions will be visible in the blockchain. Users who are exploited can report this and prove their claim by showing the expression that matches the hash. If this becomes an issue, a more advanced use case of having multiple oracles required may prevent this problem (requiring 3 of 5 signatures, for example, and having 3 oracles involved).
More Than Two PartiesThe expression language does not support more than two parties, although this could be extended. A case structure syntax could be used for outcomes. The contract signature would have to be modified so that losing parties could not collaborate to claim the contract. An example of a script to do this would require one of the parties (1 of N signature) AND n of m oracles to redeem. Such scripts get more complicated, but are possible.
Multiple OraclesMultiple oracles can reduce the risk of having one oracle enter a contract as a party and always adjudicating in his favor if he is involved. There still is a risk that multiple oracles could collude or even be the same entity. There would also have to be a coordination of oracles to agree to the same event identifiers and outcomes such that the contracts could be processed.
Transferring ContractsA party may want to buy the rights to a contract from one of the parties who currently own it. This could be done by creating a transaction that takes two inputs- one from the new party and the contract transaction, and one output (an updated contract with Party 3’s address and public key in place of Party 1). The oracle could allow this to occur because Party 2’s rights do not change in this case and sign the original contract’s output along with Party 1. A new transaction would have to be given to Part 2, who now would be unable to redeem the original contract transaction since it would be spent.