Fix nullpointer, add check for miningfee

This commit is contained in:
Manfred Karrer 2016-02-02 02:39:06 +01:00
parent 4232a10f47
commit 9d9ce5918b
6 changed files with 106 additions and 45 deletions

View File

@ -1040,18 +1040,4 @@ public class TradeWalletService {
throw new WalletException(t);
}
}
// not used
/* private Coin getBalance(List<TransactionOutput> transactionOutputs, Address address) {
Coin balance = Coin.ZERO;
for (TransactionOutput transactionOutput : transactionOutputs) {
if (transactionOutput.getScriptPubKey().isSentToAddress() || transactionOutput.getScriptPubKey().isPayToScriptHash()) {
Address addressOutput = transactionOutput.getScriptPubKey().getToAddress(params);
if (addressOutput.equals(address))
balance = balance.add(transactionOutput.getValue());
}
}
return balance;
}*/
}

View File

@ -53,6 +53,7 @@ import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
@ -86,6 +87,7 @@ public class WalletService {
private final IntegerProperty numPeers = new SimpleIntegerProperty(0);
private final ObjectProperty<List<Peer>> connectedPeers = new SimpleObjectProperty<>();
public final BooleanProperty shutDownDone = new SimpleBooleanProperty();
private ArbitraryTransactionBloomFilter arbitraryTransactionBloomFilter;
///////////////////////////////////////////////////////////////////////////////////////////
@ -129,7 +131,11 @@ public class WalletService {
walletAppKit.wallet().allowSpendingUnconfirmedTransactions();
if (params != RegTestParams.get())
walletAppKit.peerGroup().setMaxConnections(11);
// https://groups.google.com/forum/#!msg/bitcoinj/Ys13qkTwcNg/9qxnhwnkeoIJ
// DEFAULT_BLOOM_FILTER_FP_RATE = 0.00001
walletAppKit.peerGroup().setBloomFilterFalsePositiveRate(0.00001);
wallet = walletAppKit.wallet();
wallet.addEventListener(walletEventListener);
@ -613,18 +619,36 @@ public class WalletService {
}
}
}
/* // TODO
private class BloomFilterForForeignTx extends AbstractPeerEventListener implements PeerFilterProvider {
private final String txId;
public BloomFilterForForeignTx(String txId) {
this.txId = txId;
public void requestTransactionFromBlockChain(Transaction transaction, Consumer<Coin> resultHandler) {
arbitraryTransactionBloomFilter = new ArbitraryTransactionBloomFilter(transaction, resultHandler);
PeerGroup peerGroup = walletAppKit.peerGroup();
peerGroup.addEventListener(arbitraryTransactionBloomFilter);
peerGroup.addPeerFilterProvider(arbitraryTransactionBloomFilter);
}
private class ArbitraryTransactionBloomFilter extends AbstractPeerEventListener implements PeerFilterProvider {
private final Transaction transaction;
private final Consumer<Coin> resultHandler;
private final Set<TransactionOutPoint> transactionOutPoints;
public ArbitraryTransactionBloomFilter(Transaction transaction, Consumer<Coin> resultHandler) {
this.transaction = transaction;
this.resultHandler = resultHandler;
transactionOutPoints = transaction.getInputs().stream()
.map(e -> e.getOutpoint() != null ? e.getOutpoint() : null)
.filter(e -> e != null)
.collect(Collectors.toSet());
log.debug("transaction=" + transaction);
log.debug("transaction.fee=" + transaction.getFee());
log.debug("outpoints=" + transactionOutPoints);
}
@Override
public long getEarliestKeyCreationTime() {
return Utils.currentTimeSeconds();
return System.currentTimeMillis() / 1000;
}
@Override
@ -633,16 +657,15 @@ public class WalletService {
@Override
public int getBloomFilterElementCount() {
return 1;
return transactionOutPoints.size();
}
@Override
public BloomFilter getBloomFilter(int size, double falsePositiveRate, long nTweak) {
BloomFilter filter = new BloomFilter(size, falsePositiveRate, nTweak);
*//* for (TransactionOutPoint pledge : allPledges.keySet()) {
filter.insert(pledge.bitcoinSerialize());
}*//*
// how to add txid ???
for (TransactionOutPoint transactionOutPoint : transactionOutPoints) {
filter.insert(transactionOutPoint.bitcoinSerialize());
}
return filter;
}
@ -656,20 +679,15 @@ public class WalletService {
}
@Override
public void onTransaction(Peer peer, Transaction t) {
// executor.checkOnThread();
// TODO: Gate this logic on t being announced by multiple peers.
// checkForRevocation(t);
// TODO: Watch out for the confirmation. If no confirmation of the revocation occurs within N hours, alert the user.
public void onTransaction(Peer peer, Transaction tx) {
if (transactionOutPoints.contains(tx))
transactionOutPoints.remove(tx);
if (transactionOutPoints.isEmpty())
resultHandler.accept(transaction.getFee());
log.debug("onTransaction: transaction=" + tx);
log.debug("onTransaction: transaction.fee=" + tx.getFee());
}
}
// TODO
public void findTxInBlockChain(String txId) {
// https://groups.google.com/forum/?hl=de#!topic/bitcoinj/kinFP7lLsRE
// https://groups.google.com/forum/?hl=de#!topic/bitcoinj/f7m87kCWdb8
// https://groups.google.com/forum/?hl=de#!topic/bitcoinj/jNE5ohLExVM
walletAppKit.peerGroup().addPeerFilterProvider(new BloomFilterForForeignTx(txId));
}*/
}

