我正在尝试通过bitcoinj(版本0.14.3)进行交易,我希望付款后能找回零钱。我正在使用testnet,它不是真正的比特币。
我有下一个代码:
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);
因此,我将两个输出放入事务中:
汇款地址
我的钱包地址以找回零钱
我先寄了一些钱到第一个地址。然后,我向第二个地址发送下一个值:我钱包中的所有可用金额减去收到的发送至第一个地址的金额。
但是广播后我得到了意外的结果。使用此方案进行了几次交易后,我注意到从我的钱包中提取了错误的值。出乎意料的是,有时有钱在提取,但有时有钱在钱包里。
Here is the link to testnet explorer
有人可以解释我在做什么错以及如何解决吗?
最佳答案
交易未按预期进行的原因是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));
});
关于java - 通过比特币付款的正确方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39556376/