2016-09-18 87 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)); 
});