Dash Developer Examples

Find examples of how to build programs using Dash.

BETA: This documentation has not been extensively reviewed by Dash experts and so likely contains numerous errors. Please use the Issue and Edit links on the bottom left menu to help us improve. Click here to close this disclaimer. X

The following guide aims to provide examples to help you start building Dash-based applications. To make the best use of this document, you may want to install the current version of Dash Core, either from source or from a pre-compiled executable.

Once installed, you’ll have access to three programs: dashd, dash-qt, and dash-cli.

  • dash-qt provides a combination full Dash peer and wallet frontend. From the Help menu, you can access a console where you can enter the RPC commands used throughout this document.

  • dashd is more useful for programming: it provides a full peer which you can interact with through RPCs to port 9998 (or 19998 for testnet / 18332 for regtest).

  • dash-cli allows you to send RPC commands to dashd from the command line. For example, dash-cli help

Configuration file

All three programs get settings from dash.conf in the DashCore application directory:

  • Windows: %APPDATA%\DashCore\

  • OSX: $HOME/Library/Application Support/DashCore/

  • Linux: $HOME/.dashcore/

To use dashd and dash-cli, you will need to add a RPC password to your dash.conf file. Both programs will read from the same file if both run on the same system as the same user, so any long random password will work:

rpcpassword=change_this_to_a_long_random_password

You should also make the dash.conf file only readable to its owner. On Linux, Mac OSX, and other Unix-like systems, this can be accomplished by running the following command in the Dash Core application directory:

chmod 0600 dash.conf

For development, it’s safer and cheaper to use Dash’s test network (testnet), regression test mode (regtest), or a develper network (devnet) described below.

Questions about Dash use are best sent to the Dash forum and Discord channels. Errors or suggestions related to documentation on dash-docs.github.io can be submitted as an issue.

In the following documentation, some strings have been shortened or wrapped: “[…]” indicates extra data was removed, and lines ending in a single backslash “\” are continued below. If you hover your mouse over a paragraph, cross-reference links will be shown in blue. If you hover over a cross-reference link, a brief definition of the term will be displayed in a tooltip.

Testing Applications

Dash Core provides testing tools designed to let developers test their applications with reduced risks and limitations.

Testnet

When run with no arguments, all Dash Core programs default to Dash’s main network (mainnet). However, for development, it’s safer and cheaper to use Dash’s test network (testnet) where the duffs spent have no real-world value. Testnet also relaxes some restrictions (such as standard transaction checks) so you can test functions which might currently be disabled by default on mainnet.

To use testnet, use the argument -testnet with dash-cli, dashd or dash-qt or add testnet=1 to your dash.conf file as described earlier. To get free duffs for testing, check the faucets listed below. They are community supported and due to potentially frequent Testnet changes, one or more of them may be unavailable at a given time:

Testnet is a public resource provided for free by members of the community, so please don’t abuse it.

Regtest Mode

For situations where interaction with random peers and blocks is unnecessary or unwanted, Dash Core’s regression test mode (regtest mode) lets you instantly create a brand-new private block chain with the same basic rules as testnet—but one major difference: you choose when to create new blocks, so you have complete control over the environment.

Many developers consider regtest mode the preferred way to develop new applications. The following example will let you create a regtest environment after you first configure dashd.

> dashd -regtest -daemon
Dash Core server starting

Start dashd in regtest mode to create a private block chain.

## Dash Core
dash-cli -regtest generate 101

Generate 101 blocks using a special RPC which is only available in regtest mode. This takes less than a second on a generic PC. Because this is a new block chain using Dash’s default rules, the first blocks pay a block reward of 500 dash. Unlike mainnet, in regtest mode only the first 150 blocks pay a reward of 500 dash. However, a block must have 100 confirmations before that reward can be spent, so we generate 101 blocks to get access to the coinbase transaction from block #1.

dash-cli -regtest getbalance
500.00000000

Verify that we now have 500 dash available to spend.

You can now use Dash Core RPCs prefixed with dash-cli -regtest.

Regtest wallets and block chain state (chainstate) are saved in the regtest subdirectory of the Dash Core configuration directory. You can safely delete the regtest subdirectory and restart Dash Core to start a new regtest. (See the Developer Examples Introduction for default configuration directory locations on various operating systems. Always back up mainnet wallets before performing dangerous operations such as deleting.)

Devnet Mode

Developer networks (devnets) have some aspects of testnet and some aspects of regtest. Unlike testnet, multiple independent devnets can be created and coexist without interference. Each one is identified by a name which is hardened into a “devnet genesis” block, which is automatically positioned at height 1. Validation rules will ensure that a node from devnet=test1 never be able to accept blocks from devnet=test2. This is done by checking the expected devnet genesis block.

The genesis block of the devnet is the same as the one from regtest. This starts the devnet with a very low difficulty, allowing quick generation of a sufficient balance to create a masternode.

The devnet name is put into the sub-version of the version message. If a node connects to the wrong network, it will immediately be disconnected.

To use devnet, use the argument -devnet=<name> with dash-cli, dashdor dash-qt or add devnet=<name> to your dash.conf file as described earlier.

Devnets must be assigned both -port and -rpcport unless they are not listening (-listen=0). It is possible to run a devnet on a private (RFC1918) network by using the -allowprivatenet=1 argument.

Example devnet start command:

> dashd -devnet=mydevnet -rpcport=18998 -port=18999 -daemon
Dash Core server starting

You can now use Dash Core RPCs prefixed with dash-cli -devnet=<name>.

Devnet wallets and block chain state (chainstate) are saved in the devnet-<name> subdirectory of the Dash Core configuration directory. You can safely delete the devnet-<name> subdirectory and restart Dash Core to start a new devnet. (See the Developer Examples Introduction for default configuration directory locations on various operating systems. Always back up mainnet wallets before performing dangerous operations such as deleting.)

Eventually, there may be many public and/or private devnets that vary in size and function. Providing the correct devnet name and the seed node of the network will be all that is required to join.

An old devnet can be easily dropped and a new one started just by destroying all nodes and recreating them with a new devnet name. This works best in combination with an automated deployment using something like Ansible and Terraform. The Dash Cluster Ansible provides a way to do this (currently a work-in-progress at an early development stage).

Transactions

Transaction Tutorial

Creating transactions is something most Dash applications do. This section describes how to use Dash Core’s RPC interface to create transactions with various attributes.

Your applications may use something besides Dash Core to create transactions, but in any system, you will need to provide the same kinds of data to create transactions with the same attributes as those described below.

In order to use this tutorial, you will need to setup Dash Core and create a regression test mode environment with 500 DASH in your test wallet.

Simple Spending

Dash Core provides several RPCs which handle all the details of spending, including creating change outputs and paying appropriate fees. Even advanced users should use these RPCs whenever possible to decrease the chance that duffs will be lost by mistake.

> dash-cli -regtest getnewaddress
yLp6ZJueuigiF4s9E1Pv8tEunDPEsjyQfd

> NEW_ADDRESS=yLp6ZJueuigiF4s9E1Pv8tEunDPEsjyQfd

Get a new Dash address and save it in the shell variable $NEW_ADDRESS.

> dash-cli -regtest sendtoaddress $NEW_ADDRESS 10.00
c7e5ae1240fdd83bb94c94a93816ed2ab7bcb56ec3ff8a9725c5c1e0482684ea

Send 10 dash to the address using the sendtoaddress RPC. The returned hex string is the transaction identifier (txid).

The sendtoaddress RPC automatically selects an unspent transaction output (UTXO) from which to spend the duffs. In this case, it withdrew the duffs from our only available UTXO, the coinbase transaction for block #1 which matured with the creation of block #101. To spend a specific UTXO, you could use the sendfrom RPC instead.

> dash-cli -regtest listunspent
[
]

Use the listunspent RPC to display the UTXOs belonging to this wallet. The list is empty because it defaults to only showing confirmed UTXOs and we just spent our only confirmed UTXO.

