Bitcoin for beginners, Part 3: The BitCoinJ API

Build a Java-based Bitcoin transaction client

1 2 3 Page 3
Page 3 of 3
001|package com.waferthin.bitcoinj;
002|
003|import java.io.IOException;
004|import java.net.InetAddress;
005|import java.net.UnknownHostException;
006|import java.util.concurrent.ExecutionException;
007|import java.util.concurrent.Future;
008|
009|import com.google.bitcoin.core.*;
010|import com.google.bitcoin.store.BlockStore;
011|import com.google.bitcoin.store.BlockStoreException;
012|import com.google.bitcoin.store.MemoryBlockStore;
013|
014|public class FetchGenesisBlock {
015|
016|    public static void main(String[] args) {
017|
018|        // work with testnet
019|        final NetworkParameters netParams = NetworkParameters.testNet();
020|
021|        // data structure for block chain storage
022|        BlockStore blockStore = new MemoryBlockStore(netParams);
023|
024|        // declare object to store and understand block chain
025|        BlockChain chain;
026|        
027|        try {
028|            
029|            // initialize BlockChain object
030|            chain = new BlockChain(netParams, blockStore);
031|            
032|            // instantiate Peer object to handle connections
033|            final Peer peer = new Peer(netParams, new PeerAddress(InetAddress.getLocalHost()), chain);
034|
035|            // connect to peer node on localhost
036|            peer.connect();
037|            
038|            // run Peer's message handling loop in a thread
039|            new Thread(new Runnable() {
040|                public void run() {
041|                    try {
042|                        peer.run();
043|                    } catch (PeerException e) {
044|                        throw new RuntimeException(e);
045|                    }
046|                }
047|            }).start();
048|
049|            // we found the hash of the genesis block on Bitcoin Block Explorer 
050|            Sha256Hash blockHash = new Sha256Hash("00000007199508e34a9ff81e6ec0c477a4cccff2a4767a8eee39c11db367b008");
051|            
052|            // ask the node to which we're connected for the block
053|            // and wait for a response
054|            Future<Block> future = peer.getBlock(blockHash);
055|            System.out.println("Waiting for node to send us the requested block: " + blockHash);
056|            
057|            // get and use the Block's toString() to output the genesis block
058|            Block block = future.get();
059|            System.out.println("Here is the genesis block:\n" + block);
060|            
061|            // we're done; disconnect from the peer node
062|            peer.disconnect();
063|
064|        // handle the various exceptions; this needs more work
065|        } catch (BlockStoreException e) {
066|            e.printStackTrace();
067|        } catch (UnknownHostException e) {
068|            e.printStackTrace();
069|        } catch (PeerException e) {
070|            e.printStackTrace();
071|        } catch (IOException e) {
072|            e.printStackTrace();
073|        } catch (InterruptedException e) {
074|            e.printStackTrace();
075|        } catch (ExecutionException e) {
076|            e.printStackTrace();
077|        }
078|    }
079|}

Below is the output produced by running our example.

Waiting for node to send us the requested block: 00000007199508e34a9ff81e6ec0c477a4cccff2a4767a8eee39c11db367b008
Here is the genesis block:
v1 block: 
   previous block: 0000000000000000000000000000000000000000000000000000000000000000
   merkle root: 4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
   time: [1296688602] Wed Feb 02 15:16:42 PST 2011
   difficulty target (nBits): 487063544
   nonce: 384568319
   with 1 transaction(s):
     == COINBASE TXN (scriptSig [4]ffff001d ?(4) [69]5468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73 )  (scriptPubKey [65]04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f CHECKSIG )

Sending Bitcoins

For our last exercise we will create a small application to send Bitcoins from our wallet to a Bitcoin address. For this task, we will use the Wallet class's sendCoins(Peer peer, Address to, BigInteger nanocoins) method.

If you want to experiment with the test network, you can get Bitcoins for free from Bitcoin Faucet.

Unlike in the other examples, this time we will get all our input from the command line. Our application will require the following arguments in the order given:

  1. Which network ("test" or "prod")
  2. The name of the wallet file containing Bitcoins
  3. Number of nano Bitcoins to send
  4. Bitcoin address of the recipient

In Listing 5 we handle the command-line arguments (lines 18 to 29) and initialize various components we have seen before, including instances of the NetworkParameters, BlockChain, Wallet, and Peer classes. The amount to send is specified as a BigInteger, where each unit represents 1/100000000th of a Bitcoin (line 59). We instantiate an Address object based on a Bitcoin address provided by the standard client (line 71). We then invoke the Wallet class's sendCoins() method to initiate the transaction (line 74). A return value of null would indicate that not enough funds were in the wallet for the requested transaction. Otherwise, we output a confirmation and a link to our send transaction on the Bitcoin Block Explorer site.

Listing 5. SendCoins

