1
0
mirror of https://github.com/bitcoinbook/bitcoinbook synced 2024-12-23 15:18:11 +00:00
bitcoinbook/ch03.asciidoc
2016-02-02 14:03:50 -06:00

972 lines
51 KiB
Plaintext

[[ch03_bitcoin_client]]
== Bitcoin Development Environment
If you're a developer, you will want to setup a development environment with all the tools, libraries and support software for writing bitcoin applications. If you're not a developer, you might want to skip this chapter entirely.
=== Bitcoin Core: The Reference Implementation
Bitcoin is an _open source_ project and the source code is available under an open (MIT) license, free to download and use for any purpose. Open source means more than simply free to use. It also means that bitcoin is developed by an open community of volunteers. At first, that community consisted of only Satoshi Nakamoto. By 2016, bitcoin's source code has more than 340 contributors with about a dozen developers working on the code almost full time and several dozen more on a part-time basis. Anyone can contribute to the code - including you!
((("bitcoin client", id="ix_ch03-asciidoc0", range="startofrange")))((("bitcoin client","Bitcoin Core", id="ix_ch03-asciidoc1", range="startofrange")))((("Bitcoin Core client", id="ix_ch03-asciidoc2", range="startofrange")))((("Satoshi client", see="Bitcoin Core client")))
When bitcoin was created by Satoshi Nakamoto, the software was actually completed before the white paper <<satoshi_whitepaper>>. Satoshi wanted to make sure it worked before writing about it. That first implementation, then simply known as "Bitcoin" or "Satoshi client", has been heavily modified and improved. It has evolved into what is known as _Bitcoin Core_, to differentiate it from other compatible implementations. Bitcoin Core is the _reference implementation_ of the bitcoin system, meaning that it is the authoritative reference on how each part of the technology should be implemented. Bitcoin Core implements all aspects of bitcoin, including wallets, a transaction and block validation engine, and a full network node in the peer-to-peer bitcoin network.
[WARNING]
====
Even though Bitcoin Core includes a reference implementation of a wallet, this is not intended to be used as a production wallet for users or for applications. Application developers are advised to build wallets using modern standards such as BIP39 and BIP32 (see <<mnemonic_code_words>> and <<hd_wallets>>).
====
[[compiling_core]]
=== Compiling Bitcoin Core from the Source Code
((("Bitcoin Core client","compiling from source code", id="ix_ch03-asciidoc3", range="startofrange")))((("bitcoind client", see="Bitcoin Core client")))Bitcoin Core's source code can be downloaded as a ZIP archive or by cloning the authoritative source repository from GitHub. ((("Bitcoin Core client","source code, downloading")))((("GitHub, downloading Bitcoin Core from"))) On the https://github.com/bitcoin/bitcoin[GitHub bitcoin page], select Download ZIP from the sidebar. Alternatively, use the git command line to create a local copy of the source code on your system.
[TIP]
====
In many of the examples in this chapter we will be using the operating system's command-line interface (also known as a "shell"), accessed via a "terminal" application. The shell will display a prompt; you type a command; and the shell responds with some text and a new prompt for your next command. The prompt may look different on your system, but in the examples below it is denoted by a +$+ symbol. In the examples when you see text after a +$+ symbol, don't type the +$+ symbol but type the command immediately following it, then press enter to execute the command. In the examples, the lines below each command are the operating system's responses to that command. When you see the next +$+ prefix, you'll know it's a new command and you should repeat the process.
====
In this example, we are using the +git+ command to create a local copy ("clone") of the source code.
----
$ git clone https://github.com/bitcoin/bitcoin.git
Cloning into 'bitcoin'...
remote: Counting objects: 66193, done.
remote: Total 66193 (delta 0), reused 0 (delta 0), pack-reused 66193
Receiving objects: 100% (66193/66193), 63.39 MiB | 574.00 KiB/s, done.
Resolving deltas: 100% (48395/48395), done.
Checking connectivity... done.
$
----
[TIP]
====
Git is the most widely used distributed version control system, an essential part of any software developer's toolkit. You may need to install the +git+ command, or a graphical user interface for git, on your operating system if you do not have it already.
====
When the git cloning operation has completed, you will have a complete local copy of the source code repository in the directory _bitcoin_. Change to this directory by typing +cd bitcoin+ at the prompt:
----
$ cd bitcoin
----
==== Selecting a Bitcoin Core Release
By default, the local copy will be synchronized with the most recent code, which might be an unstable or beta version of bitcoin. Before compiling the code, select a specific version by checking out a((("release tags"))) release _tag_. This will synchronize the local copy with a specific snapshot of the code repository identified by a keyword tag. Tags are used by the developers to mark specific releases of the code by version number. First, to find the available tags, we use the +git tag+ command:
----
$ git tag
v0.1.5
v0.1.6test1
v0.10.0
...
v0.11.2
v0.11.2rc1
v0.12.0rc1
v0.12.0rc2
...
----
The list of tags shows all the released versions of bitcoin. By convention,((("release candidates"))) _release candidates_, which are intended for testing, have the suffix "rc". Stable releases that can be run on production systems have no suffix. From the preceding list, select the highest version release, which at this writing was v0.11.2. To synchronize the local code with this version, use the +git checkout+ command:
----
$ git checkout v0.11.2
HEAD is now at 7e27892... Merge pull request #6975
----
You can confirm you have the desired version "checked out" by issuing the +git status+ command:
----
$ git status
HEAD detached at v0.11.2
nothing to commit, working directory clean
----
==== Configuring the Bitcoin Core Build
((("Bitcoin Core client","documentation")))The source code includes documentation, which can be found in a number of files. Review the main documentation located in _README.md_ in the bitcoin directory by typing +more README.md+ at the prompt and using the space bar to progress to the next page. In this chapter, we will build the command-line bitcoin client, also known as +bitcoind+ on Linux. Review the instructions for compiling the bitcoind command-line client on your platform by typing +more doc/build-unix.md+. Alternative instructions for Mac OS X and Windows can be found in the _doc_ directory, as _build-osx.md_ or _build-msw.md_, respectively.
Carefully review the build prerequisites, which are in the first part of the build documentation. These are libraries that must be present on your system before you can begin to compile bitcoin. If these prerequisites are missing, the build process will fail with an error. If this happens because you missed a prerequisite, you can install it and then resume the build process from where you left off. Assuming the prerequisites are installed, you start the build process by generating a set of build scripts using the _autogen.sh_ script.
[NOTE]
====
The Bitcoin Core build process was changed to use the autogen/configure/make system starting with version 0.9. Older versions use a simple Makefile and work slightly differently from the following example. Follow the instructions for the version you want to compile. The autogen/configure/make introduced in 0.9 is likely to be the build system used for all future versions of the code and is the system demonstrated in the following examples.
====
----
$ ./autogen.sh
...
glibtoolize: copying file 'build-aux/m4/libtool.m4'
glibtoolize: copying file 'build-aux/m4/ltoptions.m4'
glibtoolize: copying file 'build-aux/m4/ltsugar.m4'
glibtoolize: copying file 'build-aux/m4/ltversion.m4'
...
configure.ac:10: installing 'build-aux/compile'
configure.ac:5: installing 'build-aux/config.guess'
configure.ac:5: installing 'build-aux/config.sub'
configure.ac:9: installing 'build-aux/install-sh'
configure.ac:9: installing 'build-aux/missing'
Makefile.am: installing 'build-aux/depcomp'
...
----
((("autogen.sh script")))The _autogen.sh_ script creates a set of automatic configuration scripts that will interrogate your system to discover the correct settings and ensure you have all the necessary libraries to compile the code. The most important of these is the((("configure script"))) +configure+ script that offers a number of different options to customize the build process. Type +./configure --help+ to see the various options:
----
$ ./configure --help
`configure' configures Bitcoin Core 0.11.2 to adapt to many kinds of systems.
Usage: ./configure [OPTION]... [VAR=VALUE]...
...
Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--enable-wallet enable wallet (default is yes)
--with-gui[=no|qt4|qt5|auto]
...
----
The +configure+ script allows you to enable or disable certain features of bitcoind through the use of the +--enable-FEATURE+ and +--disable-FEATURE+ flags, where +FEATURE+ is replaced by the feature name, as listed in the help output. In this chapter, we will build the bitcoind client with all the default features. We won't be using the configuration flags, but you should review them to understand what optional features are part of the client. If you are in an academic setting, computer lab restrictions may require you to install applications in your home directory (e.g. using --prefix=$HOME).
[TIP]
====
Here are some useful options that override the default behavior of the configure script:
+--prefix=$HOME+: This overrides the default installation location (which is +/usr/local/+) for the resulting executable. Use $HOME to put everything in your home directory, or a different path.
+--disable-wallet+: This is used to disable the reference wallet implementation.
+--with-incompatible-bdb+: If you are building a wallet, allow the use of an incompatible version of the Berkeley DB library.
+--with-gui=no+: Don't build the graphical user interface, which requires the Qt library. This builds server and command-line bitcoin only.
====
Next, run the +configure+ script to automatically discover all the necessary libraries and create a customized build script for your system:
----
$ ./configure
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
...
[many pages of configuration tests follow]
...
$
----
If all goes well, the +configure+ command will end by creating the customized build scripts that will allow us to compile bitcoind. If there are any missing libraries or errors, the +configure+ command will terminate with an error instead of creating the build scripts. If an error occurs, it is most likely because of a missing or incompatible library. Review the build documentation again and make sure you install the missing prerequisites. Then run +configure+ again and see if that fixes the error.
==== Building the Bitcoin Core Executables
Next, you will compile the source code, a process that can take up to an hour to complete, depending on the speed of your CPU and available memory. During the compilation process you should see output every few seconds or every few minutes, or an error if something goes wrong. If an error occurs, or the compilation process is interrupted, it can be resumed any time by typing +make+ again. Type +make+ to start compiling the executable application:
----
$ make
Making all in src
CXX crypto/libbitcoinconsensus_la-hmac_sha512.lo
CXX crypto/libbitcoinconsensus_la-ripemd160.lo
CXX crypto/libbitcoinconsensus_la-sha1.lo
CXX crypto/libbitcoinconsensus_la-sha256.lo
CXX crypto/libbitcoinconsensus_la-sha512.lo
CXX libbitcoinconsensus_la-hash.lo
CXX primitives/libbitcoinconsensus_la-transaction.lo
CXX libbitcoinconsensus_la-pubkey.lo
CXX script/libbitcoinconsensus_la-bitcoinconsensus.lo
CXX script/libbitcoinconsensus_la-interpreter.lo
[... many more compilation messages follow ...]
$
----
If all goes well, Bitcoin Core is now compiled. The final step is to install the various executables on your system using the +sudo make install+ command. You may be prompted for your user password, because this step requires administrative privileges:
----
$ sudo make install
Password:
Making install in src
../build-aux/install-sh -c -d '/usr/local/lib'
libtool: install: /usr/bin/install -c bitcoind /usr/local/bin/bitcoind
libtool: install: /usr/bin/install -c bitcoin-cli /usr/local/bin/bitcoin-cli
libtool: install: /usr/bin/install -c bitcoin-tx /usr/local/bin/bitcoin-tx
...
$
----
The default installation of bitcoind puts it in _/usr/local/bin_. You can confirm that Bitcoin Core is correctly installed by asking the system for the path of the executables, as follows:
----
$ which bitcoind
/usr/local/bin/bitcoind
$ which bitcoin-cli
/usr/local/bin/bitcoin-cli
----
=== Running a Bitcoin Core Node
Bitcoin's peer-to-peer network is composed of network "nodes", run mostly by volunteers and some of the businesses that build bitcoin applications. Those running bitcoin nodes have a direct and authoritative view of the bitcoin blockchain, with a local copy of all the transactions, independently validated by their own system. By running a node, you don't have to rely on any third party to validate a transaction. Moreover, by running a bitcoin node you contribute to the bitcoin network by making it more robust.
Running a node, however, requires a permanently connected system with enough resources to process all bitcoin transactions. Depending on whether you choose to index all transactions and keep a full copy of the blockchain, you may also need a lot of disk space and RAM. In early 2016, a full-index node needs 2GB of RAM and 80GB of disk space. Bitcoin nodes also transmit and receive bitcoin transactions and blocks, consuming Internet bandwidth. If your Internet connection is limited, has a low data cap, or is metered (charged by the gigabit), you should probably not run a bitcoin node on it, or run it in a way that constrains its bandwidth (see <<constrained_resources>>).
[TIP]
====
((("Bitcoin Core","runtime requirement for")))((("runtime requirements for Bitcoin Core")))Bitcoin Core keeps a full copy of the blockchain by default, with every transaction that has ever occurred on the bitcoin network since its inception in 2009. This dataset is several gigabytes in size and is downloaded incrementally over several hours or days, depending on the speed of your CPU and Internet connection. Bitcoin Core will not be able to process transactions or update account balances until the full blockchain dataset is downloaded. Make sure you have enough disk space, bandwidth, and time to complete the initial synchronization. You can configure Bitcoin Core to reduce the size of the blockchain by discarding old blocks (see <<constrained_resources>>) but it will still download the entire dataset before discarding data.
====
Despite these resource requirements, thousands of volunteers run bitcoin nodes. Some are running on systems as simple as a Raspberry Pi (a $35 USD computer the size of a pack of cards). Many volunteers also run bitcoin nodes on rented servers, usually some variant of Linux. A _Virtual Private Server_ (VPS) or _Cloud Computing_ server instance can be used to run a bitcoin node. Such servers can be rented for $12 to $18 USD per month from a variety of providers.
Why would you want to run a node? Here are some of the most common reasons for running a node:
* If you are developing bitcoin software and need to rely on a bitcoin node for programmable (API) access to the network and blockchain.
* If you are building applications that must validate transactions according to bitcoin's consensus rules. Typically, bitcoin software companies run several nodes.
* If you want to support bitcoin. Running a node makes the network more robust and able to serve more wallets, more users and more transactions.
* If you do not want to rely on any third party for processing your own transactions or validating transactions.
If you're reading this book and interested in developing bitcoin software, you should be running your own node.
==== Running Bitcoin Core for the First Time
When you first run bitcoind, it will remind you to create a configuration file with a strong password for the JSON-RPC interface. This password controls access to the Application Programming Interface (API) offered by Bitcoin Core.
Run bitcoind by typing +bitcoind+ into the terminal:
----
$ bitcoind
Error: To use the "-server" option, you must set a rpcpassword in the configuration file:
/home/ubuntu/.bitcoin/bitcoin.conf
It is recommended you use the following random password:
rpcuser=bitcoinrpc
rpcpassword=2XA4DuKNCbtZXsBQRRNDEwEY2nM6M4H9Tx5dFjoAVVbK
(you do not need to remember this password)
The username and password MUST NOT be the same.
If the file does not exist, create it with owner-readable-only file permissions.
It is also recommended to set alertnotify so you are notified of problems;
for example: alertnotify=echo %s | mail -s "Bitcoin Alert" admin@foo.com
----
==== Configuring the Bitcoin Core Node
Edit the configuration file in your preferred editor and set the parameters, replacing the password with a strong password as recommended by bitcoind. Do _not_ use the password shown in the book. Create a file inside the +.bitcoin+ directory (under your user's home directory) so that it is named +.bitcoin/bitcoin.conf+ and provide a username and password:
[source,ini]
----
rpcuser=bitcoinrpc
rpcpassword=CHANGE_THIS
----
While you're editing this configuration file, you might want to set a few other options. In addition to the +rpcuser+ and +rpcpassword+ options, Bitcoin Core offers dozens of configuration options that modify the behavior of the network node, the storage of the blockchain and many other aspects of its operation.
To see a listing of these options, run +bitcoind --help+:
----
bitcoind --help
Bitcoin Core Daemon version v0.11.2
Usage:
bitcoind [options] Start Bitcoin Core Daemon
Options:
-?
This help message
-alerts
Receive and display P2P network alerts (default: 1)
-alertnotify=<cmd>
Execute command when a relevant alert is received or we see a really
long fork (%s in cmd is replaced by message)
...
[many more options]
...
-rpcsslciphers=<ciphers>
Acceptable ciphers (default:
TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH)
----
Here are some of the most important options that can set in the configuration file, or as command-line parameters to bitcoind:
alertnotify::Run a specified command or script to send emergency alerts to the owner of this node, usually by sending email.
conf::An alternative location for the configuration file. This only makes sense as a command-line parameter to bitcoind, as it can't be inside the configuration file it refers to.
datadir::Select the directory and filesystem to put all the blockchain data. By default this is the +.bitcoin+ subdirectory of your home directory. Make sure this filesystem has several gigabytes free space.
prune::Reduce the disk space requirements to this many megabytes, by deleting old blocks. Use this on a resource-constrained node that can't fit the full blockchain.
txindex::Maintain an index of all transactions. This means a complete copy of the blockchain and allows you to programmatically retrieve any transaction by ID.
maxconnections::Set the maximum number of nodes from which to accept connections. Reducing this from the default will reduce your bandwidth consumption. Use if you have a data cap or pay by the gigabyte.
minrelaytxfee::Increase the minimum acceptable transaction fee. Use this on memory-constrained nodes to reduce the size of the in-memory transaction pool.
Here's how you might combine the above options:
A fully-indexed node, running as an API back-end for a bitcoin application:
[[full_index_node]]
.Sample configuration of a full-index node
====
----
alertnotify=myemailscript.sh "Alert: %s"
datadir=/lotsofspace/bitcoin
txindex=1
rpcuser=bitcoinrpc
rpcpassword=CHANGE_THIS
----
====
A resource-constrained node running on a smaller server:
[[constrained_resources]]
.Sample configuration of a resource-constrained system
====
----
alertnotify=myemailscript.sh "Alert: %s"
maxconnections=15
prune=5000
minrelaytxfee=0.0001
rpcuser=bitcoinrpc
rpcpassword=CHANGE_THIS
----
====
Now, run the Bitcoin Core client. The first time you run it, it will reconstruct a complete local copy of the bitcoin blockchain by downloading all the blocks.
To test your configuration, run Bitcoin Core with the option +printtoconsole+ to run in the foreground with output to the console:(((range="endofrange", startref="ix_ch03-asciidoc3")))
----
$ bitcoind -printtoconsole
Bitcoin version v0.11.20.0
Using OpenSSL version OpenSSL 1.0.2e 3 Dec 2015
Startup time: 2015-01-02 19:56:17
Using data directory /tmp/bitcoin
Using config file /tmp/bitcoin/bitcoin.conf
Using at most 125 connections (275 file descriptors available)
Using 2 threads for script verification
scheduler thread start
HTTP: creating work queue of depth 16
No rpcpassword set - using random cookie authentication
Generated RPC authentication cookie /tmp/bitcoin/.cookie
HTTP: starting 4 worker threads
Bound to [::]:8333
Bound to 0.0.0.0:8333
Cache configuration:
* Using 2.0MiB for block index database
* Using 32.5MiB for chain state database
* Using 65.5MiB for in-memory UTXO set
init message: Loading block index...
Opening LevelDB in /tmp/bitcoin/blocks/index
Opened LevelDB successfully
[... more startup messages ...]
----
You can hit +CTRL+C+ to interrupt the process once you are satisfied that it is loading the correct settings and running as you expect it.
To run Bitcoin Core in the background as a process, start it with the +daemon+ option, as +bitcoind -daemon+.
To monitor the progress and runtime status of your bitcoin node, use the command +bitcoin-cli getinfo+:
----
$ bitcoin-cli getinfo
----
[source,json]
----
{
"version" : 110200,
"protocolversion" : 70002,
"blocks" : 396328,
"timeoffset" : 0,
"connections" : 15,
"proxy" : "",
"difficulty" : 120033340651.23696899,
"testnet" : false,
"relayfee" : 0.00010000,
"errors" : ""
}
----
This shows a node running Bitcoin Core version 0.11.2, with a blockchain height of 396328 blocks and 15 active network connections.
Once you are happy with the configuration options you have selected, you should add bitcoin to the startup scripts in your operating system, so that it runs continuously and restarts when the operating system restarts. You will find a number of example startup scripts for various operating systems in bitcoin's source directory under +contrib/init+ and a +README.md+ file showing which system uses which script.
=== Using Bitcoin Core's JSON-RPC API from the Command Line
((("Bitcoin Core client","JSON-RPC API for", id="ix_ch03-asciidoc5", range="startofrange")))((("Bitcoin Core client","using from command line", id="ix_ch03-asciidoc6", range="startofrange")))((("bitcoin-cli command line helper", id="ix_ch03-asciidoc7", range="startofrange")))The Bitcoin Core client implements a JSON-RPC interface that can also be accessed using the command-line helper +bitcoin-cli+. The command line allows us to experiment interactively with the capabilities that are also available programmatically via the API. To start, invoke the +help+ command to see a list of the available bitcoin RPC commands:
[[bitcoind_commands]]
----
$ bitcoin-cli help
addmultisigaddress nrequired ["key",...] ( "account" )
addnode "node" "add|remove|onetry"
backupwallet "destination"
createmultisig nrequired ["key",...]
createrawtransaction [{"txid":"id","vout":n},...] {"address":amount,...}
decoderawtransaction "hexstring"
decodescript "hex"
dumpprivkey "bitcoinaddress"
dumpwallet "filename"
getaccount "bitcoinaddress"
getaccountaddress "account"
getaddednodeinfo dns ( "node" )
getaddressesbyaccount "account"
getbalance ( "account" minconf )
getbestblockhash
getblock "hash" ( verbose )
getblockchaininfo
getblockcount
getblockhash index
getblocktemplate ( "jsonrequestobject" )
getconnectioncount
getdifficulty
getgenerate
gethashespersec
getinfo
getmininginfo
getnettotals
getnetworkhashps ( blocks height )
getnetworkinfo
getnewaddress ( "account" )
getpeerinfo
getrawchangeaddress
getrawmempool ( verbose )
getrawtransaction "txid" ( verbose )
getreceivedbyaccount "account" ( minconf )
getreceivedbyaddress "bitcoinaddress" ( minconf )
gettransaction "txid"
gettxout "txid" n ( includemempool )
gettxoutsetinfo
getunconfirmedbalance
getwalletinfo
getwork ( "data" )
help ( "command" )
importprivkey "bitcoinprivkey" ( "label" rescan )
importwallet "filename"
keypoolrefill ( newsize )
listaccounts ( minconf )
listaddressgroupings
listlockunspent
listreceivedbyaccount ( minconf includeempty )
listreceivedbyaddress ( minconf includeempty )
listsinceblock ( "blockhash" target-confirmations )
listtransactions ( "account" count from )
listunspent ( minconf maxconf ["address",...] )
lockunspent unlock [{"txid":"txid","vout":n},...]
move "fromaccount" "toaccount" amount ( minconf "comment" )
ping
sendfrom "fromaccount" "tobitcoinaddress" amount ( minconf "comment" "comment-to" )
sendmany "fromaccount" {"address":amount,...} ( minconf "comment" )
sendrawtransaction "hexstring" ( allowhighfees )
sendtoaddress "bitcoinaddress" amount ( "comment" "comment-to" )
setaccount "bitcoinaddress" "account"
setgenerate generate ( genproclimit )
settxfee amount
signmessage "bitcoinaddress" "message"
signrawtransaction "hexstring" ( [{"txid":"id","vout":n,"scriptPubKey":"hex","redeemScript":"hex"},...] ["privatekey1",...] sighashtype )
stop
submitblock "hexdata" ( "jsonparametersobject" )
validateaddress "bitcoinaddress"
verifychain ( checklevel numblocks )
verifymessage "bitcoinaddress" "signature" "message"
walletlock
walletpassphrase "passphrase" timeout
walletpassphrasechange "oldpassphrase" "newpassphrase"
----
==== Getting Information on the Bitcoin Core Client Status
Commands: +getinfo+
((("Bitcoin Core client","client status, getting")))((("bitcoin-cli command line helper","getinfo command")))((("client status, getting")))((("getinfo command (bitcoin-cli)")))Bitcoin's +getinfo+ RPC command displays basic information about the status of the bitcoin network node, the wallet, and the blockchain database. Use +bitcoin-cli+ to run it:
----
$ bitcoin-cli getinfo
----
[source,json]
----
{
"version" : 90000,
"protocolversion" : 70002,
"walletversion" : 60000,
"balance" : 0.00000000,
"blocks" : 286216,
"timeoffset" : -72,
"connections" : 4,
"proxy" : "",
"difficulty" : 2621404453.06461525,
"testnet" : false,
"keypoololdest" : 1374553827,
"keypoolsize" : 101,
"paytxfee" : 0.00000000,
"errors" : ""
}
----
The data is returned in((("JavaScript Object Notation (JSON)"))) JavaScript Object Notation (JSON), a format that can easily be "consumed" by all programming languages but is also quite human-readable. Among this data we see the version numbers for the bitcoin software client (90000), protocol (70002), and wallet (60000). We see the current balance contained in the wallet, which is zero. We see the current block height, showing us how many blocks are known to this client (286216). We also see various statistics about the bitcoin network and the settings related to this client. We will explore these settings in more detail in the rest of this chapter.
[TIP]
====
It will take some time, perhaps more than a day, for the bitcoind client to "catch up" to the current blockchain height as it downloads blocks from other bitcoin clients. You can check its progress using +getinfo+ to see the number of known blocks.
====
==== Exploring and Decoding Transactions
Commands: +gettransaction+, +getrawtransaction+, +decoderawtransaction+
((("bitcoin-cli command line helper","decoderawtransaction command", id="ix_ch03-asciidoc23", range="startofrange")))((("bitcoin-cli command line helper","getrawtransaction command", id="ix_ch03-asciidoc24", range="startofrange")))((("bitcoin-cli command line helper","gettransaction command", id="ix_ch03-asciidoc25", range="startofrange")))((("decoderawtransaction command (bitcoin-cli)", id="ix_ch03-asciidoc26", range="startofrange")))((("getrawtransaction command (bitcoin-cli)", id="ix_ch03-asciidoc27", range="startofrange")))((("gettransaction command (bitcoin-cli)", id="ix_ch03-asciidoc28", range="startofrange")))((("transactions","decoding", id="ix_ch03-asciidoc29", range="startofrange")))((("transactions","exploring", id="ix_ch03-asciidoc30", range="startofrange")))We'll now explore the incoming transaction that was listed previously using the +gettransaction+ command. We can retrieve a transaction by its transaction hash, shown at +txid+ earlier, with the +gettransaction+ command:
++++
<pre data-type="programlisting">
$ bitcoin-cli gettransaction 9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66&#x21b5;
c309acbae2c14ae3
</pre>
++++
[source,json]
----
{
"amount" : 0.05000000,
"confirmations" : 0,
"txid" : "9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae3",
"time" : 1392660908,
"timereceived" : 1392660908,
"details" : [
{
"account" : "",
"address" : "1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL",
"category" : "receive",
"amount" : 0.05000000
}
]
}
----
[TIP]
====
Transaction IDs are not authoritative until a transaction has been confirmed. Absence of a transaction hash in the blockchain does not mean the transaction was not processed. This is known as((("transaction malleability"))) "transaction malleability," because transaction hashes can be modified prior to confirmation in a block. After confirmation, the txid is immutable and authoritative.
====
The transaction form shown with the command +gettransaction+ is the simplified form. To retrieve the full transaction code and decode it, we will use two commands: +getrawtransaction+ and +decoderawtransaction+. First, +getrawtransaction+ takes the _transaction hash (txid)_ as a parameter and returns the full transaction as a "raw" hex string, exactly as it exists on the bitcoin network:
++++
<pre data-type="programlisting">
$ bitcoin-cli getrawtransaction 9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1f&#x21b5;
c66c309acbae2c14ae3
0100000001d717279515f88e2f56ce4e8a31e2ae3e9f00ba1d0add648e80c480ea22e0c7d3000&#x21b5;
000008b483045022100a4ebbeec83225dedead659bbde7da3d026c8b8e12e61a2df0dd0758e22&#x21b5;
7383b302203301768ef878007e9ef7c304f70ffaf1f2c975b192d34c5b9b2ac1bd193dfba2014&#x21b5;
104793ac8a58ea751f9710e39aad2e296cc14daa44fa59248be58ede65e4c4b884ac5b5b6dede&#x21b5;
05ba84727e34c8fd3ee1d6929d7a44b6e111d41cc79e05dbfe5ceaffffffff02404b4c0000000&#x21b5;
0001976a91407bdb518fa2e6089fd810235cf1100c9c13d1fd288ac1f312906000000001976a9&#x21b5;
14107b7086b31518935c8d28703d66d09b3623134388ac00000000
</pre>
++++
To decode this hex string, use the +decoderawtransaction+ command. Copy and paste the hex as the first parameter of +decoderawtransaction+ to get the full contents interpreted as a JSON data structure (for formatting reasons the hex string is shortened in the following example):
++++
<pre data-type="programlisting">
$ bitcoin-cli decoderawtransaction 0100000001d717279515f88e2f56ce4e8a31e2ae3e&#x21b5;
9f00ba1d0add648e80c480ea22e0c7d3000000008b483045022100a4ebbeec83225dedead659b&#x21b5;
bde7da3d026c8b8e12e61a2df0dd0758e227383b302203301768ef878007e9ef7c304f70ffaf1&#x21b5;
f2c975b192d34c5b9b2ac1bd193dfba2014104793ac8a58ea751f9710e39aad2e296cc14daa44&#x21b5;
fa59248be58ede65e4c4b884ac5b5b6dede05ba84727e34c8fd3ee1d6929d7a44b6e111d41cc7&#x21b5;
9e05dbfe5ceaffffffff02404b4c00000000001976a91407bdb518fa2e6089fd810235cf1100c&#x21b5;
9c13d1fd288ac1f312906000000001976a914107b7086b31518935c8d28703d66d09b36231343&#x21b5;
88ac00000000
</pre>
++++
++++
<pre data-type="programlisting">
{
"txid" : "9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae3",
"version" : 1,
"locktime" : 0,
"vin" : [
{
"txid" : "d3c7e022ea80c4808e64dd0a1dba009f3eaee2318a4ece562f8ef815&#x21b5;
952717d7",
"vout" : 0,
"scriptSig" : {
"asm" : "3045022100a4ebbeec83225dedead659bbde7da3d026c8b8e12e&#x21b5;
61a2df0dd0758e227383b302203301768ef878007e9ef7c304f70ffaf1f2c975b192d34c5b9b2&#x21b5;
ac1bd193dfba20104793ac8a58ea751f9710e39aad2e296cc14daa44fa59248be58ede65e4c4b&#x21b5;
884ac5b5b6dede05ba84727e34c8fd3ee1d6929d7a44b6e111d41cc79e05dbfe5cea",
"hex": "483045022100a4ebbeec83225dedead659bbde7da3d026c8b8e1&#x21b5;
2e61a2df0dd0758e227383b302203301768ef878007e9ef7c304f70ffaf1f2c975b192d34c5b9&#x21b5;
b2ac1bd193dfba2014104793ac8a58ea751f9710e39aad2e296cc14daa44fa59248be58ede65e&#x21b5;
4c4b884ac5b5b6dede05ba84727e34c8fd3ee1d6929d7a44b6e111d41cc79e05dbfe5cea"
},
"sequence" : 4294967295
}
],
"vout" : [
{
"value" : 0.05000000,
"n" : 0,
"scriptPubKey" : {
"asm" : "OP_DUP OP_HASH160 07bdb518fa2e6089fd810235cf1100c9c&#x21b5;
13d1fd2 OP_EQUALVERIFY OP_CHECKSIG",
"hex" : "76a91407bdb518fa2e6089fd810235cf1100c9c13d1fd288ac",
"reqSigs" : 1,
"type" : "pubkeyhash",
"addresses" : [
"1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL"
]
}
},
{
"value" : 1.03362847,
"n" : 1,
"scriptPubKey" : {
"asm" : "OP_DUP OP_HASH160 107b7086b31518935c8d28703d66d09b36&#x21b5;
231343 OP_EQUALVERIFY OP_CHECKSIG",
"hex" : "76a914107b7086b31518935c8d28703d66d09b3623134388ac",
"reqSigs" : 1,
"type" : "pubkeyhash",
"addresses" : [
"12W9goQ3P7Waw5JH8fRVs1e2rVAKoGnvoy"
]
}
}
]
}
</pre>
++++
The transaction decode shows all the components of this transaction, including the transaction inputs and outputs. In this case we see that the transaction that credited our new address with 50 millibits used one input and generated two outputs. The input to this transaction was the output from a previously confirmed transaction (shown as the vin txid starting with +d3c7+). The two outputs correspond to the 50 millibit credit and an output with change back to the sender.
We can further explore the blockchain by examining the previous transaction referenced by its txid in this transaction using the same commands (e.g., +gettransaction+). Jumping from transaction to transaction we can follow a chain of transactions back as the coins are transmitted from owner address to owner address.
Once the transaction we received has been confirmed by inclusion in a block, the +gettransaction+ command will return additional information, showing the _block hash (identifier)_ in which the transaction was included:
++++
<pre data-type="programlisting">
$ bitcoin-cli gettransaction 9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66&#x21b5;
c309acbae2c14ae3
</pre>
++++
++++
<pre data-type="programlisting">
{
"amount" : 0.05000000,
"confirmations" : 1,
"blockhash" : "000000000000000051d2e759c63a26e247f185ecb7926ed7a6624bc31c&#x21b5;
2a717b",
"blockindex" : 18,
"blocktime" : 1392660808,
"txid" : "9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae3",
"time" : 1392660908,
"timereceived" : 1392660908,
"details" : [
{
"account" : "",
"address" : "1hvzSofGwT8cjb8JU7nBsCSfEVQX5u9CL",
"category" : "receive",
"amount" : 0.05000000
}
]
}
</pre>
++++
Here, we see the new information in the entries +blockhash+ (the hash of the block in which the transaction was included), and +blockindex+ with value 18 (indicating that our transaction was the 18th transaction in that block).
[[txindex]]
.Transaction Database Index and txindex Option
****
((("transaction database index")))By default, Bitcoin Core builds a database containing _only_ the transactions related to the user's wallet. If you want to be able to access _any_ transaction with commands like +gettransaction+, you need to configure Bitcoin Core to build a complete transaction index, which can be achieved with the((("txindex option (Bitcoin Core)"))) +txindex+ option. Set +txindex=1+ in the Bitcoin Core configuration file (usually found in your home directory under _.bitcoin/bitcoin.conf_). Once you change this parameter, you need to restart bitcoind and wait for it to rebuild the index.(((range="endofrange", startref="ix_ch03-asciidoc30")))(((range="endofrange", startref="ix_ch03-asciidoc29")))(((range="endofrange", startref="ix_ch03-asciidoc28")))(((range="endofrange", startref="ix_ch03-asciidoc27")))(((range="endofrange", startref="ix_ch03-asciidoc26")))(((range="endofrange", startref="ix_ch03-asciidoc25")))(((range="endofrange", startref="ix_ch03-asciidoc24")))(((range="endofrange", startref="ix_ch03-asciidoc23")))
****
==== Exploring Blocks
Commands: +getblock+, +getblockhash+
((("bitcoin-cli command line helper","getblock command")))((("bitcoin-cli command line helper","getblockhash command")))((("blocks","exploring")))((("getblock command (bitcoin-cli)")))((("getblockhash command (bitcoin-cli)")))Now that we know which block our transaction was included in, we can query that block. We use the +getblock+ command with the block hash as the parameter:
++++
<pre data-type="programlisting">
$ bitcoin-cli getblock 000000000000000051d2e759c63a26e247f185ecb7926ed7a6624b&#x21b5;
c31c2a717b true
</pre>
++++
++++
<pre data-type="programlisting">
{
"hash" : "000000000000000051d2e759c63a26e247f185ecb7926ed7a6624bc31c2a717&#x21b5;
b",
"confirmations" : 2,
"size" : 248758,
"height" : 286384,
"version" : 2,
"merkleroot" : "9891747e37903016c3b77c7a0ef10acf467c530de52d84735bd555387&#x21b5;
19f9916",
"tx" : [
"46e130ab3c67d31d2b2c7f8fbc1ca71604a72e6bc504c8a35f777286c6d89bf0",
"2d5625725b66d6c1da88b80b41e8c07dc5179ae2553361c96b14bcf1ce2c3868",
"923392fc41904894f32d7c127059bed27dbb3cfd550d87b9a2dc03824f249c80",
"f983739510a0f75837a82bfd9c96cd72090b15fa3928efb9cce95f6884203214",
"190e1b010d5a53161aa0733b953eb29ef1074070658aaa656f933ded1a177952",
"ee791ec8161440262f6e9144d5702f0057cef7e5767bc043879b7c2ff3ff5277",
"4c45449ff56582664abfadeb1907756d9bc90601d32387d9cfd4f1ef813b46be",
"3b031ed886c6d5220b3e3a28e3261727f3b4f0b29de5f93bc2de3e97938a8a53",
"14b533283751e34a8065952fd1cd2c954e3d37aaa69d4b183ac6483481e5497d",
"57b28365adaff61aaf60462e917a7cc9931904258127685c18f136eeaebd5d35",
"8c0cc19fff6b66980f90af39bee20294bc745baf32cd83199aa83a1f0cd6ca51",
"1b408640d54a1409d66ddaf3915a9dc2e8a6227439e8d91d2f74e704ba1cdae2",
"0568f4fad1fdeff4dc70b106b0f0ec7827642c05fe5d2295b9deba4f5c5f5168",
"9194bfe5756c7ec04743341a3605da285752685b9c7eebb594c6ed9ec9145f86",
"765038fc1d444c5d5db9163ba1cc74bba2b4f87dd87985342813bd24021b6faf",
"bff1caa9c20fa4eef33877765ee0a7d599fd1962417871ca63a2486476637136",
"d76aa89083f56fcce4d5bf7fcf20c0406abdac0375a2d3c62007f64aa80bed74",
"e57a4c70f91c8d9ba0ff0a55987ea578affb92daaa59c76820125f31a9584dfc",
"9ca8f969bd3ef5ec2a8685660fdbf7a8bd365524c2e1fc66c309acbae2c14ae3",
#[... many more transactions ...]
],
"time" : 1392660808,
"nonce" : 3888130470,
"bits" : "19015f53",
"difficulty" : 3129573174.52228737,
"chainwork" : "000000000000000000000000000000000000000000001931d1658fc048&#x21b5;
79e466",
"previousblockhash" : "0000000000000000177e61d5f6ba6b9450e0dade9f39c257b4&#x21b5;
d48b4941ac77e7",
"nextblockhash" : "0000000000000001239d2c3bf7f4c68a4ca673e434702a57da8fe0&#x21b5;
d829a92eb6"
</pre>
++++
The block contains 367 transactions and as you can see, the 18th transaction listed (+9ca8f9...+) is the txid of the one crediting 50 millibits to our address. The +height+ entry tells us this is the 286384th block in the blockchain.
We can also retrieve a block by its block height using the +getblockhash+ command, which takes the block height as the parameter and returns the block hash for that block:
++++
<pre data-type="programlisting">
$ bitcoin-cli getblockhash 0
000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
</pre>
++++
Here, we retrieve the block hash of the "genesis block," the first block mined by Satoshi Nakamoto, at height zero. Retrieving this block shows:
++++
<pre data-type="programlisting">
$ bitcoin-cli getblock 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1&#x21b5;b60a8ce26f
</pre>
++++
++++
<pre data-type="programlisting">
{
"hash" : "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26&#x21b5;
f",
"confirmations" : 286388,
"size" : 285,
"height" : 0,
"version" : 1,
"merkleroot" : "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7af&#x21b5;
deda33b",
"tx" : [
"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"
],
"time" : 1231006505,
"nonce" : 2083236893,
"bits" : "1d00ffff",
"difficulty" : 1.00000000,
"chainwork" : "0000000000000000000000000000000000000000000000000000000100&#x21b5;
010001",
"nextblockhash" : "00000000839a8e6886ab5951d76f411475428afc90947ee320161b&#x21b5;
bf18eb6048"
}
</pre>
++++
The +getblock+, +getblockhash+, and +gettransaction+ commands can be used to explore the blockchain database, programmatically.
[[alt_libraries]]
=== Alternative Clients, Libraries, and Toolkits
((("clients, alternative", id="ix_ch03-asciidoc47", range="startofrange")))((("libraries, alternative", id="ix_ch03-asciidoc48", range="startofrange")))((("toolkits, alternative", id="ix_ch03-asciidoc49", range="startofrange")))Beyond the reference client (bitcoind), other clients and libraries can be used to interact with the bitcoin network and data structures. These are implemented in a variety of programming languages, offering programmers native interfaces in their own language.
Alternative implementations include:
https://github.com/libbitcoin/libbitcoin[libbitcoin]:: ((("libbitcoin library")))Bitcoin Cross-Platform C++ Development Toolkit
https://github.com/libbitcoin/libbitcoin-explorer[bitcoin explorer]:: ((("Bitcoin Explorer")))Bitcoin Command Line Tool
https://github.com/libbitcoin/libbitcoin-server[bitcoin server]:: ((("Bitcoin Server")))Bitcoin Full Node and Query Server
https://code.google.com/p/bitcoinj/[bitcoinj]:: ((("BitcoinJ library")))A Java full-node client library
https://opensource.conformal.com/wiki/btcd[btcd]:: ((("btcd","client")))A Go language full-node bitcoin client
https://bitsofproof.com[Bits of Proof (BOP)]:: ((("Bits of Proof (BOP)")))A Java enterprise-class implementation of bitcoin
https://github.com/jgarzik/picocoin[picocoin]:: ((("picocoin")))A C implementation of a lightweight client library for bitcoin
https://github.com/vbuterin/pybitcointools[pybitcointools]:: ((("pybitcointools library")))A Python bitcoin library
https://github.com/richardkiss/pycoin[pycoin]:: ((("pycoin library")))Another Python bitcoin library
Many more libraries exist in a variety of other programming languages and more are created all the time.
[[libbitcoin]]
==== Libbitcoin and Bitcoin Explorer
The ((("libbitcoin library")))((("libraries, alternative","libbitcoin library")))libbitcoin library is a cross-platform C++ development toolkit that supports the ((("Bitcoin Server")))((("libraries, alternative","Bitcoin Server")))libbitcoin-server full node and the ((("Bitcoin Explorer")))((("libraries, alternative","Bitcoin Explorer")))Bitcoin Explorer (bx) command line tool.
The bx commands offer many of the same capabilities as the bitcoind client commands we illustrated in this chapter. The bx commands also offer some key management and manipulation tools that are not offered by bitcoind, including type-2 deterministic keys and mnemonic key encoding, as well as stealth address, payment, and query support.
===== Installing Bitcoin Explorer
((("Bitcoin Explorer","installing")))To use Bitcoin Explorer, simply https://github.com/libbitcoin/libbitcoin-explorer/wiki/Download[download the signed executable for your operating system]. Builds are available for mainnet and testnet for Linux, OS X, and Windows.
Type +bx+ with no parameters to display the list of all available commands (see <<appdx_bx>>).
Bitcoin Explorer also provides an installer for https://github.com/libbitcoin/libbitcoin-explorer/wiki/Build[building from sources on Linux and OS X, as well as Visual Studio projects for Windows]. Sources can also be built manually using Autotools. These also install the ((("libbitcoin library","installing")))libbitcoin library dependency.
[TIP]
====
Bitcoin Explorer offers many useful commands for encoding and decoding addresses, and converting to and from different formats and representations. Use them to explore the various formats such as Base16 (hex), Base58, Base58Check, Base64, etc.
====
===== Installing Libbitcoin
((("libbitcoin library","installing")))The libbitcoin library provides an installer for https://github.com/libbitcoin/libbitcoin/wiki/Build[building from sources on Linux and OS X, as well as Visual Studio projects for Windows]. Sources can also be built manually using Autotools.
[TIP]
====
The Bitcoin Explorer installer installs both bx and the libbitcoin library, so if you have built bx from sources, you can skip this step.
====
==== pycoin
((("libraries, alternative","pycoin library")))((("pycoin library")))((("Python","pycoin library")))The Python library http://github.com/richardkiss/pycoin[_pycoin_], originally written and maintained by((("Kiss, Richard"))) Richard Kiss, is a Python-based library that supports manipulation of bitcoin keys and transactions, even supporting the scripting language enough to properly deal with nonstandard transactions.
The pycoin library supports both Python 2 (2.7.x) and Python 3 (after 3.3), and comes with some handy command-line utilities, ku and tx. To install pycoin 0.42 under Python 3 in a virtual environment (venv), use the following:
====
----
$ python3 -m venv /tmp/pycoin
$ . /tmp/pycoin/bin/activate
$ pip install pycoin==0.42
Downloading/unpacking pycoin==0.42
Downloading pycoin-0.42.tar.gz (66kB): 66kB downloaded
Running setup.py (path:/tmp/pycoin/build/pycoin/setup.py) egg_info for package pycoin
Installing collected packages: pycoin
Running setup.py install for pycoin
Installing tx script to /tmp/pycoin/bin
Installing cache_tx script to /tmp/pycoin/bin
Installing bu script to /tmp/pycoin/bin
Installing fetch_unspent script to /tmp/pycoin/bin
Installing block script to /tmp/pycoin/bin
Installing spend script to /tmp/pycoin/bin
Installing ku script to /tmp/pycoin/bin
Installing genwallet script to /tmp/pycoin/bin
Successfully installed pycoin
Cleaning up...
$
----
====
Here's a sample Python script to fetch and spend some bitcoin using the pycoin library:
====
[source,python]
----
include::code/pycoin_example.py[]
----
====
For examples using the command-line utilities ku and tx, see <<appdx-pycoin>>.
==== btcd
((("btcd")))((("clients, alternative","btcd")))btcd is a full-node bitcoin implementation written in((("Go programming language"))) Go. It currently downloads, validates, and serves the blockchain using the exact rules (including bugs) for block acceptance as the reference implementation, bitcoind. It also properly relays newly mined blocks, maintains a transaction pool, and relays individual transactions that have not yet made it into a block. It ensures that all individual transactions admitted to the pool follow the rules required and also includes the vast majority of the more strict checks that filter transactions based on miner requirements ("standard" transactions).
One key difference between btcd and bitcoind is that btcd does not include wallet functionality, and this was a very intentional design decision. This means you can't actually make or receive payments directly with btcd. That functionality is provided by the btcwallet and btcgui projects, which are both under active development. Other notable differences between btcd and bitcoind include btcd support for both HTTP POST requests (such as bitcoind) and the preferred Websockets, and the fact that btcd's RPC connections are TLS-enabled by default.
===== Installing btcd
((("btcd","installing")))To install btcd for Windows, download and run the msi available at https://github.com/conformal/btcd/releases[GitHub], or run the following command on Linux, assuming you already have installed the Go language:
----
$ go get github.com/conformal/btcd/...
----
To update btcd to the latest version, just run:
----
$ go get -u -v github.com/conformal/btcd/...
----
===== Controlling btcd
((("btcd","controlling")))btcd has a number of configuration options, which you can view by running:
[source,bash]
----
$ btcd --help
----
btcd comes prepackaged with some goodies such as btcctl, which is a command-line utility that can be used to both control and query btcd via RPC. btcd does not enable its RPC server by default; you must configure at minimum both an RPC username and password in the following configuration files:
* _btcd.conf_:
[source,ini]
----
[Application Options]
rpcuser=myuser
rpcpass=SomeDecentp4ssw0rd
----
* _btcctl.conf_:
[source,ini]
----
[Application Options]
rpcuser=myuser
rpcpass=SomeDecentp4ssw0rd
----
Or if you want to override the configuration files from the command line:
[source,bash]
----
$ btcd -u myuser -P SomeDecentp4ssw0rd
$ btcctl -u myuser -P SomeDecentp4ssw0rd
----
For a list of available options, run the following: (((range="endofrange", startref="ix_ch03-asciidoc49")))(((range="endofrange", startref="ix_ch03-asciidoc48")))(((range="endofrange", startref="ix_ch03-asciidoc47")))(((range="endofrange", startref="ix_ch03-asciidoc0")))
----
$ btcctl --help
----