> dash-cli -regtest listunspent 0
[  
   {  
      "txid":"c7e5ae1240fdd83bb94c94a93816ed2ab7bcb56ec3ff8a9725c5c1e0482684ea",
      "vout":0,
      "address":"yLp6ZJueuigiF4s9E1Pv8tEunDPEsjyQfd",
      "account":"",
      "scriptPubKey":"76a914056b1fe57914236149feb21dcbc6b86f4bdd9f4988ac",
      "amount":10.00000000,
      "confirmations":0,
      "ps_rounds":-2,
      "spendable":true,
      "solvable":true
   },
   {  
      "txid":"c7e5ae1240fdd83bb94c94a93816ed2ab7bcb56ec3ff8a9725c5c1e0482684ea",
      "vout":1,
      "address":"yeP6Tw2uW4nWAFWRytw8TyshErTq59dUkN",
      "scriptPubKey":"76a914c622e98a6ccf34d02620612f58f20a50061cf4b188ac",
      "amount":490.00000000,
      "confirmations":0,
      "ps_rounds":-2,
      "spendable":true,
      "solvable":true
   }
]

Re-running the listunspent RPC with the argument “0” to also display unconfirmed transactions shows that we have two UTXOs, both with the same txid. The first UTXO shown is a change output that sendtoaddress created using a new address from the key pool. The second UTXO shown is the spend to the address we provided. If we had spent those duffs to someone else, that second transaction would not be displayed in our list of UTXOs.

> dash-cli -regtest generate 1

> unset NEW_ADDRESS

Create a new block to confirm the transaction above (takes less than a second) and clear the shell variable.

Simple Spending Script

Shell script to run the previous example:

Simple Raw Transaction

The raw transaction RPCs allow users to create custom transactions and delay broadcasting those transactions. However, mistakes made in raw transactions may not be detected by Dash Core, and a number of raw transaction users have permanently lost large numbers of duffs, so please be careful using raw transactions on mainnet.

This subsection covers one of the simplest possible raw transactions.

> dash-cli -regtest listunspent
[
  {
    "txid": "f84ca4ad33ec7889d3c6ac670152137a3ee1603c4096230a10562976f700d130",
    "vout": 0,
    "address": "yRdk89fwSW1mUBxQo5fCmEfTva7b4wh2H5",
    "account": "",
    "scriptPubKey": "76a9143a4e8960f26c1fa82d937046959b656e4dd7966688ac",
    "amount": 10.00000000,
    "confirmations": 1,
    "ps_rounds": -2,
    "spendable": true,
    "solvable": true
  },
  {
    "txid": "f84ca4ad33ec7889d3c6ac670152137a3ee1603c4096230a10562976f700d130",
    "vout": 1,
    "address": "yavnyFMebbfX4F2VC25P18FW6LS66h2wqJ",
    "scriptPubKey": "76a914a0411dbed3eab4341d5c41496d61b4fa1b22037e88ac",
    "amount": 490.00000000,
    "confirmations": 1,
    "ps_rounds": -2,
    "spendable": true,
    "solvable": true
  },
  {
    "txid": "9036265a8f577421e556cd4f729752d73469953deea759de11efa9ba354936a8",
    "vout": 0,
    "address": "yWtgzKSckhedxtJ8NXhShWGjfBivkvBGgG",
    "scriptPubKey": "21023fff9c9dc9088c0aeba90d75413705091111311d761054de23ac\
                      dd217450869aac",
    "amount": 500.00000000,
    "confirmations": 101,
    "ps_rounds": -2,
    "spendable": true,
    "solvable": true
  }
]
> UTXO_TXID=9036265a8f577421e556cd4f729752d73469953deea759de11ef[...]
> UTXO_VOUT=0

Re-rerun listunspent. We now have three UTXOs: the two transactions we created before plus the coinbase transaction from block #2. We save the txid and output index number (vout) of that coinbase UTXO to shell variables.

> dash-cli -regtest getnewaddress
yfV9Wirf5RkYHgNDttjpBz8Wdi8BavLHcP

> NEW_ADDRESS=yfV9Wirf5RkYHgNDttjpBz8Wdi8BavLHcP

Get a new address to use in the raw transaction.

## Outputs - inputs = transaction fee, so always double-check your math!
> dash-cli -regtest createrawtransaction '''
    [
      {
        "txid": "'$UTXO_TXID'",
        "vout": '$UTXO_VOUT'
      }
    ]
    ''' '''
    {
      "'$NEW_ADDRESS'": 499.9999
    }'''
0100000001a8364935baa9ef11de59a7ee3d956934d75297724fcd56e5217457\
8f5a2636900000000000ffffffff01f04c3ba40b0000001976a914d240140859\
744755d73e5967081c3bedceffc5db88ac00000000

> RAW_TX=0100000001a8364935baa9ef11de59a7ee3d956934d75297724fcd5[...]

Using two arguments to the createrawtransaction RPC, we create a new raw format transaction. The first argument (a JSON array) references the txid of the coinbase transaction from block #2 and the index number (0) of the output from that transaction we want to spend. The second argument (a JSON object) creates the output with the address (public key hash) and number of dash we want to transfer. We save the resulting raw format transaction to a shell variable.

Warning icon Warning: createrawtransaction does not automatically create change outputs, so you can easily accidentally pay a large transaction fee. In this example, our input had 500.0000 dash and our output ($NEW_ADDRESS) is being paid 499.9999 dash, so the transaction will include a fee of 0.0001 dash. If we had paid $NEW_ADDRESS only 100 dash with no other changes to this transaction, the transaction fee would be a whopping 400 dash. See the Complex Raw Transaction subsection below for how to create a transaction with multiple outputs so you can send the change back to yourself.

> dash-cli -regtest decoderawtransaction $RAW_TX
{
  "txid": "7cbd2245ee5d824c00fc08b3bf2f694ad9a215d38d897fcf2df64a43c59bb97b",
  "size": 85,
  "version": 1,
  "locktime": 0,
  "vin": [
    {
      "txid": "9036265a8f577421e556cd4f729752d73469953deea759de11efa9ba354936a8",
      "vout": 0,
      "scriptSig": {
        "asm": "",
        "hex": ""
      },
      "sequence": 4294967295
    }
  ],
  "vout": [
    {
      "value": 499.99990000,
      "valueSat": 49999990000,
      "n": 0,
      "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 d240140859744755d73e5967081c3bedceffc5db\
                  OP_EQUALVERIFY OP_CHECKSIG",
        "hex": "76a914d240140859744755d73e5967081c3bedceffc5db88ac",
        "reqSigs": 1,
        "type": "pubkeyhash",
        "addresses": [
          "yfV9Wirf5RkYHgNDttjpBz8Wdi8BavLHcP"
        ]
      }
    }
  ]
}

Use the decoderawtransaction RPC to see exactly what the transaction we just created does.

> dash-cli -regtest signrawtransaction $RAW_TX
{
  "hex": "0100000001a8364935baa9ef11de59a7ee3d956934d75297724fcd\
          56e52174578f5a2636900000000049483045022100b4e5e9224afa\
          de8686bb22a957d1ec1587a66ee84943761b2d9061d5f751cd7602\
          203c88d4064641a413ce3d0824264d6d87908960487afe9a3a133e\
          7d67a22fd05101ffffffff01f04c3ba40b0000001976a914d24014\
          0859744755d73e5967081c3bedceffc5db88ac00000000",
  "complete": true
}
> SIGNED_RAW_TX=0100000001a8364935baa9ef11de59a7ee3d956934d75297[...]

Use the signrawtransaction RPC to sign the transaction created by createrawtransaction and save the returned “hex” raw format signed transaction to a shell variable.

Even though the transaction is now complete, the Dash Core node we’re connected to doesn’t know anything about the transaction, nor does any other part of the network. We’ve created a spend, but we haven’t actually spent anything because we could simply unset the $SIGNED_RAW_TX variable to eliminate the transaction.

> dash-cli -regtest sendrawtransaction $SIGNED_RAW_TX
fa0f4105b0a2b2706d65581c5e6411d3970253c7f231944fa2f978b4a3d9010d

Send the signed transaction to the connected node using the sendrawtransaction RPC. After accepting the transaction, the node would usually then broadcast it to other peers, but we’re not currently connected to other peers because we started in regtest mode.

> dash-cli -regtest generate 1

> unset UTXO_TXID UTXO_VOUT NEW_ADDRESS RAW_TX SIGNED_RAW_TX

Generate a block to confirm the transaction and clear our shell variables.

Complex Raw Transaction

