2016-09-18 90 views
1

我正在嘗試通過bitcoinj(版本0.14.3)進行交易,並且我期望在付款後獲得更改。我正在使用testnet,它不是真正的比特幣。 我有下面的代碼:通過bitcoinj付款的正確方法

Transaction tx = new Transaction(this.networkParameters); 
Coin coinToSent = Coin.valueOf(Config.APP_COST); 
Coin coinToChange = Coin.valueOf(walletBalance.getValue() - coinToSent.getValue()); 
tx.addOutput(coinToSent, appAddress); 
tx.addOutput(coinToChange, changeAddress); 

SendRequest request = SendRequest.forTx(tx); 
try { 
    this.walletAppKit.wallet().completeTx(request); 
} catch (InsufficientMoneyException e) { 
    e.printStackTrace(); 
    return false; 
} 
this.walletAppKit.wallet().commitTx(request.tx); 
this.walletAppKit.peerGroup().broadcastTransaction(request.tx); 

所以,我把兩個輸出到交易:

  1. 地址來發送錢我的錢包
  2. 地址獲取變回

給我的第一個地址,我寄了一些錢。對於第二個地址,我發送下一個值:我的錢包上的所有可用錢減去收到的第一個地址的錢。

但廣播後,我有一個意外的結果。在與這個計劃進行了幾次交易之後,我注意到從我的錢包中退出的錯誤值。令人驚訝的是,有時候金錢正在退出,但有時候金錢來到了錢包。

Here is the link to testnet explorer

有人可以解釋我做錯了,如何解決呢?

回答

0

交易未按預期工作的原因是Bitcoinj Wallet類在後臺爲您做了很多事情 - 在這種情況下,它會自動生成更改地址,以便將更改存儲在哪裏交易。另一個因素是,bitcoinj計算一筆費用,它可以讓礦工處理交易,這就是爲什麼你看到變更地址獲得的錢少了你的要求(在生產網絡上它會拋出一個例外,如果你不願意的話)沒有足夠的資金來支付這筆費用)。

對於相對簡單的案例,我認爲最好的解決方案是使用Wallet API並讓它自動生成更改地址(它使用確定性鑰匙串,因此所有地址和密鑰都可以在你丟失錢包的情況下再生)。例如:

public static Transaction send(Wallet wallet, 
           String destinationAddress, 
           long satoshis) throws Exception { 
    Address dest = Address.fromBase58(params, destinationAddress); 
    SendRequest request = SendRequest.to(dest, Coin.valueOf(satoshis)); 
    SendResult result = wallet.sendCoins(request); 
    Transaction endTransaction = result.broadcastComplete.get(); 
    return endTransaction; 
} 

sendCoins完成,交易播出後,錢包將維持剩下的(你可以將它保存到一個文件後,transactin是完整的,如果你真的想確保你有鑰匙對於更改地址),可以通過以下方法查看10個更改地址及其公鑰/私鑰的列表:

NetworkParameters params = new MainNetParams(); 
List<DeterministicKey> keys = wallet.freshKeys(KeyChain.KeyPurpose.CHANGE, 10); 
keys.forEach(key -> { 
    Address address = new Address(params, key.getPubKeyHash()); 
    System.out.println(address +" : " + key.toStringWithPrivate(params)); 
});