Generating Segwit Change Addresses in Bitcoin 0.15

Segwit was activated on the Bitcoin network in August 2017. Unfortunately, there are still not many segwit transactions on mainnet, and most blocks are still about 1 MB in size. One of the obstacles here is that the current version of Bitcoin Core, 0.15.1, does not include “native” segwit support. Bitcoin Core can actually generate segwit addresses relatively easily, with a single RPC call to addwitnessaddress. But at least at the moment, there’s no way to easy receive change output at a segwit change when using sendtoaddress.

Actually Bitcoin Core 0.15 does support this, you just have to use the raw transaction API. This might sound scary, but it’s actually not that hard. In this post I’ll show how to create and use segwit change addresses using the raw transaction API available in Bitcoin Core 0.15.

Bitcoin Regtest

Bitcoin Core comes with a “regression test” mode called regtest. In regtest mode you start with a completely empty blockchain, and there is a special RPC method that can be used to generate new blocks (as if you were mining, but without the wait!). This mode is extremely useful for testing Bitcoin features, because you don’t need to wait for real blocks to be mined on mainnet or testnet.

The first step here will be to run a bitcoind instance in regtest mode and generate some blocks:

# Launch an instance of bitcoind in regtest mode.
$ bitcoind -daemon -regtest

# Generate some new blocks. You must generate at least 432 to enable segwit.
$ bitcoin-cli -regtest generate 432
# <lots of output here>

# Verify that segwit is enabled.
$ bitcoin-cli -regtest getblockchaininfo | jq .bip9_softforks.segwit.status -
"active"

# Check our balance.
$ bitcoin-cli -regtest getbalance
14949.69482000

You may get a slightly different balance than what is shown here. The important thing is that the balance is non-zero, and that segwit has the “active” status.

Also note that all of the bitcoin-cli commands I’m using here will use the -regtest flag. If you are doing a lot of work with regtest you can add regtest=1 to bitcoin.conf to make it the default. However, I’m going to opt to manually use -regtest throughout this article to make it explicit that we’re on regtest rather than mainnet.

Using sendtoaddress To Create A Transaction

First we’re going to use the regular sendtoaddress RPC to send funds to a segwit address to understand how it works better. As mentioned earlier, this will use a non-segwit address for change. To create a new segwit address we make a getnewaddress RPC, and then we pass the returned address to addwitnessaddress:

# Get a new receive address.
$ bitcoin-cli -regtest getnewaddress
mjwataWwyVAMDtfCqTvWyRTuX441Njd66B

# Turn it into a segwit address.
bitcoin-cli -regtest addwitnessaddress mjwataWwyVAMDtfCqTvWyRTuX441Njd66B
2N6DAGPjL9SDTS9PE3G36VABpCcCRn3FwT4

Note that you will not get the exact same addresses as I have here, which is OK. The important thing to note there is that the segwit address starts with a 2, which means it’s a regtest script hash address. Now let’s send it 10 BTC:

# Send funds to the segwit address.
$ bitcoin-cli -regtest sendtoaddress 2N6DAGPjL9SDTS9PE3G36VABpCcCRn3FwT4 10
bd2f3932c3e250d67400cd73689814f5e2dd5801eca52bd7983e67cfa4ee3d1b

The output of sendtoaddress is a txid, which we can look at using the getrawtransaction RPC method:

# Look at the vout of the raw transaction
$ bitcoin-cli -regtest getrawtransaction bd2f3932c3e250d67400cd73689814f5e2dd5801eca52bd7983e67cfa4ee3d1b true | jq .vout

Note that I’ve restricted this to just the vout information using jq. For the transaction I just created locally, I get the following vout data:

[
  {
    "value": 0.01113949,
    "n": 0,
    "scriptPubKey": {
      "asm": "OP_DUP OP_HASH160 59d1ce2347d8effe9b609db05e0e5bb7d22aea61 OP_EQUALVERIFY OP_CHECKSIG",
      "hex": "76a91459d1ce2347d8effe9b609db05e0e5bb7d22aea6188ac",
      "reqSigs": 1,
      "type": "pubkeyhash",
      "addresses": [
        "mohsmedSgjFbHQYKn6JZ2XArVwk5W6RWis"
      ]
    }
  },
  {
    "value": 10,
    "n": 1,
    "scriptPubKey": {
      "asm": "OP_HASH160 8e35b2321aa379e834a974c2ea11712a79b034d2 OP_EQUAL",
      "hex": "a9148e35b2321aa379e834a974c2ea11712a79b034d287",
      "reqSigs": 1,
      "type": "scripthash",
      "addresses": [
        "2N6DAGPjL9SDTS9PE3G36VABpCcCRn3FwT4"
      ]
    }
  }
]

