From 7592d8fbcaf419f18660eb1b8b8cd9ed94e679ca Mon Sep 17 00:00:00 2001 From: woodser Date: Sat, 28 Oct 2023 10:04:47 -0400 Subject: [PATCH] fix payment sent ack after offline: 'Cannot get peer's pub key ring' --- .../core/trade/protocol/TradeProtocol.java | 26 ++++++++++++------- .../tasks/ProcessPaymentReceivedMessage.java | 15 ++++++++--- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/haveno/core/trade/protocol/TradeProtocol.java b/core/src/main/java/haveno/core/trade/protocol/TradeProtocol.java index 4a840685..95b8d6a9 100644 --- a/core/src/main/java/haveno/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/haveno/core/trade/protocol/TradeProtocol.java @@ -519,18 +519,26 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D return; } synchronized (trade) { - if (trade.getPhase().ordinal() >= Trade.Phase.PAYMENT_RECEIVED.ordinal()) { - log.warn("Received another PaymentReceivedMessage which was already processed, ACKing"); - handleTaskRunnerSuccess(peer, message); - return; - } latchTrade(); Validator.checkTradeId(processModel.getOfferId(), message); processModel.setTradeMessage(message); - expect(anyPhase( - trade.isBuyer() ? new Trade.Phase[] {Trade.Phase.PAYMENT_SENT, Trade.Phase.PAYMENT_RECEIVED} : - trade.isArbitrator() ? new Trade.Phase[] {Trade.Phase.DEPOSITS_CONFIRMED, Trade.Phase.DEPOSITS_UNLOCKED, Trade.Phase.PAYMENT_SENT} : // arbitrator syncs slowly after deposits confirmed - new Trade.Phase[] {Trade.Phase.DEPOSITS_UNLOCKED, Trade.Phase.PAYMENT_SENT}) + + + // check minimum trade phase + if (trade.isBuyer() && trade.getPhase().ordinal() < Trade.Phase.PAYMENT_SENT.ordinal()) { + log.warn("Received PaymentReceivedMessage before payment sent for {} {}, ignoring", trade.getClass().getSimpleName(), trade.getId()); + return; + } + if (trade.isArbitrator() && trade.getPhase().ordinal() < Trade.Phase.DEPOSITS_CONFIRMED.ordinal()) { + log.warn("Received PaymentReceivedMessage before deposits confirmed for {} {}, ignoring", trade.getClass().getSimpleName(), trade.getId()); + return; + } + if (trade.isSeller() && trade.getPhase().ordinal() < Trade.Phase.DEPOSITS_UNLOCKED.ordinal()) { + log.warn("Received PaymentReceivedMessage before deposits unlocked for {} {}, ignoring", trade.getClass().getSimpleName(), trade.getId()); + return; + } + + expect(anyPhase() .with(message) .from(peer)) .setup(tasks( diff --git a/core/src/main/java/haveno/core/trade/protocol/tasks/ProcessPaymentReceivedMessage.java b/core/src/main/java/haveno/core/trade/protocol/tasks/ProcessPaymentReceivedMessage.java index 5e67d2b9..9fba9b29 100644 --- a/core/src/main/java/haveno/core/trade/protocol/tasks/ProcessPaymentReceivedMessage.java +++ b/core/src/main/java/haveno/core/trade/protocol/tasks/ProcessPaymentReceivedMessage.java @@ -53,6 +53,17 @@ public class ProcessPaymentReceivedMessage extends TradeTask { // verify signature of payment received message HavenoUtils.verifyPaymentReceivedMessage(trade, message); + // update to the latest peer address of our peer if message is correct + trade.getSeller().setNodeAddress(processModel.getTempTradePeerNodeAddress()); + if (trade.getSeller().getNodeAddress().equals(trade.getBuyer().getNodeAddress())) trade.getBuyer().setNodeAddress(null); // tests can reuse addresses + + // ack and complete if already processed + if (trade.getPhase().ordinal() >= Trade.Phase.PAYMENT_RECEIVED.ordinal()) { + log.warn("Received another PaymentReceivedMessage which was already processed, ACKing"); + complete(); + return; + } + // save message for reprocessing processModel.setPaymentReceivedMessage(message); trade.requestPersistence(); @@ -62,10 +73,6 @@ public class ProcessPaymentReceivedMessage extends TradeTask { trade.getBuyer().setUpdatedMultisigHex(message.getPaymentSentMessage().getUpdatedMultisigHex()); trade.getBuyer().setAccountAgeWitness(message.getBuyerAccountAgeWitness()); - // update to the latest peer address of our peer if message is correct - trade.getSeller().setNodeAddress(processModel.getTempTradePeerNodeAddress()); - if (trade.getSeller().getNodeAddress().equals(trade.getBuyer().getNodeAddress())) trade.getBuyer().setNodeAddress(null); // tests can reuse addresses - // close open disputes if (trade.getDisputeState().ordinal() >= Trade.DisputeState.DISPUTE_REQUESTED.ordinal()) { trade.advanceDisputeState(Trade.DisputeState.DISPUTE_CLOSED);