BITCOIN PROGRAMMING WITH BITCOINJ - Bitcoin for the Befuddled (2015)

Bitcoin for the Befuddled (2015)

B. BITCOIN PROGRAMMING WITH BITCOINJ

In Appendix A, we dabbled with JavaScript code that could perform some basic actions with a Bitcoin wallet by automating a preexisting wallet. In this appendix, we’ll write far more powerful programs that directly insert themselves into the Bitcoin network. As discussed previously, Bitcoin programs written this way—meaning those that do not rely on APIs from external companies and avoid dependencies on separate wallet programs—are usually the smartest solution for serious Bitcoin development projects.

The Best Programming Language for Connecting to the Bitcoin Network

If you’re an experienced programmer, most likely you have a favorite programming language you would prefer to use to write your Bitcoin programs. However, only a few mature libraries currently exist that can connect directly to the Bitcoin network. One is the C++ reference implementation with which all the first full clients of the Bitcoin system were written.1 Large enterprise companies interested in supporting bitcoins should use this library. However, working with C++ is difficult for novices.

Another mature library is written in Java and is called bitcoinJ.2 Because Java is easier to work with than C++, it is the library we’ll use. (The bitcoinJ library can also be used easily from languages built on top of the Java Virtual Machine, such as Scala or Clojure.)

Currently, the options for other languages are rather limited. By searching the Internet, you will find Bitcoin libraries for other languages, such as Ruby, C#, and Python. However, most of these libraries are either in extremely early development or simply use the more limited JSON-RPC interface, which was discussed in Appendix A.

NOTE
Some serious attempts are being made to offer full Bitcoin client support within the Go programming language. However, at the time of this writing, these libraries are either still in early development (such as gocoin3) or are missing major features (such as btcd 4).

No matter which library you choose, keep in mind that you must be vigilant about security. Essentially, when you use any of these libraries, you’ll be giving the library authors the keys to your Bitcoin kingdom. As we warned previously, technically it would be relatively easy to introduce rogue code into one of these libraries to steal all your money!

Installing Java, Maven, and the BitcoinJ Library

Let’s ready your computer to do Java and bitcoinJ programming. The following steps should work on any major OS: Windows, Mac, or Linux.

Step 1: Installing Java

The Java programming language is maintained by Oracle Corporation. Your computer may already have Java installed, but if you’ve never done Java development, your computer may only contain the Java JRE (Java Runtime Engine), which can run Java programs but is not adequate for developing them. Instead, you need the Java JDK (Java Development Kit). To download the JDK, do a Google search for Java JDK. The first link (which should be a link on the official Oracle website) should direct you to the right place to access the download.

NOTE
Linux developers: Some versions of Linux may install the OpenJDK version of Java by default. At the time of this writing, this unofficial Java variant is missing some components that this tutorial depends on. Instead, look online for information about installing the Oracle JDK on your version of Linux and make it the default Java version on your system.

Step 2: Installing Maven

Maven is a packaging tool for Java. Essentially, you specify which libraries your program needs, and Maven automatically downloads them from the Internet and makes them available to your program. This is analogous to the Node Package Manager used in Appendix A.

You can download Maven and find instructions for installing Maven on each OS at https://maven.apache.org/. Just follow the instructions at the main Maven website to install it or search Google for tutorials. Because more than a million other people have had to install Maven, if you run into installation problems, just type your problem into Google. It is very likely you’ll get helpful information on how to solve your problem.

NOTE
Windows users: At the time of this writing, detailed instructions for installing Maven on Windows are cleverly hidden at the very bottom of http://maven.apache.org/download.cgi. Mac/Linux users: You can use your package managers here: brew install maven for Mac and sudo apt-get install maven for Debian Linux.

To ensure Maven is properly installed, a version message should display when you type mvn --version from a console.

For typical Java programming, we could stop here because any needed additional libraries could be downloaded through the Maven package system. However, because we’re writing programs that work with money, the bitcoinJ maintainers require all developers to take a few extra precautions and install a couple of additional tools that directly relate to security issues.

Step 3: Installing Git

For security reasons, we’ll install Git, which is a popular source code management tool. But it also offers features for securely downloading source code from online repositories that we’ll rely on. Download Git from http://git-scm.com/.

