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); 

だから、私はトランザクションに2つの出力を入れています:

  1. 送金先住所
  2. おつりを返すための私の財布のアドレス

最初のアドレスに送金します。そして、2 番目のアドレスに、次の値を送信します。つまり、ウォレットで利用可能なすべてのお金から、最初のアドレスに受け取ったお金を差し引いたものです。

しかし、放送後、予想外の結果がありました。このスキームでいくつかの取引を行った後、間違った値がウォレットから引き出されていることに気付きました。驚くべきことに、お金が引き出されることもあれば、財布にお金が入ってくることもあります。

ここにテストネットエクスプローラーへのリンクがあります

誰かが私が間違っていることとそれを修正する方法を説明できますか?

4

1 に答える 1

-1

トランザクションが期待どおりに機能しない理由は、Bitcoinj Wallet クラスがバックグラウンドで多くのことを行っているためです。この場合、トランザクションの変更を格納する変更アドレスを自動的に生成しています。もう 1 つの要因は、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 に答える