diff --git a/core/src/main/java/haveno/core/trade/protocol/ArbitratorProtocol.java b/core/src/main/java/haveno/core/trade/protocol/ArbitratorProtocol.java index 248833273f..8818fcf49c 100644 --- a/core/src/main/java/haveno/core/trade/protocol/ArbitratorProtocol.java +++ b/core/src/main/java/haveno/core/trade/protocol/ArbitratorProtocol.java @@ -53,30 +53,38 @@ public class ArbitratorProtocol extends DisputeProtocol { public void sendDisputeOpenedMessageIfApplicable() { ThreadUtils.execute(() -> { + if (!needsToResendDisputeOpenedMessage()) return; if (trade.isShutDownStarted() || trade.isPayoutPublished()) return; synchronized (trade.getLock()) { - if (trade.isShutDownStarted() || trade.isPayoutPublished()) return; - if (trade.getDisputeState() == Trade.DisputeState.DISPUTE_OPENED) { - latchTrade(); - given(new Condition(trade)) - .setup(tasks( - ArbitratorSendDisputeOpenedMessageToBuyer.class, - ArbitratorSendDisputeOpenedMessageToSeller.class) - .using(new TradeTaskRunner(trade, - () -> { - unlatchTrade(); - }, - (errorMessage) -> { - log.warn("Error sending DisputeOpenedMessage: " + errorMessage); - unlatchTrade(); - }))) - .executeTasks(); - awaitTradeLatch(); - } + if (!needsToResendDisputeOpenedMessage()) return; + latchTrade(); + given(new Condition(trade)) + .setup(tasks( + ArbitratorSendDisputeOpenedMessageToBuyer.class, + ArbitratorSendDisputeOpenedMessageToSeller.class) + .using(new TradeTaskRunner(trade, + () -> { + unlatchTrade(); + }, + (errorMessage) -> { + log.warn("Error sending DisputeOpenedMessage: " + errorMessage); + unlatchTrade(); + }))) + .executeTasks(); + awaitTradeLatch(); } }, trade.getId()); } + private boolean needsToResendDisputeOpenedMessage() { + if (trade.isShutDownStarted()) return false; + if (trade.isPayoutPublished()) return false; + if (trade.getBuyer().getDisputeOpenedMessage() == null && trade.getSeller().getDisputeOpenedMessage() == null) return false; + if (trade.getDisputeState() != Trade.DisputeState.DISPUTE_OPENED) return false; + if (!((ArbitratorTrade) trade).resendDisputeOpenedMessageWithinDuration()) return false; + return !trade.getProcessModel().isDisputeOpenedMessageAckedOrStored(); + } + /////////////////////////////////////////////////////////////////////////////////////////// // Incoming messages /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/core/src/main/java/haveno/core/trade/protocol/ProcessModel.java b/core/src/main/java/haveno/core/trade/protocol/ProcessModel.java index 68a1dcdbb7..1ca9b3b54e 100644 --- a/core/src/main/java/haveno/core/trade/protocol/ProcessModel.java +++ b/core/src/main/java/haveno/core/trade/protocol/ProcessModel.java @@ -313,6 +313,10 @@ public class ProcessModel implements Model, PersistablePayload { return getArbitrator().isPaymentReceivedMessageAckedOrStored() && getBuyer().isPaymentReceivedMessageAckedOrStored(); } + public boolean isDisputeOpenedMessageAckedOrStored() { + return getBuyer().isDisputeOpenedMessageAckedOrStored() || getSeller().isDisputeOpenedMessageAckedOrStored(); + } + void setDepositTxSentAckMessage(AckMessage ackMessage) { MessageState messageState = ackMessage.isSuccess() ? MessageState.ACKNOWLEDGED : diff --git a/core/src/main/java/haveno/core/trade/protocol/TradePeer.java b/core/src/main/java/haveno/core/trade/protocol/TradePeer.java index fe8f9290d1..3a97b3a0e4 100644 --- a/core/src/main/java/haveno/core/trade/protocol/TradePeer.java +++ b/core/src/main/java/haveno/core/trade/protocol/TradePeer.java @@ -304,6 +304,10 @@ public final class TradePeer implements PersistablePayload { return disputeOpenedMessageStateProperty.get() == MessageState.ACKNOWLEDGED || disputeOpenedMessageStateProperty.get() == MessageState.STORED_IN_MAILBOX || disputeOpenedMessageStateProperty.get() == MessageState.NACKED; } + public boolean isDisputeOpenedMessageAckedOrStored() { + return disputeOpenedMessageStateProperty.get() == MessageState.ACKNOWLEDGED || disputeOpenedMessageStateProperty.get() == MessageState.STORED_IN_MAILBOX; + } + @Override public Message toProtoMessage() { final protobuf.TradePeer.Builder builder = protobuf.TradePeer.newBuilder();