diff --git a/core/src/main/java/haveno/core/support/dispute/DisputeManager.java b/core/src/main/java/haveno/core/support/dispute/DisputeManager.java index ba8d3b73..628d8845 100644 --- a/core/src/main/java/haveno/core/support/dispute/DisputeManager.java +++ b/core/src/main/java/haveno/core/support/dispute/DisputeManager.java @@ -365,7 +365,7 @@ public abstract class DisputeManager> extends Sup UUID.randomUUID().toString(), getSupportType(), updatedMultisigHex, - trade.getProcessModel().getPaymentSentMessage()); + trade.getArbitrator().getPaymentSentMessage()); log.info("Send {} to peer {}. tradeId={}, openNewDisputeMessage.uid={}, " + "chatMessage.uid={}", disputeOpenedMessage.getClass().getSimpleName(), agentNodeAddress, @@ -647,7 +647,7 @@ public abstract class DisputeManager> extends Sup UUID.randomUUID().toString(), getSupportType(), updatedMultisigHex, - trade.getProcessModel().getPaymentSentMessage()); + trade.getArbitrator().getPaymentSentMessage()); log.info("Send {} to peer {}. tradeId={}, peerOpenedDisputeMessage.uid={}, chatMessage.uid={}", peerOpenedDisputeMessage.getClass().getSimpleName(), peersNodeAddress, diff --git a/core/src/main/java/haveno/core/support/dispute/arbitration/ArbitrationManager.java b/core/src/main/java/haveno/core/support/dispute/arbitration/ArbitrationManager.java index ce79347a..17ededd8 100644 --- a/core/src/main/java/haveno/core/support/dispute/arbitration/ArbitrationManager.java +++ b/core/src/main/java/haveno/core/support/dispute/arbitration/ArbitrationManager.java @@ -224,13 +224,13 @@ public final class ArbitrationManager extends DisputeManager { reprocessDisputeClosedMessageCounts.put(trade.getId(), reprocessDisputeClosedMessageCounts.get(trade.getId()) + 1); // increment reprocess count @@ -325,12 +325,12 @@ public final class ArbitrationManager extends DisputeManager= Trade.DisputeState.DISPUTE_CLOSED.ordinal()) { + if (trade.isArbitrator() || trade.getArbitrator().getDisputeClosedMessage() == null || trade.getArbitrator().getDisputeClosedMessage().getUnsignedPayoutTxHex() == null || trade.getDisputeState().ordinal() >= Trade.DisputeState.DISPUTE_CLOSED.ordinal()) { return; } log.warn("Reprocessing dispute closed message for {} {}", trade.getClass().getSimpleName(), trade.getId()); - new Thread(() -> handleDisputeClosedMessage(trade.getProcessModel().getDisputeClosedMessage(), reprocessOnError)).start(); + new Thread(() -> handleDisputeClosedMessage(trade.getArbitrator().getDisputeClosedMessage(), reprocessOnError)).start(); } } @@ -343,7 +343,7 @@ public final class ArbitrationManager extends DisputeManager nonSignedDisputePayoutTxHexes = new HashSet(); - if (trade.getProcessModel().getPaymentSentMessage() != null) nonSignedDisputePayoutTxHexes.add(trade.getProcessModel().getPaymentSentMessage().getPayoutTxHex()); - if (trade.getProcessModel().getPaymentReceivedMessage() != null) { - nonSignedDisputePayoutTxHexes.add(trade.getProcessModel().getPaymentReceivedMessage().getUnsignedPayoutTxHex()); - nonSignedDisputePayoutTxHexes.add(trade.getProcessModel().getPaymentReceivedMessage().getSignedPayoutTxHex()); + if (trade.getTradePeer().getPaymentSentMessage() != null) nonSignedDisputePayoutTxHexes.add(trade.getTradePeer().getPaymentSentMessage().getPayoutTxHex()); + if (trade.getTradePeer().getPaymentReceivedMessage() != null) { + nonSignedDisputePayoutTxHexes.add(trade.getTradePeer().getPaymentReceivedMessage().getUnsignedPayoutTxHex()); + nonSignedDisputePayoutTxHexes.add(trade.getTradePeer().getPaymentReceivedMessage().getSignedPayoutTxHex()); } boolean signed = trade.getPayoutTxHex() != null && !nonSignedDisputePayoutTxHexes.contains(trade.getPayoutTxHex()); diff --git a/core/src/main/java/haveno/core/trade/Trade.java b/core/src/main/java/haveno/core/trade/Trade.java index c5c8b85f..7534ef39 100644 --- a/core/src/main/java/haveno/core/trade/Trade.java +++ b/core/src/main/java/haveno/core/trade/Trade.java @@ -1859,7 +1859,7 @@ public abstract class Trade implements Tradable, Model { if (isDepositsUnlocked() && !isPayoutPublished()) wallet.rescanSpent(); // get txs from trade wallet - boolean payoutExpected = isPaymentReceived() || processModel.getPaymentReceivedMessage() != null || disputeState.ordinal() > DisputeState.ARBITRATOR_SENT_DISPUTE_CLOSED_MSG.ordinal() || processModel.getDisputeClosedMessage() != null; + boolean payoutExpected = isPaymentReceived() || getSeller().getPaymentReceivedMessage() != null || disputeState.ordinal() >= DisputeState.ARBITRATOR_SENT_DISPUTE_CLOSED_MSG.ordinal() || getArbitrator().getDisputeClosedMessage() != null; boolean checkPool = !isDepositsConfirmed() || (!isPayoutConfirmed() && payoutExpected); MoneroTxQuery query = new MoneroTxQuery().setIncludeOutputs(true); if (!checkPool) query.setInTxPool(false); // avoid pool check if possible 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 4b9f8b4a..2173da46 100644 --- a/core/src/main/java/haveno/core/trade/protocol/ProcessModel.java +++ b/core/src/main/java/haveno/core/trade/protocol/ProcessModel.java @@ -18,7 +18,6 @@ package haveno.core.trade.protocol; import com.google.protobuf.ByteString; -import haveno.common.app.Version; import haveno.common.crypto.KeyRing; import haveno.common.crypto.PubKeyRing; import haveno.common.proto.ProtoUtil; @@ -34,12 +33,9 @@ import haveno.core.payment.payload.PaymentAccountPayload; import haveno.core.proto.CoreProtoResolver; import haveno.core.support.dispute.arbitration.arbitrator.ArbitratorManager; import haveno.core.support.dispute.mediation.mediator.MediatorManager; -import haveno.core.support.dispute.messages.DisputeClosedMessage; import haveno.core.support.dispute.refund.refundagent.RefundAgentManager; import haveno.core.trade.Trade; import haveno.core.trade.TradeManager; -import haveno.core.trade.messages.PaymentReceivedMessage; -import haveno.core.trade.messages.PaymentSentMessage; import haveno.core.trade.messages.TradeMessage; import haveno.core.trade.statistics.ReferralIdService; import haveno.core.trade.statistics.TradeStatisticsManager; @@ -139,18 +135,6 @@ public class ProcessModel implements Model, PersistablePayload { @Getter @Setter private String multisigAddress; - @Nullable - @Setter - @Getter - private PaymentSentMessage paymentSentMessage; - @Nullable - @Setter - @Getter - private PaymentReceivedMessage paymentReceivedMessage; - @Nullable - @Setter - @Getter - private DisputeClosedMessage disputeClosedMessage; // We want to indicate the user the state of the message delivery of the // PaymentSentMessage. As well we do an automatic re-send in case it was not ACKed yet. @@ -204,9 +188,6 @@ public class ProcessModel implements Model, PersistablePayload { Optional.ofNullable(mediatedPayoutTxSignature).ifPresent(e -> builder.setMediatedPayoutTxSignature(ByteString.copyFrom(e))); Optional.ofNullable(makerSignature).ifPresent(e -> builder.setMakerSignature(ByteString.copyFrom(e))); Optional.ofNullable(multisigAddress).ifPresent(e -> builder.setMultisigAddress(multisigAddress)); - Optional.ofNullable(paymentSentMessage).ifPresent(e -> builder.setPaymentSentMessage(paymentSentMessage.toProtoNetworkEnvelope().getPaymentSentMessage())); - Optional.ofNullable(paymentReceivedMessage).ifPresent(e -> builder.setPaymentReceivedMessage(paymentReceivedMessage.toProtoNetworkEnvelope().getPaymentReceivedMessage())); - Optional.ofNullable(disputeClosedMessage).ifPresent(e -> builder.setDisputeClosedMessage(disputeClosedMessage.toProtoNetworkEnvelope().getDisputeClosedMessage())); return builder.build(); } @@ -232,9 +213,6 @@ public class ProcessModel implements Model, PersistablePayload { MessageState paymentSentMessageState = ProtoUtil.enumFromProto(MessageState.class, paymentSentMessageStateString); processModel.setPaymentSentMessageState(paymentSentMessageState); - processModel.setPaymentSentMessage(proto.hasPaymentSentMessage() ? PaymentSentMessage.fromProto(proto.getPaymentSentMessage(), Version.getP2PMessageVersion()) : null); - processModel.setPaymentReceivedMessage(proto.hasPaymentReceivedMessage() ? PaymentReceivedMessage.fromProto(proto.getPaymentReceivedMessage(), Version.getP2PMessageVersion()) : null); - processModel.setDisputeClosedMessage(proto.hasDisputeClosedMessage() ? DisputeClosedMessage.fromProto(proto.getDisputeClosedMessage(), Version.getP2PMessageVersion()) : null); return processModel; } 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 af2e0d86..7a381831 100644 --- a/core/src/main/java/haveno/core/trade/protocol/TradePeer.java +++ b/core/src/main/java/haveno/core/trade/protocol/TradePeer.java @@ -19,12 +19,16 @@ package haveno.core.trade.protocol; import com.google.protobuf.ByteString; import com.google.protobuf.Message; +import haveno.common.app.Version; import haveno.common.crypto.PubKeyRing; import haveno.common.proto.ProtoUtil; import haveno.common.proto.persistable.PersistablePayload; import haveno.core.account.witness.AccountAgeWitness; import haveno.core.payment.payload.PaymentAccountPayload; import haveno.core.proto.CoreProtoResolver; +import haveno.core.support.dispute.messages.DisputeClosedMessage; +import haveno.core.trade.messages.PaymentReceivedMessage; +import haveno.core.trade.messages.PaymentSentMessage; import haveno.network.p2p.NodeAddress; import lombok.Getter; import lombok.Setter; @@ -79,6 +83,19 @@ public final class TradePeer implements PersistablePayload { private String contractAsJson; @Nullable private byte[] contractSignature; + @Nullable + @Setter + @Getter + private PaymentSentMessage paymentSentMessage; + @Nullable + @Setter + @Getter + private PaymentReceivedMessage paymentReceivedMessage; + @Nullable + @Setter + @Getter + private DisputeClosedMessage disputeClosedMessage; + // added in v 0.6 @Nullable @@ -164,6 +181,9 @@ public final class TradePeer implements PersistablePayload { Optional.ofNullable(accountAgeWitnessSignature).ifPresent(e -> builder.setAccountAgeWitnessSignature(ByteString.copyFrom(e))); Optional.ofNullable(accountAgeWitness).ifPresent(e -> builder.setAccountAgeWitness(accountAgeWitness.toProtoAccountAgeWitness())); Optional.ofNullable(mediatedPayoutTxSignature).ifPresent(e -> builder.setMediatedPayoutTxSignature(ByteString.copyFrom(e))); + Optional.ofNullable(paymentSentMessage).ifPresent(e -> builder.setPaymentSentMessage(paymentSentMessage.toProtoNetworkEnvelope().getPaymentSentMessage())); + Optional.ofNullable(paymentReceivedMessage).ifPresent(e -> builder.setPaymentReceivedMessage(paymentReceivedMessage.toProtoNetworkEnvelope().getPaymentReceivedMessage())); + Optional.ofNullable(disputeClosedMessage).ifPresent(e -> builder.setDisputeClosedMessage(disputeClosedMessage.toProtoNetworkEnvelope().getDisputeClosedMessage())); Optional.ofNullable(reserveTxHash).ifPresent(e -> builder.setReserveTxHash(reserveTxHash)); Optional.ofNullable(reserveTxHex).ifPresent(e -> builder.setReserveTxHex(reserveTxHex)); Optional.ofNullable(reserveTxKey).ifPresent(e -> builder.setReserveTxKey(reserveTxKey)); @@ -207,6 +227,9 @@ public final class TradePeer implements PersistablePayload { tradePeer.setAccountAgeWitness(protoAccountAgeWitness.getHash().isEmpty() ? null : AccountAgeWitness.fromProto(protoAccountAgeWitness)); tradePeer.setCurrentDate(proto.getCurrentDate()); tradePeer.setMediatedPayoutTxSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getMediatedPayoutTxSignature())); + tradePeer.setPaymentSentMessage(proto.hasPaymentSentMessage() ? PaymentSentMessage.fromProto(proto.getPaymentSentMessage(), Version.getP2PMessageVersion()) : null); + tradePeer.setPaymentReceivedMessage(proto.hasPaymentReceivedMessage() ? PaymentReceivedMessage.fromProto(proto.getPaymentReceivedMessage(), Version.getP2PMessageVersion()) : null); + tradePeer.setDisputeClosedMessage(proto.hasDisputeClosedMessage() ? DisputeClosedMessage.fromProto(proto.getDisputeClosedMessage(), Version.getP2PMessageVersion()) : null); tradePeer.setReserveTxHash(ProtoUtil.stringOrNullFromProto(proto.getReserveTxHash())); tradePeer.setReserveTxHex(ProtoUtil.stringOrNullFromProto(proto.getReserveTxHex())); tradePeer.setReserveTxKey(ProtoUtil.stringOrNullFromProto(proto.getReserveTxKey())); 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 95b8d6a9..62893050 100644 --- a/core/src/main/java/haveno/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/haveno/core/trade/protocol/TradeProtocol.java @@ -274,12 +274,12 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D synchronized (trade) { // skip if no need to reprocess - if (trade.isSeller() || trade.getProcessModel().getPaymentReceivedMessage() == null || trade.getState().ordinal() >= Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG.ordinal()) { + if (trade.isSeller() || trade.getSeller().getPaymentReceivedMessage() == null || trade.getState().ordinal() >= Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG.ordinal()) { return; } log.warn("Reprocessing payment received message for {} {}", trade.getClass().getSimpleName(), trade.getId()); - new Thread(() -> handle(trade.getProcessModel().getPaymentReceivedMessage(), trade.getProcessModel().getPaymentReceivedMessage().getSenderNodeAddress(), reprocessOnError)).start(); + new Thread(() -> handle(trade.getSeller().getPaymentReceivedMessage(), trade.getSeller().getPaymentReceivedMessage().getSenderNodeAddress(), reprocessOnError)).start(); } } @@ -552,7 +552,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D processModel.getTradeManager().requestPersistence(); // schedule to reprocess message unless deleted - if (trade.getProcessModel().getPaymentReceivedMessage() != null) { + if (trade.getSeller().getPaymentReceivedMessage() != null) { UserThread.runAfter(() -> { reprocessPaymentReceivedMessageCount++; maybeReprocessPaymentReceivedMessage(reprocessOnError); diff --git a/core/src/main/java/haveno/core/trade/protocol/tasks/BuyerPreparePaymentSentMessage.java b/core/src/main/java/haveno/core/trade/protocol/tasks/BuyerPreparePaymentSentMessage.java index d108ec08..11b21a77 100644 --- a/core/src/main/java/haveno/core/trade/protocol/tasks/BuyerPreparePaymentSentMessage.java +++ b/core/src/main/java/haveno/core/trade/protocol/tasks/BuyerPreparePaymentSentMessage.java @@ -45,9 +45,9 @@ public class BuyerPreparePaymentSentMessage extends TradeTask { try { runInterceptHook(); - // skip if already created - if (processModel.getPaymentSentMessage() != null) { - log.warn("Skipping preparation of payment sent message since it's already created for {} {}", trade.getClass().getSimpleName(), trade.getId()); + // skip if payout tx already created + if (trade.getPayoutTxHex() != null) { + log.warn("Skipping preparation of payment sent message because payout tx is already created for {} {}", trade.getClass().getSimpleName(), trade.getId()); complete(); return; } diff --git a/core/src/main/java/haveno/core/trade/protocol/tasks/BuyerSendPaymentSentMessage.java b/core/src/main/java/haveno/core/trade/protocol/tasks/BuyerSendPaymentSentMessage.java index 5d52805a..6a5d2264 100644 --- a/core/src/main/java/haveno/core/trade/protocol/tasks/BuyerSendPaymentSentMessage.java +++ b/core/src/main/java/haveno/core/trade/protocol/tasks/BuyerSendPaymentSentMessage.java @@ -28,6 +28,7 @@ import haveno.core.trade.HavenoUtils; import haveno.core.trade.Trade; import haveno.core.trade.messages.PaymentSentMessage; import haveno.core.trade.messages.TradeMailboxMessage; +import haveno.core.trade.protocol.TradePeer; import haveno.core.util.JsonUtil; import haveno.network.p2p.NodeAddress; import javafx.beans.value.ChangeListener; @@ -56,9 +57,17 @@ public abstract class BuyerSendPaymentSentMessage extends SendMailboxMessageTask super(taskHandler, trade); } - protected abstract NodeAddress getReceiverNodeAddress(); + protected abstract TradePeer getReceiver(); - protected abstract PubKeyRing getReceiverPubKeyRing(); + @Override + protected NodeAddress getReceiverNodeAddress() { + return getReceiver().getNodeAddress(); + } + + @Override + protected PubKeyRing getReceiverPubKeyRing() { + return getReceiver().getPubKeyRing(); + } @Override protected void run() { @@ -72,7 +81,7 @@ public abstract class BuyerSendPaymentSentMessage extends SendMailboxMessageTask @Override protected TradeMailboxMessage getTradeMailboxMessage(String tradeId) { - if (processModel.getPaymentSentMessage() == null) { + if (getReceiver().getPaymentSentMessage() == null) { // We do not use a real unique ID here as we want to be able to re-send the exact same message in case the // peer does not respond with an ACK msg in a certain time interval. To avoid that we get dangling mailbox @@ -98,13 +107,13 @@ public abstract class BuyerSendPaymentSentMessage extends SendMailboxMessageTask String messageAsJson = JsonUtil.objectToJson(message); byte[] sig = HavenoUtils.sign(processModel.getP2PService().getKeyRing(), messageAsJson); message.setBuyerSignature(sig); - processModel.setPaymentSentMessage(message); + getReceiver().setPaymentSentMessage(message); trade.requestPersistence(); } catch (Exception e) { throw new RuntimeException (e); } } - return processModel.getPaymentSentMessage(); + return getReceiver().getPaymentSentMessage(); } @Override diff --git a/core/src/main/java/haveno/core/trade/protocol/tasks/BuyerSendPaymentSentMessageToArbitrator.java b/core/src/main/java/haveno/core/trade/protocol/tasks/BuyerSendPaymentSentMessageToArbitrator.java index 16959e17..e43504c5 100644 --- a/core/src/main/java/haveno/core/trade/protocol/tasks/BuyerSendPaymentSentMessageToArbitrator.java +++ b/core/src/main/java/haveno/core/trade/protocol/tasks/BuyerSendPaymentSentMessageToArbitrator.java @@ -17,10 +17,9 @@ package haveno.core.trade.protocol.tasks; -import haveno.common.crypto.PubKeyRing; import haveno.common.taskrunner.TaskRunner; import haveno.core.trade.Trade; -import haveno.network.p2p.NodeAddress; +import haveno.core.trade.protocol.TradePeer; import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; @@ -32,12 +31,9 @@ public class BuyerSendPaymentSentMessageToArbitrator extends BuyerSendPaymentSen super(taskHandler, trade); } - protected NodeAddress getReceiverNodeAddress() { - return trade.getArbitrator().getNodeAddress(); - } - - protected PubKeyRing getReceiverPubKeyRing() { - return trade.getArbitrator().getPubKeyRing(); + @Override + protected TradePeer getReceiver() { + return trade.getArbitrator(); } @Override diff --git a/core/src/main/java/haveno/core/trade/protocol/tasks/BuyerSendPaymentSentMessageToSeller.java b/core/src/main/java/haveno/core/trade/protocol/tasks/BuyerSendPaymentSentMessageToSeller.java index 343e4e55..d47f700e 100644 --- a/core/src/main/java/haveno/core/trade/protocol/tasks/BuyerSendPaymentSentMessageToSeller.java +++ b/core/src/main/java/haveno/core/trade/protocol/tasks/BuyerSendPaymentSentMessageToSeller.java @@ -17,11 +17,10 @@ package haveno.core.trade.protocol.tasks; -import haveno.common.crypto.PubKeyRing; import haveno.common.taskrunner.TaskRunner; import haveno.core.trade.Trade; import haveno.core.trade.messages.TradeMessage; -import haveno.network.p2p.NodeAddress; +import haveno.core.trade.protocol.TradePeer; import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; @@ -33,12 +32,9 @@ public class BuyerSendPaymentSentMessageToSeller extends BuyerSendPaymentSentMes super(taskHandler, trade); } - protected NodeAddress getReceiverNodeAddress() { - return trade.getSeller().getNodeAddress(); - } - - protected PubKeyRing getReceiverPubKeyRing() { - return trade.getSeller().getPubKeyRing(); + @Override + protected TradePeer getReceiver() { + return trade.getSeller(); } // continue execution on fault so payment sent message is sent to arbitrator 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 9fba9b29..5bd51aa2 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 @@ -26,6 +26,7 @@ import haveno.core.trade.BuyerTrade; import haveno.core.trade.HavenoUtils; import haveno.core.trade.Trade; import haveno.core.trade.messages.PaymentReceivedMessage; +import haveno.core.trade.messages.PaymentSentMessage; import haveno.core.util.Validator; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -65,13 +66,13 @@ public class ProcessPaymentReceivedMessage extends TradeTask { } // save message for reprocessing - processModel.setPaymentReceivedMessage(message); - trade.requestPersistence(); + trade.getSeller().setPaymentReceivedMessage(message); // set state trade.getSeller().setUpdatedMultisigHex(message.getUpdatedMultisigHex()); trade.getBuyer().setUpdatedMultisigHex(message.getPaymentSentMessage().getUpdatedMultisigHex()); trade.getBuyer().setAccountAgeWitness(message.getBuyerAccountAgeWitness()); + trade.requestPersistence(); // close open disputes if (trade.getDisputeState().ordinal() >= Trade.DisputeState.DISPUTE_REQUESTED.ordinal()) { @@ -100,7 +101,7 @@ public class ProcessPaymentReceivedMessage extends TradeTask { // do not reprocess illegal argument if (t instanceof IllegalArgumentException) { - processModel.setPaymentReceivedMessage(null); // do not reprocess + trade.getSeller().setPaymentReceivedMessage(null); // do not reprocess trade.requestPersistence(); } @@ -134,8 +135,9 @@ public class ProcessPaymentReceivedMessage extends TradeTask { trade.verifyPayoutTx(message.getSignedPayoutTxHex(), false, true); } else { try { - if (trade.getProcessModel().getPaymentSentMessage() == null) throw new RuntimeException("Process model does not have payment sent message for " + trade.getClass().getSimpleName() + " " + trade.getId()); - if (StringUtils.equals(trade.getPayoutTxHex(), trade.getProcessModel().getPaymentSentMessage().getPayoutTxHex())) { // unsigned + PaymentSentMessage paymentSentMessage = (trade.isArbitrator() ? trade.getBuyer() : trade.getArbitrator()).getPaymentSentMessage(); + if (paymentSentMessage == null) throw new RuntimeException("Process model does not have payment sent message for " + trade.getClass().getSimpleName() + " " + trade.getId()); + if (StringUtils.equals(trade.getPayoutTxHex(), paymentSentMessage.getPayoutTxHex())) { // unsigned log.info("{} {} verifying, signing, and publishing seller's payout tx", trade.getClass().getSimpleName(), trade.getId()); trade.verifyPayoutTx(message.getUnsignedPayoutTxHex(), true, true); } else { diff --git a/core/src/main/java/haveno/core/trade/protocol/tasks/ProcessPaymentSentMessage.java b/core/src/main/java/haveno/core/trade/protocol/tasks/ProcessPaymentSentMessage.java index d6cc42a8..4f0eb0d4 100644 --- a/core/src/main/java/haveno/core/trade/protocol/tasks/ProcessPaymentSentMessage.java +++ b/core/src/main/java/haveno/core/trade/protocol/tasks/ProcessPaymentSentMessage.java @@ -48,7 +48,7 @@ public class ProcessPaymentSentMessage extends TradeTask { trade.getBuyer().setNodeAddress(processModel.getTempTradePeerNodeAddress()); // update state from message - processModel.setPaymentSentMessage(message); + trade.getBuyer().setPaymentSentMessage(message); trade.setPayoutTxHex(message.getPayoutTxHex()); trade.getBuyer().setUpdatedMultisigHex(message.getUpdatedMultisigHex()); trade.getSeller().setAccountAgeWitness(message.getSellerAccountAgeWitness()); diff --git a/core/src/main/java/haveno/core/trade/protocol/tasks/SellerPreparePaymentReceivedMessage.java b/core/src/main/java/haveno/core/trade/protocol/tasks/SellerPreparePaymentReceivedMessage.java index ed2b0ad1..5183a24b 100644 --- a/core/src/main/java/haveno/core/trade/protocol/tasks/SellerPreparePaymentReceivedMessage.java +++ b/core/src/main/java/haveno/core/trade/protocol/tasks/SellerPreparePaymentReceivedMessage.java @@ -39,7 +39,7 @@ public class SellerPreparePaymentReceivedMessage extends TradeTask { trade.checkDaemonConnection(); // handle first time preparation - if (processModel.getPaymentReceivedMessage() == null) { + if (trade.getArbitrator().getPaymentReceivedMessage() == null) { // import multisig hex trade.importMultisigHex(); @@ -56,11 +56,11 @@ public class SellerPreparePaymentReceivedMessage extends TradeTask { } else { createUnsignedPayoutTx(); } - } else if (processModel.getPaymentReceivedMessage().getSignedPayoutTxHex() != null && !trade.isPayoutPublished()) { + } else if (trade.getArbitrator().getPaymentReceivedMessage().getSignedPayoutTxHex() != null && !trade.isPayoutPublished()) { // republish payout tx from previous message log.info("Seller re-verifying and publishing payout tx for trade {}", trade.getId()); - trade.verifyPayoutTx(processModel.getPaymentReceivedMessage().getSignedPayoutTxHex(), false, true); + trade.verifyPayoutTx(trade.getArbitrator().getPaymentReceivedMessage().getSignedPayoutTxHex(), false, true); } processModel.getTradeManager().requestPersistence(); diff --git a/core/src/main/java/haveno/core/trade/protocol/tasks/SellerSendPaymentReceivedMessage.java b/core/src/main/java/haveno/core/trade/protocol/tasks/SellerSendPaymentReceivedMessage.java index 477dbe75..2da344f3 100644 --- a/core/src/main/java/haveno/core/trade/protocol/tasks/SellerSendPaymentReceivedMessage.java +++ b/core/src/main/java/haveno/core/trade/protocol/tasks/SellerSendPaymentReceivedMessage.java @@ -27,6 +27,7 @@ import haveno.core.trade.HavenoUtils; import haveno.core.trade.Trade; import haveno.core.trade.messages.PaymentReceivedMessage; import haveno.core.trade.messages.TradeMailboxMessage; +import haveno.core.trade.protocol.TradePeer; import haveno.core.util.JsonUtil; import haveno.network.p2p.NodeAddress; import lombok.EqualsAndHashCode; @@ -37,16 +38,23 @@ import static com.google.common.base.Preconditions.checkNotNull; @Slf4j @EqualsAndHashCode(callSuper = true) public abstract class SellerSendPaymentReceivedMessage extends SendMailboxMessageTask { - PaymentReceivedMessage message = null; SignedWitness signedWitness = null; public SellerSendPaymentReceivedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } + + protected abstract TradePeer getReceiver(); + + @Override + protected NodeAddress getReceiverNodeAddress() { + return getReceiver().getNodeAddress(); + } - protected abstract NodeAddress getReceiverNodeAddress(); - - protected abstract PubKeyRing getReceiverPubKeyRing(); + @Override + protected PubKeyRing getReceiverPubKeyRing() { + return getReceiver().getPubKeyRing(); + } @Override protected void run() { @@ -61,7 +69,7 @@ public abstract class SellerSendPaymentReceivedMessage extends SendMailboxMessag @Override protected TradeMailboxMessage getTradeMailboxMessage(String tradeId) { checkNotNull(trade.getPayoutTxHex(), "Payout tx must not be null"); - if (message == null) { + if (getReceiver().getPaymentReceivedMessage() == null) { // sign account witness AccountAgeWitnessService accountAgeWitnessService = processModel.getAccountAgeWitnessService(); @@ -75,7 +83,7 @@ public abstract class SellerSendPaymentReceivedMessage extends SendMailboxMessag // messages where only the one which gets processed by the peer would be removed we use the same uid. All // other data stays the same when we re-send the message at any time later. String deterministicId = HavenoUtils.getDeterministicId(trade, PaymentReceivedMessage.class, getReceiverNodeAddress()); - message = new PaymentReceivedMessage( + PaymentReceivedMessage message = new PaymentReceivedMessage( tradeId, processModel.getMyNodeAddress(), deterministicId, @@ -85,7 +93,7 @@ public abstract class SellerSendPaymentReceivedMessage extends SendMailboxMessag trade.getState().ordinal() >= Trade.State.SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG.ordinal(), // informs to expect payout trade.getTradePeer().getAccountAgeWitness(), signedWitness, - processModel.getPaymentSentMessage() + trade.getBuyer().getPaymentSentMessage() ); // sign message @@ -93,13 +101,13 @@ public abstract class SellerSendPaymentReceivedMessage extends SendMailboxMessag String messageAsJson = JsonUtil.objectToJson(message); byte[] sig = Sig.sign(processModel.getP2PService().getKeyRing().getSignatureKeyPair().getPrivate(), messageAsJson.getBytes(Charsets.UTF_8)); message.setSellerSignature(sig); - processModel.setPaymentReceivedMessage(message); + getReceiver().setPaymentReceivedMessage(message); trade.requestPersistence(); } catch (Exception e) { throw new RuntimeException(e); } } - return message; + return getReceiver().getPaymentReceivedMessage(); } @Override diff --git a/core/src/main/java/haveno/core/trade/protocol/tasks/SellerSendPaymentReceivedMessageToArbitrator.java b/core/src/main/java/haveno/core/trade/protocol/tasks/SellerSendPaymentReceivedMessageToArbitrator.java index 3d9f466b..3ae2cea2 100644 --- a/core/src/main/java/haveno/core/trade/protocol/tasks/SellerSendPaymentReceivedMessageToArbitrator.java +++ b/core/src/main/java/haveno/core/trade/protocol/tasks/SellerSendPaymentReceivedMessageToArbitrator.java @@ -17,10 +17,9 @@ package haveno.core.trade.protocol.tasks; -import haveno.common.crypto.PubKeyRing; import haveno.common.taskrunner.TaskRunner; import haveno.core.trade.Trade; -import haveno.network.p2p.NodeAddress; +import haveno.core.trade.protocol.TradePeer; import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; @@ -32,11 +31,8 @@ public class SellerSendPaymentReceivedMessageToArbitrator extends SellerSendPaym super(taskHandler, trade); } - protected NodeAddress getReceiverNodeAddress() { - return trade.getArbitrator().getNodeAddress(); - } - - protected PubKeyRing getReceiverPubKeyRing() { - return trade.getArbitrator().getPubKeyRing(); + @Override + protected TradePeer getReceiver() { + return trade.getArbitrator(); } } diff --git a/core/src/main/java/haveno/core/trade/protocol/tasks/SellerSendPaymentReceivedMessageToBuyer.java b/core/src/main/java/haveno/core/trade/protocol/tasks/SellerSendPaymentReceivedMessageToBuyer.java index f9d98e8f..7228b403 100644 --- a/core/src/main/java/haveno/core/trade/protocol/tasks/SellerSendPaymentReceivedMessageToBuyer.java +++ b/core/src/main/java/haveno/core/trade/protocol/tasks/SellerSendPaymentReceivedMessageToBuyer.java @@ -17,13 +17,10 @@ package haveno.core.trade.protocol.tasks; -import haveno.common.crypto.PubKeyRing; import haveno.common.taskrunner.TaskRunner; import haveno.core.trade.Trade; -import haveno.core.trade.messages.PaymentReceivedMessage; -import haveno.core.trade.messages.TradeMailboxMessage; import haveno.core.trade.messages.TradeMessage; -import haveno.network.p2p.NodeAddress; +import haveno.core.trade.protocol.TradePeer; import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; @@ -35,21 +32,9 @@ public class SellerSendPaymentReceivedMessageToBuyer extends SellerSendPaymentRe super(taskHandler, trade); } - @Override - protected TradeMailboxMessage getTradeMailboxMessage(String tradeId) { - if (processModel.getPaymentReceivedMessage() == null) { - processModel.setPaymentReceivedMessage((PaymentReceivedMessage) super.getTradeMailboxMessage(tradeId)); // save payment received message for buyer - } - return processModel.getPaymentReceivedMessage(); - } - - protected NodeAddress getReceiverNodeAddress() { - return trade.getBuyer().getNodeAddress(); - } - - protected PubKeyRing getReceiverPubKeyRing() { - return trade.getBuyer().getPubKeyRing(); + protected TradePeer getReceiver() { + return trade.getBuyer(); } // continue execution on fault so payment received message is sent to arbitrator diff --git a/proto/src/main/proto/pb.proto b/proto/src/main/proto/pb.proto index 9f967b45..9a9ce239 100644 --- a/proto/src/main/proto/pb.proto +++ b/proto/src/main/proto/pb.proto @@ -1546,9 +1546,6 @@ message ProcessModel { TradePeer arbitrator = 11; NodeAddress temp_trade_peer_node_address = 12; string multisig_address = 13; - PaymentSentMessage payment_sent_message = 14; - PaymentReceivedMessage payment_received_message = 15; - DisputeClosedMessage dispute_closed_message = 16; bytes mediated_payout_tx_signature = 17; // placeholder if mediation used in future int64 buyer_payout_amount_from_mediation = 18; int64 seller_payout_amount_from_mediation = 19; @@ -1572,6 +1569,9 @@ message TradePeer { AccountAgeWitness account_age_witness = 20; int64 current_date = 21; bytes mediated_payout_tx_signature = 22; + PaymentSentMessage payment_sent_message = 23; + PaymentReceivedMessage payment_received_message = 24; + DisputeClosedMessage dispute_closed_message = 25; string reserve_tx_hash = 1001; string reserve_tx_hex = 1002;