This transaction has two outputs. Output #0 is the change output, and sends 0.01113949 BTC to mohsmedSgjFbHQYKn6JZ2XArVwk5W6RWis. Since the address starts with an m we know that it’s a non-segwit P2PKH address. Output #1 is the actual payment, and sends 10 BTC to 2N6DAGPjL9SDTS9PE3G36VABpCcCRn3FwT4.

We can use the special regtest generate method to include this transaction in a block:

# Mine a new block, to confirm the previous transaction.
$ bitcoin-cli -regtest generate 1
# <output omitted>

Creating A Segwit Change Address with fundrawtransaction

Now I’m going to illustrate generating a new transaction using the raw transaction API. In this example we’ll have a 1 in 2 out transaction. Both the payment destination and the change address will be segwit addresses!

First, we need a segwit payment address:

# Generate a segwit address to send funds to.
$ bitcoin-cli -regtest addwitnessaddress $(bitcoin-cli -regtest getnewaddress)
2NEff7hVChUxBg599ohiaDbbhZhzZY8BvLe

Again we’re going to send 10 BTC to the address. We begin the process by calling createrawtransaction to create an empty transactions with no inputs and just the 10 BTC output:

# Create a raw transaction that sends 10 BTC to the segwit payment address.
$ bitcoin-cli -regtest createrawtransaction '[]' '{"2NEff7hVChUxBg599ohiaDbbhZhzZY8BvLe": 10}'
02000000000100ca9a3b0000000017a914eaf999a752ea5a289020a8ccc5c6f0546cb710088700000000

The output hex represents an invalid transaction (because it has no inputs). We can request that the inputs to the transaction be funded, and specify a change address. First we create a segwit change address using getnewaddress and addwitnessaddress, and then fund the transaction using fundrawtransaction with a changeAddress request:

# Generate a segwit change address.
$ bitcoin-cli -regtest addwitnessaddress $(bitcoin-cli -regtest getnewaddress)
2N14FFwwWuPexqUuBNCUJXJeDesQv7gJTUu

# Fund the transaction.
$ bitcoin-cli -regtest fundrawtransaction 02000000000100ca9a3b0000000017a914eaf999a752ea5a289020a8ccc5c6f0546cb710088700000000 '{"changeAddress": "2N14FFwwWuPexqUuBNCUJXJeDesQv7gJTUu"}'
{
  "hex": "02000000064bc7ee6647910c47ae5e400d3c0cfb6c1f8dce6378b6459d908393e3e16d15f70000000000feffffff9a93dbaa10567899c6d8adaf14245074023e5856103e5fa7e64918966bd401630000000000feffffffbc94ff6061352469ae2a194e919afd2d041a3bf47bd39519cb4e151c234cd4a80000000000feffffffc2a7d416e2408a80ac909675d1690abc79ada67921abe169cf5e9d04c421dd480000000000feffffffd12a7a129d32514bc86ce5f1ef8bd68cc80e117ca6c8454fb2c91af3368b46d60000000000feffffffe42f204825ff58f64d407409935d90a6d30773367aa3fcc51f2d6ded8d70e8d00000000000feffffff0200ca9a3b0000000017a914eaf999a752ea5a289020a8ccc5c6f0546cb710088785ff10000000000017a91455ad7dab1cdb8792b6ef77eac4050f8f5d11e9048700000000",
  "changepos": 1,
  "fee": 0.00015160
}

The hex field in the output is the raw transaction data. As you can see, bitcoind has decided that a 0.00015160 BTC transaction fee is appropriate for this transaction. There are other options to fundrawtransaction that allow you to control the transaction fee; I encourage you to look at the output of bitcoin-cli help fundrawtransaction to learn more.

What’s actually in the transaction? Let’s take a look before signing it. We’ll do this using decoderawtransaction with the hex string from above:

$ bitcoin-cli -regtest decoderawtransaction 02000000064bc7ee6647910c47ae5e400d3c0cfb6c1f8dce6378b6459d908393e3e16d15f70000000000feffffff9a93dbaa10567899c6d8adaf14245074023e5856103e5fa7e64918966bd401630000000000feffffffbc94ff6061352469ae2a194e919afd2d041a3bf47bd39519cb4e151c234cd4a80000000000feffffffc2a7d416e2408a80ac909675d1690abc79ada67921abe169cf5e9d04c421dd480000000000feffffffd12a7a129d32514bc86ce5f1ef8bd68cc80e117ca6c8454fb2c91af3368b46d60000000000feffffffe42f204825ff58f64d407409935d90a6d30773367aa3fcc51f2d6ded8d70e8d00000000000feffffff0200ca9a3b0000000017a914eaf999a752ea5a289020a8ccc5c6f0546cb710088785ff10000000000017a91455ad7dab1cdb8792b6ef77eac4050f8f5d11e9048700000000

The JSON output looks like this:

{
  "txid": "17f714a55183a62b037b33bdd4365915e84d0a27e82a587207f8bcf9eb55fa2f",
  "hash": "17f714a55183a62b037b33bdd4365915e84d0a27e82a587207f8bcf9eb55fa2f",
  "version": 2,
  "size": 320,
  "vsize": 320,
  "locktime": 0,
  "vin": [
    {
      "txid": "f7156de1e39383909d45b67863ce8d1f6cfb0c3c0d405eae470c914766eec74b",
      "vout": 0,
      "scriptSig": {
        "asm": "",
        "hex": ""
      },
      "sequence": 4294967294
    },
    {
      "txid": "6301d46b961849e6a75f3e1056583e0274502414afadd8c699785610aadb939a",
      "vout": 0,
      "scriptSig": {
        "asm": "",
        "hex": ""
      },
      "sequence": 4294967294
    },
    {
      "txid": "a8d44c231c154ecb1995d37bf43b1a042dfd9a914e192aae6924356160ff94bc",
      "vout": 0,
      "scriptSig": {
        "asm": "",
        "hex": ""
      },
      "sequence": 4294967294
    },
    {
      "txid": "48dd21c4049d5ecf69e1ab2179a6ad79bc0a69d1759690ac808a40e216d4a7c2",
      "vout": 0,
      "scriptSig": {
        "asm": "",
        "hex": ""
      },
      "sequence": 4294967294
    },
    {
      "txid": "d6468b36f31ac9b24f45c8a67c110ec88cd68beff1e56cc84b51329d127a2ad1",
      "vout": 0,
      "scriptSig": {
        "asm": "",
        "hex": ""
      },
      "sequence": 4294967294
    },
    {
      "txid": "d0e8708ded6d2d1fc5fca37a367307d3a6905d930974404df658ff2548202fe4",
      "vout": 0,
      "scriptSig": {
        "asm": "",
        "hex": ""
      },
      "sequence": 4294967294
    }
  ],
  "vout": [
    {
      "value": 10.00000000,
      "n": 0,
      "scriptPubKey": {
        "asm": "OP_HASH160 eaf999a752ea5a289020a8ccc5c6f0546cb71008 OP_EQUAL",
        "hex": "a914eaf999a752ea5a289020a8ccc5c6f0546cb7100887",
        "reqSigs": 1,
        "type": "scripthash",
        "addresses": [
          "2NEff7hVChUxBg599ohiaDbbhZhzZY8BvLe"
        ]
      }
    },
    {
      "value": 0.01113989,
      "n": 1,
      "scriptPubKey": {
        "asm": "OP_HASH160 55ad7dab1cdb8792b6ef77eac4050f8f5d11e904 OP_EQUAL",
        "hex": "a91455ad7dab1cdb8792b6ef77eac4050f8f5d11e90487",
        "reqSigs": 1,
        "type": "scripthash",
        "addresses": [
          "2N14FFwwWuPexqUuBNCUJXJeDesQv7gJTUu"
        ]
      }
    }
  ]
}

The inputs here were chosen automatically. Note in particular that at this point we’re told that the transaction has size 320 and vsize 320. The size fields is the number of bytes in the raw transaction, and the vsize is a modified form of the block weight. The vsize shown here is not accurate since the transaction hasn’t been signed yet. Let’s do that now:

# Sign the transaction.
$ bitcoin-cli -regtest signrawtransaction 02000000064bc7ee6647910c47ae5e400d3c0cfb6c1f8dce6378b6459d908393e3e16d15f70000000000feffffff9a93dbaa10567899c6d8adaf14245074023e5856103e5fa7e64918966bd401630000000000feffffffbc94ff6061352469ae2a194e919afd2d041a3bf47bd39519cb4e151c234cd4a80000000000feffffffc2a7d416e2408a80ac909675d1690abc79ada67921abe169cf5e9d04c421dd480000000000feffffffd12a7a129d32514bc86ce5f1ef8bd68cc80e117ca6c8454fb2c91af3368b46d60000000000feffffffe42f204825ff58f64d407409935d90a6d30773367aa3fcc51f2d6ded8d70e8d00000000000feffffff0200ca9a3b0000000017a914eaf999a752ea5a289020a8ccc5c6f0546cb710088785ff10000000000017a91455ad7dab1cdb8792b6ef77eac4050f8f5d11e9048700000000

The JSON output from signrawtransaction gives us the new raw transaction hex representation:

{
  "hex": "02000000064bc7ee6647910c47ae5e400d3c0cfb6c1f8dce6378b6459d908393e3e16d15f700000000494830450221008a1aee405f8b1dc7876921bbf428d21ed7fe97492a6a9cc27bd762108570cb1f02207150931f3bd9f68eb0201a929c60ee53425d7a90aeb7aaab28aa92b8b858bef501feffffff9a93dbaa10567899c6d8adaf14245074023e5856103e5fa7e64918966bd4016300000000484730440220170082e5f7c2add8cb9b624efd3dead9b585e7c7df3dafbdc9537a1ac295869402201127b14b239086adb321a8337fd256239bf2ebcdd9ff1f07b71690e88fb7fe5201feffffffbc94ff6061352469ae2a194e919afd2d041a3bf47bd39519cb4e151c234cd4a80000000048473044022020679382919d4dd87c1ef618a7613413ea9f53907e196dd8a6565f0c264b7a9c022063c51f55df0c86ae055e999fc8b2b58bccc3c13672ba2c2396bed1e57a6914b601feffffffc2a7d416e2408a80ac909675d1690abc79ada67921abe169cf5e9d04c421dd480000000049483045022100a43b15029139cace8852027d35864b27706c5f1ce4f1c8c9a9b5d5b5abca8ba10220683a96ac1ae6ccb8e73c80077e06e4ffd22469513a045330b07af7a1346c7a9801feffffffd12a7a129d32514bc86ce5f1ef8bd68cc80e117ca6c8454fb2c91af3368b46d60000000048473044022041228046b0fe139ee8decb9e67d7afb13f435159936b74778c9c6c0a68a0828f022038699853f0c4b703bc79a477268a9d854624ee71d0f5c490fba57ef76de9a99f01feffffffe42f204825ff58f64d407409935d90a6d30773367aa3fcc51f2d6ded8d70e8d000000000494830450221008d510ce4d0dc43525d3098cb62587f7a493eb65cf0668cf59f4f55cb861db7bf0220562aaa3d07aff11926156f6e1a318b3a1eeabad55d33455cc9202363f923f73201feffffff0200ca9a3b0000000017a914eaf999a752ea5a289020a8ccc5c6f0546cb710088785ff10000000000017a91455ad7dab1cdb8792b6ef77eac4050f8f5d11e9048700000000",
  "complete": true
}

The transaction is also now “complete” since it’s valid and has been signed. At this point if we pass the raw hex string to decoderawtransaction we’ll see a few small differences: the size and vsize have both increased to 755 (due to the extra signature data), and the txid has changed.

To finish the exercise, we’ll send the transaction and generate a new block to actually include it in our regtest blockchain:

# Send the signed transaction.
$ bitcoin-cli -regtest sendrawtransaction 02000000064bc7ee6647910c47ae5e400d3c0cfb6c1f8dce6378b6459d908393e3e16d15f700000000494830450221008a1aee405f8b1dc7876921bbf428d21ed7fe97492a6a9cc27bd762108570cb1f02207150931f3bd9f68eb0201a929c60ee53425d7a90aeb7aaab28aa92b8b858bef501feffffff9a93dbaa10567899c6d8adaf14245074023e5856103e5fa7e64918966bd4016300000000484730440220170082e5f7c2add8cb9b624efd3dead9b585e7c7df3dafbdc9537a1ac295869402201127b14b239086adb321a8337fd256239bf2ebcdd9ff1f07b71690e88fb7fe5201feffffffbc94ff6061352469ae2a194e919afd2d041a3bf47bd39519cb4e151c234cd4a80000000048473044022020679382919d4dd87c1ef618a7613413ea9f53907e196dd8a6565f0c264b7a9c022063c51f55df0c86ae055e999fc8b2b58bccc3c13672ba2c2396bed1e57a6914b601feffffffc2a7d416e2408a80ac909675d1690abc79ada67921abe169cf5e9d04c421dd480000000049483045022100a43b15029139cace8852027d35864b27706c5f1ce4f1c8c9a9b5d5b5abca8ba10220683a96ac1ae6ccb8e73c80077e06e4ffd22469513a045330b07af7a1346c7a9801feffffffd12a7a129d32514bc86ce5f1ef8bd68cc80e117ca6c8454fb2c91af3368b46d60000000048473044022041228046b0fe139ee8decb9e67d7afb13f435159936b74778c9c6c0a68a0828f022038699853f0c4b703bc79a477268a9d854624ee71d0f5c490fba57ef76de9a99f01feffffffe42f204825ff58f64d407409935d90a6d30773367aa3fcc51f2d6ded8d70e8d000000000494830450221008d510ce4d0dc43525d3098cb62587f7a493eb65cf0668cf59f4f55cb861db7bf0220562aaa3d07aff11926156f6e1a318b3a1eeabad55d33455cc9202363f923f73201feffffff0200ca9a3b0000000017a914eaf999a752ea5a289020a8ccc5c6f0546cb710088785ff10000000000017a91455ad7dab1cdb8792b6ef77eac4050f8f5d11e9048700000000
5cc2bc6b943aea4ae9445addd64064b11004d0d3b22a34c3864d0bd8bff21ca9

# Force regtest to include it in a block.
$ bitcoin-cli generate 1

