Working with contracts
How to design and implement contract based applications.
Introduction
Contracts are an exciting feature of Bitcoin that has opened up a new research field - using flexible digital money to produce compelling and innovative applications. The linked wiki page contains some examples of what can be done, but it can sometimes be unclear how to convert them into code.
In this article, we’ll look at a few common techniques that are used when implementing contract-based applications. It assumes you’re already familiar with how the Bitcoin protocol works and have understood the theory on the contracts page - if something is unclear, please ask the community for advice.
Creating multi-signature outputs
Contracts very often use multi-signature outputs in order to allocate value to a group of users … typically, the participants in the contract protocol. Multi-signature outputs are easy to create with bitcoinj. For the next few examples, we will not be using P2SH (pay to script hash), so the set of keys chosen won’t be representable as a 3… type address. We’ll learn more about P2SH at the end.
Let’s see how to do it:
Alright, now we have broadcast the transaction - note that in some contract protocols, you don’t actually broadcast right away. The example above just does it for completeness.
But how do we get the money back again? For that, we need a transaction that includes two signatures, one calculated by us, and one by them.
Partial signing
A common requirement when implementing contract protocols is to pass around and sign incomplete transactions.
The Wallet
class doesn’t know how to handle outputs that aren’t fully owned by it. So we’ll have to sign the spending transaction ourselves.
The key point to bear in mind is that when you sign a transaction, what you actually sign is only parts of that transaction. Which parts are controlled by the signature hash (sighash) flags. But no matter which flags you select, the contents of input scripts are never signed. Indeed that must be the case, because otherwise you could never build a transaction - the act of signing the second input would modify the version of the transaction signed by the first, breaking the signature.
This means that signatures can be calculated and sent between different parties in a contract, then inserted into a transaction to make it valid.
Let’s look at what the server-side code might look like:
The server receives the contract and decides to give all the money back to the client (how generous of it!). It constructs a transaction and signs it. Now the client must repeat the process and construct exactly the same transaction and calculate a signature in the same way. It is then in possession of two valid signatures over the same transaction, one from itself and one from the server. All that is left is to put them both into the transaction:
As you can see, the process involves building a transaction that spends the first one, calculating a signature and then manually building the script that can spend the multi-signature output. Once we’ve built it, we use verify()
to ensure the script we wrote satisfies the multisig output correct, and thus that the other side didn’t hand us a garbage signature.
Other SIGHASH modes
You can specify alternative SIGHASH modes to control what is signed and how the other parties can modify the transaction without breaking your signature. These modes are documented on the contracts page linked to above. However, please note that the API for this is likely to change a bit in future.
P2SH (pay to script hash)
Many kinds of application that use contracts don’t need to expose their inner workings to end users, because they can use custom protocols to move the necessary data around instead. But if you want to represent a complex script in a form that a regular wallet can send to, you can create a P2SH address. This looks a bit like a regular Bitcoin address but instead of encoding the hash of a public key, it encodes the hash of a complete script. A P2SH output includes a special kind of non-script which is pattern matched and special rules applied instead of being executed as normal. The scriptSig of the spending input then includes both the “real” scriptPubKey, which must hash to the value in the output, and the inputs to the so-called redeem script.
There are utility methods for creating P2SH style scripts using the ScriptBuilder
class. When signing for a P2SH output, you should pass the redeem script (not the P2SH scriptPubKey) to Transaction.hashTransactionForSignature
.