View File

@ -42,7 +42,8 @@ import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.SetChangeListener;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.*;
import org.bitcoinj.script.Script;
import org.bitcoinj.utils.ExchangeRate;
import org.bitcoinj.utils.Fiat;
import org.jetbrains.annotations.NotNull;
@ -84,6 +85,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
final BooleanProperty isWalletFunded = new SimpleBooleanProperty();
final BooleanProperty useMBTC = new SimpleBooleanProperty();
final BooleanProperty insufficientFee = new SimpleBooleanProperty();
final ObjectProperty<Coin> amountAsCoin = new SimpleObjectProperty<>();
final ObjectProperty<Coin> minAmountAsCoin = new SimpleObjectProperty<>();
@ -160,9 +162,43 @@ class CreateOfferDataModel extends ActivatableDataModel {
private void addListeners() {
walletService.addBalanceListener(balanceListener);
walletService.getWallet().addEventListener(new WalletEventListener() {
@Override
public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
walletService.requestTransactionFromBlockChain(tx, fee -> {
if (fee == null || fee.compareTo(FeePolicy.getFeePerKb()) < 0)
insufficientFee.set(true);
});
}
@Override
public void onCoinsSent(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
}
@Override
public void onReorganize(Wallet wallet) {
}
@Override
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx) {
}
@Override
public void onWalletChanged(Wallet wallet) {
}
@Override
public void onScriptsChanged(Wallet wallet, List<Script> scripts, boolean isAddingScripts) {
}
@Override
public void onKeysAdded(List<ECKey> keys) {
}
});
user.getPaymentAccountsAsObservable().addListener(paymentAccountsChangeListener);
}
private void removeListeners() {
walletService.removeBalanceListener(balanceListener);
user.getPaymentAccountsAsObservable().removeListener(paymentAccountsChangeListener);
@ -323,7 +359,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
if (direction == Offer.Direction.BUY)
totalToPayAsCoin.set(offerFeeAsCoin.add(networkFeeAsCoin).add(securityDepositAsCoin));
else
totalToPayAsCoin.set(offerFeeAsCoin.add(networkFeeAsCoin).add(securityDepositAsCoin).add(amountAsCoin.get()));
totalToPayAsCoin.set(offerFeeAsCoin.add(networkFeeAsCoin).add(securityDepositAsCoin).add(amountAsCoin.get() == null ? Coin.ZERO : amountAsCoin.get()));
}
}