In this example, we’ll create a transaction with two inputs and two outputs. We’ll sign each of the inputs separately, as might happen if the two inputs belonged to different people who agreed to create a transaction together (such as a CoinJoin transaction).

> dash-cli -regtest listunspent
[
  {
    "txid": "fa0f4105b0a2b2706d65581c5e6411d3970253c7f231944fa2f978b4a3d9010d",
    "vout": 0,
    "address": "yfV9Wirf5RkYHgNDttjpBz8Wdi8BavLHcP",
    "account": "",
    "scriptPubKey": "76a914d240140859744755d73e5967081c3bedceffc5db88ac",
    "amount": 499.99990000,
    "confirmations": 1,
    "ps_rounds": -2,
    "spendable": true,
    "solvable": true
  },
  {
    "txid": "f84ca4ad33ec7889d3c6ac670152137a3ee1603c4096230a10562976f700d130",
    "vout": 0,
    "address": "yRdk89fwSW1mUBxQo5fCmEfTva7b4wh2H5",
    "account": "",
    "scriptPubKey": "76a9143a4e8960f26c1fa82d937046959b656e4dd7966688ac",
    "amount": 10.00000000,
    "confirmations": 2,
    "ps_rounds": -2,
    "spendable": true,
    "solvable": true
  },
  {
    "txid": "f84ca4ad33ec7889d3c6ac670152137a3ee1603c4096230a10562976f700d130",
    "vout": 1,
    "address": "yavnyFMebbfX4F2VC25P18FW6LS66h2wqJ",
    "scriptPubKey": "76a914a0411dbed3eab4341d5c41496d61b4fa1b22037e88ac",
    "amount": 490.00000000,
    "confirmations": 2,
    "ps_rounds": -2,
    "spendable": true,
    "solvable": true
  },
  {
    "txid": "ea6d596da55a137846f8b08bfd414b4667ce456f9e3b3182e6f05810e8613d84",
    "vout": 0,
    "address": "yWtgzKSckhedxtJ8NXhShWGjfBivkvBGgG",
    "scriptPubKey": "21023fff9c9dc9088c0aeba90d75413705091111311d761054de23\
                      acdd217450869aac",
    "amount": 500.00000000,
    "confirmations": 101,
    "ps_rounds": -2,
    "spendable": true,
    "solvable": true
  }
]
> UTXO1_TXID=ea6d596da55a137846f8b08bfd414b4667ce456f9e3b3182e6f05810e8613d84
> UTXO1_VOUT=0
> UTXO1_ADDRESS=yWtgzKSckhedxtJ8NXhShWGjfBivkvBGgG

> UTXO2_TXID=f84ca4ad33ec7889d3c6ac670152137a3ee1603c4096230a10562976f700d130
> UTXO2_VOUT=0
> UTXO2_ADDRESS=yRdk89fwSW1mUBxQo5fCmEfTva7b4wh2H5

For our two inputs, we select two UTXOs by placing the txid and output index numbers (vouts) in shell variables. We also save the addresses corresponding to the public keys (hashed or unhashed) used in those transactions. We need the addresses so we can get the corresponding private keys from our wallet.

> dash-cli -regtest dumpprivkey $UTXO1_ADDRESS
cNL522MEQUnQxsZJo4ryPH8sPd2uVZaFKjKnZivo9DyVjpAGU7qP

> dash-cli -regtest dumpprivkey $UTXO2_ADDRESS
cPtZ9nagmjQ5bRKMuqoDz8xni6hRPfZ1zp3TSrqH3j3RyUThTYGN

> UTXO1_PRIVATE_KEY=cNL522MEQUnQxsZJo4ryPH8sPd2uVZaFKjKnZivo9DyVjpAGU7qP

> UTXO2_PRIVATE_KEY=cPtZ9nagmjQ5bRKMuqoDz8xni6hRPfZ1zp3TSrqH3j3RyUThTYGN

Use the dumpprivkey RPC to get the private keys corresponding to the public keys used in the two UTXOs out inputs we will be spending. We need the private keys so we can sign each of the inputs separately.

Warning icon Warning: Users should never manually manage private keys on mainnet. As dangerous as raw transactions are (see warnings above), making a mistake with a private key can be much worse—as in the case of a HD wallet cross-generational key compromise. These examples are to help you learn, not for you to emulate on mainnet.

> dash-cli -regtest getnewaddress
yhshGrdbh3rWt9EPaSi7xSGRFMvFdzTZ8n
> dash-cli -regtest getnewaddress
yesLaP5XFTaLZiWAo2zK8mFfUCtV8rRhKw

> NEW_ADDRESS1=yhshGrdbh3rWt9EPaSi7xSGRFMvFdzTZ8n
> NEW_ADDRESS2=yesLaP5XFTaLZiWAo2zK8mFfUCtV8rRhKw

For our two outputs, get two new addresses.

## Outputs - inputs = transaction fee, so always double-check your math!
> dash-cli -regtest createrawtransaction '''
    [
      {
        "txid": "'$UTXO1_TXID'",
        "vout": '$UTXO1_VOUT'
      },
      {
        "txid": "'$UTXO2_TXID'",
        "vout": '$UTXO2_VOUT'
      }
    ]
    ''' '''
    {
      "'$NEW_ADDRESS1'": 499.9999,
      "'$NEW_ADDRESS2'": 10
    }'''
0100000002843d61e81058f0e682313b9e6f45ce67464b41fd8bb0f84678135a\
a56d596dea0000000000ffffffff30d100f7762956100a2396403c60e13e7a13\
520167acc6d38978ec33ada44cf80000000000ffffffff02f04c3ba40b000000\
1976a914ec73fe6129b249617bb5f20c8760708055fb6fdb88ac00ca9a3b0000\
00001976a914cb7a56b046479f8c247875d672d3e1aed18c33f488ac00000000

> RAW_TX=0100000002843d61e81058f0e682313b9e6f45ce67464b41fd8bb0f[...]

Create the raw transaction using createrawtransaction much the same as before, except now we have two inputs and two outputs.

> dash-cli -regtest signrawtransaction $RAW_TX '[]' '''
    [
      "'$UTXO1_PRIVATE_KEY'"
    ]'''
{
  "hex": "0100000002843d61e81058f0e682313b9e6f45ce67464b41fd8bb0\
  f84678135aa56d596dea00000000494830450221009f7f356c0cc2d3337b5f\
  76dfc6de9f9be7c8c5ac2074cbeeba4815b90329602002207790f23361480e\
  2a5a2d1fa6e293ccd5cd01279ad301176f091b84d6dd8e8f6501ffffffff30\
  d100f7762956100a2396403c60e13e7a13520167acc6d38978ec33ada44cf8\
  0000000000ffffffff02f04c3ba40b0000001976a914ec73fe6129b249617b\
  b5f20c8760708055fb6fdb88ac00ca9a3b000000001976a914cb7a56b04647\
  9f8c247875d672d3e1aed18c33f488ac00000000",
  "complete": false,
  "errors": [
    {
      "txid": "f84ca4ad33ec7889d3c6ac670152137a3ee1603c4096230a1\
                0562976f700d130",
      "vout": 0,
      "scriptSig": "",
      "sequence": 4294967295,
      "error": "Operation not valid with the current stack size"
    }
  ]
}
> PARTLY_SIGNED_RAW_TX=0100000002843d61e81058f0e682313b9e6f45ce6[...]

Signing the raw transaction with signrawtransaction gets more complicated as we now have three arguments:

  1. The unsigned raw transaction.

  2. An empty array. We don’t do anything with this argument in this operation, but some valid JSON must be provided to get access to the later positional arguments.

  3. The private key we want to use to sign one of the inputs.

The result is a raw transaction with only one input signed; the fact that the transaction isn’t fully signed is indicated by value of the complete JSON field. We save the incomplete, partly-signed raw transaction hex to a shell variable.

