我正在尝试通过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
有人可以解释我做错了什么以及如何解决它?
答案 0 :(得分:0)
交易没有按预期工作的原因是Bitcoinj Wallet类在后台为您做了很多事情 - 在这种情况下,它会自动生成一个更改地址,其中将存储更改交易。另一个因素是比特币计算了一个费用,它会让矿工处理交易,这就是为什么你会看到更改地址获得你所要求的更少的硬币(在生产网络上它会抛出异常,如果你没有足够的资金支付费用。)
我认为,对于相对简单的情况,此处的最佳解决方案是使用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完成后将其保存到文件中),此处和#39;您可以看到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));
});