比特幣(BitCoin)是一種基於區塊鏈(BlockChain)技術的數字化貨幣. 本文介紹了使用基於Java語言的BitCoinJ API實現一個簡單的收取和支付比特幣的示例程序.
本示例使用BitCoinJ(https://bitcoinj.github.io/) API, 目前的發布版本是0.14.3, 其JAR包可以從官網下載, 也可以通過如下的Maven定義在項目POM中引用.
<dependencies>
<dependency>
<groupId>org.bitcoinj</groupId>
<artifactId>bitcoinj-core</artifactId>
<version>0.14.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
收取比特幣的示例代碼如下
public class BitCoinHelloWorld implements WalletCoinsReceivedEventListener {
publicstaticvoidmain(String[] args) {
BitCoinHelloWorld demo = new BitCoinHelloWorld();
demo.run();
}
publicvoidrun() {
try {
init();
System.out.println("Waiting for coins...");
while (true) {
Thread.sleep(20);
}
} catch (BlockStoreException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
privatevoidinit() throws BlockStoreException {
NetworkParameters params = TestNet3Params.get();
ECKey key = new ECKey();
System.out.println("We created a new key:\n" + key);
Address addressFromKey = key.toAddress(params);
System.out.println("Public Address generated: " + addressFromKey);
System.out.println("Private key is: " + key.getPrivateKeyEncoded(params).toString());
Wallet wallet = new Wallet(params);
wallet.importKey(key);
File blockFile = new File("/tmp/bitcoin-blocks");
SPVBlockStore blockStore = new SPVBlockStore(params, blockFile);
BlockChain blockChain = new BlockChain(params, wallet, blockStore);
PeerGroup peerGroup = new PeerGroup(params, blockChain);
peerGroup.addPeerDiscovery(new DnsDiscovery(params));
peerGroup.addWallet(wallet);
System.out.println("Start peer group");
peerGroup.start();
System.out.println("Downloading block chain");
peerGroup.downloadBlockChain();
System.out.println("Block chain downloaded");
wallet.addCoinsReceivedEventListener(this);
}
@Override
publicvoidonCoinsReceived(final Wallet wallet, final Transaction transaction, Coin prevBalance, Coin newBalance) {
final Coin value = transaction.getValueSentToMe(wallet);
System.out.println("Received tx for " + value.toFriendlyString() + ": " + transaction);
System.out.println("Previous balance is " + prevBalance.toFriendlyString());
System.out.println("New estimated balance is " + newBalance.toFriendlyString());
System.out.println("Coin received, wallet balance is :" + wallet.getBalance());
Futures.addCallback(transaction.getConfidence().getDepthFuture(1), new FutureCallback<TransactionConfidence>() {
publicvoidonSuccess(TransactionConfidence result) {
System.out.println("Transaction confirmed, wallet balance is :" + wallet.getBalance());
}
publicvoidonFailure(Throwable t) {
t.printStackTrace();
}
});
}
}
該示例程序首先調用init
方法進行初始化, 然後進入一個等待循環, 當有比特幣到來時, onCoinsReceived
方法就被觸發.
各個步驟的具體分析如下
比特幣應用可以在三種不同的環境中運行: 正式流通網絡, 測試流通網絡以及本地開發環境. 初始化的第一步是通過設置一個NetworkParameters
變量來選擇運行環境, 以下代碼使用測試流通網絡
NetworkParameters params = TestNet3Params.get();
以下代碼首先創建一個可用於接受比特幣的地址, 並將其導入相應的錢包對象中.
ECKey key = new ECKey();
System.out.println("We created a new key:\n" + key);
Address addressFromKey = key.toAddress(params);
System.out.println("Public Address generated: " + addressFromKey);
System.out.println("Private key is: " + key.getPrivateKeyEncoded(params).toString());
Wallet wallet = new Wallet(params);
wallet.importKey(key);
以下代碼接入流通網絡並下載比特幣區塊
File blockFile = new File("/tmp/bitcoin-blocks");
SPVBlockStore blockStore = new SPVBlockStore(params, blockFile);
BlockChain blockChain = new BlockChain(params, wallet, blockStore);
PeerGroup peerGroup = new PeerGroup(params, blockChain);
peerGroup.addPeerDiscovery(new DnsDiscovery(params));
peerGroup.addWallet(wallet);
System.out.println("Start peer group");
peerGroup.start();
System.out.println("Downloading block chain");
peerGroup.downloadBlockChain();
System.out.println("Block chain downloaded");
需要注意的是peerGroup.downloadBlockChain();
這一步可能會運行很長時間.
以下代碼設置當比特幣到來時的事件響應
wallet.addCoinsReceivedEventListener(this);
當比特幣到來時onCoinsReceived
方法就會觸發, 注意該方法的newBalance
參數提供的是錢包中金額的估計值,其實際金額要等到交易被網絡確認後才會提現在wallet.getBalance()
的返回值中, 如以下代碼所示
Futures.addCallback(transaction.getConfidence().getDepthFuture(1), new FutureCallback<TransactionConfidence>() {
publicvoidonSuccess(TransactionConfidence result) {
System.out.println("Transaction confirmed, wallet balance is :" + wallet.getBalance());
}
publicvoidonFailure(Throwable t) {
t.printStackTrace();
}
});
支付比特幣的過程相對簡單, 首選設置要支付的金額.
final Coin amountToSend = Coin.valueOf(10, 0);
其次設置接收方的地址
Address toAddress = Address.fromBase58(params, "n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi");
然後發送該支付交易
final Wallet.SendResult sendResult = wallet.sendCoins(peerGroup, toAddress, amountToSend);
並設置交易完成後的事件響應
sendResult.broadcastComplete.addListener(new Runnable() {
@Override
publicvoidrun() {
System.out.println("Coins Sent! Transaction hash is " + sendResult.tx.getHashAsString());
}
}, MoreExecutors.sameThreadExecutor());
本文給出了一個基於BitCoinJ的比特幣收發示例程序, 並對BitCoinJ的編程模式以及其事件響應機制做了初步介紹。