Suffix

Published by Simon Schoeters

Send coins to a multisig address

The Bitcoin protocol has built-in support for multisig addresses. A multisig address needs n out of i signatures before the coins can be withdrawn. A good example is an escrow-like service that allows safer payments by holding the buyer's coins in escrow until the terms of the sale are met.

Currently none of the Bitcoin clients support these kind of addresses via the GUI, but it's fully supported via the Bitcoin Core (previously named Bitcoin-Qt) client's API.

You might want to run the Bitcoin Core client in testnet mode to play with fake coins.

The example code assumes you have the Ruby JSON-RPC wrapper to make things a little easier.

We create a BitcoinRPC instance which we'll reuse in our examples.

rpc = BitcoinRPC.new('http://user:pass@127.0.0.1:8332')

Bits & pieces

We'll create an address that needs 2 signatures out of 3 to withdraw the coins, but you can choose whatever combination you desire. Say we have the following 3 addresses:

  1. Buyer: muYqjrmbDQTGgdJRaFwJiihk8qEionVVm4
  2. Seller: mrtnMnUBDqdavGdWHuZRBNPRjfLCQMv1tC
  3. Escrow: mj6zqxdBANVw4cA4MFu4E9dxL44dxGbQmH

Create a multisig address

Let's get started by creating a new multisig address. The first parameter defines the number of signatures needed to withdraw the coins (2 in our example):

rpc.createmultisig(2, [
  "muYqjrmbDQTGgdJRaFwJiihk8qEionVVm4",
  "mrtnMnUBDqdavGdWHuZRBNPRjfLCQMv1tC",
  "mj6zqxdBANVw4cA4MFu4E9dxL44dxGbQmH"
])

This returns a new multisig address:

{
  "address" => "2NEgZ6xYqJBNDuEnPQg8rVAUySvmPCqFWfM",
  "redeemScript" => "52210357f11...e33e917d9b7e52ae"
}

This address will NOT be visible on the Bitcoin network (you can use btclook.com or testnet.btclook.com to check) as we haven't announced it to the network yet.

Send funds

We now need to fiddle with some transactions. Addresses are an abstraction in the Bitcoin protocol, the basic units are transactions. Take a few minutes to learn why transactions are so important if you are not up to speed yet and want the following to make sense.

First, find an unspent transaction:

rpc.listunspent

It lists all the unspent transactions in your Bitcoin Core client:

[
  {
    "txid" => "2d1aa015385...286d958d6d9ee93cdc5821d1f",
    "vout" => 0,
    "address" => "mfm1Q7TFDb2bXwr34d6uFjD56FKRfTSr1v",
    "scriptPubKey" => "76a91402a86...1512694f175888ac",
    "amount" => 0.00663676,
    "confirmations" => 573
  },
  ...
] 

I took the first one in the list, but you probably want to mix and match transactions from this list to get to the bitcoin amount you need.

Create a new raw transaction for the multisig address. The vout is the index of the input or output as a transaction can have multiple inputs and outputs:

rpc.createrawtransaction(
  [{
    "txid" => "2d1aa015385...286d958d6d9ee93cdc5821d1f",
    "vout" => 0
  }],
  { "2NEgZ6xYqJBNDuEnPQg8rVAUySvmPCqFWfM" => 0.006 }
)

This returns a long transaction hash:

"01000000011f1d82c5cd93eed9d658d98682cc968c2fe48bee5d2a177ce6e2583815a01a2d0000000000ffffffff01c02709000000000017a914eb24ff395813fd1411c2093394396266d77722ff8700000000"

DONE You now have a transaction of 0.006 BTC linked to the multisig address. You'll need 2 of the 3 signatures to spend these coins.

Announce to the network

You can optionally announce the transaction to your local Bitcoin node (the Bitcoin Core client) and the network. Send the raw transaction from the previous step:

rpc.sendrawtransaction("01000000011f...722ff8700000000")

Have a look at the Bitcoin Core transactions tab. There should be a new pending transaction waiting for confirmation.

Resources

  • TwoOfThree.sh: the shell script where this post is based upon.
  • Bitrated: implementation of an escrow service with multisig addresses.

This blog post is open source. Did you spot a mistake? Have any ideas for improvements? Contribute to this post via Github. Thank you!