> dash-cli -regtest signrawtransaction $PARTLY_SIGNED_RAW_TX '[]' '''
    [
      "'$UTXO2_PRIVATE_KEY'"
    ]'''
{
  "hex": "0100000002843d61e81058f0e682313b9e6f45ce67464b41fd8bb0\
  f84678135aa56d596dea00000000494830450221009f7f356c0cc2d3337b5f\
  76dfc6de9f9be7c8c5ac2074cbeeba4815b90329602002207790f23361480e\
  2a5a2d1fa6e293ccd5cd01279ad301176f091b84d6dd8e8f6501ffffffff30\
  d100f7762956100a2396403c60e13e7a13520167acc6d38978ec33ada44cf8\
  000000006a47304402207867e88e3fe2c926df29376d77eba81daf9f4a5573\
  44d4f02e9c7dcee96a51e4022076274c2365dc069e7ef797c95c75ab6e01ca\
  3757342f3e6f21a3d9d01086efb7012102ff9005f79aa4c22ac48fa93d9b7f\
  40f321db1c13cd70cf08bdab3e23c8d19620ffffffff02f04c3ba40b000000\
  1976a914ec73fe6129b249617bb5f20c8760708055fb6fdb88ac00ca9a3b00\
  0000001976a914cb7a56b046479f8c247875d672d3e1aed18c33f488ac0000\
  0000",
  "complete": true
}

To sign the second input, we repeat the process we used to sign the first input using the second private key. Now that both inputs are signed, the complete result is true.

> unset PARTLY_SIGNED_RAW_TX RAW_TX NEW_ADDRESS1 [...]

Clean up the shell variables used. Unlike previous subsections, we’re not going to send this transaction to the connected node with sendrawtransaction. This will allow us to illustrate in the Offline Signing subsection below how to spend a transaction which is not yet in the block chain or memory pool.

Offline Signing

We will now spend the transaction created in the Complex Raw Transaction subsection above without sending it to the local node first. This is the same basic process used by wallet programs for offline signing—which generally means signing a transaction without access to the current UTXO set.

Offline signing is safe. However, in this example we will also be spending an output which is not part of the block chain because the transaction containing it has never been broadcast. That can be unsafe:

Warning icon Warning: Transactions which spend outputs from unconfirmed transactions are vulnerable to transaction malleability. Be sure to read about transaction malleability and adopt good practices before spending unconfirmed transactions on mainnet.

> OLD_SIGNED_RAW_TX=0100000002843d61e81058f0e682313b9e6f45ce67464b41fd8bb0\
      f84678135aa56d596dea00000000494830450221009f7f356c0cc2d3337b5f76dfc6\
      de9f9be7c8c5ac2074cbeeba4815b90329602002207790f23361480e2a5a2d1fa6e2\
      93ccd5cd01279ad301176f091b84d6dd8e8f6501ffffffff30d100f7762956100a23\
      96403c60e13e7a13520167acc6d38978ec33ada44cf8000000006a47304402207867\
      e88e3fe2c926df29376d77eba81daf9f4a557344d4f02e9c7dcee96a51e402207627\
      4c2365dc069e7ef797c95c75ab6e01ca3757342f3e6f21a3d9d01086efb7012102ff\
      9005f79aa4c22ac48fa93d9b7f40f321db1c13cd70cf08bdab3e23c8d19620ffffff\
      ff02f04c3ba40b0000001976a914ec73fe6129b249617bb5f20c8760708055fb6fdb\
      88ac00ca9a3b000000001976a914cb7a56b046479f8c247875d672d3e1aed18c33f4\
      88ac00000000

Put the previously signed (but not sent) transaction into a shell variable.

> dash-cli -regtest decoderawtransaction $OLD_SIGNED_RAW_TX
{
  "txid": "5efd61cf24c9644d79646627c4d1e192e9b2a760a5c720db8f4a9f76cb781077",
  "size": 339,
  "version": 1,
  "locktime": 0,
  "vin": [
    {
      "txid": "ea6d596da55a137846f8b08bfd414b4667ce456f9e3b3182e6f05810e86\
                13d84",
      "vout": 0,
      "scriptSig": {
        "asm": "30450221009f7f356c0cc2d3337b5f76dfc6de9f9be7c8c5ac2074cbee\
                ba4815b90329602002207790f23361480e2a5a2d1fa6e293ccd5cd0127\
                9ad301176f091b84d6dd8e8f65[ALL]",
        "hex": "4830450221009f7f356c0cc2d3337b5f76dfc6de9f9be7c8c5ac2074cb\
                eeba4815b90329602002207790f23361480e2a5a2d1fa6e293ccd5cd01\
                279ad301176f091b84d6dd8e8f6501"
      },
      "sequence": 4294967295
    },
    {
      "txid": "f84ca4ad33ec7889d3c6ac670152137a3ee1603c4096230a10562976f70\
                0d130",
      "vout": 0,
      "scriptSig": {
        "asm": "304402207867e88e3fe2c926df29376d77eba81daf9f4a557344d4f02e\
                9c7dcee96a51e4022076274c2365dc069e7ef797c95c75ab6e01ca3757\
                342f3e6f21a3d9d01086efb7[ALL] 02ff9005f79aa4c22ac48fa93d9b\
                7f40f321db1c13cd70cf08bdab3e23c8d19620",
        "hex": "47304402207867e88e3fe2c926df29376d77eba81daf9f4a557344d4f0\
                2e9c7dcee96a51e4022076274c2365dc069e7ef797c95c75ab6e01ca37\
                57342f3e6f21a3d9d01086efb7012102ff9005f79aa4c22ac48fa93d9b\
                7f40f321db1c13cd70cf08bdab3e23c8d19620"
      },
      "sequence": 4294967295
    }
  ],
  "vout": [
    {
      "value": 499.99990000,
      "valueSat": 49999990000,
      "n": 0,
      "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 ec73fe6129b249617bb5f20c8760708055fb6fdb\
                OP_EQUALVERIFY OP_CHECKSIG",
        "hex": "76a914ec73fe6129b249617bb5f20c8760708055fb6fdb88ac",
        "reqSigs": 1,
        "type": "pubkeyhash",
        "addresses": [
          "yhshGrdbh3rWt9EPaSi7xSGRFMvFdzTZ8n"
        ]
      }
    },
    {
      "value": 10.00000000,
      "valueSat": 1000000000,
      "n": 1,
      "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 cb7a56b046479f8c247875d672d3e1aed18c33f4\
                OP_EQUALVERIFY OP_CHECKSIG",
        "hex": "76a914cb7a56b046479f8c247875d672d3e1aed18c33f488ac",
        "reqSigs": 1,
        "type": "pubkeyhash",
        "addresses": [
          "yesLaP5XFTaLZiWAo2zK8mFfUCtV8rRhKw"
        ]
      }
    }
  ]
}
> UTXO_TXID=5efd61cf24c9644d79646627c4d1e192e9b2a760a5c720db8f4a9f76cb781077
> UTXO_VOUT=1
> UTXO_OUTPUT_SCRIPT=76a914cb7a56b046479f8c247875d672d3e1aed18c33f488ac

Decode the signed raw transaction so we can get its txid. Also, choose a specific one of its UTXOs to spend and save that UTXO’s output index number (vout) and hex pubkey script (scriptPubKey) into shell variables.

> dash-cli -regtest getnewaddress
yfijhy7gYY34J2U77xFKdMwfA8k5mVnSRa

> NEW_ADDRESS=yfijhy7gYY34J2U77xFKdMwfA8k5mVnSRa

Get a new address to spend the duffs to.

## Outputs - inputs = transaction fee, so always double-check your math!
> dash-cli -regtest createrawtransaction '''
    [
      {
        "txid": "'$UTXO_TXID'",
        "vout": '$UTXO_VOUT'
      }
    ]
    ''' '''
    {
      "'$NEW_ADDRESS'": 9.9999
    }'''
0100000001771078cb769f4a8fdb20c7a560a7b2e992e1d1c4276664794d64c9\
24cf61fd5e0100000000ffffffff01f0a29a3b000000001976a914d4d2078580\
a9eea0ca9368d1c99c097279b8081f88ac00000000

> RAW_TX=0100000001771078cb769f4a8fdb20c7a560a7b2e992e1d1c427666[...]

Create the raw transaction the same way we’ve done in the previous subsections.

