Правильный способ оплаты через биткойнj

Я пытаюсь совершить транзакцию через биткойн (версия 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. Адрес моего кошелька для возврата сдачи

На первый адрес я посылаю немного денег. И на второй адрес я отправляю следующее значение: все доступные деньги на моем кошельке за вычетом денег, полученных на первый адрес.

Но после трансляции у меня был неожиданный результат. Совершив несколько транзакций по этой схеме, я заметил, что из моего кошелька выводятся неправильные суммы. Что удивительно, иногда деньги снимаются, а иногда приходят на кошелек.

Вот ссылка на testnet explorer

Может кто-нибудь объяснить, что я делаю неправильно и как это исправить?


person yar_resh    schedule 18.09.2016    source источник


Ответы (1)


Причина, по которой транзакция не работает должным образом, заключается в том, что класс кошелька Bitcoinj выполняет за вас множество действий в фоновом режиме — в данном случае он автоматически генерирует адрес для сдачи, где он будет хранить сдачу для транзакции. Другим фактором является то, что биткойн рассчитывает комиссию, которую он дает майнерам за обработку транзакции, поэтому вы видите, что адрес изменения получает меньше монет, чем вы запрашивали (в производственной сети он выдаст исключение, если вы этого не сделаете). t иметь достаточно средств для оплаты пошлины).

Я думаю, что лучшее решение здесь, для относительно простых случаев, — это работать с 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));
});
person ohad serfaty    schedule 11.01.2017