2

我正在尝试通过 bitcoinj(版本 0.14.3)进行交易,我希望在付款后取回零钱。我正在使用测试网,它不是真正的比特币。我有下一个代码:

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. 取回零钱的钱包地址

我寄一些钱到第一个地址。我向第二个地址发送下一个值:我钱包上的所有可用资金减去收到到第一个地址的钱。

但播出后我有一个意想不到的结果。在使用此方案进行了一些交易后,我注意到从我的钱包中提取的错误值。令人惊讶的是,有时钱会被提取,但有时钱会进入钱包。

这是测试网资源管理器的链接

有人可以解释我做错了什么以及如何解决吗?

4

1 回答 1

-1

交易未按预期工作的原因是 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 完成并广播交易后,钱包将维护其余部分(如果您确实想确保您拥有更改地址的密钥,可以在交易完成后将其保存到文件中),这是您的一种方式可以看到 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));
});
于 2017-01-11T00:02:13.643 回答