> dash-cli -regtest signrawtransaction $RAW_TX
{
  "hex": "0100000001771078cb769f4a8fdb20c7a560a7b2e992e1d1c4276664794d64c9\
          24cf61fd5e0100000000ffffffff01f0a29a3b000000001976a914d4d2078580\
          a9eea0ca9368d1c99c097279b8081f88ac00000000",
  "complete": false,
  "errors": [
    {
      "txid": "5efd61cf24c9644d79646627c4d1e192e9b2a760a5c720db8f4a9f76cb7\
                81077",
      "vout": 1,
      "scriptSig": "",
      "sequence": 4294967295,
      "error": "Input not found or already spent"
    }
  ]
}

Attempt to sign the raw transaction without any special arguments, the way we successfully signed the the raw transaction in the Simple Raw Transaction subsection. If you’ve read the Transaction section of the guide, you may know why the call fails and leaves the raw transaction hex unchanged.

Old Transaction Data Required To Be Signed

As illustrated above, the data that gets signed includes the txid and vout from the previous transaction. That information is included in the createrawtransaction raw transaction. But the data that gets signed also includes the pubkey script from the previous transaction, even though it doesn’t appear in either the unsigned or signed transaction.

In the other raw transaction subsections above, the previous output was part of the UTXO set known to the wallet, so the wallet was able to use the txid and output index number to find the previous pubkey script and insert it automatically.

In this case, you’re spending an output which is unknown to the wallet, so it can’t automatically insert the previous pubkey script.

> dash-cli -regtest signrawtransaction $RAW_TX '''
    [
      {
        "txid": "'$UTXO_TXID'",
        "vout": '$UTXO_VOUT',
        "scriptPubKey": "'$UTXO_OUTPUT_SCRIPT'"
      }
    ]'''
{
  "hex": "0100000001771078cb769f4a8fdb20c7a560a7b2e992e1d1c4276664794d64c9\
          24cf61fd5e010000006a47304402204ee3aae064dccedb511a84fcade3f35f2d\
          95119283e2e9f23659d91ce799cb6d02203a4cecbd7c154de8394b9505814f1e\
          c842e890980e7c4c20ed182f09a71d65f3012103b0b12fb25b6382b0680ce4b0\
          379bc201c4cbb391d3c0e171181f24c9a5df1468ffffffff01f0a29a3b000000\
          001976a914d4d2078580a9eea0ca9368d1c99c097279b8081f88ac00000000",
  "complete": true
}
> SIGNED_RAW_TX=0100000001771078cb769f4a8fdb20c7a560a7b2e992e1d1[...]

Successfully sign the transaction by providing the previous pubkey script and other required input data.

This specific operation is typically what offline signing wallets do. The online wallet creates the raw transaction and gets the previous pubkey scripts for all the inputs. The user brings this information to the offline wallet. After displaying the transaction details to the user, the offline wallet signs the transaction as we did above. The user takes the signed transaction back to the online wallet, which broadcasts it.

> dash-cli -regtest sendrawtransaction $SIGNED_RAW_TX
error code: -25
error message:
Missing inputs

error: {"code":-22,"message":"TX rejected"}

Attempt to broadcast the second transaction before we’ve broadcast the first transaction. The node rejects this attempt because the second transaction spends an output which is not a UTXO the node knows about.

> dash-cli -regtest sendrawtransaction $OLD_SIGNED_RAW_TX
5efd61cf24c9644d79646627c4d1e192e9b2a760a5c720db8f4a9f76cb781077
> dash-cli -regtest sendrawtransaction $SIGNED_RAW_TX
f89deefb927fbd03c5acab194de2ba8f98ab160b9c4b3f57bde63073c4b5f060

Broadcast the first transaction, which succeeds, and then broadcast the second transaction—which also now succeeds because the node now sees the UTXO.

> dash-cli -regtest getrawmempool
[
  "f89deefb927fbd03c5acab194de2ba8f98ab160b9c4b3f57bde63073c4b5f060",
  "5efd61cf24c9644d79646627c4d1e192e9b2a760a5c720db8f4a9f76cb781077"
]

We have once again not generated an additional block, so the transactions above have not yet become part of the regtest block chain. However, they are part of the local node’s memory pool.

> unset OLD_SIGNED_RAW_TX SIGNED_RAW_TX RAW_TX [...]

Remove old shell variables.

P2SH Multisig

In this subsection, we will create a P2SH multisig address, spend duffs to it, and then spend those duffs from it to another address.

Creating a multisig address is easy. Multisig outputs have two parameters, the minimum number of signatures required (m) and the number of public keys to use to validate those signatures. This is called m-of-n, and in this case we’ll be using 2-of-3.

    > dash-cli -regtest getnewaddress
    yYtWtpW7akCc2a5En8NsXeTGENyYbNgv9q
    > dash-cli -regtest getnewaddress
    yarm2x9eDFd9dKCycyPigwwj1vfJcYFxsH
    > dash-cli -regtest getnewaddress
    yLknHbtnjJRVWQr78aTfCPfNB42jfNkDWK

    > NEW_ADDRESS1=yYtWtpW7akCc2a5En8NsXeTGENyYbNgv9q
    > NEW_ADDRESS2=yarm2x9eDFd9dKCycyPigwwj1vfJcYFxsH
    > NEW_ADDRESS3=yLknHbtnjJRVWQr78aTfCPfNB42jfNkDWK

Generate three new P2PKH addresses. P2PKH addresses cannot be used with the multisig redeem script created below. (Hashing each public key is unnecessary anyway—all the public keys are protected by a hash when the redeem script is hashed.) However, Dash Core uses addresses as a way to reference the underlying full (unhashed) public keys it knows about, so we get the three new addresses above in order to use their public keys.

Recall from the Guide that the hashed public keys used in addresses obfuscate the full public key, so you cannot give an address to another person or device as part of creating a typical multisig output or P2SH multisig redeem script. You must give them a full public key.

> dash-cli -regtest validateaddress $NEW_ADDRESS3
{
  "isvalid": true,
  "address": "yLknHbtnjJRVWQr78aTfCPfNB42jfNkDWK",
  "scriptPubKey": "76a91404caa000366b99780f8e606ccc818883ca7f48f888ac",
  "ismine": true,
  "iswatchonly": false,
  "isscript": false,
  "pubkey": "038007ef6fd812d73da054271b68a42dae06672cff2a30b2814935537e593\
              0ebf6",
  "iscompressed": true,
  "account": ""
}
> NEW_ADDRESS3_PUBLIC_KEY=038007ef6fd812d73da054271b68a42dae0667[...]

Use the validateaddress RPC to display the full (unhashed) public key for one of the addresses. This is the information which will actually be included in the multisig redeem script. This is also the information you would give another person or device as part of creating a multisig output or P2SH multisig redeem script.

We save the address returned to a shell variable.

> dash-cli -regtest createmultisig 2 '''
    [
      "'$NEW_ADDRESS1'",
      "'$NEW_ADDRESS2'",
      "'$NEW_ADDRESS3_PUBLIC_KEY'"
    ]'''
{
  "address": "8meEZF54K7GxhHhdLCCeNwFQjHENv4CK86",
  "redeemScript": "522103fa8866cccae3c975a72884443a351801a0ea9721cbe721558\
                  6ddd6fab5f39f262103b2259f42a241f4870e794521594f2af7aadf0\
                  e4c580a43582e58630e4618634621038007ef6fd812d73da054271b6\
                  8a42dae06672cff2a30b2814935537e5930ebf653ae"
}
> P2SH_ADDRESS=8meEZF54K7GxhHhdLCCeNwFQjHENv4CK86
> P2SH_REDEEM_SCRIPT=522103fa8866cccae3c975a72884443a351801a0ea9[...]

Use the createmultisig RPC with two arguments, the number (n) of signatures required and a list of addresses or public keys. Because P2PKH addresses can’t be used in the multisig redeem script created by this RPC, the only addresses which can be provided are those belonging to a public key in the wallet. In this case, we provide two addresses and one public key—all of which will be converted to public keys in the redeem script.

The P2SH address is returned along with the redeem script which must be provided when we spend duffs sent to the P2SH address.

Warning icon Warning: You must not lose the redeem script, especially if you don’t have a record of which public keys you used to create the P2SH multisig address. You need the redeem script to spend any dash sent to the P2SH address. If you lose the redeem script, you can recreate it by running the same command above, with the public keys listed in the same order. However, if you lose both the redeem script and even one of the public keys, you will never be able to spend duffs sent to that P2SH address.