Note that sendrawtransaction returns 5cc2bc6b943aea4ae9445addd64064b11004d0d3b22a34c3864d0bd8bff21ca9 as the txid. We’ll use this in the next section.

Creating A Fully Segwit Transaction

The last example was a little boring because the inputs were all non-segwit addresses. This means that the transaction had the same size and vsize, and therefore didn’t get any block weight discount for being a segwit transaction. Let’s take a look at something more interesting: a fully segwit transaction. The transaction we’ll create will spend the 10 BTC we just sent to 2NEff7hVChUxBg599ohiaDbbhZhzZY8BvLe. It will send 9 BTC to a new segwit address, and get back about 1 BTC in change.

First we create segwit address to send funds to:

# Generate a new segwit address for the payment.
$ bitcoin-cli -regtest addwitnessaddress $(bitcoin-cli -regtest getnewaddress)
2MsiDwQcPTnTsnADRcZszHr92ktN5uQDGR6

Now we begin a new transaction using createrawtransaction as before. However, this time we’ll explicitly ask to use the segwit vout of our last transaction. That will ensure that the transaction only has segwit. The previous transaction used vout 0 for the 10 BTC payment, and vout 1 was used for change. Therefore we have to ask to fund the transaction using txid 5cc2bc6b943aea4ae9445addd64064b11004d0d3b22a34c3864d0bd8bff21ca9 vout 0. This means the first argument to createrawtransaction will be:

[
  {
    "txid": "5cc2bc6b943aea4ae9445addd64064b11004d0d3b22a34c3864d0bd8bff21ca9",
    "vout": 0
  }
]

The second argument will be:

{
  "2MsiDwQcPTnTsnADRcZszHr92ktN5uQDGR6": 9
}

All together, this becomes:

# Create a partial transaction.
$ bitcoin-cli -regtest createrawtransaction '[{"txid":"5cc2bc6b943aea4ae9445addd64064b11004d0d3b22a34c3864d0bd8bff21ca9","vout":0}]' '{"2MsiDwQcPTnTsnADRcZszHr92ktN5uQDGR6":9}'
0200000001a91cf2bfd80b4d86c3342ab2d3d00410b16440d6dd5a44e94aea3a946bbcc25c0000000000ffffffff0100e9a4350000000017a914051b3087fb0ed89184e7b7acf8e0ee5f6c229fe28700000000

Now we need to create a change address. This is done the same way as before:

# Create a segwit change address.
$ bitcoin-cli -regtest addwitnessaddress $(bitcoin-cli -regtest getnewaddress)
2N93s7izzQqxwFPNPmpavm7TSo1BqDAwjze

# Add the change address to our transaction.
$ bitcoin-cli -regtest fundrawtransaction 0200000001a91cf2bfd80b4d86c3342ab2d3d00410b16440d6dd5a44e94aea3a946bbcc25c0000000000ffffffff0100e9a4350000000017a914051b3087fb0ed89184e7b7acf8e0ee5f6c229fe28700000000 '{"changeAddress": "2N93s7izzQqxwFPNPmpavm7TSo1BqDAwjze"}'
{
  "hex": "0200000001a91cf2bfd80b4d86c3342ab2d3d00410b16440d6dd5a44e94aea3a946bbcc25c0000000000ffffffff0208d4f5050000000017a914ad5c039e7f850fcf4b31781c7ec8e3653d28b6288700e9a4350000000017a914051b3087fb0ed89184e7b7acf8e0ee5f6c229fe28700000000",
  "changepos": 0,
  "fee": 0.00003320
}

Let’s once again inspect the transaction using decoderawtransaction:

# Decode the raw, unsigned transaction.
$ bitcoin-cli -regtest decoderawtransaction 0200000001a91cf2bfd80b4d86c3342ab2d3d00410b16440d6dd5a44e94aea3a946bbcc25c0000000000ffffffff0208d4f5050000000017a914ad5c039e7f850fcf4b31781c7ec8e3653d28b6288700e9a4350000000017a914051b3087fb0ed89184e7b7acf8e0ee5f6c229fe28700000000

The following JSON is returned:

