Skip to content

Commit

Permalink
Merge pull request #3830 from chimp1984/only-move-to-failed-trades-fo…
Browse files Browse the repository at this point in the history
…r-critical-reject-msg

Only move to failed trades if the reject msg is critical
  • Loading branch information
ripcurlx authored Jan 2, 2020
2 parents 91774c6 + 7e44c60 commit 9a55847
Showing 1 changed file with 69 additions and 39 deletions.
108 changes: 69 additions & 39 deletions core/src/main/java/bisq/core/app/BisqSetup.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
import bisq.common.util.Utilities;

import org.bitcoinj.core.Coin;
import org.bitcoinj.core.RejectMessage;

import javax.inject.Inject;
import javax.inject.Named;
Expand Down Expand Up @@ -703,50 +704,79 @@ private void initDomainServices() {
balances.onAllServicesInitialized();

walletAppSetup.getRejectedTxException().addListener((observable, oldValue, newValue) -> {
// We delay as we might get the rejected tx error before we have completed the create offer protocol
UserThread.runAfter(() -> {
if (rejectedTxErrorMessageHandler != null && newValue != null && newValue.getTxId() != null) {
String txId = newValue.getTxId();
openOfferManager.getObservableList().stream()
.filter(openOffer -> txId.equals(openOffer.getOffer().getOfferFeePaymentTxId()))
.forEach(openOffer -> {
// We delay to avoid concurrent modification exceptions
UserThread.runAfter(() -> {
openOffer.getOffer().setErrorMessage(newValue.getMessage());
rejectedTxErrorMessageHandler.accept(Res.get("popup.warning.openOffer.makerFeeTxRejected", openOffer.getId(), txId));
openOfferManager.removeOpenOffer(openOffer, () -> {
log.warn("We removed an open offer because the maker fee was rejected by the Bitcoin " +
"network. OfferId={}, txId={}", openOffer.getShortId(), txId);
}, log::warn);
}, 1);
});

tradeManager.getTradableList().stream()
.filter(trade -> trade.getOffer() != null)
.forEach(trade -> {
String details = null;
if (txId.equals(trade.getDepositTxId())) {
details = Res.get("popup.warning.trade.txRejected.deposit");
}
if (txId.equals(trade.getOffer().getOfferFeePaymentTxId()) || txId.equals(trade.getTakerFeeTxId())) {
details = Res.get("popup.warning.trade.txRejected.tradeFee");
}

if (details != null) {
if (newValue == null || newValue.getTxId() == null) {
return;
}

RejectMessage rejectMessage = newValue.getRejectMessage();
log.warn("We received reject message: {}", rejectMessage);

// TODO: Find out which reject messages are critical and which not.
// We got a report where a "tx already known" message caused a failed trade but the deposit tx was valid.
// To avoid such false positives we only handle reject messages which we consider clearly critical.

switch (rejectMessage.getReasonCode()) {
case OBSOLETE:
case DUPLICATE:
case NONSTANDARD:
case CHECKPOINT:
case OTHER:
// We ignore those cases to avoid that not critical reject messages trigger a failed trade.
log.warn("We ignore that reject message as it is likely not critical.");
break;
case MALFORMED:
case INVALID:
case DUST:
case INSUFFICIENTFEE:
// We delay as we might get the rejected tx error before we have completed the create offer protocol
log.warn("We handle that reject message as it is likely critical.");
UserThread.runAfter(() -> {
String txId = newValue.getTxId();
openOfferManager.getObservableList().stream()
.filter(openOffer -> txId.equals(openOffer.getOffer().getOfferFeePaymentTxId()))
.forEach(openOffer -> {
// We delay to avoid concurrent modification exceptions
String finalDetails = details;
UserThread.runAfter(() -> {
trade.setErrorMessage(newValue.getMessage());
rejectedTxErrorMessageHandler.accept(Res.get("popup.warning.trade.txRejected",
finalDetails, trade.getShortId(), txId));
tradeManager.addTradeToFailedTrades(trade);
openOffer.getOffer().setErrorMessage(newValue.getMessage());
if (rejectedTxErrorMessageHandler != null) {
rejectedTxErrorMessageHandler.accept(Res.get("popup.warning.openOffer.makerFeeTxRejected", openOffer.getId(), txId));
}
openOfferManager.removeOpenOffer(openOffer, () -> {
log.warn("We removed an open offer because the maker fee was rejected by the Bitcoin " +
"network. OfferId={}, txId={}", openOffer.getShortId(), txId);
}, log::warn);
}, 1);
}
});
}
}, 3);
});

tradeManager.getTradableList().stream()
.filter(trade -> trade.getOffer() != null)
.forEach(trade -> {
String details = null;
if (txId.equals(trade.getDepositTxId())) {
details = Res.get("popup.warning.trade.txRejected.deposit");
}
if (txId.equals(trade.getOffer().getOfferFeePaymentTxId()) || txId.equals(trade.getTakerFeeTxId())) {
details = Res.get("popup.warning.trade.txRejected.tradeFee");
}

if (details != null) {
// We delay to avoid concurrent modification exceptions
String finalDetails = details;
UserThread.runAfter(() -> {
trade.setErrorMessage(newValue.getMessage());
if (rejectedTxErrorMessageHandler != null) {
rejectedTxErrorMessageHandler.accept(Res.get("popup.warning.trade.txRejected",
finalDetails, trade.getShortId(), txId));
}
tradeManager.addTradeToFailedTrades(trade);
}, 1);
}
});
}, 3);
}
});


arbitratorManager.onAllServicesInitialized();
mediatorManager.onAllServicesInitialized();
refundAgentManager.onAllServicesInitialized();
Expand Down

0 comments on commit 9a55847

Please sign in to comment.