View File

@ -20,6 +20,7 @@ package io.bitsquare.gui.main.offer.createoffer;
import de.jensd.fx.fontawesome.AwesomeDude;
import de.jensd.fx.fontawesome.AwesomeIcon;
import io.bitsquare.app.BitsquareApp;
import io.bitsquare.btc.FeePolicy;
import io.bitsquare.common.util.Tuple2;
import io.bitsquare.common.util.Tuple3;
import io.bitsquare.gui.Navigation;
@ -100,9 +101,10 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
private ChangeListener<String> errorMessageListener;
private ChangeListener<Boolean> isPlaceOfferSpinnerVisibleListener;
private ChangeListener<Boolean> showTransactionPublishedScreen;
private ChangeListener<Boolean> insufficientFeeListener;
private EventHandler<ActionEvent> paymentAccountsComboBoxSelectionHandler;
private EventHandler<ActionEvent> currencyComboBoxSelectionHandler;
private EventHandler<ActionEvent> currencyComboBoxSelectionHandler;
private int gridRow = 0;
@ -186,7 +188,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
public void onClose() {
// we use model.requestPlaceOfferSuccess to not react on close caused by placeOffer
if (model.dataModel.isWalletFunded.get() && !model.requestPlaceOfferSuccess.get())
new Popup().warning("You have already funds paid in.\nIn the <Funds/Open for withdrawal> section you can withdraw those funds.").show();
new Popup().warning("You have already funds paid in.\nIn the \"Funds/Open for withdrawal\" section you can withdraw those funds.").show();
}
public void setCloseHandler(OfferView.CloseHandler closeHandler) {
@ -421,6 +423,19 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
placeOfferSpinner.setVisible(newValue);
};
insufficientFeeListener = (observable, oldValue, newValue) -> {
if (newValue) {
new Popup().warning("You need to use at least a mining fee of " +
model.formatCoin(FeePolicy.getFeePerKb()) +
".\n\nThe trade transactions might take too much time to be included in " +
"a block if the fee is too low.\n" +
"Please withdraw the amount you have funded back to your wallet and " +
"do a funding again with the correct fee.")
.onClose(() -> close())
.show();
}
};
paymentAccountsComboBoxSelectionHandler = e -> onPaymentAccountsComboBoxSelected();
currencyComboBoxSelectionHandler = e -> onCurrencyComboBoxSelected();
@ -464,6 +479,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
model.showWarningAdjustedVolume.addListener(showWarningAdjustedVolumeListener);
model.errorMessage.addListener(errorMessageListener);
model.isPlaceOfferSpinnerVisible.addListener(isPlaceOfferSpinnerVisibleListener);
model.dataModel.insufficientFee.addListener(insufficientFeeListener);
model.requestPlaceOfferSuccess.addListener(showTransactionPublishedScreen);
@ -485,6 +501,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
model.showWarningAdjustedVolume.removeListener(showWarningAdjustedVolumeListener);
model.errorMessage.removeListener(errorMessageListener);
model.isPlaceOfferSpinnerVisible.removeListener(isPlaceOfferSpinnerVisibleListener);
model.dataModel.insufficientFee.removeListener(insufficientFeeListener);
model.requestPlaceOfferSuccess.removeListener(showTransactionPublishedScreen);

View File

@ -476,6 +476,10 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
return paymentLabel;
}
public String formatCoin(Coin coin) {
return formatter.formatCoin(coin);
}
public Offer createAndGetOffer() {
offer = dataModel.createAndGetOffer();
return offer;

View File

@ -347,7 +347,7 @@ public class PeerManager implements ConnectionListener, MessageListener {
"Reported peers:");
reportedPeers.stream().forEach(e -> result.append("\n").append(e));
result.append("\n------------------------------------------------------------\n");
log.trace(result.toString());
//log.trace(result.toString());
log.info("Number of reported peers: {}", reportedPeers.size());
}
}