{
  "txid": "3e620123d5485694c7ec426c87c2a8d8b03eb82213ca6c53695bc9e549df6908",
  "hash": "3e620123d5485694c7ec426c87c2a8d8b03eb82213ca6c53695bc9e549df6908",
  "version": 2,
  "size": 115,
  "vsize": 115,
  "locktime": 0,
  "vin": [
    {
      "txid": "5cc2bc6b943aea4ae9445addd64064b11004d0d3b22a34c3864d0bd8bff21ca9",
      "vout": 0,
      "scriptSig": {
        "asm": "",
        "hex": ""
      },
      "sequence": 4294967295
    }
  ],
  "vout": [
    {
      "value": 0.99996680,
      "n": 0,
      "scriptPubKey": {
        "asm": "OP_HASH160 ad5c039e7f850fcf4b31781c7ec8e3653d28b628 OP_EQUAL",
        "hex": "a914ad5c039e7f850fcf4b31781c7ec8e3653d28b62887",
        "reqSigs": 1,
        "type": "scripthash",
        "addresses": [
          "2N93s7izzQqxwFPNPmpavm7TSo1BqDAwjze"
        ]
      }
    },
    {
      "value": 9.00000000,
      "n": 1,
      "scriptPubKey": {
        "asm": "OP_HASH160 051b3087fb0ed89184e7b7acf8e0ee5f6c229fe2 OP_EQUAL",
        "hex": "a914051b3087fb0ed89184e7b7acf8e0ee5f6c229fe287",
        "reqSigs": 1,
        "type": "scripthash",
        "addresses": [
          "2MsiDwQcPTnTsnADRcZszHr92ktN5uQDGR6"
        ]
      }
    }
  ]
}

As we expected, we have one vin and two vouts. Let’s sign the transaction and then decode the signed transaction hex:

# Sign the transaction.
$ bitcoin-cli -regtest signrawtransaction 0200000001a91cf2bfd80b4d86c3342ab2d3d00410b16440d6dd5a44e94aea3a946bbcc25c0000000000ffffffff0208d4f5050000000017a914ad5c039e7f850fcf4b31781c7ec8e3653d28b6288700e9a4350000000017a914051b3087fb0ed89184e7b7acf8e0ee5f6c229fe28700000000
{
  "hex": "02000000000101a91cf2bfd80b4d86c3342ab2d3d00410b16440d6dd5a44e94aea3a946bbcc25c000000001716001404ab8b3104064d457b9d54be5d95cda85374a43fffffffff0208d4f5050000000017a914ad5c039e7f850fcf4b31781c7ec8e3653d28b6288700e9a4350000000017a914051b3087fb0ed89184e7b7acf8e0ee5f6c229fe2870247304402205124a08b4d7c4c692b7e6c63516c62937df4eddcd77c9dd2323408c67e6c253202202fd74bc94fea08e41df6917bff122b88a1be816321878e5dcdeb062c74131c1b0121024c028276702a230caaf3894f5ded167b653dacee685ccafd5d4f63d2d20bb4ee00000000",
  "complete": true
}

# Decode the signed transaction.
$ bitcoin-cli -regtest decoderawtransaction 02000000000101a91cf2bfd80b4d86c3342ab2d3d00410b16440d6dd5a44e94aea3a946bbcc25c000000001716001404ab8b3104064d457b9d54be5d95cda85374a43fffffffff0208d4f5050000000017a914ad5c039e7f850fcf4b31781c7ec8e3653d28b6288700e9a4350000000017a914051b3087fb0ed89184e7b7acf8e0ee5f6c229fe2870247304402205124a08b4d7c4c692b7e6c63516c62937df4eddcd77c9dd2323408c67e6c253202202fd74bc94fea08e41df6917bff122b88a1be816321878e5dcdeb062c74131c1b0121024c028276702a230caaf3894f5ded167b653dacee685ccafd5d4f63d2d20bb4ee00000000

The output looks like this:

{
  "txid": "17d2ff338a8c01ceea7908704d744ff257c334f7acd465abb8874273c902f37e",
  "hash": "5f861105e3c415f60664bc6e5ad35c9b4c58d4ecf5eb080d2d7983d4bdc96ea8",
  "version": 2,
  "size": 247,
  "vsize": 166,
  "locktime": 0,
  "vin": [
    {
      "txid": "5cc2bc6b943aea4ae9445addd64064b11004d0d3b22a34c3864d0bd8bff21ca9",
      "vout": 0,
      "scriptSig": {
        "asm": "001404ab8b3104064d457b9d54be5d95cda85374a43f",
        "hex": "16001404ab8b3104064d457b9d54be5d95cda85374a43f"
      },
      "txinwitness": [
        "304402205124a08b4d7c4c692b7e6c63516c62937df4eddcd77c9dd2323408c67e6c253202202fd74bc94fea08e41df6917bff122b88a1be816321878e5dcdeb062c74131c1b01",
        "024c028276702a230caaf3894f5ded167b653dacee685ccafd5d4f63d2d20bb4ee"
      ],
      "sequence": 4294967295
    }
  ],
  "vout": [
    {
      "value": 0.99996680,
      "n": 0,
      "scriptPubKey": {
        "asm": "OP_HASH160 ad5c039e7f850fcf4b31781c7ec8e3653d28b628 OP_EQUAL",
        "hex": "a914ad5c039e7f850fcf4b31781c7ec8e3653d28b62887",
        "reqSigs": 1,
        "type": "scripthash",
        "addresses": [
          "2N93s7izzQqxwFPNPmpavm7TSo1BqDAwjze"
        ]
      }
    },
    {
      "value": 9.00000000,
      "n": 1,
      "scriptPubKey": {
        "asm": "OP_HASH160 051b3087fb0ed89184e7b7acf8e0ee5f6c229fe2 OP_EQUAL",
        "hex": "a914051b3087fb0ed89184e7b7acf8e0ee5f6c229fe287",
        "reqSigs": 1,
        "type": "scripthash",
        "addresses": [
          "2MsiDwQcPTnTsnADRcZszHr92ktN5uQDGR6"
        ]
      }
    }
  ]
}