Neither the address nor the redeem script are stored in the wallet when you use createmultisig. To store them in the wallet, use the addmultisigaddress RPC instead. If you add an address to the wallet, you should also make a new backup.

> dash-cli -regtest sendtoaddress $P2SH_ADDRESS 10.00
ddb2a2eb2402a9ae61d7db93a9a48c0747859d899e704b10f5b72145779f9c52

> UTXO_TXID=ddb2a2eb2402a9ae61d7db93a9a48c0747859d899e704b10f5b7[...]

Paying the P2SH multisig address with Dash Core is as simple as paying a more common P2PKH address. Here we use the same command (but different variable) we used in the Simple Spending subsection. As before, this command automatically selects an UTXO, creates a change output to a new one of our P2PKH addresses if necessary, and pays a transaction fee if necessary.

We save that txid to a shell variable as the txid of the UTXO we plan to spend next.

> dash-cli -regtest getrawtransaction $UTXO_TXID 1
{
  "hex": "010000000130d100f7762956100a2396403c60e13e7a13520167acc6d38978ec\
          33ada44cf8010000006b48304502210084effe3132550e6ba43a7f4cc54ad30d\
          001c0dbc3ea66d638e5f3d6039a28c2b022044c8cd89cf455b8650fe259306eb\
          2a30b0112969717e469a722bca0263e0975d01210324c2226564b19f0948306b\
          b7160a735c28001bbd046cd46059df9f8434f41254feffffff0200ca9a3b0000\
          000017a9144f334f26e350c8903c92ff25b733670902cfad5a8700e0052d0b00\
          00001976a91479165c2155b8fec5c702ec7f251d0982f27b402988ac67000000",
  "txid": "ddb2a2eb2402a9ae61d7db93a9a48c0747859d899e704b10f5b72145779f9c52",
  "size": 224,
  "version": 1,
  "locktime": 103,
  "vin": [
    {
      "txid": "f84ca4ad33ec7889d3c6ac670152137a3ee1603c4096230a10562976f70\
                0d130",
      "vout": 1,
      "scriptSig": {
        "asm": "304502210084effe3132550e6ba43a7f4cc54ad30d001c0dbc3ea66d63\
                8e5f3d6039a28c2b022044c8cd89cf455b8650fe259306eb2a30b01129\
                69717e469a722bca0263e0975d[ALL] 0324c2226564b19f0948306bb7\
                160a735c28001bbd046cd46059df9f8434f41254",
        "hex": "48304502210084effe3132550e6ba43a7f4cc54ad30d001c0dbc3ea66d\
                638e5f3d6039a28c2b022044c8cd89cf455b8650fe259306eb2a30b011\
                2969717e469a722bca0263e0975d01210324c2226564b19f0948306bb7\
                160a735c28001bbd046cd46059df9f8434f41254"
      },
      "sequence": 4294967294
    }
  ],
  "vout": [
    {
      "value": 10.00000000,
      "valueSat": 1000000000,
      "n": 0,
      "scriptPubKey": {
        "asm": "OP_HASH160 4f334f26e350c8903c92ff25b733670902cfad5a OP_EQUAL",
        "hex": "a9144f334f26e350c8903c92ff25b733670902cfad5a87",
        "reqSigs": 1,
        "type": "scripthash",
        "addresses": [
          "8meEZF54K7GxhHhdLCCeNwFQjHENv4CK86"
        ]
      }
    },
    {
      "value": 480.00000000,
      "valueSat": 48000000000,
      "n": 1,
      "scriptPubKey": {
        "asm": "OP_DUP OP_HASH160 79165c2155b8fec5c702ec7f251d0982f27b4029\
                OP_EQUALVERIFY OP_CHECKSIG",
        "hex": "76a91479165c2155b8fec5c702ec7f251d0982f27b402988ac",
        "reqSigs": 1,
        "type": "pubkeyhash",
        "addresses": [
          "yXMhQ1L5q3PcnJgEhyAFztQPPRaEr8Mh8s"
        ]
      }
    }
  ]
}
> UTXO_VOUT=0
> UTXO_OUTPUT_SCRIPT=a9144f334f26e350c8903c92ff25b733670902cfad5a87

We use the getrawtransaction RPC with the optional second argument (true) to get the decoded transaction we just created with sendtoaddress. We choose one of the outputs to be our UTXO and get its output index number (vout) and pubkey script (scriptPubKey).

> dash-cli -regtest getnewaddress
yZSxAakpoWGG3vcsvpk9qNtsYREhump4Cr

> NEW_ADDRESS4=yZSxAakpoWGG3vcsvpk9qNtsYREhump4Cr

We generate a new P2PKH address to use in the output we’re about to create.

## Outputs - inputs = transaction fee, so always double-check your math!
> dash-cli -regtest createrawtransaction '''
    [
      {
        "txid": "'$UTXO_TXID'",
        "vout": '$UTXO_VOUT'
      }
   ]
   ''' '''
   {
     "'$NEW_ADDRESS4'": 9.998
   }'''

0100000001529c9f774521b7f5104b709e899d8547078ca4a993dbd761aea902\
24eba2b2dd0000000000ffffffff01c0bc973b000000001976a914900504f96c\
55d6ebe1c33581ba9430ca05b12a1488ac00000000

010000000175e1769813db8418fea17576694af1ff31cb2b512b7333e6eb42f0\
30d0d778720000000000ffffffff01c0bc973b000000001976a914b6f64f5bf3\
e38f25ead28817df7929c06fe847ee88ac00000000

> RAW_TX=0100000001529c9f774521b7f5104b709e899d8547078ca4a993dbd[...]

We generate the raw transaction the same way we did in the Simple Raw Transaction subsection.

> dash-cli -regtest dumpprivkey $NEW_ADDRESS1
cThhxbQUtBDzHZbZrW6XAR4XkXfaQf4Abo7BQaTK2zVp7sVrHdmv
> dash-cli -regtest dumpprivkey $NEW_ADDRESS3
cUbYymPeHhRszTn64Xg7dzYKez8YC83M39ZTPJDiBDu8dRD3EjzF

> NEW_ADDRESS1_PRIVATE_KEY=cThhxbQUtBDzHZbZrW6XAR4XkXfaQf4Abo7BQ[...]
> NEW_ADDRESS3_PRIVATE_KEY=cUbYymPeHhRszTn64Xg7dzYKez8YC83M39ZTP[...]

We get the private keys for two of the public keys we used to create the transaction, the same way we got private keys in the Complex Raw Transaction subsection. Recall that we created a 2-of-3 multisig pubkey script, so signatures from two private keys are needed.

Warning icon Reminder: Users should never manually manage private keys on mainnet. See the warning in the complex raw transaction section.

> dash-cli -regtest signrawtransaction $RAW_TX '''
    [
      {
        "txid": "'$UTXO_TXID'",
        "vout": '$UTXO_VOUT',
        "scriptPubKey": "'$UTXO_OUTPUT_SCRIPT'",
        "redeemScript": "'$P2SH_REDEEM_SCRIPT'"
      }
    ]
    ''' '''
    [
      "'$NEW_ADDRESS1_PRIVATE_KEY'"
    ]'''
{
  "hex": "0100000001529c9f774521b7f5104b709e899d8547078ca4a993dbd761aea902\
          24eba2b2dd00000000b40047304402201cc50eac6d2db04dabd8ccd68b3116c0\
          a8d37e7e41335e0d0ab441a5aa08cdcd02204011d184dca2489758c05e01556f\
          f2ff9c48c39ff434fdfb1d9e0284fbde7701014c69522103fa8866cccae3c975\
          a72884443a351801a0ea9721cbe7215586ddd6fab5f39f262103b2259f42a241\
          f4870e794521594f2af7aadf0e4c580a43582e58630e4618634621038007ef6f\
          d812d73da054271b68a42dae06672cff2a30b2814935537e5930ebf653aeffff\
          ffff01c0bc973b000000001976a914900504f96c55d6ebe1c33581ba9430ca05\
          b12a1488ac00000000",
  "complete": false,
  "errors": [
    {
      "txid": "ddb2a2eb2402a9ae61d7db93a9a48c0747859d899e704b10f5b72145779\
                f9c52",
      "vout": 0,
      "scriptSig": "0047304402201cc50eac6d2db04dabd8ccd68b3116c0a8d37e7e41\
                    335e0d0ab441a5aa08cdcd02204011d184dca2489758c05e01556f\
                    f2ff9c48c39ff434fdfb1d9e0284fbde7701014c69522103fa8866\
                    cccae3c975a72884443a351801a0ea9721cbe7215586ddd6fab5f3\
                    9f262103b2259f42a241f4870e794521594f2af7aadf0e4c580a43\
                    582e58630e4618634621038007ef6fd812d73da054271b68a42dae\
                    06672cff2a30b2814935537e5930ebf653ae",
      "sequence": 4294967295,
      "error": "Operation not valid with the current stack size"
    }
  ]
}
> PARTLY_SIGNED_RAW_TX=010000000175e1769813db8418fea17576694af1f[...]

