From c49b811da313d1e087e186ca36e8c46ab4c08319 Mon Sep 17 00:00:00 2001 From: HenrikJannsen Date: Wed, 2 Nov 2022 23:24:05 -0500 Subject: [PATCH] Add verification of chain of transactions at DisputeSummaryWindow Signed-off-by: HenrikJannsen --- .../resources/i18n/displayStrings.properties | 5 ++ .../windows/DisputeSummaryWindow.java | 50 ++++++++++++++++++- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index ee16fa6c5c..8ec4f81e15 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -2736,6 +2736,11 @@ disputeSummaryWindow.reason=Reason of dispute disputeSummaryWindow.tradePeriodEnd=Trade period end disputeSummaryWindow.extraInfo=Extra information disputeSummaryWindow.delayedPayoutStatus=Delayed Payout Status +disputeSummaryWindow.requestingTxs=Requesting blockchain transactions from block explorer... +disputeSummaryWindow.requestTransactionsError=Requesting the 4 trade transactions failed. Error message: {0}.\n\n\ + Please verify the transactions manually before closing the dispute. +disputeSummaryWindow.delayedPayoutTxVerificationFailed=Verification of the delayed payout transaction failed. Error message: {0}.\n\n\ + Please do not make the payout but get in touch with developers to clearify the case. # dynamic values are not recognized by IntelliJ # suppress inspection "UnusedProperty" diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/DisputeSummaryWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/DisputeSummaryWindow.java index adea7f53f0..5d59792537 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/DisputeSummaryWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/DisputeSummaryWindow.java @@ -55,6 +55,7 @@ import bisq.core.util.coin.CoinUtil; import bisq.common.UserThread; import bisq.common.app.DevEnv; +import bisq.common.config.Config; import bisq.common.handlers.ResultHandler; import bisq.common.util.Tuple2; import bisq.common.util.Tuple3; @@ -692,9 +693,9 @@ public class DisputeSummaryWindow extends Overlay { !peersDisputeOptional.get().isClosed()) { showPayoutTxConfirmation(contract, disputeResult, - () -> doCloseIfValid(closeTicketButton)); + () -> doCloseAfterTxsVerified(closeTicketButton)); } else { - doCloseIfValid(closeTicketButton); + doCloseAfterTxsVerified(closeTicketButton); } }); @@ -811,6 +812,51 @@ public class DisputeSummaryWindow extends Overlay { } } + private void doCloseAfterTxsVerified(Button closeTicketButton) { + var disputeManager = getDisputeManager(dispute); + // Only RefundAgent need to verify transactions to ensure payout is safe + if (disputeManager instanceof RefundManager && Config.baseCurrencyNetwork().isMainnet()) { + RefundManager refundManager = (RefundManager) disputeManager; + Contract contract = dispute.getContract(); + String makerFeeTxId = contract.getOfferPayload().getOfferFeePaymentTxId(); + String takerFeeTxId = contract.getTakerFeeTxID(); + String depositTxId = dispute.getDepositTxId(); + String delayedPayoutTxId = dispute.getDelayedPayoutTxId(); + Popup requestingTxsPopup = new Popup().feedback(Res.get("disputeSummaryWindow.requestingTxs")); + requestingTxsPopup.show(); + refundManager.requestBlockchainTransactions(makerFeeTxId, + takerFeeTxId, + depositTxId, + delayedPayoutTxId + ).whenComplete((txList, throwable) -> { + UserThread.execute(() -> { + if (throwable == null) { + try { + requestingTxsPopup.hide(); + refundManager.verifyTradeTxChain(txList); + doCloseIfValid(closeTicketButton); + } catch (Throwable error) { + UserThread.runAfter(() -> + new Popup().warning(Res.get("disputeSummaryWindow.delayedPayoutTxVerificationFailed", error.getMessage())) + .show(), + 100, + TimeUnit.MILLISECONDS); + } + } else { + UserThread.runAfter(() -> + new Popup().warning(Res.get("disputeSummaryWindow.requestTransactionsError", throwable.getMessage())) + .onAction(() -> doCloseIfValid(closeTicketButton)) + .show(), + 100, + TimeUnit.MILLISECONDS); + } + }); + }); + } else { + doCloseIfValid(closeTicketButton); + } + } + private void doCloseIfValid(Button closeTicketButton) { var disputeManager = checkNotNull(getDisputeManager(dispute)); try {