Since this transaction has segwit inputs and segwit outputs, the vsize and size are different. The raw transaction size is 247 bytes, but the block weight is only 166. That’s not bad: the fees on this will be about two thirds of what they would be for a non-segwit transaction.

If you are familiar with how block weight is computed, you might be surprised to see that the vsize value is smaller than size. The normal block weight formula is calculated as 4*base + witness, where base is the number of bytes in the non-witness data, and witness is the number of witness bytes. For some reason the vsize output fields is actually computed the inverse way, using base + witness/4 (rounded up to the next integer). Either way, a smaller vsize value is better.

A Final, Minimal Example

I’m going to put this all together now in one final example. This will just show the minimal steps to send coins to an address and get segwit change. In this example we’ll send funds to n3F1SEw5KSmxts7bNuMSyMMxDazspA8A4S, and get segwit change back.

# Start a transaction sending 1 BTC to n3F1SEw5KSmxts7bNuMSyMMxDazspA8A4S.
$ bitcoin-cli -regtest createrawtransaction '[]' '{"n3F1SEw5KSmxts7bNuMSyMMxDazspA8A4S": 1}'
02000000000100e1f505000000001976a914ee4ebbe4babcb2c6f00ee7c69eb41310f22def1788ac00000000

# Generate a segwit change address.
$ bitcoin-cli -regtest addwitnessaddress $(bitcoin-cli -regtest getnewaddress)
2N4DTd2AwQGdUsM3H4ZUCZ7QC7ZCwj95Eae

# Fund the raw transaction.
$ bitcoin-cli -regtest fundrawtransaction 02000000000100e1f505000000001976a914ee4ebbe4babcb2c6f00ee7c69eb41310f22def1788ac00000000 '{"changeAddress": "2N4DTd2AwQGdUsM3H4ZUCZ7QC7ZCwj95Eae"}'
{
  "hex": "020000000605bca14ed8fab9d6618771c76c3fcbf17bde79ed8c751b4dab7fb30df2d6b7450000000000feffffff25aebed97244116b04108522ca803e8bac7bba26473f25d50263f12f5b245c150000000000feffffff879041670a2b9d6a307477d1959ca073263d582160799e73b001180601739cfc0000000000feffffffbb3df81d92adf04f748a4b9798f28c2c0f32829c8967ff4d4fd9ccfebd65de4d0000000000feffffffcfbc93bcf3419981399c304371e4a65a63e59c74996f628aca0c3c5194d2bfcd0000000000feffffffdd293edcbed67bd83afdb1ddf84e578f95b8d4c99df3b032a92c22448ef02c760000000000feffffff025d3a0f000000000017a9147853eeaa3d743731931cf86631b2b573b636f5c18700e1f505000000001976a914ee4ebbe4babcb2c6f00ee7c69eb41310f22def1788ac00000000",
  "changepos": 0,
  "fee": 0.00015200
}

