Bitcoin smart contracts
Recent interest in the so-called “Blockchain technology” drived businesses and people interest to smart contracts, resulting in a growing interest in Ethereum and the EVM technology (the real meaning of “Blockchain technology” for most of them). This growing interest led to the idea that Bitcoin does not permit it, being therefore obsolete, and that the future is made of “Blockchain technology” and smart contracts.
Want to hear a big news ? Bitcoin does support smart contracts (and actually it is the core of the technology), does provide a language to build them, and developers do make big things with it. Some examples are :
- P2PKH : Signature verification is done with the Script language.
- P2SH : Since 2012, you can send funds to a script (written in Script), which could be used to, for example, create a multisig address or lock some coins.
- Atomic swaps.
- Lightning network.
This article is intended to people having some knowledge about crypto-currencies, or some good will.
What is a smart contract ?
A smart contract is a computerized transaction protocol that executes the terms of a contract. The general objectives of smart contract design are to satisfy common contractual conditions (such as payment terms, liens, confidentiality, and even enforcement), minimize exceptions both malicious and accidental, and minimize the need for trusted intermediaries. Related economic goals include lowering fraud loss, arbitration and enforcement costs, and other transaction costs.
Why use a smart contract ?
How are they implemented in Bitcoin ?
Bitcoin uses a stack-based language called “Script”, which is intentionally not Turing-complete, which means you can’t do everything a Turing machine is able to do (for instance a loop), which means it minimizes exceptions both malicious and accidental.
“Where” do we put this code ?
In transactions. A transaction is consisted of one or more input(s), and one or more output(s). The script is divided in two parts : the first one is stored in the input and the second in the output, so that creating a transaction by linking an output to an input reveals the entire code to execute.
Usually, the script in the input will describe a condition to spend that input (called locking script, or scriptPubKey), and the script in the output will pass data to satisfy that condition (called unlocking script, or scriptSig). An output without any locking script specified is spendable by everyone. Actually, “sending” bitcoins to an address is just a smart contract (locking script) telling this output can be spent only by specifying a signature from the corresponding private key. Here is what it looks like :
ScriptSig : <Signature> <pubkey>
ScriptPubKey : OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
How is it executed ?
Let’s take the above script in order to understand. Since it is a stack-based language we need a stack (the execution is stopped and returns an error if whenever during the process,
FALSE) is returned)
In this stack we execute our operations, we start with the first instructions :
DUP opcode duplicates the item on top of the stack :
HASH160 opcode applies the ripemd160(sha256()) function on the item at the top of the stack (the function used to get an address from a public key) :
We add the address specified in the locking script :
And we check if the address who tries to spend the output (the public key we duplicated and hashed in order to have an address) is the same as the one specified in the locking script, using the
EQUALVERIFY opcode, which returns
1if the two items at the top of the stack are equal,
0 (which stops the execution) else. If they are equal, there are just the signature and the public key left :
On which we apply the
CHECKSIG opcode, which returns
1 if the signature is valid for the public key (meaning we have the private key corresponding),
0 else. So, if they are equal :
1 left on the stack without any other operation to execute means that the script has been successfully executed : the unlocking script satisfies the condition set by the locking one.
Can we make more ?
Yes we can !
It requires more thought, because less possibilities implies more complex algorithms. We’ll see 3 concrete examples to conclude this post : multisig, atomic swaps, payment channels.
1 — Multisig
“Multisig” stands for multi-signature address : a type of address which requires more than one signature (from a private key) to spend coins from it. In order to create this kind of address we commonly use P2SH (an address created from a Bitcoin script). But since an entire post could be made about this type of address, I’ll use just what I explained in the previous part. Script (the language) provides us a great opcode called
CHECKMULTISIG which will take as argument
M <pubkey 1> ... <pubkey N> N with
N the number of keys which can unlock the funds and
M the minimal number of them which are required.
N can be equal to
M . Here is an example of a locking script for a multisignature address which funds can be spent by 3 addresses if 2 of them are provided :
2 <Public Key A> <Public Key B> <Public Key C> 3 CHECKMULTISIG
The corresponding unlocking script is :
0 <Signature B> <Signature C>
With a zero which corresponds to a bug which became part of the consensus rule. Here you can notice that the locking script (scriptPubKey) is quite long, which results in higher fees for the transaction containing it. Since this is not the owner of the multisig address which include it in its transaction(s) (the owner just unlock the incoming transaction and therefore includes the unlocking script), a P2SH address is used for this type of addresses to avoid this problem. You can learn more about the bug and P2SH (and anything about Bitcoin) in Mastering Bitcoin, from Andreas Antonopoulos.
2 — Atomic swaps
With time, some forks of Bitcoin (networks which have the same underlying process, but different history ->different ledgers) began to gain interest and their users wanted to change tokens from this network for bitcoins or for another similar network’s tokens. Since user may not be able to do the transaction in person, and could not use a centralized market place (which would be incredible, for a decentralized currency ;) ), a smart contract algorithm has been designed and used to change these tokens from a network to another without trusting anyone, not even the person whom you make the transaction with.
The main things used here are shared secret and locktime. Basically, the process is that the first person involved, let’s call him Cartman, wants to swap his tokens, let’s say bitcoins, with the second person involved, let’s call him Kyle, who owns litecoins. Cartman will choose a secret “number” and prepare a transaction on the Bitcoin network which can be spendable only by providing a signature with Kyle’s key, and the secret. Kyle will do the same thing on the Litecoin network. Cartman will spend the output on the Litecoin network, by providing its signature and the secret. This way Kyle will be able to access the secret and then spend the output on the Bitcoin network (by providing its signature and the secret). Adding a locktime to transactions provides safety so that nobody (especially Cartman) can cheat on each other.
To be accurate, the process is a little more tricky than this (but not too much !) and if you are interested you can checkout the algorithm initially proposed by TierNolan on bitcointalk, this algorithm revisited on the wiki, or the algorithm explained by Mike Hearn. It is really not too complex, I just did not want to do copy/paste.
3 — Payment channels
A payment channel is (an abstraction and) something shared by 2 users in order to make payment without recording them in the block chain, which means without waiting for a miner to add it in a block and paying fees to this miner for his work. Again, the goal of this process is to minimize trust, so each party should be able to exchange bitcoins without trusting anybody, or each other.
The process to achieve this is similar to atomic swaps, we will use shared secrets and timelocks. Since this post is intended to be an overview of Bitcoin smart contracts and not a detailed explanation of payment channels, I will just give here a general and basic explanation of state channels.
A state channel has to be initiated (funding), used (committed), and settled : we will use transactions for every state, since this is the only thing that can be done on the Bitcoin network. First, to initiate a channel, we have to create a funding transaction which is basically a MULTISIG address to which each participant sends bitcoins (let’s take our friends Alice and Bob this time). The amount sent to this address will be the maximum amount we will be able to transact inside the channel. Once this transaction has been confirmed, we create commitment transactions which spend some coins from the MULTISIG address to each of the addresses of the participants (ex: if the channel was funded with 10 mBTC, send 5 to Alice and 5 to Bob). These transactions are not broadcast but are valid (signed by both parties) : just the participants know about the balances on the channel, but they can be broadcast in case of trouble. We can make many more commitment transaction, so that “Alice pays Bob 1 mBTC” just means making two new transactions sending 4 mBTC from the MULTISIG address to Alice and 5 mBTC to Bob. After we made enough transactions we can make a settlement transaction, which is actually sending the last commitment transaction (the last state of the channel) to the network.
Using a state channel permits to do n transactions with the cost, in time and money, of 2 (only the funding and the settlement transactions are added to the chain).
Attribution : “Mastering Bitcoin by Andreas M. Antonopoulos (O’Reilly). Copyright 2017 Andreas M. Antonopoulos, 978–1–491–95438–6.” because most of what I know about Bitcoin (and what I talked about in this post) comes from this book.