NOTE
Once again, Mac and Linux users can use their package managers: brew install git and apt-get install git, respectively. Do you see a pattern?

Step 4: Installing BitcoinJ

BitcoinJ is a Bitcoin library that can “talk bitcoin” and can connect directly to the Bitcoin network. By calling functions in this library, we can send and receive bitcoins in real time.

We’ll build bitcoinJ directly from its authoritative source. Navigate to a directory from the console where you want to install the bitcoinJ library (your Home directory would be a good place).

NOTE
A new subdirectory will be created, so other existing files in this directory will not be affected by this installation.

Enter the following into your console (on Windows you may need to use the special Git Bash console that was installed when you installed Git):

> git clone https://github.com/bitcoinj/bitcoinj.git ➊
> cd bitcoinj
> git checkout cbbb1a2 ➋
> mvn install ➌

The first line downloads the bitcoinJ code from the authoritative website ➊. Then, we use git to switch to an older version of this library using the git checkout command ➋. During this tutorial, this command will shield us from any problems that might be caused by newer versions of the library. However, when you’ve completed the tutorials, you can switch to the newest version of bitcoinJ (git checkout master) to experiment with its shiny new features. The last line installs the package into the local Maven package repository ➌. When we reference bitcoinJ from our programs, Maven will fetch it from this repository (instead of grabbing it from the Internet), and we can be confident we’re using an uncorrupted version of this library.

Now we can finally start programming!

Creating a Starter Project for hello-money

In Appendix A, we created a JavaScript program called Hello Money! that detects when money is sent to a Bitcoin address. Now, we’ll write a more sophisticated program with Java and bitcoinJ that accomplishes the same task. From the console, navigate to a directory where you want your new program to live, such as your computer’s Home or Documents folder. A subdirectory will be created in this place.

Now type the following to have Maven create an empty starter project:

mvn archetype:generate -DgroupId=hellomoney -DartifactId=hello-money
-DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

These commands create a directory called hello-money at the current location with the hello-money starter project.

NOTE
If Maven prompts you for answers during this process, just keep pressing ENTER to use the default setting.

Next, we need to inform Maven that this program will use a couple of external libraries. We do this by editing the file pom.xml, which should now exist in the new directory. Also in this file should be a section named <dependencies> where we’ll add bitcoinJ as a new dependency. After the previous dependency (i.e., after the line that reads </dependency> singular), add the following:

<dependency>
<groupId>com.google</groupId>
<artifactId>bitcoinj</artifactId>
<version>0.8</version>
<scope>compile</scope>
</dependency>

Now we’ll add a plug-in called exec-maven-plugin to our program. A plug-in is a special type of library. The exec-maven-plugin will make it easier to run our finished program from the command line.

At the very bottom of the projects in pom.xml (i.e., after the line that reads </dependencies> plural), add the following lines:

<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<arguments>
</arguments>
<mainClass>hellomoney.App</mainClass>
</configuration>
</plugin>
</plugins>
</build>

Now we’re ready to run this empty program for the first time as a test. To do this, execute the following lines from the console in the program’s directory:

> mvn install ➊
> mvn exec:java ➋

Hello World!

The first line ➊ loads all the necessary libraries into the project and builds the program into a Java bytecode file. The second line ➋ actually runs the program.

If the program runs successfully, you should see Hello World! printed on the screen. This means Maven has successfully created a functioning Java program and that we’re now ready to start writing the core Bitcoin code.

Writing the Code for hello-money

The entirety of the code for our hello-money program follows. To add this to the project, open the file src/main/java/hellomoney/App.java and replace its contents with this program:

package hellomoney;
import com.google.bitcoin.core.*;
import com.google.bitcoin.store.*;
import com.google.bitcoin.discovery.DnsDiscovery;
import java.io.File;
import java.math.BigInteger;