# Sign the transaction.
$ bitcoin-cli -regtest signrawtransaction 020000000605bca14ed8fab9d6618771c76c3fcbf17bde79ed8c751b4dab7fb30df2d6b7450000000000feffffff25aebed97244116b04108522ca803e8bac7bba26473f25d50263f12f5b245c150000000000feffffff879041670a2b9d6a307477d1959ca073263d582160799e73b001180601739cfc0000000000feffffffbb3df81d92adf04f748a4b9798f28c2c0f32829c8967ff4d4fd9ccfebd65de4d0000000000feffffffcfbc93bcf3419981399c304371e4a65a63e59c74996f628aca0c3c5194d2bfcd0000000000feffffffdd293edcbed67bd83afdb1ddf84e578f95b8d4c99df3b032a92c22448ef02c760000000000feffffff025d3a0f000000000017a9147853eeaa3d743731931cf86631b2b573b636f5c18700e1f505000000001976a914ee4ebbe4babcb2c6f00ee7c69eb41310f22def1788ac00000000
{
  "hex": "020000000605bca14ed8fab9d6618771c76c3fcbf17bde79ed8c751b4dab7fb30df2d6b7450000000049483045022100984eda16524d315866d58291ed954a986981b50646339b98be9d8075c2b01f2f02207caa6ac1e955a4ebee7d2d3203f802c9c1b774539b05baef6ddad299298987d401feffffff25aebed97244116b04108522ca803e8bac7bba26473f25d50263f12f5b245c150000000048473044022059bc94aebac8d27180c754a906e2339952c8135c2b847cfa385e3a6afcdcc48402200828ff00342390a9c745d7ac6121b6f074999d93838ae5f24187f67854ac97d101feffffff879041670a2b9d6a307477d1959ca073263d582160799e73b001180601739cfc0000000048473044022039744f6d60b625c1fb28dc7c1b5a04095ecb648c70ea81e1fd430b79c389037202203458f69efdf9fb0e57bf7f5ee276ad9220cb617b259fa46c39fdfd058748161201feffffffbb3df81d92adf04f748a4b9798f28c2c0f32829c8967ff4d4fd9ccfebd65de4d000000004847304402207ef08607618dafc59a132cca32dd3e8bc400af86a679b038407e073844beccef022069c843dd092bd1a1795b5894de7e832b66aec8f5cc814041403212e3be89e8cd01feffffffcfbc93bcf3419981399c304371e4a65a63e59c74996f628aca0c3c5194d2bfcd0000000048473044022014de3b75e814a8988369775461d9c1bd8f6e91defef25d5672d65d56eaef97e002206b2cc42ac152fbff1dfaf363f62ddb0e8879f93d1648d147506978992eed63a001feffffffdd293edcbed67bd83afdb1ddf84e578f95b8d4c99df3b032a92c22448ef02c7600000000484730440220434db12ed651a8b90eed95c7b364df8531aabda2d9bd1379827c5cf96177dec10220501947bc8b2f6375b2366a149e218b267e598beac49f66c0ab7496a452b6c23201feffffff025d3a0f000000000017a9147853eeaa3d743731931cf86631b2b573b636f5c18700e1f505000000001976a914ee4ebbe4babcb2c6f00ee7c69eb41310f22def1788ac00000000",
  "complete": true
}

# Send the transaction to the network.
$ bitcoin-cli -regtest sendrawtransaction 020000000605bca14ed8fab9d6618771c76c3fcbf17bde79ed8c751b4dab7fb30df2d6b7450000000049483045022100984eda16524d315866d58291ed954a986981b50646339b98be9d8075c2b01f2f02207caa6ac1e955a4ebee7d2d3203f802c9c1b774539b05baef6ddad299298987d401feffffff25aebed97244116b04108522ca803e8bac7bba26473f25d50263f12f5b245c150000000048473044022059bc94aebac8d27180c754a906e2339952c8135c2b847cfa385e3a6afcdcc48402200828ff00342390a9c745d7ac6121b6f074999d93838ae5f24187f67854ac97d101feffffff879041670a2b9d6a307477d1959ca073263d582160799e73b001180601739cfc0000000048473044022039744f6d60b625c1fb28dc7c1b5a04095ecb648c70ea81e1fd430b79c389037202203458f69efdf9fb0e57bf7f5ee276ad9220cb617b259fa46c39fdfd058748161201feffffffbb3df81d92adf04f748a4b9798f28c2c0f32829c8967ff4d4fd9ccfebd65de4d000000004847304402207ef08607618dafc59a132cca32dd3e8bc400af86a679b038407e073844beccef022069c843dd092bd1a1795b5894de7e832b66aec8f5cc814041403212e3be89e8cd01feffffffcfbc93bcf3419981399c304371e4a65a63e59c74996f628aca0c3c5194d2bfcd0000000048473044022014de3b75e814a8988369775461d9c1bd8f6e91defef25d5672d65d56eaef97e002206b2cc42ac152fbff1dfaf363f62ddb0e8879f93d1648d147506978992eed63a001feffffffdd293edcbed67bd83afdb1ddf84e578f95b8d4c99df3b032a92c22448ef02c7600000000484730440220434db12ed651a8b90eed95c7b364df8531aabda2d9bd1379827c5cf96177dec10220501947bc8b2f6375b2366a149e218b267e598beac49f66c0ab7496a452b6c23201feffffff025d3a0f000000000017a9147853eeaa3d743731931cf86631b2b573b636f5c18700e1f505000000001976a914ee4ebbe4babcb2c6f00ee7c69eb41310f22def1788ac00000000
deade2df83a7b7908aceb5a11915b9539048810b3dec0ca424661d1e61e02317

That’s it! This is a new transaction that has segwit change.

Conclusion

What I’ve shown here is a little complicated. By my own admission, it’s too complicated for all but the most devoted hobbyists. However, it’s also not rocket science. As shown in the last example, it’s just five commands to generate a segwit change address and create, fund, sign, and send a raw transaction using that change address.

While this might be too complicated for a regular end user, I don’t think the process is too complicated for an exchange. I can’t really imagine how this could be more than a few days of work for even a fairly complex site. Especially due to the fact that exchanges will save money by enabling segwit, it defies logic that major exchanges would refuse to implement segwit deposit addresses and change addresses.