We make the first signature. The input argument (JSON object) takes the additional redeem script parameter so that it can append the redeem script to the signature script after the two signatures.

> dash-cli -regtest signrawtransaction $PARTLY_SIGNED_RAW_TX '''
    [
      {
        "txid": "'$UTXO_TXID'",
        "vout": '$UTXO_VOUT',
        "scriptPubKey": "'$UTXO_OUTPUT_SCRIPT'",
        "redeemScript": "'$P2SH_REDEEM_SCRIPT'"
      }
    ]
    ''' '''
    [
      "'$NEW_ADDRESS3_PRIVATE_KEY'"
    ]'''
{
  "hex": "0100000001529c9f774521b7f5104b709e899d8547078ca4a993dbd761aea902\
          24eba2b2dd00000000fdfd000047304402201cc50eac6d2db04dabd8ccd68b31\
          16c0a8d37e7e41335e0d0ab441a5aa08cdcd02204011d184dca2489758c05e01\
          556ff2ff9c48c39ff434fdfb1d9e0284fbde770101483045022100e0e1f95f1a\
          b85814ee0920d5bd28c6831086e838af4bec344fd8654a0b58525f022075989f\
          d3a677e1522aa85d45c41720aec9e7c127acadb6c14338c3b1a768ab28014c69\
          522103fa8866cccae3c975a72884443a351801a0ea9721cbe7215586ddd6fab5\
          f39f262103b2259f42a241f4870e794521594f2af7aadf0e4c580a43582e5863\
          0e4618634621038007ef6fd812d73da054271b68a42dae06672cff2a30b28149\
          35537e5930ebf653aeffffffff01c0bc973b000000001976a914900504f96c55\
          d6ebe1c33581ba9430ca05b12a1488ac00000000",
  "complete": true
}
> SIGNED_RAW_TX=0100000001529c9f774521b7f5104b709e899d8547078ca4[...]

The signrawtransaction call used here is nearly identical to the one used above. The only difference is the private key used. Now that the two required signatures have been provided, the transaction is marked as complete.

> dash-cli -regtest sendrawtransaction $SIGNED_RAW_TX
483061b32894aacf6c4050291252a480c2a4c869eb85bd45082fb87d6b175ae8

We send the transaction spending the P2SH multisig output to the local node, which accepts it.

P2P Network

Creating A Bloom Filter

In this section, we’ll use variable names that correspond to the field names in the filterload message documentation. Each code block precedes the paragraph describing it.

#!/usr/bin/env python

BYTES_MAX = 36000
FUNCS_MAX = 50

nFlags = 0

We start by setting some maximum values defined in BIP37: the maximum number of bytes allowed in a filter and the maximum number of hash functions used to hash each piece of data. We also set nFlags to zero, indicating we don’t want the remote node to update the filter for us. (We won’t use nFlags again in the sample program, but real programs will need to use it.)

n = 1
p = 0.0001

We define the number (n) of elements we plan to insert into the filter and the false positive rate (p) we want to help protect our privacy. For this example, we will set n to one element and p to a rate of 1-in-10,000 to produce a small and precise filter for illustration purposes. In actual use, your filters will probably be much larger.

from math import log
nFilterBytes = int(min((-1 / log(2)**2 * n * log(p)) / 8, BYTES_MAX))
nHashFuncs = int(min(nFilterBytes * 8 / n * log(2), FUNCS_MAX))

from bitarray import bitarray  # from pypi.python.org/pypi/bitarray
vData = nFilterBytes * 8 * bitarray('0', endian="little")

Using the formula described in BIP37, we calculate the ideal size of the filter (in bytes) and the ideal number of hash functions to use. Both are truncated down to the nearest whole number and both are also constrained to the maximum values we defined earlier. The results of this particular fixed computation are 2 filter bytes and 11 hash functions. We then use nFilterBytes to create a little-endian bit array of the appropriate size.

nTweak = 0

We also should choose a value for nTweak. In this case, we’ll simply use zero.

import pyhash  # from https://github.com/flier/pyfasthash
murmur3 = pyhash.murmur3_32()

def bloom_hash(nHashNum, data):
    seed = (nHashNum * 0xfba4c795 + nTweak) & 0xffffffff
    return( murmur3(data, seed=seed) % (nFilterBytes * 8) )

We setup our hash function template using the formula and 0xfba4c795 constant set in BIP37. Note that we limit the size of the seed to four bytes and that we’re returning the result of the hash modulo the size of the filter in bits.

data_to_hash = "019f5b01d4195ecbc9398fbf3c3b1fa9" \
               + "bb3183301d7a1fb3bd174fcfa40a2b65"
data_to_hash = data_to_hash.decode("hex")

For the data to add to the filter, we’re adding a TXID. Note that the TXID is in internal byte order.

print "                             Filter (As Bits)"
print "nHashNum   nIndex   Filter   0123456789abcdef"
print "~~~~~~~~   ~~~~~~   ~~~~~~   ~~~~~~~~~~~~~~~~"
for nHashNum in range(nHashFuncs):
    nIndex = bloom_hash(nHashNum, data_to_hash)

    ## Set the bit at nIndex to 1
    vData[nIndex] = True

    ## Debug: print current state
    print '      {0:2}      {1:2}     {2}   {3}'.format(
        nHashNum,
        hex(int(nIndex)),
        vData.tobytes().encode("hex"),
        vData.to01()
    )

print
print "Bloom filter:", vData.tobytes().encode("hex")

Now we use the hash function template to run a slightly different hash function for nHashFuncs times. The result of each function being run on the transaction is used as an index number: the bit at that index is set to 1. We can see this in the printed debugging output:

                             Filter (As Bits)
nHashNum   nIndex   Filter   0123456789abcdef
~~~~~~~~   ~~~~~~   ~~~~~~   ~~~~~~~~~~~~~~~~
       0      0x7     8000   0000000100000000
       1      0x9     8002   0000000101000000
       2      0xa     8006   0000000101100000
       3      0x2     8406   0010000101100000
       4      0xb     840e   0010000101110000
       5      0x5     a40e   0010010101110000
       6      0x0     a50e   1010010101110000
       7      0x8     a50f   1010010111110000
       8      0x5     a50f   1010010111110000
       9      0x8     a50f   1010010111110000
      10      0x4     b50f   1010110111110000

Bloom filter: b50f

Notice that in iterations 8 and 9, the filter did not change because the corresponding bit was already set in a previous iteration (5 and 7, respectively). This is a normal part of bloom filter operation.

We only added one element to the filter above, but we could repeat the process with additional elements and continue to add them to the same filter. (To maintain the same false-positive rate, you would need a larger filter size as computed earlier.)

Note: for a more optimized Python implementation with fewer external dependencies, see python-bitcoinlib’s bloom filter module which is based directly on Bitcoin Core’s C++ implementation.

Using the filterload message format, the complete filter created above would be the binary form of the annotated hexdump shown below:

02 ......... Filter bytes: 2
b50f ....... Filter: 1010 1101 1111 0000
0b000000 ... nHashFuncs: 11
00000000 ... nTweak: 0/none
00 ......... nFlags: BLOOM_UPDATE_NONE

Evaluating A Bloom Filter

Using a bloom filter to find matching data is nearly identical to constructing a bloom filter—except that at each step we check to see if the calculated index bit is set in the existing filter.