001|package com.waferthin.bitcoinj;
002|
003|import java.io.File;
004|import java.io.IOException;
005|import java.math.BigInteger;
006|import java.net.InetAddress;
007|import java.net.UnknownHostException;
008|
009|import com.google.bitcoin.core.*;
010|import com.google.bitcoin.store.BlockStore;
011|import com.google.bitcoin.store.BlockStoreException;
012|import com.google.bitcoin.store.MemoryBlockStore;
013|
014|public class SendCoins {
015|
016|    public static void main(String[] args) {
017|
018|        if (args.length != 4) {
019|            System.out.println("Usage: java SendCoins prod|test wallet amount recipient");
020|            System.exit(1);
021|        }
022|        
023|        // we get the following from the command line ...
024|        // (this is not secure - needs validation)
025|        String network          = args[0];  // "test" or "prod"
026|        String walletFileName   = args[1];  // wallet file name
027|        String amountToSend     = args[2];  // milli-BTC
028|        String recipient        = args[3];  // Bitcoin address
029|
030|        // the Bitcoin network to use
031|        final NetworkParameters netParams;
032|        
033|        // check for production Bitcoin network ...
034|        if (network.equalsIgnoreCase("prod")) {
035|            netParams = NetworkParameters.prodNet();
036|        // ... otherwise use the testnet
037|        } else {
038|            netParams = NetworkParameters.testNet();
039|        }
040|
041|        // data structure for block chain storage
042|        BlockStore blockStore = new MemoryBlockStore(netParams);
043|
044|        // declare object to store and understand block chain
045|        BlockChain chain;
046|        
047|        // declare wallet
048|        Wallet wallet;
049|        
050|        try {
051|            
052|            // wallet file that contains Bitcoins we can send
053|            final File walletFile = new File(walletFileName);
054|
055|            // load wallet from file
056|            wallet = Wallet.loadFromFile(walletFile);
057|            
058|            // how man milli-Bitcoins to send
059|            BigInteger btcToSend = new BigInteger(amountToSend);
060|                    
061|            // initialize BlockChain object
062|            chain = new BlockChain(netParams, wallet, blockStore);
063|
064|            // instantiate Peer object to handle connections
065|            final Peer peer = new Peer(netParams, new PeerAddress(InetAddress.getLocalHost()), chain);
066|
067|            // connect to peer node on localhost
068|            peer.connect();
069|            
070|            // recipient address provided by official Bitcoin client
071|            Address recipientAddress = new Address(netParams, recipient);
072|
073|            // tell peer to send amountToSend to recipientAddress
074|            Transaction sendTxn = wallet.sendCoins(peer, recipientAddress, btcToSend);
075|            
076|            // null means we didn't have enough Bitcoins in our wallet for the transaction
077|            if (sendTxn == null) {
078|                System.out.println("Cannot send requested amount of " + Utils.bitcoinValueToFriendlyString(btcToSend)
079|                                + " BTC; wallet only contains " + Utils.bitcoinValueToFriendlyString(wallet.getBalance()) + " BTC.");
080|            } else {
081|                
081|                // once communicated to the network (via our local peer),
083|                // the transaction will appear on Bitcoin explorer sooner or later
084|                System.out.println(Utils.bitcoinValueToFriendlyString(btcToSend) + " BTC sent. You can monitor the transaction here:\n"
085|                                + "http://blockexplorer.com/tx/" + sendTxn.getHashAsString());
086|            }
087|
088|            // save wallet with new transaction(s)
089|            wallet.saveToFile(walletFile);
090|
091|        // handle the various exceptions; this needs more work
092|        } catch (BlockStoreException e) {
093|            e.printStackTrace();
094|        } catch (UnknownHostException e) {
095|            e.printStackTrace();
096|        } catch (PeerException e) {
097|            e.printStackTrace();
098|        } catch (AddressFormatException e) {
099|            e.printStackTrace();
100|        } catch (IOException e) {
101|            e.printStackTrace();
102|        }
103|    }
104|}

Following is the output from running the command line: java com.waferthin.bitcoinj.SendCoins prod sendcoins-prodnet.wallet 2000000 13RwREqwoNhVkcbpKSUMg9Ea6JnNuy85Qz:

0.02 BTC sent. You can monitor the transaction here:
http://blockexplorer.com/tx/078e0fc3577a039afac327c6509aa0e0cc680a51011ebb67486b5fc05e28a139

Figure 4 shows the coins being received at the recipient address.

Figure 4. Coins being received (click to enlarge)

After a few minutes we can view the transaction online at the Bitcoin Block Explorer link provided by the application:

Figure 5. View the transaction with Bitcoin Block Explorer (click to enlarge)

In conclusion

That's it for our whirlwind tour of the BitCoinJ project. There is still much functionality that was not covered in this article, but with a solid understanding of the basic components provided by BitCoinJ, you should be able fill in the blanks. A worthwhile followup exercise would be downloading the whole block chain and iterating over it while outputting some piece of information about each block. Also, figuring out how to receive Bitcoins would be another instructive exercise.

Hopefully you can take what you have learned in this article as a starting point for creating more complex applications. Maybe you can even start contributing to the BitCoinJ project itself.

Dirk Merkel is the CTO at VivanTech Inc. He has been developing software in a variety of languages for over 25 years and has been getting paid for it for over 15 years. In his spare time, he likes to learn about new technologies and ruin perfectly good open-source projects by submitting unsolicited patches. He also writes about technology, software development, and architecture. He lives in San Diego with his lovely wife and two wonderful daughters. Dirk can be reached at dmerkel@vivantech.com.

Learn more about this topic

More from JavaWorld

  • See the JavaWorld Site Map for a complete listing of research centers focused on client-side, enterprise, and core Java development tools and topics.
  • JavaWorld's Java Technology Insider is a podcast series that lets you learn from Java technology experts on your way to work.
1 2 3 Page 3
Page 3 of 3