public class App
{
public static void main( String[] args ) throws BlockStoreException
{
NetworkParameters params = NetworkParameters.prodNet();
Wallet wallet = new Wallet(params);
ECKey key = new ECKey();
System.out.println("Public address: " +
key.toAddress(params).toString());
System.out.println("Private key: " +
key.getPrivateKeyEncoded(params).toString());
wallet.addKey(key);
File file = new File("my-blockchain");
SPVBlockStore store=new SPVBlockStore(params, file);
BlockChain chain = new BlockChain(params, wallet, store);
PeerGroup peerGroup = new PeerGroup(params, chain);
peerGroup.addPeerDiscovery(new DnsDiscovery(params));
peerGroup.addWallet(wallet);
peerGroup.start();
peerGroup.downloadBlockChain();
wallet.addEventListener(new AbstractWalletEventListener()
{
public void onCoinsReceived(Wallet wallet,
Transaction tx, BigInteger prevBalance,
BigInteger newBalance)
{
System.out.println("Hello Money! Balance: "
+ newBalance + " satoshis");
}
});
while(true){}
}
}

Next, run the command mvn install, which checks the syntax of this new program code and builds it into a program file. If the build works, the message BUILD SUCCESS should appear (along with tons of other esoteric messages).

Before we run the program, let’s walk through it step-by-step to see what it does.

Declarations at the Top of the Program

The first line in the program declares the name of the package:

package hellomoney;

Next, we declare all the libraries the program will reference:

import com.google.bitcoin.core.*;
import com.google.bitcoin.store.*;
import com.google.bitcoin.discovery.DnsDiscovery;
import java.io.File;
import java.math.BigInteger;

Three of these references are for Bitcoin classes: First, we’ll use the core libraries to access basic Bitcoin classes (such as classes for wallets and keys). Second, we need classes for storing the blockchain (called a block store in BitcoinJ lingo). Third, we need to use the DnsDiscoveryclass, which helps us find other nodes participating in the Bitcoin network. We import the java.io.File class because we’ll be writing our block store to a file, and we import the java.math.BigInteger class to work with, well, big integers.

Now let’s define the Java class that holds the program:

public class App
{
public static void main( String[] args ) throws BlockStoreException
{

The program code is stored in a new class called App, which contains a single member function main. We mentioned this hellomoney.App class in the pom.xml file, declaring it as the main class of the program.

Let’s look at individual lines in the main function.

Initializing Our Java Objects

Here is the code that initializes the Java object we need from the bitcoinJ library.

NetworkParameters params = NetworkParameters.prodNet();➊
Wallet wallet = new Wallet(params);➋
ECKey key = new ECKey();➌
System.out.println("Public address: " +➍
key.toAddress(params).toString());
System.out.println("Private key: " +➎
key.getPrivateKeyEncoded(params).toString());
wallet.addKey(key);➏

We start by fetching the network parameters for the main, production Bitcoin network ➊. Although only one true Bitcoin network is actually used for transactions, it’s difficult to test the Bitcoin system thoroughly with real money; therefore, Bitcoin developers also maintain a second Bitcoin network called TestNet for testing only. The NetworkParameters structure contains information about the genesis block (the first block in the block-chain) as well as information about the maximum number of coins and several other assorted details, which may differ between the main Bitcoin network and the TestNet. By having all this information packed in the NetworkParameters data structure, it’s easy to connect our program to another network besides the main Bitcoin network, such as the TestNet, as desired.

Next, we create a new, empty wallet that we’ll set up to receive our coins ➋. As discussed earlier, Bitcoin wallets contain one or more Bitcoin addresses, and each Bitcoin address consists of a public and a private key. Here ➌, the bitcoinJ library creates a new key pair for us. Then, we print out the public address and private keys that were generated ➍➎. Finally, we add our new key pair to the wallet ➏.

WARNING
Usually, when using bitcoinJ, you should reuse the same wallet every time the program runs and load/save it every time the program starts/stops or your program can lose track of money. This is not an issue for the simple hello-money program. However, before you build more sophisticated bitcoinJ programs, read “Gotchas When Using Wallets in BitcoinJ” on page 239.

Not only does a Bitcoin app need a wallet, it also needs a blockchain. The following lines initialize a new blockchain for us:

File file = new File("my-blockchain");➊
SPVBlockStore store = new SPVBlockStore(params, file);➋
BlockChain chain = new BlockChain(params, wallet, store);➌

Because blockchains consume lots of space, we’ll write it to a file named my-blockchain ➊. Next, we create a block store, which is an object that manages the data for our copious blockchain data ➋. BitcoinJ offers several block store types, all with different feature and performance trade-offs. In this example, we’ll use an SPVBlockStore object, which is usually the best choice for most apps.

So what are the trade-offs you need to know about? Well, the biggest performance challenge any app that works with bitcoins has to deal with is that the official Bitcoin blockchain is larger than 10GB in size. Do most Bitcoin apps really need all 10GB of the blockchain?

To answer this question, let’s consider why the blockchain exists. At a simplified level, a Bitcoin blockchain is responsible for two main jobs:

1. Figuring out how much money everyone on the network has

2. Figuring out whether new transactions broadcast across the network are valid

For the first task, the blockchain allows us to examine all the historical blocks in the blockchain and compile comprehensive data about every Bitcoin address ever used and how much money each contains. For the second task, it allows us to examine new blocks of transactions created by the network and then to verify that these blocks have the appropriate hashing information that proves they are correctly mined blocks according to the latest difficulty requirements.

But consider the first job of the blockchain: Do most apps need to discern how much money is in every wallet in existence? No, most apps only need to identify the amount of money in one or a small number of wallets. Therefore, not all 10GB of data are needed. The prescient Satoshi, in his original Bitcoin whitepaper, was able to see that in this case, an optimization called Simplified Payment Verification (SPV) was possible.

NOTE
We also covered SPV a bit in Chapter 9, when comparing different types of Bitcoin wallets.

Here’s a quick refresher of how SPV works: If you know you’re interested in a single wallet ahead of time, you can just tally up how much money is in that one wallet as you pull the entire historical blockchain off the Bitcoin network. At that point, you only need to store header information of blocks and can ignore information in older blocks entirely in most situations, which is what SPVBlockStore does. In doing so, the SPVBlockStore (as of 2014) is less than 1GB in size, less than a one-tenth the size of the official blockchain, and this is why we useSPVBlockChain to store our data.

Once we’ve created the block store, we can use it to create a BlockChain object ➌. Notice that when we create this BlockChain object, we must pass in our wallet as created. Because we’re not downloading all 10GB, the block-chain object needs to know ahead of time which wallets (and their addresses) are important to us so it can select the right blockchain data to download.

NOTE
Even though SPVBlockStore is much smaller than the full blockchain, it can still take a long time for your app to download all the needed data from the network—usually, about 20 minutes. However, it will write this data to a file, and an SPVBlockStore object is smart enough to check the supplied file to see whether any data has already been downloaded since the last time the program was run. If so, it downloads only new data that has arrived after the program was last run.

Connecting to the Bitcoin Network

With a wallet and a place to store the blockchain data, we can now connect to the actual Bitcoin network. A Bitcoin node connects to the Bitcoin network by connecting to several semirandom peer nodes. Here is the code that fires up a connection to several peers:

PeerGroup peerGroup = new PeerGroup(params, chain);➊
peerGroup.addPeerDiscovery(new DnsDiscovery(params));➋
peerGroup.addWallet(wallet);➌
peerGroup.start();➍
peerGroup.downloadBlockChain();➎

First we create a PeerGroup object ➊ that manages these connections. Next, we choose some random peers to connect to. We do this by adding a peer discovery algorithm to the PeerGroup ➋. The DnsDiscovery class basically uses the URLs of some well-established and trusted nodes as a starting point to discover peers that are willing to accept new connections. Then we add our wallet to the PeerGroup object ➌.

Now we’re finally ready to inject the app into the Bitcoin network! We do this by calling PeerGroup.start ➍, which will find and connect to some nodes and perform the appropriate handshake operations via network sockets. And, like any Bitcoin node, we request that the peers send us the blockchain so we can become a fully functional node ➎. As mentioned previously, this step will take a while to run, but only the first time we run the program.

Listening for New Money

One last feature we need to add to the hello-money program is a hook to detect when money has arrived:

wallet.addEventListener(new AbstractWalletEventListener()➊
{
public void onCoinsReceived(Wallet wallet, Transaction tx,➋
BigInteger prevBalance, BigInteger newBalance)
{
System.out.println("Hello Money! Balance: "
+ newBalance + " satoshis");
}
});

The bitcoinJ wallet object has an addEventListener member function, and we can create an anonymous class of type EventListener, which intercepts and listens to different events that might happen to a wallet ➊. In our app, we’re interested in the onCoinsReceivedfunction ➋, which will be called every time money is received by this wallet. Let’s explore in more detail exactly what this means.

Because the program lives directly in the Bitcoin network, it can listen to the bitcoin firehose, a stream of data that contains every Bitcoin transaction happening anywhere in the world in close to real time. Each transaction is examined to see whether it involves receiving money into any Bitcoin address contained in our wallet. In our app, the wallet contains only one address. As soon as this transaction arrives (even before it has been incorporated into a mined block), our function onCoinsReceved will be called.

NOTE
In the hello-money program, we won’t worry about capturing confirmation events on the money received; we’ll only listen for the transmission of new, unconfirmed transactions. However, if we were interested in confirmations, we could capture them via the onTransactionConfidenceChanged function. Because we’re running a full Bitcoin client, we can do what we want, whereas in Appendix A we were forced to look only at confirmed transactions due to the limitations of the JSON-RPC interface.

The onCoinsReceived function has four parameters passed into it ➋: the wallet object, a transaction object, the previous balance in the wallet, and the new balance. The bitcoinJ library uses the Java BigInteger class to encode Bitcoin balances, because this numerical type can handle very large integers precisely. If you’ve written financial software before, you’ll know why the BigInteger class is used (or you may recall how the bank heist was done in the movie Office Space). The fact is that it’s very easy to botch a financial transaction due to rounding errors, and using big, precise integers prevents this problem. Hence, bitcoinJ performs all Bitcoin math using satoshis, the smallest unit of bitcoins, which are worth one one-hundred-millionth of a bitcoin.

NOTE
Because we added the event listener after we downloaded the initial blockchain, the onCoinsReceived function will be called only when new transactions appear as the program is running. If we had declared it before downloading the initial blockchain, the design of bitcoinJ is such that onCoinsReceived would also have been called on relevant historical transactions.

Finally, we put the program into an infinite loop, so the program continues running as we wait for money to arrive:

while(true){}

Running and Testing the hello-money Java Program

We’re ready to run and test the program! As before, we first compile and then run the program:

> mvn install
> mvn exec:java

Some messages should then appear as your program connects to the Bitcoin network and downloads the blockchain. The first time the program is run, this may take a while:

Public address: 16YavT6SmJCuJpZgzRa6XG9WefPEu2M45
Private key: L3eoA1rXiD8kWFUzdxw744NWjoZNB5BGsxhzVas6y5KJgVteZ4uD
Downloading block chain of size 265184. This may take a while.
Chain download 1% done with 262532 blocks to go, block date Feb 1, 2009 5:09:55 PM
Chain download 2% done with 259880 blocks to go, block date Feb 22, 2009 11:32:14 PM
Chain download 3% done with 257228 blocks to go, block date Mar 18, 2009 9:59:38 PM
Chain download 4% done with 254576 blocks to go, block date Apr 11, 2009 4:27:52 PM
Chain download 5% done with 251924 blocks to go, block date May 4, 2009 9:23:54 AM
...
Done downloading block chain

After the blockchain has finished downloading, you can test the hello-money program and send it some tiny sum from your favorite wallet app. Simply send 0.0002 BTC to the public address and record the private key (we’ll be using this money in the follow-up example program later in this appendix). The program should detect when the money arrives and display a message like this:

Hello Money! Balance: 20000 satoshis

The new balance in the wallet should display in satoshis (divide by 100,000,000 to see that this number is indeed 0.0002 BTC).

You’ve successfully written a bitcoinJ program that creates a Bitcoin wallet and reports on any money received. Now let’s write a second program that uses the newly stored money!

Bye-Bye Money

Now, let’s write a brand-new program that can send money from an arbitrary Bitcoin address. To create a new bye-bye-money program, run the following from your top-level program directory:

mvn archetype:generate -DgroupId=byebyemoney -DartifactId=bye-bye-money
-DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

Then, make the exact additions to the pom.xml file as we did in the hello-money example, except for the line that reads <mainClass>hellomoney.App</mainClass>. Change that line to <mainClass>byebyemoney.App</mainClass>. (These steps are analogous to those we followed for our hello-money program in “Creating a Starter Project for hello-money” on page 228.)

Just as before, open the file src/main/java/byebyemoney/App.java and replace its contents with the following program:

package byebyemoney;

import com.google.bitcoin.core.*;
import com.google.bitcoin.store.*;
import com.google.bitcoin.discovery.DnsDiscovery;
import java.util.concurrent.ExecutionException;
import java.io.File;
import java.math.BigInteger;

public class App
{
public static void main( String[] args )
throws BlockStoreException, AddressFormatException,
InterruptedException, ExecutionException
{
NetworkParameters params = NetworkParameters.prodNet();
Wallet wallet = new Wallet(params);
DumpedPrivateKey key = new DumpedPrivateKey(params,
"L1vJHdDqQ5kcY5q4QoY124zD21UVgFe6NL2835mp8UgG2FNU94Sy");
wallet.addKey(key.getKey());
BlockChain chain = new BlockChain(params, wallet,
new MemoryBlockStore(params));
PeerGroup peerGroup = new PeerGroup(params, chain);
peerGroup.addPeerDiscovery(new DnsDiscovery(params));
peerGroup.addWallet(wallet);
peerGroup.start();
peerGroup.downloadBlockChain();
BigInteger balance = wallet.getBalance();
System.out.println("Wallet balance: " + balance);
Address destinationAddress = new Address(params,
"1BTCorgHwCg6u2YSAWKgS17qUad6kHmtQW");
BigInteger fee=BigInteger.valueOf(10000);
Wallet.SendRequest req = Wallet.SendRequest.to(
destinationAddress,balance.subtract(fee));
req.fee = fee;
Wallet.SendResult result = wallet.sendCoins(peerGroup, req);
if(result != null)
{
result.broadcastComplete.get();
System.out.println("The money was sent!");
}
else
{
System.out.println("Something went wrong sending the money.");
}
}
}

Many of the lines in this new program are shared with our previous hello-money program, but let’s look carefully at the new parts.

Importing a Private Key

To send money from our program, we need to import the private key of the Bitcoin address from the previous example. Here is the code that does this:

DumpedPrivateKey key = new DumpedPrivateKey(params,➊
"L1vJHdDqQ5kcY5q4QoY124zD21UVgFe6NL2835mp8UgG2FNU94Sy");
wallet.addKey(key.getKey());➋
BlockChain chain = new BlockChain(params, wallet,➌
new MemoryBlockStore(params));

In the first lines, we’re explicitly adding a new, preexisting private key to our wallet ➊➋. This is the key associated with the Bitcoin address that received the money in the hello-money program. You need to replace the private key shown on this line with the private key you wrote down when running the previous example. Also, in this new program we’re not using the SPVBlockStore function; instead, we’re using bitcoinJ’s MemoryBlockStore ➌ function for variety. This block store won’t create a file, but by using it, our program will need to redownload the blockchain every time the program runs. (This also guarantees that bitcoinJ will assign the correct balance to the wallet. We’ll discuss why in “Gotchas When Using Wallets in BitcoinJ” on page 239.)

Sending the Money

Now let’s look at the code that actually sends the money:

BigInteger balance = wallet.getBalance();➊
System.out.println("Wallet balance: " + balance);➋
Address destinationAddress = new Address(params,➌
"1BTCorgHwCg6u2YSAWKgS17qUad6kHmtQW");
BigInteger fee = BigInteger.valueOf(10000);➍
Wallet.SendRequest req = Wallet.SendRequest.to(➎
destinationAddress,balance.subtract(fee));
req.fee = fee;➏
Wallet.SendResult result = wallet.sendCoins(peerGroup, req);➐

First, we get the balance contained in the wallet ➊ and display it ➋. Next, we declare the destination address the money should be sent to ➌. In this example, we input the main donation address for the Bitcoin Foundation; feel free to substitute a public address of one of your own wallets.

Nowadays, it’s best to include a transaction fee when sending bitcoins, which we declare to be 10,000 satoshis ➍. Next, we create a SendRequest object ➎, which is a structure to hold the basic information about what we’re sending and includes the destination address and the amount to be sent (which is the balance minus the fee). Then, we set the fee on this object ➏ and send our money ➐!

Ensuring the Money Transmission

If we try to send more money than we have, if the fee is inadequate, or if the Internet connection drops out at the wrong moment, the money might never be accepted by the network. Therefore, we need to write code that waits and ensures that the money we sent is transmitted to the network. Here’s what we’ll add to do this:

result.broadcastComplete.get();➊
System.out.println("The money was sent!");➋

The first line of code ➊ retrieves a Java future object, which indicates that the send transaction has been properly broadcast to the network. (A standard in Java, futures retrieve information about a separate execution thread—in this case the thread that monitors communication with the Bitcoin network.) If this line completes without throwing an exception, we display a message indicating that the money was sent ➋.

Running bye-bye-money

We can run bye-bye-money in the usual way (remember to input your own private key):

> mvn install
> mvn exec:java

EXCEPTION TYPES IN BITCOINJ

One feature we skimped on in this example is error handling: The main function simply rethrows a variety of different exceptions for operations that can go wrong as we attempt to send our money. These include the following exceptions:

• BlockStoreException: This is thrown when the block store cannot be created (most commonly, this happens with block store types that write to a file when something corrupts the file).

• AddressFormatException: This is thrown when the format of the address is incorrect.

• InterruptedException: This is thrown when network connection problems occur.

• ExecutionException: This is thrown when we’re using a future object and an exception occurs in the other thread (as happens when we check for completion of the transaction broadcast).

In a more sophisticated Bitcoin app, you should catch all of these exception types separately and add more descriptive error messages for your app’s users.

Because this program churns through the blockchain in memory, you’ll need to wait a few minutes or more for it to complete (even when you rerun it). If the program is successful, you’ll see the message The money was sent!, and the money should arrive at the destination wallet. You can also access a blockchain information site (such as http://blockchain.info/), enter the source or destination address, and see that the details of the transaction are part of the public record.

Congratulations! You now understand the basics of writing a Bitcoin application!

Gotchas When Using Wallets in BitcoinJ

To the novice, the way wallets and the BlockChain object work in bitcoinJ can be very confusing. If you don’t fully understand bitcoinJ’s behavior, bitcoinJ can also report incorrect wallet balances.

This happens because bitcoinJ is optimized around the concept of an SPV blockchain. The performance benefits of SPV blockchains were discussed earlier, but because they contain only limited blockchain data, you need to follow a few basic rules to ensure they work properly for you in bitcoinJ:

1. If your app’s wallet already has money in it, bitcoinJ needs to know the amount before the blockchain is downloaded from the network.

2. After the blockchain is loaded, bitcoinJ will perform the necessary tasks to ensure the wallet’s accuracy as new transactions appear on the network.

3. If you use a block store type that supports saving to a disk file, your app is responsible for saving the wallet to a file, as well (it is also responsible for loading the block store and wallet data).

As you saw when we constructed a BlockChain object, bitcoinJ expects the app to pass in a wallet object. This allows the wallet to be updated when relevant historical transactions are found in downloaded blocks and allows rule #1 to be enforced: Be sure not to add additional keys to your wallet after the fact and expect your wallet to work without redownloading the blockchain.

Similarly, when we initialized the PeerGroup object, we called addWallet() to add our wallet to the peer group. By doing so, bitcoinJ keeps the wallet balance in sync with any new transactions that appear in the Bitcoin network as the program is running, enforcing rule #2.

To make sure rule #3 is adhered to, you can use the Wallet.loadFromFile() and Wallet.saveToFile()functions. A Wallet.autoSaveToFile() function is also available that can help with loading and saving the block store and wallet data. To learn how to use these functions properly, look at the example programs in the bitcoinJ repository.

If you keep the previously listed three basic tenets in mind, you’ll avoid most of the pitfalls that accompany mastering bitcoinJ.

Conclusion

We hope you’ve enjoyed this tour of bitcoinJ programming, and we look forward to seeing any awesome new apps that you build. After all, the app you build just might completely reinvent how people interact with their money in the Internet age!