vData = bitarray(endian='little')
vData.frombytes("b50f".decode("hex"))
nHashFuncs = 11
nTweak = 0
nFlags = 0

Using the bloom filter created above, we import its various parameters. Note, as indicated in the section above, we won’t actually use nFlags to update the filter.

def contains(nHashFuncs, data_to_hash):
    for nHashNum in range(nHashFuncs):
        ## bloom_hash as defined in previous section
        nIndex = bloom_hash(nHashNum, data_to_hash)

        if vData[nIndex] != True:
            print "MATCH FAILURE: Index {0} not set in {1}".format(
                hex(int(nIndex)),
                vData.to01()
            )
            return False

We define a function to check an element against the provided filter. When checking whether the filter might contain an element, we test to see whether a particular bit in the filter is already set to 1 (if it isn’t, the match fails).

## Test 1: Same TXID as previously added to filter
data_to_hash = "019f5b01d4195ecbc9398fbf3c3b1fa9" \
               + "bb3183301d7a1fb3bd174fcfa40a2b65"
data_to_hash = data_to_hash.decode("hex")
contains(nHashFuncs, data_to_hash)

Testing the filter against the data element we previously added, we get no output (indicating a possible match). Recall that bloom filters have a zero false negative rate—so they should always match the inserted elements.

## Test 2: Arbitrary string
data_to_hash = "1/10,000 chance this ASCII string will match"
contains(nHashFuncs, data_to_hash)

Testing the filter against an arbitrary element, we get the failure output below. Note: we created the filter with a 1-in-10,000 false positive rate (which was rounded up somewhat when we truncated), so it was possible this arbitrary string would’ve matched the filter anyway. It is not possible to set a bloom filter to a false positive rate of zero, so your program will always have to deal with false positives. The output below shows us that one of the hash functions returned an index number of 0x06, but that bit wasn’t set in the filter, causing the match failure:

MATCH FAILURE: Index 0x6 not set in 1010110111110000

Bloom Filter Script

Complete Python script demonstrating the Creating/ Evaluating bloom filter examples:

Retrieving A MerkleBlock

For the merkleblock message documentation on the reference page, an actual merkle block was retrieved from the network and manually processed. This section walks through each step of the process, demonstrating basic network communication and merkle block processing.

#!/usr/bin/env python

from time import sleep
from hashlib import sha256
import struct
import sys

network_string = "f9beb4d9".decode("hex")  # Mainnet

def send(msg,payload):
    ## Command is ASCII text, null padded to 12 bytes
    command = msg + ( ( 12 - len(msg) ) * "\00" )

    ## Payload length is a uint32_t
    payload_raw = payload.decode("hex")
    payload_len = struct.pack("I", len(payload_raw))

    ## Checksum is first 4 bytes of SHA256(SHA256(<payload>))
    checksum = sha256(sha256(payload_raw).digest()).digest()[:4]

    sys.stdout.write(
        network_string
        + command
        + payload_len
        + checksum
        + payload_raw
    )
    sys.stdout.flush()

To connect to the P2P network, the trivial Python function above was developed to compute message headers and send payloads decoded from hex.

## Create a version message
send("version",
      "71110100" # ........................ Protocol Version: 70001
    + "0000000000000000" # ................ Services: Headers Only (SPV)
    + "c6925e5400000000" # ................ Time: 1415484102
    + "00000000000000000000000000000000"
    + "0000ffff7f000001208d" # ............ Receiver IP Address/Port
    + "00000000000000000000000000000000"
    + "0000ffff7f000001208d" # ............ Sender IP Address/Port
    + "0000000000000000" # ................ Nonce (not used here)
    + "1b" # .............................. Bytes in version string
    + "2f426974636f696e2e6f726720457861"
    + "6d706c653a302e392e332f" # .......... Version string
    + "93050500" # ........................ Starting block height: 329107
    + "00" # .............................. Relay transactions: false
)

Peers on the network will not accept any requests until you send them a version message. The receiving node will reply with their version message and a verack message.

sleep(1)
send("verack", "")

We’re not going to validate their version message with this simple script, but we will sleep a short bit and send back our own verack message as if we had accepted their version message.

send("filterload",
      "02"  # ........ Filter bytes: 2
    + "b50f" # ....... Filter: 1010 1101 1111 0000
    + "0b000000" # ... nHashFuncs: 11
    + "00000000" # ... nTweak: 0/none
    + "00" # ......... nFlags: BLOOM_UPDATE_NONE
)

We set a bloom filter with the filterload message. This filter is described in the two preceding sections.

send("getdata",
      "01" # ................................. Number of inventories: 1
    + "03000000" # ........................... Inventory type: filtered block
    + "a4deb66c0d726b0aefb03ed51be407fb"
    + "ad7331c6e8f9eef231b7000000000000" # ... Block header hash
)

We request a merkle block for transactions matching our filter, completing our script.

To run the script, we simply pipe it to the Unix netcat command or one of its many clones, one of which is available for practically any platform. For example, with the original netcat and using hexdump (hd) to display the output:

## Connect to the Bitcoin Core peer running on localhost
python get-merkle.py | nc localhost 8333 | hd

Part of the response is shown in the section below.

Parsing A MerkleBlock

In the section above, we retrieved a merkle block from the network; now we will parse it. Most of the block header has been omitted. For a more complete hexdump, see the example in the merkleblock message section.

7f16c5962e8bd963659c793ce370d95f
093bc7e367117b3c30c1f8fdd0d97287 ... Merkle root

07000000 ........................... Transaction count: 7
04 ................................. Hash count: 4

3612262624047ee87660be1a707519a4
43b1c1ce3d248cbfc6c15870f6c5daa2 ... Hash #1
019f5b01d4195ecbc9398fbf3c3b1fa9
bb3183301d7a1fb3bd174fcfa40a2b65 ... Hash #2
41ed70551dd7e841883ab8f0b16bf041
76b7d1480e4f0af9f3d4c3595768d068 ... Hash #3
20d2a7bc994987302e5b1ac80fc425fe
25f8b63169ea78e68fbaaefa59379bbf ... Hash #4

01 ................................. Flag bytes: 1
1d ................................. Flags: 1 0 1 1 1 0 0 0

We parse the above merkleblock message using the following instructions. Each illustration is described in the paragraph below it.

Parsing A MerkleBlock

We start by building the structure of a merkle tree based on the number of transactions in the block.

Parsing A MerkleBlock

The first flag is a 1 and the merkle root is (as always) a non-TXID node, so we will need to compute the hash later based on this node’s children. Accordingly, we descend into the merkle root’s left child and look at the next flag for instructions.

Parsing A MerkleBlock

The next flag in the example is a 0 and this is also a non-TXID node, so we apply the first hash from the merkleblock message to this node. We also don’t process any child nodes—according to the peer which created the merkleblock message, none of those nodes will lead to TXIDs of transactions that match our filter, so we don’t need them. We go back up to the merkle root and then descend into its right child and look at the next (third) flag for instructions.

Parsing A MerkleBlock

The third flag in the example is another 1 on another non-TXID node, so we descend into its left child.

Parsing A MerkleBlock

The fourth flag is also a 1 on another non-TXID node, so we descend again—we will always continue descending until we reach a TXID node or a non-TXID node with a 0 flag (or we finish filling out the tree).

Parsing A MerkleBlock

Finally, on the fifth flag in the example (a 1), we reach a TXID node. The 1 flag indicates this TXID’s transaction matches our filter and that we should take the next (second) hash and use it as this node’s TXID.

Parsing A MerkleBlock

The sixth flag also applies to a TXID, but it’s a 0 flag, so this TXID’s transaction doesn’t match our filter; still, we take the next (third) hash and use it as this node’s TXID.

Parsing A MerkleBlock

We now have enough information to compute the hash for the fourth node we encountered—it’s the hash of the concatenated hashes of the two TXIDs we filled out.

Parsing A MerkleBlock

Moving to the right child of the third node we encountered, we fill it out using the seventh flag and final hash—and discover there are no more child nodes to process.

Parsing A MerkleBlock

We hash as appropriate to fill out the tree. Note that the eighth flag is not used—this is acceptable as it was required to pad out a flag byte.

The final steps would be to ensure the computed merkle root is identical to the merkle root in the header and check the other steps of the parsing checklist in the merkleblock message section.