From d698555c9a628dcc88d7d6f07abb4dd247ca5c0a Mon Sep 17 00:00:00 2001 From: woodser Date: Tue, 20 Sep 2022 10:48:27 -0400 Subject: [PATCH] trade completion fixes with payment key and multisig hex on confirmation preserve peer multisig hex when arbitrator provides payment key process payment received using persistent, non-transient data payout_tx_published_msg represents payment_received_msg after payout update arbitrator's peer address on payout published schedule payment account key request after deposit request --- core/src/main/java/bisq/core/trade/Trade.java | 1 - .../trade/messages/PayoutTxPublishedMessage.java | 8 ++++++++ .../java/bisq/core/trade/protocol/BuyerProtocol.java | 2 +- .../ArbitratorProcessPayoutTxPublishedMessage.java | 4 ++++ .../tasks/BuyerProcessPaymentAccountKeyResponse.java | 12 ++++-------- .../tasks/BuyerProcessPaymentReceivedMessage.java | 6 +++--- .../tasks/BuyerSendPayoutTxPublishedMessage.java | 1 + .../SellerMaybeSendPayoutTxPublishedMessage.java | 1 + .../tasks/SellerProcessPaymentSentMessage.java | 2 +- .../tasks/SellerSendPaymentReceivedMessage.java | 10 ++++++---- proto/src/main/proto/pb.proto | 7 ++++--- 11 files changed, 33 insertions(+), 21 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index 2e0fc19d47..2f314d8026 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -831,7 +831,6 @@ public abstract class Trade implements Tradable, Model { // update trade state getSelf().setPayoutTxHex(payoutTxHex); setPayoutTx(describedTxSet.getTxs().get(0)); - setPayoutTxId(describedTxSet.getTxs().get(0).getHash()); // submit payout tx if (publish) { diff --git a/core/src/main/java/bisq/core/trade/messages/PayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/messages/PayoutTxPublishedMessage.java index 97c12e1ccd..69a7602767 100644 --- a/core/src/main/java/bisq/core/trade/messages/PayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/messages/PayoutTxPublishedMessage.java @@ -38,6 +38,7 @@ import javax.annotation.Nullable; @Value public final class PayoutTxPublishedMessage extends TradeMailboxMessage { private final NodeAddress senderNodeAddress; + private final boolean isMaker; private final String signedPayoutTxHex; // Added in v1.4.0 @@ -46,10 +47,12 @@ public final class PayoutTxPublishedMessage extends TradeMailboxMessage { public PayoutTxPublishedMessage(String tradeId, NodeAddress senderNodeAddress, + boolean isMaker, @Nullable SignedWitness signedWitness, String signedPayoutTxHex) { this(tradeId, senderNodeAddress, + isMaker, signedWitness, UUID.randomUUID().toString(), Version.getP2PMessageVersion(), @@ -63,12 +66,14 @@ public final class PayoutTxPublishedMessage extends TradeMailboxMessage { private PayoutTxPublishedMessage(String tradeId, NodeAddress senderNodeAddress, + boolean isMaker, @Nullable SignedWitness signedWitness, String uid, String messageVersion, String signedPayoutTxHex) { super(messageVersion, tradeId, uid); this.senderNodeAddress = senderNodeAddress; + this.isMaker = isMaker; this.signedWitness = signedWitness; this.signedPayoutTxHex = signedPayoutTxHex; } @@ -78,6 +83,7 @@ public final class PayoutTxPublishedMessage extends TradeMailboxMessage { protobuf.PayoutTxPublishedMessage.Builder builder = protobuf.PayoutTxPublishedMessage.newBuilder() .setTradeId(tradeId) .setSenderNodeAddress(senderNodeAddress.toProtoMessage()) + .setIsMaker(isMaker) .setUid(uid) .setSignedPayoutTxHex(signedPayoutTxHex); Optional.ofNullable(signedWitness).ifPresent(signedWitness -> builder.setSignedWitness(signedWitness.toProtoSignedWitness())); @@ -93,6 +99,7 @@ public final class PayoutTxPublishedMessage extends TradeMailboxMessage { null; return new PayoutTxPublishedMessage(proto.getTradeId(), NodeAddress.fromProto(proto.getSenderNodeAddress()), + proto.getIsMaker(), signedWitness, proto.getUid(), messageVersion, @@ -103,6 +110,7 @@ public final class PayoutTxPublishedMessage extends TradeMailboxMessage { public String toString() { return "PayoutTxPublishedMessage{" + "\n senderNodeAddress=" + senderNodeAddress + + ",\n isMaker=" + isMaker + ",\n signedWitness=" + signedWitness + ",\n signedPayoutTxHex=" + signedPayoutTxHex + "\n} " + super.toString(); diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java index 50fd68481a..e11337ed06 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java @@ -109,8 +109,8 @@ public abstract class BuyerProtocol extends DisputeProtocol { @Override public void handleSignContractResponse(SignContractResponse response, NodeAddress sender) { - sendPaymentAccountKeyRequestIfWhenNeeded(BuyerEvent.DEPOSIT_TXS_CONFIRMED, true); super.handleSignContractResponse(response, sender); + sendPaymentAccountKeyRequestIfWhenNeeded(BuyerEvent.DEPOSIT_TXS_CONFIRMED, true); } public void handle(PaymentAccountKeyResponse response, NodeAddress sender) { diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/ArbitratorProcessPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/ArbitratorProcessPayoutTxPublishedMessage.java index db1091866d..ead62e287e 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/ArbitratorProcessPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/ArbitratorProcessPayoutTxPublishedMessage.java @@ -40,6 +40,10 @@ public class ArbitratorProcessPayoutTxPublishedMessage extends TradeTask { // verify and publish payout tx trade.verifyPayoutTx(request.getSignedPayoutTxHex(), false, true); + // update latest peer address + if (request.isMaker()) trade.setMakerNodeAddress(processModel.getTempTradingPeerNodeAddress()); + else trade.setTakerNodeAddress(processModel.getTempTradingPeerNodeAddress()); + // TODO: publish signed witness data? //request.getSignedWitness() diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/BuyerProcessPaymentAccountKeyResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/BuyerProcessPaymentAccountKeyResponse.java index dec7439c2d..eb936b06b6 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/BuyerProcessPaymentAccountKeyResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/BuyerProcessPaymentAccountKeyResponse.java @@ -41,18 +41,14 @@ public class BuyerProcessPaymentAccountKeyResponse extends TradeTask { trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress()); } - // buyer may already have decrypted payment account payload from arbitrator request - if (trade.getTradingPeer().getPaymentAccountPayload() != null) { - complete(); - return; - } - // decrypt peer's payment account payload PaymentAccountKeyResponse request = (PaymentAccountKeyResponse) processModel.getTradeMessage(); - trade.decryptPeersPaymentAccountPayload(request.getPaymentAccountKey()); + if (trade.getTradingPeer().getPaymentAccountPayload() == null) { + trade.decryptPeersPaymentAccountPayload(request.getPaymentAccountKey()); + } // store updated multisig hex for processing on payment sent - trade.getTradingPeer().setUpdatedMultisigHex(request.getUpdatedMultisigHex()); + if (request.getUpdatedMultisigHex() != null) trade.getTradingPeer().setUpdatedMultisigHex(request.getUpdatedMultisigHex()); // persist and complete processModel.getTradeManager().requestPersistence(); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/BuyerProcessPaymentReceivedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/BuyerProcessPaymentReceivedMessage.java index f229e16c92..7e2bd6552f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/BuyerProcessPaymentReceivedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/BuyerProcessPaymentReceivedMessage.java @@ -56,11 +56,11 @@ public class BuyerProcessPaymentReceivedMessage extends TradeTask { trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress()); // handle if payout tx is not seen on network - if (trade.getPayoutTx() == null) { + if (trade.getPhase().ordinal() < Trade.Phase.PAYOUT_PUBLISHED.ordinal()) { // publish payout tx if signed. otherwise verify, sign, and publish payout tx - boolean fullySigned = trade.getSelf().getPayoutTx() != null; - if (fullySigned) { + boolean previouslySigned = trade.getBuyer().getPayoutTxHex() != null; + if (previouslySigned) { log.info("Buyer publishing signed payout tx from seller"); XmrWalletService walletService = processModel.getProvider().getXmrWalletService(); MoneroWallet multisigWallet = walletService.getMultisigWallet(trade.getId()); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/BuyerSendPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/BuyerSendPayoutTxPublishedMessage.java index 600ed17215..cd454f4c3e 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/BuyerSendPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/BuyerSendPayoutTxPublishedMessage.java @@ -54,6 +54,7 @@ public class BuyerSendPayoutTxPublishedMessage extends SendMailboxMessageTask { return new PayoutTxPublishedMessage( tradeId, processModel.getMyNodeAddress(), + trade.isMaker(), null, // TODO: send witness data? trade.getSelf().getPayoutTxHex() ); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/SellerMaybeSendPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/SellerMaybeSendPayoutTxPublishedMessage.java index 98ab66df64..6872e0ddef 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/SellerMaybeSendPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/SellerMaybeSendPayoutTxPublishedMessage.java @@ -69,6 +69,7 @@ public class SellerMaybeSendPayoutTxPublishedMessage extends SendMailboxMessageT return new PayoutTxPublishedMessage( tradeId, processModel.getMyNodeAddress(), + trade.isMaker(), null, // TODO: send witness data? trade.getSelf().getPayoutTxHex() ); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/SellerProcessPaymentSentMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/SellerProcessPaymentSentMessage.java index 8f3e0f3a1b..a84561c5d0 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/SellerProcessPaymentSentMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/SellerProcessPaymentSentMessage.java @@ -57,7 +57,7 @@ public class SellerProcessPaymentSentMessage extends TradeTask { walletService.closeMultisigWallet(trade.getId()); } - // update to the latest peer address of our peer if the message is correct // TODO (woodser): update to latest peer addresses where needed + // update latest peer address trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress()); String counterCurrencyTxId = message.getCounterCurrencyTxId(); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/SellerSendPaymentReceivedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/SellerSendPaymentReceivedMessage.java index 429c9ed4a2..ec5aefea2e 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/SellerSendPaymentReceivedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/SellerSendPaymentReceivedMessage.java @@ -65,9 +65,11 @@ public class SellerSendPaymentReceivedMessage extends SendMailboxMessageTask { ); } + // TODO: using PAYOUT_TX_PUBLISHED_MSG to represent PAYMENT_RECEIVED_MSG after payout, but PAYOUT_TX_PUBLISHED_MSG is specifically for arbitrator. delete *PAYOUT_TX_PUBLISHED* messages and check payout field manually? + @Override protected void setStateSent() { - trade.setState(trade.getState() == Trade.State.SELLER_PUBLISHED_PAYOUT_TX ? Trade.State.SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG : Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG); + trade.setState(trade.getState().ordinal() >= Trade.State.SELLER_PUBLISHED_PAYOUT_TX.ordinal() ? Trade.State.SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG : Trade.State.SELLER_SENT_PAYMENT_RECEIVED_MSG); log.info("Sent SellerReceivedPaymentMessage: tradeId={} at peer {} SignedWitness {}", trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness); processModel.getTradeManager().requestPersistence(); @@ -75,7 +77,7 @@ public class SellerSendPaymentReceivedMessage extends SendMailboxMessageTask { @Override protected void setStateArrived() { - trade.setState(trade.getState() == Trade.State.SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG ? Trade.State.SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG : Trade.State.SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG); + trade.setState(trade.getState().ordinal() >= Trade.State.SELLER_PUBLISHED_PAYOUT_TX.ordinal() ? Trade.State.SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG : Trade.State.SELLER_SAW_ARRIVED_PAYMENT_RECEIVED_MSG); log.info("Seller's PaymentReceivedMessage arrived: tradeId={} at peer {} SignedWitness {}", trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness); processModel.getTradeManager().requestPersistence(); @@ -83,7 +85,7 @@ public class SellerSendPaymentReceivedMessage extends SendMailboxMessageTask { @Override protected void setStateStoredInMailbox() { - trade.setState(trade.getState() == Trade.State.SELLER_PUBLISHED_PAYOUT_TX ? Trade.State.SELLER_STORED_IN_MAILBOX_PAYOUT_TX_PUBLISHED_MSG : Trade.State.SELLER_STORED_IN_MAILBOX_PAYMENT_RECEIVED_MSG); + trade.setState(trade.getState().ordinal() >= Trade.State.SELLER_PUBLISHED_PAYOUT_TX.ordinal() ? Trade.State.SELLER_STORED_IN_MAILBOX_PAYOUT_TX_PUBLISHED_MSG : Trade.State.SELLER_STORED_IN_MAILBOX_PAYMENT_RECEIVED_MSG); log.info("Seller's PaymentReceivedMessage stored in mailbox: tradeId={} at peer {} SignedWitness {}", trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness); processModel.getTradeManager().requestPersistence(); @@ -91,7 +93,7 @@ public class SellerSendPaymentReceivedMessage extends SendMailboxMessageTask { @Override protected void setStateFault() { - trade.setState(trade.getState() == Trade.State.SELLER_PUBLISHED_PAYOUT_TX ? Trade.State.SELLER_SEND_FAILED_PAYOUT_TX_PUBLISHED_MSG : Trade.State.SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG); + trade.setState(trade.getState().ordinal() >= Trade.State.SELLER_PUBLISHED_PAYOUT_TX.ordinal() ? Trade.State.SELLER_SEND_FAILED_PAYOUT_TX_PUBLISHED_MSG : Trade.State.SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG); log.error("SellerReceivedPaymentMessage failed: tradeId={} at peer {} SignedWitness {}", trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness); processModel.getTradeManager().requestPersistence(); diff --git a/proto/src/main/proto/pb.proto b/proto/src/main/proto/pb.proto index e9f0b0ae91..3b2f63cc01 100644 --- a/proto/src/main/proto/pb.proto +++ b/proto/src/main/proto/pb.proto @@ -461,9 +461,10 @@ message PaymentReceivedMessage { message PayoutTxPublishedMessage { string trade_id = 1; NodeAddress sender_node_address = 2; - string uid = 3; - SignedWitness signed_witness = 4; - string signed_payout_tx_hex = 5; + bool is_maker = 3; + string uid = 4; + SignedWitness signed_witness = 5; + string signed_payout_tx_hex = 6; } message ArbitratorPayoutTxRequest {