From 66a26893f052dbdbaa24cb9108be6615683df1d8 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 18:55:49 -0500 Subject: [PATCH 001/143] Always show deposit and delayed payout tx in trade details window. If null it shows N/A --- .../overlays/windows/TradeDetailsWindow.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java index 1fe5f8d8258..dae9eb3ad47 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java @@ -42,6 +42,7 @@ import bisq.common.UserThread; +import org.bitcoinj.core.Transaction; import org.bitcoinj.core.Utils; import javax.inject.Inject; @@ -165,15 +166,10 @@ private void addContent() { addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.paymentMethod"), paymentMethodText); // second group - rows = 6; + rows = 8; PaymentAccountPayload buyerPaymentAccountPayload = null; PaymentAccountPayload sellerPaymentAccountPayload = null; - /* if (offer.getAcceptedCountryCodes() != null) - rows++; - if (offer.getAcceptedBanks() != null) - rows++;*/ - if (contract != null) { rows++; @@ -191,8 +187,7 @@ private void addContent() { if (trade.getTakerFeeTxId() != null) rows++; - if (trade.getDepositTx() != null) - rows++; + if (trade.getPayoutTx() != null) rows++; boolean showDisputedTx = arbitrationManager.findOwnDispute(trade.getId()).isPresent() && @@ -288,9 +283,14 @@ private void addContent() { if (trade.getTakerFeeTxId() != null) addLabelTxIdTextField(gridPane, ++rowIndex, Res.get("shared.takerFeeTxId"), trade.getTakerFeeTxId()); - if (trade.getDepositTx() != null) - addLabelTxIdTextField(gridPane, ++rowIndex, Res.get("shared.depositTransactionId"), - trade.getDepositTx().getTxId().toString()); + Transaction depositTx = trade.getDepositTx(); + String depositTxString = depositTx != null ? depositTx.getTxId().toString() : Res.get("shared.na"); + addLabelTxIdTextField(gridPane, ++rowIndex, Res.get("shared.depositTransactionId"), depositTxString); + + Transaction delayedPayoutTx = trade.getDelayedPayoutTx(); + String delayedPayoutTxString = delayedPayoutTx != null ? delayedPayoutTx.getTxId().toString() : Res.get("shared.na"); + addLabelTxIdTextField(gridPane, ++rowIndex, Res.get("shared.delayedPayoutTxId"), delayedPayoutTxString); + if (trade.getPayoutTx() != null) addLabelTxIdTextField(gridPane, ++rowIndex, Res.get("shared.payoutTxId"), trade.getPayoutTx().getTxId().toString()); From 690104e6eac57d73a1623051cfe692e5b871ffa0 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 18:56:58 -0500 Subject: [PATCH 002/143] Show popup on MissingDelayedPayoutTxException. Update display string of popup --- .../main/resources/i18n/displayStrings.properties | 13 +++++++------ .../pendingtrades/steps/buyer/BuyerStep1View.java | 6 ++---- .../pendingtrades/steps/buyer/BuyerStep2View.java | 6 ++---- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index a36cef1a568..06bb9868b66 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -559,9 +559,10 @@ portfolio.tab.history=History portfolio.tab.failed=Failed portfolio.tab.editOpenOffer=Edit offer -portfolio.pending.invalidDelayedPayoutTx=Please do NOT send the Altcoin or Fiat payment but contact the Bisq \ - developers at 'https://bisq.community' or the Keybase channel.\n\n\ - {0} +portfolio.pending.invalidDelayedPayoutTx=There is an issue with a missing or invalid transaction.\n\n\ + Please do NOT send the Altcoin or Fiat payment but contact the Bisq \ + developers at 'https://bisq.community' or the Keybase channel for further assistance.\n\n\ + Error message: {0} portfolio.pending.step1.waitForConf=Wait for blockchain confirmation portfolio.pending.step2_buyer.startPayment=Start payment @@ -904,10 +905,10 @@ portfolio.failed.Failed=Failed portfolio.failed.unfail=Before proceeding, make sure you have a backup of your data directory!\n\ Do you want to move this trade back to open trades?\n\ This is a way to unlock funds stuck in a failed trade. -portfolio.failed.cantUnfail=This trade cannot be moved back to open trades at the moment. \n\ +portfolio.failed.cantUnfail=This trade cannot be moved back to pending trades at the moment. \n\ Try again after completion of trade(s) {0} -portfolio.failed.depositTxNull=The trade cannot be completed. Deposit transaction is null -portfolio.failed.delayedPayoutTxNull=The trade cannot be completed. Delayed payout transaction is null +portfolio.failed.depositTxNull=The trade cannot be reverted to a pending trade. Deposit transaction is null. +portfolio.failed.delayedPayoutTxNull=The trade cannot be reverted to a pending trade. Delayed payout transaction is null. #################################################################### diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep1View.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep1View.java index 184dcd038f9..b81ebc0f419 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep1View.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep1View.java @@ -46,13 +46,11 @@ public void activate() { } catch (DelayedPayoutTxValidation.DonationAddressException | DelayedPayoutTxValidation.InvalidTxException | DelayedPayoutTxValidation.AmountMismatchException | - DelayedPayoutTxValidation.InvalidLockTimeException e) { + DelayedPayoutTxValidation.InvalidLockTimeException | + DelayedPayoutTxValidation.MissingDelayedPayoutTxException e) { if (!model.dataModel.tradeManager.isAllowFaultyDelayedTxs()) { new Popup().warning(Res.get("portfolio.pending.invalidDelayedPayoutTx", e.getMessage())).show(); } - } catch (DelayedPayoutTxValidation.MissingDelayedPayoutTxException ignore) { - // We don't react on those errors as a failed trade might get listed initially but getting removed from the - // trade manager after initPendingTrades which happens after activate might be called. } } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java index d6d2aeabe33..b60f682ce08 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java @@ -125,13 +125,11 @@ public void activate() { } catch (DelayedPayoutTxValidation.DonationAddressException | DelayedPayoutTxValidation.InvalidTxException | DelayedPayoutTxValidation.AmountMismatchException | - DelayedPayoutTxValidation.InvalidLockTimeException e) { + DelayedPayoutTxValidation.InvalidLockTimeException | + DelayedPayoutTxValidation.MissingDelayedPayoutTxException e) { if (!model.dataModel.tradeManager.isAllowFaultyDelayedTxs()) { new Popup().warning(Res.get("portfolio.pending.invalidDelayedPayoutTx", e.getMessage())).show(); } - } catch (DelayedPayoutTxValidation.MissingDelayedPayoutTxException ignore) { - // We don't react on those errors as a failed trade might get listed initially but getting removed from the - // trade manager after initPendingTrades which happens after activate might be called. } if (timeoutTimer != null) From 944a77d6954ef73eac4e7b24ce6f8a46c7628db2 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 19:09:14 -0500 Subject: [PATCH 003/143] Refactor: - Rename getFundsNeededForTradeAsLong to getFundsNeededForTrade - Use checkNotNull instead of if/else check - Cleanups --- .../java/bisq/core/trade/TradeManager.java | 4 +- .../core/trade/protocol/ProcessModel.java | 2 +- .../SellerAsTakerCreatesDepositTxInputs.java | 37 +++++++++---------- .../tasks/taker/CreateTakerFeeTx.java | 11 +++--- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 228ac7abae5..817dcfe0b86 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -357,7 +357,7 @@ public void onUserConfirmedFiatPaymentReceived(SellerTrade sellerTrade, private void initPendingTrade(Trade trade) { initTrade(trade, trade.getProcessModel().isUseSavingsWallet(), - trade.getProcessModel().getFundsNeededForTradeAsLong()); + trade.getProcessModel().getFundsNeededForTrade()); trade.updateDepositTxFromWallet(); tradesForStatistics.add(trade); } @@ -419,7 +419,7 @@ private void handlePayDepositRequest(InputsForDepositTxRequest inputsForDepositT tradableListStorage, btcWalletService); - initTrade(trade, trade.getProcessModel().isUseSavingsWallet(), trade.getProcessModel().getFundsNeededForTradeAsLong()); + initTrade(trade, trade.getProcessModel().isUseSavingsWallet(), trade.getProcessModel().getFundsNeededForTrade()); tradableList.add(trade); ((MakerTrade) trade).handleTakeOfferRequest(inputsForDepositTxRequest, peer, errorMessage -> { if (takeOfferRequestErrorMessageHandler != null) diff --git a/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java b/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java index e2de20d065c..a09d93834e7 100644 --- a/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java +++ b/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java @@ -311,7 +311,7 @@ public PaymentAccountPayload getPaymentAccountPayload(Trade trade) { return paymentAccount != null ? paymentAccount.getPaymentAccountPayload() : null; } - public Coin getFundsNeededForTradeAsLong() { + public Coin getFundsNeededForTrade() { return Coin.valueOf(fundsNeededForTradeAsLong); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerCreatesDepositTxInputs.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerCreatesDepositTxInputs.java index 9b4b88a0ba4..9240e9f8d18 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerCreatesDepositTxInputs.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerCreatesDepositTxInputs.java @@ -18,6 +18,7 @@ package bisq.core.trade.protocol.tasks.seller_as_taker; import bisq.core.btc.model.InputsAndChangeOutput; +import bisq.core.offer.Offer; import bisq.core.trade.Trade; import bisq.core.trade.protocol.tasks.TradeTask; @@ -31,8 +32,7 @@ @Slf4j public class SellerAsTakerCreatesDepositTxInputs extends TradeTask { - @SuppressWarnings({"unused"}) - public SellerAsTakerCreatesDepositTxInputs(TaskRunner taskHandler, Trade trade) { + public SellerAsTakerCreatesDepositTxInputs(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } @@ -40,25 +40,24 @@ public SellerAsTakerCreatesDepositTxInputs(TaskRunner taskHandler, Trade trade) protected void run() { try { runInterceptHook(); - if (trade.getTradeAmount() != null) { - Coin txFee = trade.getTxFee(); - Coin takerInputAmount = checkNotNull(trade.getOffer()).getSellerSecurityDeposit() - .add(txFee) - .add(txFee) - .add(trade.getTradeAmount()); - InputsAndChangeOutput result = processModel.getTradeWalletService().takerCreatesDepositTxInputs( - processModel.getTakeOfferFeeTx(), - takerInputAmount, - txFee); - processModel.setRawTransactionInputs(result.rawTransactionInputs); - processModel.setChangeOutputValue(result.changeOutputValue); - processModel.setChangeOutputAddress(result.changeOutputAddress); + Coin tradeAmount = checkNotNull(trade.getTradeAmount()); + Offer offer = checkNotNull(trade.getOffer()); + Coin txFee = trade.getTxFee(); + Coin takerInputAmount = offer.getSellerSecurityDeposit() + .add(txFee) + .add(txFee) // We add 2 times the fee as one is for the payout tx + .add(tradeAmount); + InputsAndChangeOutput result = processModel.getTradeWalletService().takerCreatesDepositTxInputs( + processModel.getTakeOfferFeeTx(), + takerInputAmount, + txFee); - complete(); - } else { - failed("trade.getTradeAmount() = null"); - } + processModel.setRawTransactionInputs(result.rawTransactionInputs); + processModel.setChangeOutputValue(result.changeOutputValue); + processModel.setChangeOutputAddress(result.changeOutputAddress); + + complete(); } catch (Throwable t) { failed(t); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java index 3eec6c6b453..9407695ec6e 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java @@ -36,7 +36,6 @@ @Slf4j public class CreateTakerFeeTx extends TradeTask { - @SuppressWarnings({"unused"}) public CreateTakerFeeTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } @@ -51,16 +50,16 @@ protected void run() { // We enforce here to create a MULTI_SIG and TRADE_PAYOUT address entry to avoid that the change output would be used later // for those address entries. Because we do not commit our fee tx yet the change address would - // appear as unused and therefor selected for the outputs for the MS tx. + // appear as unused and therefore selected for the outputs for the MS tx. // That would cause incorrect display of the balance as // the change output would be considered as not available balance (part of the locked trade amount). walletService.getNewAddressEntry(id, AddressEntry.Context.MULTI_SIG); walletService.getNewAddressEntry(id, AddressEntry.Context.TRADE_PAYOUT); - AddressEntry addressEntry = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.OFFER_FUNDING); + AddressEntry fundingAddressEntry = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.OFFER_FUNDING); AddressEntry reservedForTradeAddressEntry = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.RESERVED_FOR_TRADE); AddressEntry changeAddressEntry = walletService.getFreshAddressEntry(); - Address fundingAddress = addressEntry.getAddress(); + Address fundingAddress = fundingAddressEntry.getAddress(); Address reservedForTradeAddress = reservedForTradeAddressEntry.getAddress(); Address changeAddress = changeAddressEntry.getAddress(); TradeWalletService tradeWalletService = processModel.getTradeWalletService(); @@ -73,7 +72,7 @@ protected void run() { fundingAddress, reservedForTradeAddress, changeAddress, - processModel.getFundsNeededForTradeAsLong(), + processModel.getFundsNeededForTrade(), processModel.isUseSavingsWallet(), trade.getTakerFee(), trade.getTxFee(), @@ -86,7 +85,7 @@ protected void run() { fundingAddress, reservedForTradeAddress, changeAddress, - processModel.getFundsNeededForTradeAsLong(), + processModel.getFundsNeededForTrade(), processModel.isUseSavingsWallet(), trade.getTxFee()); transaction = processModel.getBsqWalletService().signTx(txWithBsqFee); From 4d7b2897fc6698d16a48ebd5890fa8324041aaa4 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 19:11:07 -0500 Subject: [PATCH 004/143] Refactor: - Use `TaskRunner taskHandler` instead of `TaskRunner taskHandler` --- .../main/java/bisq/core/trade/protocol/tasks/ApplyFilter.java | 2 +- .../java/bisq/core/trade/protocol/tasks/BroadcastPayoutTx.java | 2 +- .../tasks/ProcessPeerPublishedDelayedPayoutTxMessage.java | 2 +- .../bisq/core/trade/protocol/tasks/PublishTradeStatistics.java | 2 +- .../core/trade/protocol/tasks/SendPayoutTxPublishedMessage.java | 2 +- .../bisq/core/trade/protocol/tasks/SetupPayoutTxListener.java | 2 +- .../src/main/java/bisq/core/trade/protocol/tasks/TradeTask.java | 2 +- .../core/trade/protocol/tasks/VerifyPeersAccountAgeWitness.java | 2 +- .../buyer/BuyerProcessDelayedPayoutTxSignatureRequest.java | 2 +- .../buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java | 2 +- .../tasks/buyer/BuyerProcessPayoutTxPublishedMessage.java | 2 +- .../buyer/BuyerSendCounterCurrencyTransferStartedMessage.java | 2 +- .../tasks/buyer/BuyerSendsDelayedPayoutTxSignatureResponse.java | 2 +- .../trade/protocol/tasks/buyer/BuyerSetupDepositTxListener.java | 2 +- .../trade/protocol/tasks/buyer/BuyerSetupPayoutTxListener.java | 2 +- .../bisq/core/trade/protocol/tasks/buyer/BuyerSignPayoutTx.java | 2 +- .../trade/protocol/tasks/buyer/BuyerSignsDelayedPayoutTx.java | 2 +- .../protocol/tasks/buyer/BuyerVerifiesFinalDelayedPayoutTx.java | 2 +- .../tasks/buyer/BuyerVerifiesPreparedDelayedPayoutTx.java | 2 +- .../buyer_as_maker/BuyerAsMakerCreatesAndSignsDepositTx.java | 2 +- .../BuyerAsMakerSendsInputsForDepositTxResponse.java | 2 +- .../buyer_as_taker/BuyerAsTakerCreatesDepositTxInputs.java | 2 +- .../tasks/buyer_as_taker/BuyerAsTakerSendsDepositTxMessage.java | 2 +- .../tasks/buyer_as_taker/BuyerAsTakerSignsDepositTx.java | 2 +- .../trade/protocol/tasks/maker/MakerCreateAndSignContract.java | 2 +- .../tasks/maker/MakerProcessesInputsForDepositTxRequest.java | 2 +- .../tasks/maker/MakerSendsInputsForDepositTxResponse.java | 2 +- .../bisq/core/trade/protocol/tasks/maker/MakerSetsLockTime.java | 2 +- .../trade/protocol/tasks/maker/MakerVerifyTakerAccount.java | 2 +- .../trade/protocol/tasks/maker/MakerVerifyTakerFeePayment.java | 2 +- .../protocol/tasks/mediation/BroadcastMediatedPayoutTx.java | 2 +- .../protocol/tasks/mediation/FinalizeMediatedPayoutTx.java | 2 +- .../tasks/mediation/ProcessMediatedPayoutSignatureMessage.java | 2 +- .../mediation/ProcessMediatedPayoutTxPublishedMessage.java | 2 +- .../tasks/mediation/SendMediatedPayoutSignatureMessage.java | 2 +- .../tasks/mediation/SendMediatedPayoutTxPublishedMessage.java | 2 +- .../protocol/tasks/mediation/SetupMediatedPayoutTxListener.java | 2 +- .../trade/protocol/tasks/mediation/SignMediatedPayoutTx.java | 2 +- .../trade/protocol/tasks/seller/SellerBroadcastPayoutTx.java | 2 +- .../protocol/tasks/seller/SellerCreatesDelayedPayoutTx.java | 2 +- .../protocol/tasks/seller/SellerFinalizesDelayedPayoutTx.java | 2 +- .../SellerProcessCounterCurrencyTransferStartedMessage.java | 2 +- .../seller/SellerProcessDelayedPayoutTxSignatureResponse.java | 2 +- .../trade/protocol/tasks/seller/SellerPublishesDepositTx.java | 2 +- .../tasks/seller/SellerSendDelayedPayoutTxSignatureRequest.java | 2 +- .../tasks/seller/SellerSendPayoutTxPublishedMessage.java | 2 +- .../seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java | 2 +- .../protocol/tasks/seller/SellerSignAndFinalizePayoutTx.java | 2 +- .../trade/protocol/tasks/seller/SellerSignsDelayedPayoutTx.java | 2 +- .../seller_as_maker/SellerAsMakerCreatesUnsignedDepositTx.java | 2 +- .../tasks/seller_as_maker/SellerAsMakerFinalizesDepositTx.java | 2 +- .../seller_as_maker/SellerAsMakerProcessDepositTxMessage.java | 2 +- .../SellerAsMakerSendsInputsForDepositTxResponse.java | 2 +- .../tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java | 2 +- .../bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java | 2 +- .../tasks/taker/TakerProcessesInputsForDepositTxResponse.java | 2 +- .../bisq/core/trade/protocol/tasks/taker/TakerPublishFeeTx.java | 2 +- .../tasks/taker/TakerSendInputsForDepositTxRequest.java | 2 +- .../trade/protocol/tasks/taker/TakerVerifyAndSignContract.java | 2 +- .../trade/protocol/tasks/taker/TakerVerifyMakerAccount.java | 2 +- .../trade/protocol/tasks/taker/TakerVerifyMakerFeePayment.java | 2 +- 61 files changed, 61 insertions(+), 61 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/ApplyFilter.java b/core/src/main/java/bisq/core/trade/protocol/tasks/ApplyFilter.java index cbcb0ae8c22..0b415bd58ff 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/ApplyFilter.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/ApplyFilter.java @@ -32,7 +32,7 @@ @Slf4j public class ApplyFilter extends TradeTask { @SuppressWarnings({"unused"}) - public ApplyFilter(TaskRunner taskHandler, Trade trade) { + public ApplyFilter(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/BroadcastPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/BroadcastPayoutTx.java index e74495d064e..dae4197b3f5 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/BroadcastPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/BroadcastPayoutTx.java @@ -33,7 +33,7 @@ @Slf4j public abstract class BroadcastPayoutTx extends TradeTask { @SuppressWarnings({"unused"}) - public BroadcastPayoutTx(TaskRunner taskHandler, Trade trade) { + public BroadcastPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessPeerPublishedDelayedPayoutTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessPeerPublishedDelayedPayoutTxMessage.java index d0dc9300530..1b890bb508f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessPeerPublishedDelayedPayoutTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessPeerPublishedDelayedPayoutTxMessage.java @@ -33,7 +33,7 @@ @Slf4j public class ProcessPeerPublishedDelayedPayoutTxMessage extends TradeTask { @SuppressWarnings({"unused"}) - public ProcessPeerPublishedDelayedPayoutTxMessage(TaskRunner taskHandler, Trade trade) { + public ProcessPeerPublishedDelayedPayoutTxMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/PublishTradeStatistics.java b/core/src/main/java/bisq/core/trade/protocol/tasks/PublishTradeStatistics.java index 421b69e1857..7a19d4f9177 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/PublishTradeStatistics.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/PublishTradeStatistics.java @@ -37,7 +37,7 @@ @Slf4j public class PublishTradeStatistics extends TradeTask { - public PublishTradeStatistics(TaskRunner taskHandler, Trade trade) { + public PublishTradeStatistics(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/SendPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/SendPayoutTxPublishedMessage.java index c48aa3e5ffb..f18c2be43b0 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/SendPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/SendPayoutTxPublishedMessage.java @@ -30,7 +30,7 @@ @Slf4j public abstract class SendPayoutTxPublishedMessage extends TradeTask { @SuppressWarnings({"unused"}) - public SendPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) { + public SendPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/SetupPayoutTxListener.java b/core/src/main/java/bisq/core/trade/protocol/tasks/SetupPayoutTxListener.java index 20b85539398..755cafed1ed 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/SetupPayoutTxListener.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/SetupPayoutTxListener.java @@ -41,7 +41,7 @@ public abstract class SetupPayoutTxListener extends TradeTask { private AddressConfidenceListener confidenceListener; @SuppressWarnings({"unused"}) - public SetupPayoutTxListener(TaskRunner taskHandler, Trade trade) { + public SetupPayoutTxListener(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/TradeTask.java b/core/src/main/java/bisq/core/trade/protocol/tasks/TradeTask.java index 1d76bd9b29d..f7aeeaeaa9a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/TradeTask.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/TradeTask.java @@ -30,7 +30,7 @@ public abstract class TradeTask extends Task { protected final ProcessModel processModel; protected final Trade trade; - protected TradeTask(TaskRunner taskHandler, Trade trade) { + protected TradeTask(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); this.trade = trade; diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/VerifyPeersAccountAgeWitness.java b/core/src/main/java/bisq/core/trade/protocol/tasks/VerifyPeersAccountAgeWitness.java index 2aa6e6ef177..5a118c0db8f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/VerifyPeersAccountAgeWitness.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/VerifyPeersAccountAgeWitness.java @@ -36,7 +36,7 @@ public class VerifyPeersAccountAgeWitness extends TradeTask { @SuppressWarnings({"unused"}) - public VerifyPeersAccountAgeWitness(TaskRunner taskHandler, Trade trade) { + public VerifyPeersAccountAgeWitness(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDelayedPayoutTxSignatureRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDelayedPayoutTxSignatureRequest.java index c9fe2e8b7ad..a5a08bdd902 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDelayedPayoutTxSignatureRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDelayedPayoutTxSignatureRequest.java @@ -33,7 +33,7 @@ @Slf4j public class BuyerProcessDelayedPayoutTxSignatureRequest extends TradeTask { @SuppressWarnings({"unused"}) - public BuyerProcessDelayedPayoutTxSignatureRequest(TaskRunner taskHandler, Trade trade) { + public BuyerProcessDelayedPayoutTxSignatureRequest(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java index 16be554fed3..6c8ea46cc63 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java @@ -38,7 +38,7 @@ @Slf4j public class BuyerProcessDepositTxAndDelayedPayoutTxMessage extends TradeTask { @SuppressWarnings({"unused"}) - public BuyerProcessDepositTxAndDelayedPayoutTxMessage(TaskRunner taskHandler, Trade trade) { + public BuyerProcessDepositTxAndDelayedPayoutTxMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessPayoutTxPublishedMessage.java index 245dd40aacb..382d4c99e50 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessPayoutTxPublishedMessage.java @@ -37,7 +37,7 @@ @Slf4j public class BuyerProcessPayoutTxPublishedMessage extends TradeTask { @SuppressWarnings({"unused"}) - public BuyerProcessPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) { + public BuyerProcessPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java index 40cd15750a8..3d5e63a86ca 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java @@ -35,7 +35,7 @@ @Slf4j public class BuyerSendCounterCurrencyTransferStartedMessage extends TradeTask { @SuppressWarnings({"unused"}) - public BuyerSendCounterCurrencyTransferStartedMessage(TaskRunner taskHandler, Trade trade) { + public BuyerSendCounterCurrencyTransferStartedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendsDelayedPayoutTxSignatureResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendsDelayedPayoutTxSignatureResponse.java index 887c416a546..4630df01efe 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendsDelayedPayoutTxSignatureResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendsDelayedPayoutTxSignatureResponse.java @@ -35,7 +35,7 @@ @Slf4j public class BuyerSendsDelayedPayoutTxSignatureResponse extends TradeTask { @SuppressWarnings({"unused"}) - public BuyerSendsDelayedPayoutTxSignatureResponse(TaskRunner taskHandler, Trade trade) { + public BuyerSendsDelayedPayoutTxSignatureResponse(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupDepositTxListener.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupDepositTxListener.java index 454761b4aec..aed61a8f932 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupDepositTxListener.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupDepositTxListener.java @@ -45,7 +45,7 @@ public class BuyerSetupDepositTxListener extends TradeTask { private AddressConfidenceListener confidenceListener; @SuppressWarnings({"unused"}) - public BuyerSetupDepositTxListener(TaskRunner taskHandler, Trade trade) { + public BuyerSetupDepositTxListener(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupPayoutTxListener.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupPayoutTxListener.java index db0dfff0cdf..ee8f5b190fb 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupPayoutTxListener.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupPayoutTxListener.java @@ -27,7 +27,7 @@ @Slf4j public class BuyerSetupPayoutTxListener extends SetupPayoutTxListener { @SuppressWarnings({"unused"}) - public BuyerSetupPayoutTxListener(TaskRunner taskHandler, Trade trade) { + public BuyerSetupPayoutTxListener(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignPayoutTx.java index b90a91ec22d..f9a43a13cf8 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignPayoutTx.java @@ -41,7 +41,7 @@ public class BuyerSignPayoutTx extends TradeTask { @SuppressWarnings({"unused"}) - public BuyerSignPayoutTx(TaskRunner taskHandler, Trade trade) { + public BuyerSignPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignsDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignsDelayedPayoutTx.java index 0d0bb585ae4..8ba2e19695a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignsDelayedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignsDelayedPayoutTx.java @@ -37,7 +37,7 @@ @Slf4j public class BuyerSignsDelayedPayoutTx extends TradeTask { @SuppressWarnings({"unused"}) - public BuyerSignsDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { + public BuyerSignsDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesFinalDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesFinalDelayedPayoutTx.java index fa1aeacdbe6..943dc78819d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesFinalDelayedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesFinalDelayedPayoutTx.java @@ -32,7 +32,7 @@ @Slf4j public class BuyerVerifiesFinalDelayedPayoutTx extends TradeTask { @SuppressWarnings({"unused"}) - public BuyerVerifiesFinalDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { + public BuyerVerifiesFinalDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesPreparedDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesPreparedDelayedPayoutTx.java index 3242ba8cf6a..5c9233de419 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesPreparedDelayedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesPreparedDelayedPayoutTx.java @@ -28,7 +28,7 @@ @Slf4j public class BuyerVerifiesPreparedDelayedPayoutTx extends TradeTask { @SuppressWarnings({"unused"}) - public BuyerVerifiesPreparedDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { + public BuyerVerifiesPreparedDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerCreatesAndSignsDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerCreatesAndSignsDepositTx.java index f7d2e8c8176..19710b46829 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerCreatesAndSignsDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerCreatesAndSignsDepositTx.java @@ -44,7 +44,7 @@ @Slf4j public class BuyerAsMakerCreatesAndSignsDepositTx extends TradeTask { @SuppressWarnings({"unused"}) - public BuyerAsMakerCreatesAndSignsDepositTx(TaskRunner taskHandler, Trade trade) { + public BuyerAsMakerCreatesAndSignsDepositTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerSendsInputsForDepositTxResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerSendsInputsForDepositTxResponse.java index 029a8213dcd..f21a4fe9b9c 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerSendsInputsForDepositTxResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerSendsInputsForDepositTxResponse.java @@ -27,7 +27,7 @@ @Slf4j public class BuyerAsMakerSendsInputsForDepositTxResponse extends MakerSendsInputsForDepositTxResponse { @SuppressWarnings({"unused"}) - public BuyerAsMakerSendsInputsForDepositTxResponse(TaskRunner taskHandler, Trade trade) { + public BuyerAsMakerSendsInputsForDepositTxResponse(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerCreatesDepositTxInputs.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerCreatesDepositTxInputs.java index 39af203b697..737db193144 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerCreatesDepositTxInputs.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerCreatesDepositTxInputs.java @@ -33,7 +33,7 @@ public class BuyerAsTakerCreatesDepositTxInputs extends TradeTask { @SuppressWarnings({"unused"}) - public BuyerAsTakerCreatesDepositTxInputs(TaskRunner taskHandler, Trade trade) { + public BuyerAsTakerCreatesDepositTxInputs(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSendsDepositTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSendsDepositTxMessage.java index f0391f91ebf..b6f0023127b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSendsDepositTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSendsDepositTxMessage.java @@ -33,7 +33,7 @@ @Slf4j public class BuyerAsTakerSendsDepositTxMessage extends TradeTask { @SuppressWarnings({"unused"}) - public BuyerAsTakerSendsDepositTxMessage(TaskRunner taskHandler, Trade trade) { + public BuyerAsTakerSendsDepositTxMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSignsDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSignsDepositTx.java index f5cdcb37606..a52310dbe3f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSignsDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSignsDepositTx.java @@ -43,7 +43,7 @@ public class BuyerAsTakerSignsDepositTx extends TradeTask { @SuppressWarnings({"unused"}) - public BuyerAsTakerSignsDepositTx(TaskRunner taskHandler, Trade trade) { + public BuyerAsTakerSignsDepositTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java index fcd6ec6a797..6dec9babb04 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java @@ -42,7 +42,7 @@ @Slf4j public class MakerCreateAndSignContract extends TradeTask { @SuppressWarnings({"unused"}) - public MakerCreateAndSignContract(TaskRunner taskHandler, Trade trade) { + public MakerCreateAndSignContract(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java index 68fbbc51780..882f76f15d3 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java @@ -44,7 +44,7 @@ @Slf4j public class MakerProcessesInputsForDepositTxRequest extends TradeTask { @SuppressWarnings({"unused"}) - public MakerProcessesInputsForDepositTxRequest(TaskRunner taskHandler, Trade trade) { + public MakerProcessesInputsForDepositTxRequest(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java index 2cd81721ee7..f568d453015 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java @@ -43,7 +43,7 @@ @Slf4j public abstract class MakerSendsInputsForDepositTxResponse extends TradeTask { @SuppressWarnings({"unused"}) - public MakerSendsInputsForDepositTxResponse(TaskRunner taskHandler, Trade trade) { + public MakerSendsInputsForDepositTxResponse(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSetsLockTime.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSetsLockTime.java index 94e817a340e..0de2d4d2c55 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSetsLockTime.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSetsLockTime.java @@ -29,7 +29,7 @@ @Slf4j public class MakerSetsLockTime extends TradeTask { @SuppressWarnings({"unused"}) - public MakerSetsLockTime(TaskRunner taskHandler, Trade trade) { + public MakerSetsLockTime(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerAccount.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerAccount.java index 2f24a9be971..fa9e72c8743 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerAccount.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerAccount.java @@ -27,7 +27,7 @@ @Slf4j public class MakerVerifyTakerAccount extends TradeTask { @SuppressWarnings({"unused"}) - public MakerVerifyTakerAccount(TaskRunner taskHandler, Trade trade) { + public MakerVerifyTakerAccount(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerFeePayment.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerFeePayment.java index 8f30e978959..cda032d4ec0 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerFeePayment.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerFeePayment.java @@ -28,7 +28,7 @@ public class MakerVerifyTakerFeePayment extends TradeTask { @SuppressWarnings({"unused"}) - public MakerVerifyTakerFeePayment(TaskRunner taskHandler, Trade trade) { + public MakerVerifyTakerFeePayment(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/BroadcastMediatedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/BroadcastMediatedPayoutTx.java index c1248792f6a..8b2e174f353 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/BroadcastMediatedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/BroadcastMediatedPayoutTx.java @@ -28,7 +28,7 @@ @Slf4j public class BroadcastMediatedPayoutTx extends BroadcastPayoutTx { @SuppressWarnings({"unused"}) - public BroadcastMediatedPayoutTx(TaskRunner taskHandler, Trade trade) { + public BroadcastMediatedPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/FinalizeMediatedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/FinalizeMediatedPayoutTx.java index 96d8db5b4ec..0b8decabc9a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/FinalizeMediatedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/FinalizeMediatedPayoutTx.java @@ -42,7 +42,7 @@ public class FinalizeMediatedPayoutTx extends TradeTask { @SuppressWarnings({"unused"}) - public FinalizeMediatedPayoutTx(TaskRunner taskHandler, Trade trade) { + public FinalizeMediatedPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutSignatureMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutSignatureMessage.java index 0a26804bf81..b856817b028 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutSignatureMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutSignatureMessage.java @@ -32,7 +32,7 @@ @Slf4j public class ProcessMediatedPayoutSignatureMessage extends TradeTask { @SuppressWarnings({"unused"}) - public ProcessMediatedPayoutSignatureMessage(TaskRunner taskHandler, Trade trade) { + public ProcessMediatedPayoutSignatureMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutTxPublishedMessage.java index e6c60eb4a10..025bd089dd9 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutTxPublishedMessage.java @@ -39,7 +39,7 @@ @Slf4j public class ProcessMediatedPayoutTxPublishedMessage extends TradeTask { @SuppressWarnings({"unused"}) - public ProcessMediatedPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) { + public ProcessMediatedPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutSignatureMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutSignatureMessage.java index 88e6450da47..74473ce3dfb 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutSignatureMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutSignatureMessage.java @@ -39,7 +39,7 @@ @Slf4j public class SendMediatedPayoutSignatureMessage extends TradeTask { @SuppressWarnings({"unused"}) - public SendMediatedPayoutSignatureMessage(TaskRunner taskHandler, Trade trade) { + public SendMediatedPayoutSignatureMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutTxPublishedMessage.java index b97e782d092..ff6d7144b66 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutTxPublishedMessage.java @@ -37,7 +37,7 @@ @Slf4j public class SendMediatedPayoutTxPublishedMessage extends SendPayoutTxPublishedMessage { @SuppressWarnings({"unused"}) - public SendMediatedPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) { + public SendMediatedPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SetupMediatedPayoutTxListener.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SetupMediatedPayoutTxListener.java index 716f2d76471..3b72970e599 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SetupMediatedPayoutTxListener.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SetupMediatedPayoutTxListener.java @@ -28,7 +28,7 @@ @Slf4j public class SetupMediatedPayoutTxListener extends SetupPayoutTxListener { @SuppressWarnings({"unused"}) - public SetupMediatedPayoutTxListener(TaskRunner taskHandler, Trade trade) { + public SetupMediatedPayoutTxListener(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SignMediatedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SignMediatedPayoutTx.java index 5a48240f7d4..22aa206ad09 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SignMediatedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SignMediatedPayoutTx.java @@ -42,7 +42,7 @@ public class SignMediatedPayoutTx extends TradeTask { @SuppressWarnings({"unused"}) - public SignMediatedPayoutTx(TaskRunner taskHandler, Trade trade) { + public SignMediatedPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerBroadcastPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerBroadcastPayoutTx.java index c27072538a2..1db696e75ed 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerBroadcastPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerBroadcastPayoutTx.java @@ -27,7 +27,7 @@ @Slf4j public class SellerBroadcastPayoutTx extends BroadcastPayoutTx { @SuppressWarnings({"unused"}) - public SellerBroadcastPayoutTx(TaskRunner taskHandler, Trade trade) { + public SellerBroadcastPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerCreatesDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerCreatesDelayedPayoutTx.java index 6bddc5d9d64..262216b6275 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerCreatesDelayedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerCreatesDelayedPayoutTx.java @@ -35,7 +35,7 @@ public class SellerCreatesDelayedPayoutTx extends TradeTask { @SuppressWarnings({"unused"}) - public SellerCreatesDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { + public SellerCreatesDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerFinalizesDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerFinalizesDelayedPayoutTx.java index 06161126726..309b923d299 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerFinalizesDelayedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerFinalizesDelayedPayoutTx.java @@ -37,7 +37,7 @@ @Slf4j public class SellerFinalizesDelayedPayoutTx extends TradeTask { @SuppressWarnings({"unused"}) - public SellerFinalizesDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { + public SellerFinalizesDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessCounterCurrencyTransferStartedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessCounterCurrencyTransferStartedMessage.java index ee996ffd9c1..2bd225dd69f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessCounterCurrencyTransferStartedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessCounterCurrencyTransferStartedMessage.java @@ -31,7 +31,7 @@ @Slf4j public class SellerProcessCounterCurrencyTransferStartedMessage extends TradeTask { @SuppressWarnings({"unused"}) - public SellerProcessCounterCurrencyTransferStartedMessage(TaskRunner taskHandler, Trade trade) { + public SellerProcessCounterCurrencyTransferStartedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessDelayedPayoutTxSignatureResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessDelayedPayoutTxSignatureResponse.java index e2e3d7cd37f..87422cca3d2 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessDelayedPayoutTxSignatureResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessDelayedPayoutTxSignatureResponse.java @@ -31,7 +31,7 @@ @Slf4j public class SellerProcessDelayedPayoutTxSignatureResponse extends TradeTask { @SuppressWarnings({"unused"}) - public SellerProcessDelayedPayoutTxSignatureResponse(TaskRunner taskHandler, Trade trade) { + public SellerProcessDelayedPayoutTxSignatureResponse(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerPublishesDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerPublishesDepositTx.java index be9b3fc1bd3..8a23c31d22d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerPublishesDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerPublishesDepositTx.java @@ -33,7 +33,7 @@ @Slf4j public class SellerPublishesDepositTx extends TradeTask { @SuppressWarnings({"unused"}) - public SellerPublishesDepositTx(TaskRunner taskHandler, Trade trade) { + public SellerPublishesDepositTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendDelayedPayoutTxSignatureRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendDelayedPayoutTxSignatureRequest.java index 187c274304b..b895c9c910c 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendDelayedPayoutTxSignatureRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendDelayedPayoutTxSignatureRequest.java @@ -37,7 +37,7 @@ @Slf4j public class SellerSendDelayedPayoutTxSignatureRequest extends TradeTask { @SuppressWarnings({"unused"}) - public SellerSendDelayedPayoutTxSignatureRequest(TaskRunner taskHandler, Trade trade) { + public SellerSendDelayedPayoutTxSignatureRequest(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendPayoutTxPublishedMessage.java index c8af73c7328..6e7e23b8ae6 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendPayoutTxPublishedMessage.java @@ -35,7 +35,7 @@ @Slf4j public class SellerSendPayoutTxPublishedMessage extends SendPayoutTxPublishedMessage { @SuppressWarnings({"unused"}) - public SellerSendPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) { + public SellerSendPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java index 077bca13636..81308b1cbff 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java @@ -37,7 +37,7 @@ @Slf4j public class SellerSendsDepositTxAndDelayedPayoutTxMessage extends TradeTask { @SuppressWarnings({"unused"}) - public SellerSendsDepositTxAndDelayedPayoutTxMessage(TaskRunner taskHandler, Trade trade) { + public SellerSendsDepositTxAndDelayedPayoutTxMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignAndFinalizePayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignAndFinalizePayoutTx.java index e947c543fcc..672a27ed37f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignAndFinalizePayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignAndFinalizePayoutTx.java @@ -41,7 +41,7 @@ public class SellerSignAndFinalizePayoutTx extends TradeTask { @SuppressWarnings({"unused"}) - public SellerSignAndFinalizePayoutTx(TaskRunner taskHandler, Trade trade) { + public SellerSignAndFinalizePayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignsDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignsDelayedPayoutTx.java index b8b8e155c2d..1d885d888a0 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignsDelayedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignsDelayedPayoutTx.java @@ -37,7 +37,7 @@ @Slf4j public class SellerSignsDelayedPayoutTx extends TradeTask { @SuppressWarnings({"unused"}) - public SellerSignsDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { + public SellerSignsDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerCreatesUnsignedDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerCreatesUnsignedDepositTx.java index 3f7cbdbef02..53724c56c8f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerCreatesUnsignedDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerCreatesUnsignedDepositTx.java @@ -44,7 +44,7 @@ @Slf4j public class SellerAsMakerCreatesUnsignedDepositTx extends TradeTask { @SuppressWarnings({"unused"}) - public SellerAsMakerCreatesUnsignedDepositTx(TaskRunner taskHandler, Trade trade) { + public SellerAsMakerCreatesUnsignedDepositTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerFinalizesDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerFinalizesDepositTx.java index ba490a92f3d..35f3962d368 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerFinalizesDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerFinalizesDepositTx.java @@ -31,7 +31,7 @@ @Slf4j public class SellerAsMakerFinalizesDepositTx extends TradeTask { @SuppressWarnings({"unused"}) - public SellerAsMakerFinalizesDepositTx(TaskRunner taskHandler, Trade trade) { + public SellerAsMakerFinalizesDepositTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerProcessDepositTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerProcessDepositTxMessage.java index b5962c989fa..a66af65616a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerProcessDepositTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerProcessDepositTxMessage.java @@ -31,7 +31,7 @@ @Slf4j public class SellerAsMakerProcessDepositTxMessage extends TradeTask { @SuppressWarnings({"unused"}) - public SellerAsMakerProcessDepositTxMessage(TaskRunner taskHandler, Trade trade) { + public SellerAsMakerProcessDepositTxMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerSendsInputsForDepositTxResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerSendsInputsForDepositTxResponse.java index f1fb5162809..ffea7a392c6 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerSendsInputsForDepositTxResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerSendsInputsForDepositTxResponse.java @@ -30,7 +30,7 @@ @Slf4j public class SellerAsMakerSendsInputsForDepositTxResponse extends MakerSendsInputsForDepositTxResponse { @SuppressWarnings({"unused"}) - public SellerAsMakerSendsInputsForDepositTxResponse(TaskRunner taskHandler, Trade trade) { + public SellerAsMakerSendsInputsForDepositTxResponse(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java index 6a27e1221c8..2d5d782aaac 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java @@ -43,7 +43,7 @@ @Slf4j public class SellerAsTakerSignsDepositTx extends TradeTask { @SuppressWarnings({"unused"}) - public SellerAsTakerSignsDepositTx(TaskRunner taskHandler, Trade trade) { + public SellerAsTakerSignsDepositTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java index 9407695ec6e..43ae278014d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java @@ -36,7 +36,7 @@ @Slf4j public class CreateTakerFeeTx extends TradeTask { - public CreateTakerFeeTx(TaskRunner taskHandler, Trade trade) { + public CreateTakerFeeTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java index 4eec9e57eec..4f9a023c070 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java @@ -36,7 +36,7 @@ @Slf4j public class TakerProcessesInputsForDepositTxResponse extends TradeTask { @SuppressWarnings({"unused"}) - public TakerProcessesInputsForDepositTxResponse(TaskRunner taskHandler, Trade trade) { + public TakerProcessesInputsForDepositTxResponse(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerPublishFeeTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerPublishFeeTx.java index 3ca0d64e9f6..8cf9c550a09 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerPublishFeeTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerPublishFeeTx.java @@ -36,7 +36,7 @@ @Slf4j public class TakerPublishFeeTx extends TradeTask { @SuppressWarnings({"unused"}) - public TakerPublishFeeTx(TaskRunner taskHandler, Trade trade) { + public TakerPublishFeeTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java index f9d0651383a..b7b742cb94b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java @@ -47,7 +47,7 @@ @Slf4j public class TakerSendInputsForDepositTxRequest extends TradeTask { @SuppressWarnings({"unused"}) - public TakerSendInputsForDepositTxRequest(TaskRunner taskHandler, Trade trade) { + public TakerSendInputsForDepositTxRequest(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java index c8134b59130..7b36bee59d7 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java @@ -44,7 +44,7 @@ @Slf4j public class TakerVerifyAndSignContract extends TradeTask { @SuppressWarnings({"unused"}) - public TakerVerifyAndSignContract(TaskRunner taskHandler, Trade trade) { + public TakerVerifyAndSignContract(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerAccount.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerAccount.java index 417e94c5d89..beefc4a774a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerAccount.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerAccount.java @@ -28,7 +28,7 @@ public class TakerVerifyMakerAccount extends TradeTask { @SuppressWarnings({"unused"}) - public TakerVerifyMakerAccount(TaskRunner taskHandler, Trade trade) { + public TakerVerifyMakerAccount(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerFeePayment.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerFeePayment.java index 42971acccb0..bdbc65824f6 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerFeePayment.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerFeePayment.java @@ -27,7 +27,7 @@ @Slf4j public class TakerVerifyMakerFeePayment extends TradeTask { @SuppressWarnings({"unused"}) - public TakerVerifyMakerFeePayment(TaskRunner taskHandler, Trade trade) { + public TakerVerifyMakerFeePayment(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } From 3d56312ccd1152c10d11346344fbf71f427b97a0 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 19:11:44 -0500 Subject: [PATCH 005/143] Refactor: - Remove '@SuppressWarnings({"unused"})' --- .../main/java/bisq/core/trade/protocol/tasks/ApplyFilter.java | 1 - .../java/bisq/core/trade/protocol/tasks/BroadcastPayoutTx.java | 1 - .../tasks/ProcessPeerPublishedDelayedPayoutTxMessage.java | 1 - .../core/trade/protocol/tasks/SendPayoutTxPublishedMessage.java | 1 - .../bisq/core/trade/protocol/tasks/SetupPayoutTxListener.java | 1 - .../core/trade/protocol/tasks/VerifyPeersAccountAgeWitness.java | 1 - .../tasks/buyer/BuyerProcessDelayedPayoutTxSignatureRequest.java | 1 - .../buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java | 1 - .../tasks/buyer/BuyerProcessPayoutTxPublishedMessage.java | 1 - .../buyer/BuyerSendCounterCurrencyTransferStartedMessage.java | 1 - .../tasks/buyer/BuyerSendsDelayedPayoutTxSignatureResponse.java | 1 - .../trade/protocol/tasks/buyer/BuyerSetupDepositTxListener.java | 1 - .../trade/protocol/tasks/buyer/BuyerSetupPayoutTxListener.java | 1 - .../bisq/core/trade/protocol/tasks/buyer/BuyerSignPayoutTx.java | 1 - .../trade/protocol/tasks/buyer/BuyerSignsDelayedPayoutTx.java | 1 - .../protocol/tasks/buyer/BuyerVerifiesFinalDelayedPayoutTx.java | 1 - .../tasks/buyer/BuyerVerifiesPreparedDelayedPayoutTx.java | 1 - .../buyer_as_maker/BuyerAsMakerCreatesAndSignsDepositTx.java | 1 - .../BuyerAsMakerSendsInputsForDepositTxResponse.java | 1 - .../tasks/buyer_as_taker/BuyerAsTakerCreatesDepositTxInputs.java | 1 - .../tasks/buyer_as_taker/BuyerAsTakerSendsDepositTxMessage.java | 1 - .../tasks/buyer_as_taker/BuyerAsTakerSignsDepositTx.java | 1 - .../trade/protocol/tasks/maker/MakerCreateAndSignContract.java | 1 - .../tasks/maker/MakerProcessesInputsForDepositTxRequest.java | 1 - .../tasks/maker/MakerSendsInputsForDepositTxResponse.java | 1 - .../bisq/core/trade/protocol/tasks/maker/MakerSetsLockTime.java | 1 - .../core/trade/protocol/tasks/maker/MakerVerifyTakerAccount.java | 1 - .../trade/protocol/tasks/maker/MakerVerifyTakerFeePayment.java | 1 - .../protocol/tasks/mediation/BroadcastMediatedPayoutTx.java | 1 - .../trade/protocol/tasks/mediation/FinalizeMediatedPayoutTx.java | 1 - .../tasks/mediation/ProcessMediatedPayoutSignatureMessage.java | 1 - .../tasks/mediation/ProcessMediatedPayoutTxPublishedMessage.java | 1 - .../tasks/mediation/SendMediatedPayoutSignatureMessage.java | 1 - .../tasks/mediation/SendMediatedPayoutTxPublishedMessage.java | 1 - .../protocol/tasks/mediation/SetupMediatedPayoutTxListener.java | 1 - .../trade/protocol/tasks/mediation/SignMediatedPayoutTx.java | 1 - .../trade/protocol/tasks/seller/SellerBroadcastPayoutTx.java | 1 - .../protocol/tasks/seller/SellerCreatesDelayedPayoutTx.java | 1 - .../protocol/tasks/seller/SellerFinalizesDelayedPayoutTx.java | 1 - .../SellerProcessCounterCurrencyTransferStartedMessage.java | 1 - .../seller/SellerProcessDelayedPayoutTxSignatureResponse.java | 1 - .../trade/protocol/tasks/seller/SellerPublishesDepositTx.java | 1 - .../tasks/seller/SellerSendDelayedPayoutTxSignatureRequest.java | 1 - .../tasks/seller/SellerSendPayoutTxPublishedMessage.java | 1 - .../seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java | 1 - .../protocol/tasks/seller/SellerSignAndFinalizePayoutTx.java | 1 - .../trade/protocol/tasks/seller/SellerSignsDelayedPayoutTx.java | 1 - .../seller_as_maker/SellerAsMakerCreatesUnsignedDepositTx.java | 1 - .../tasks/seller_as_maker/SellerAsMakerFinalizesDepositTx.java | 1 - .../seller_as_maker/SellerAsMakerProcessDepositTxMessage.java | 1 - .../SellerAsMakerSendsInputsForDepositTxResponse.java | 1 - .../tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java | 1 - .../tasks/taker/TakerProcessesInputsForDepositTxResponse.java | 1 - .../bisq/core/trade/protocol/tasks/taker/TakerPublishFeeTx.java | 1 - .../protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java | 1 - .../trade/protocol/tasks/taker/TakerVerifyAndSignContract.java | 1 - .../core/trade/protocol/tasks/taker/TakerVerifyMakerAccount.java | 1 - .../trade/protocol/tasks/taker/TakerVerifyMakerFeePayment.java | 1 - 58 files changed, 58 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/ApplyFilter.java b/core/src/main/java/bisq/core/trade/protocol/tasks/ApplyFilter.java index 0b415bd58ff..2b546059064 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/ApplyFilter.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/ApplyFilter.java @@ -31,7 +31,6 @@ @Slf4j public class ApplyFilter extends TradeTask { - @SuppressWarnings({"unused"}) public ApplyFilter(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/BroadcastPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/BroadcastPayoutTx.java index dae4197b3f5..df3b8df2c63 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/BroadcastPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/BroadcastPayoutTx.java @@ -32,7 +32,6 @@ @Slf4j public abstract class BroadcastPayoutTx extends TradeTask { - @SuppressWarnings({"unused"}) public BroadcastPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessPeerPublishedDelayedPayoutTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessPeerPublishedDelayedPayoutTxMessage.java index 1b890bb508f..c4aae4dd382 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessPeerPublishedDelayedPayoutTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessPeerPublishedDelayedPayoutTxMessage.java @@ -32,7 +32,6 @@ @Slf4j public class ProcessPeerPublishedDelayedPayoutTxMessage extends TradeTask { - @SuppressWarnings({"unused"}) public ProcessPeerPublishedDelayedPayoutTxMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/SendPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/SendPayoutTxPublishedMessage.java index f18c2be43b0..ea85430c9a5 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/SendPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/SendPayoutTxPublishedMessage.java @@ -29,7 +29,6 @@ @Slf4j public abstract class SendPayoutTxPublishedMessage extends TradeTask { - @SuppressWarnings({"unused"}) public SendPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/SetupPayoutTxListener.java b/core/src/main/java/bisq/core/trade/protocol/tasks/SetupPayoutTxListener.java index 755cafed1ed..bc6502a4c8b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/SetupPayoutTxListener.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/SetupPayoutTxListener.java @@ -40,7 +40,6 @@ public abstract class SetupPayoutTxListener extends TradeTask { private Subscription tradeStateSubscription; private AddressConfidenceListener confidenceListener; - @SuppressWarnings({"unused"}) public SetupPayoutTxListener(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/VerifyPeersAccountAgeWitness.java b/core/src/main/java/bisq/core/trade/protocol/tasks/VerifyPeersAccountAgeWitness.java index 5a118c0db8f..3cf2985a0bd 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/VerifyPeersAccountAgeWitness.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/VerifyPeersAccountAgeWitness.java @@ -35,7 +35,6 @@ @Slf4j public class VerifyPeersAccountAgeWitness extends TradeTask { - @SuppressWarnings({"unused"}) public VerifyPeersAccountAgeWitness(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDelayedPayoutTxSignatureRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDelayedPayoutTxSignatureRequest.java index a5a08bdd902..e64e4355cf0 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDelayedPayoutTxSignatureRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDelayedPayoutTxSignatureRequest.java @@ -32,7 +32,6 @@ @Slf4j public class BuyerProcessDelayedPayoutTxSignatureRequest extends TradeTask { - @SuppressWarnings({"unused"}) public BuyerProcessDelayedPayoutTxSignatureRequest(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java index 6c8ea46cc63..026102b8c03 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java @@ -37,7 +37,6 @@ @Slf4j public class BuyerProcessDepositTxAndDelayedPayoutTxMessage extends TradeTask { - @SuppressWarnings({"unused"}) public BuyerProcessDepositTxAndDelayedPayoutTxMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessPayoutTxPublishedMessage.java index 382d4c99e50..ebcf85eaa26 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessPayoutTxPublishedMessage.java @@ -36,7 +36,6 @@ @Slf4j public class BuyerProcessPayoutTxPublishedMessage extends TradeTask { - @SuppressWarnings({"unused"}) public BuyerProcessPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java index 3d5e63a86ca..2804eb25ed3 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java @@ -34,7 +34,6 @@ @Slf4j public class BuyerSendCounterCurrencyTransferStartedMessage extends TradeTask { - @SuppressWarnings({"unused"}) public BuyerSendCounterCurrencyTransferStartedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendsDelayedPayoutTxSignatureResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendsDelayedPayoutTxSignatureResponse.java index 4630df01efe..1d4bc214ba4 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendsDelayedPayoutTxSignatureResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendsDelayedPayoutTxSignatureResponse.java @@ -34,7 +34,6 @@ @Slf4j public class BuyerSendsDelayedPayoutTxSignatureResponse extends TradeTask { - @SuppressWarnings({"unused"}) public BuyerSendsDelayedPayoutTxSignatureResponse(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupDepositTxListener.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupDepositTxListener.java index aed61a8f932..5c3536f7f5b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupDepositTxListener.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupDepositTxListener.java @@ -44,7 +44,6 @@ public class BuyerSetupDepositTxListener extends TradeTask { private Subscription tradeStateSubscription; private AddressConfidenceListener confidenceListener; - @SuppressWarnings({"unused"}) public BuyerSetupDepositTxListener(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupPayoutTxListener.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupPayoutTxListener.java index ee8f5b190fb..befa919c47f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupPayoutTxListener.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupPayoutTxListener.java @@ -26,7 +26,6 @@ @Slf4j public class BuyerSetupPayoutTxListener extends SetupPayoutTxListener { - @SuppressWarnings({"unused"}) public BuyerSetupPayoutTxListener(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignPayoutTx.java index f9a43a13cf8..728ed405503 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignPayoutTx.java @@ -40,7 +40,6 @@ @Slf4j public class BuyerSignPayoutTx extends TradeTask { - @SuppressWarnings({"unused"}) public BuyerSignPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignsDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignsDelayedPayoutTx.java index 8ba2e19695a..5e43f265674 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignsDelayedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignsDelayedPayoutTx.java @@ -36,7 +36,6 @@ @Slf4j public class BuyerSignsDelayedPayoutTx extends TradeTask { - @SuppressWarnings({"unused"}) public BuyerSignsDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesFinalDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesFinalDelayedPayoutTx.java index 943dc78819d..adb301d6451 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesFinalDelayedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesFinalDelayedPayoutTx.java @@ -31,7 +31,6 @@ @Slf4j public class BuyerVerifiesFinalDelayedPayoutTx extends TradeTask { - @SuppressWarnings({"unused"}) public BuyerVerifiesFinalDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesPreparedDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesPreparedDelayedPayoutTx.java index 5c9233de419..37c4388a79e 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesPreparedDelayedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesPreparedDelayedPayoutTx.java @@ -27,7 +27,6 @@ @Slf4j public class BuyerVerifiesPreparedDelayedPayoutTx extends TradeTask { - @SuppressWarnings({"unused"}) public BuyerVerifiesPreparedDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerCreatesAndSignsDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerCreatesAndSignsDepositTx.java index 19710b46829..5eca415e5c7 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerCreatesAndSignsDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerCreatesAndSignsDepositTx.java @@ -43,7 +43,6 @@ @Slf4j public class BuyerAsMakerCreatesAndSignsDepositTx extends TradeTask { - @SuppressWarnings({"unused"}) public BuyerAsMakerCreatesAndSignsDepositTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerSendsInputsForDepositTxResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerSendsInputsForDepositTxResponse.java index f21a4fe9b9c..ebc60a4c65f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerSendsInputsForDepositTxResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerSendsInputsForDepositTxResponse.java @@ -26,7 +26,6 @@ @Slf4j public class BuyerAsMakerSendsInputsForDepositTxResponse extends MakerSendsInputsForDepositTxResponse { - @SuppressWarnings({"unused"}) public BuyerAsMakerSendsInputsForDepositTxResponse(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerCreatesDepositTxInputs.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerCreatesDepositTxInputs.java index 737db193144..5732ebe15f1 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerCreatesDepositTxInputs.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerCreatesDepositTxInputs.java @@ -32,7 +32,6 @@ @Slf4j public class BuyerAsTakerCreatesDepositTxInputs extends TradeTask { - @SuppressWarnings({"unused"}) public BuyerAsTakerCreatesDepositTxInputs(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSendsDepositTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSendsDepositTxMessage.java index b6f0023127b..81e82464eef 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSendsDepositTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSendsDepositTxMessage.java @@ -32,7 +32,6 @@ @Slf4j public class BuyerAsTakerSendsDepositTxMessage extends TradeTask { - @SuppressWarnings({"unused"}) public BuyerAsTakerSendsDepositTxMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSignsDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSignsDepositTx.java index a52310dbe3f..95bdbb2b91b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSignsDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSignsDepositTx.java @@ -42,7 +42,6 @@ @Slf4j public class BuyerAsTakerSignsDepositTx extends TradeTask { - @SuppressWarnings({"unused"}) public BuyerAsTakerSignsDepositTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java index 6dec9babb04..d1033fa46d3 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java @@ -41,7 +41,6 @@ @Slf4j public class MakerCreateAndSignContract extends TradeTask { - @SuppressWarnings({"unused"}) public MakerCreateAndSignContract(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java index 882f76f15d3..e8a453df4dc 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java @@ -43,7 +43,6 @@ @Slf4j public class MakerProcessesInputsForDepositTxRequest extends TradeTask { - @SuppressWarnings({"unused"}) public MakerProcessesInputsForDepositTxRequest(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java index f568d453015..c0f1081bf5b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java @@ -42,7 +42,6 @@ @Slf4j public abstract class MakerSendsInputsForDepositTxResponse extends TradeTask { - @SuppressWarnings({"unused"}) public MakerSendsInputsForDepositTxResponse(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSetsLockTime.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSetsLockTime.java index 0de2d4d2c55..068c4696448 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSetsLockTime.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSetsLockTime.java @@ -28,7 +28,6 @@ @Slf4j public class MakerSetsLockTime extends TradeTask { - @SuppressWarnings({"unused"}) public MakerSetsLockTime(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerAccount.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerAccount.java index fa9e72c8743..adf0a1d7113 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerAccount.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerAccount.java @@ -26,7 +26,6 @@ @Slf4j public class MakerVerifyTakerAccount extends TradeTask { - @SuppressWarnings({"unused"}) public MakerVerifyTakerAccount(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerFeePayment.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerFeePayment.java index cda032d4ec0..0c8a5fa67b8 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerFeePayment.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerFeePayment.java @@ -27,7 +27,6 @@ @Slf4j public class MakerVerifyTakerFeePayment extends TradeTask { - @SuppressWarnings({"unused"}) public MakerVerifyTakerFeePayment(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/BroadcastMediatedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/BroadcastMediatedPayoutTx.java index 8b2e174f353..7d67edc7d52 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/BroadcastMediatedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/BroadcastMediatedPayoutTx.java @@ -27,7 +27,6 @@ @Slf4j public class BroadcastMediatedPayoutTx extends BroadcastPayoutTx { - @SuppressWarnings({"unused"}) public BroadcastMediatedPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/FinalizeMediatedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/FinalizeMediatedPayoutTx.java index 0b8decabc9a..b9e43a84279 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/FinalizeMediatedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/FinalizeMediatedPayoutTx.java @@ -41,7 +41,6 @@ @Slf4j public class FinalizeMediatedPayoutTx extends TradeTask { - @SuppressWarnings({"unused"}) public FinalizeMediatedPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutSignatureMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutSignatureMessage.java index b856817b028..3636dbcbfe7 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutSignatureMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutSignatureMessage.java @@ -31,7 +31,6 @@ @Slf4j public class ProcessMediatedPayoutSignatureMessage extends TradeTask { - @SuppressWarnings({"unused"}) public ProcessMediatedPayoutSignatureMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutTxPublishedMessage.java index 025bd089dd9..6f0f5b3d69d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutTxPublishedMessage.java @@ -38,7 +38,6 @@ @Slf4j public class ProcessMediatedPayoutTxPublishedMessage extends TradeTask { - @SuppressWarnings({"unused"}) public ProcessMediatedPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutSignatureMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutSignatureMessage.java index 74473ce3dfb..e897027119b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutSignatureMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutSignatureMessage.java @@ -38,7 +38,6 @@ @Slf4j public class SendMediatedPayoutSignatureMessage extends TradeTask { - @SuppressWarnings({"unused"}) public SendMediatedPayoutSignatureMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutTxPublishedMessage.java index ff6d7144b66..a67ba017a0d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutTxPublishedMessage.java @@ -36,7 +36,6 @@ @Slf4j public class SendMediatedPayoutTxPublishedMessage extends SendPayoutTxPublishedMessage { - @SuppressWarnings({"unused"}) public SendMediatedPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SetupMediatedPayoutTxListener.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SetupMediatedPayoutTxListener.java index 3b72970e599..8f0ee2b106b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SetupMediatedPayoutTxListener.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SetupMediatedPayoutTxListener.java @@ -27,7 +27,6 @@ @Slf4j public class SetupMediatedPayoutTxListener extends SetupPayoutTxListener { - @SuppressWarnings({"unused"}) public SetupMediatedPayoutTxListener(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SignMediatedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SignMediatedPayoutTx.java index 22aa206ad09..3c145b981a9 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SignMediatedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SignMediatedPayoutTx.java @@ -41,7 +41,6 @@ @Slf4j public class SignMediatedPayoutTx extends TradeTask { - @SuppressWarnings({"unused"}) public SignMediatedPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerBroadcastPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerBroadcastPayoutTx.java index 1db696e75ed..2ab775d80c1 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerBroadcastPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerBroadcastPayoutTx.java @@ -26,7 +26,6 @@ @Slf4j public class SellerBroadcastPayoutTx extends BroadcastPayoutTx { - @SuppressWarnings({"unused"}) public SellerBroadcastPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerCreatesDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerCreatesDelayedPayoutTx.java index 262216b6275..5cd1ca6230c 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerCreatesDelayedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerCreatesDelayedPayoutTx.java @@ -34,7 +34,6 @@ @Slf4j public class SellerCreatesDelayedPayoutTx extends TradeTask { - @SuppressWarnings({"unused"}) public SellerCreatesDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerFinalizesDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerFinalizesDelayedPayoutTx.java index 309b923d299..ca374974adb 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerFinalizesDelayedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerFinalizesDelayedPayoutTx.java @@ -36,7 +36,6 @@ @Slf4j public class SellerFinalizesDelayedPayoutTx extends TradeTask { - @SuppressWarnings({"unused"}) public SellerFinalizesDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessCounterCurrencyTransferStartedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessCounterCurrencyTransferStartedMessage.java index 2bd225dd69f..cf1f5112948 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessCounterCurrencyTransferStartedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessCounterCurrencyTransferStartedMessage.java @@ -30,7 +30,6 @@ @Slf4j public class SellerProcessCounterCurrencyTransferStartedMessage extends TradeTask { - @SuppressWarnings({"unused"}) public SellerProcessCounterCurrencyTransferStartedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessDelayedPayoutTxSignatureResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessDelayedPayoutTxSignatureResponse.java index 87422cca3d2..cca5a552891 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessDelayedPayoutTxSignatureResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessDelayedPayoutTxSignatureResponse.java @@ -30,7 +30,6 @@ @Slf4j public class SellerProcessDelayedPayoutTxSignatureResponse extends TradeTask { - @SuppressWarnings({"unused"}) public SellerProcessDelayedPayoutTxSignatureResponse(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerPublishesDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerPublishesDepositTx.java index 8a23c31d22d..6295a7ecaeb 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerPublishesDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerPublishesDepositTx.java @@ -32,7 +32,6 @@ @Slf4j public class SellerPublishesDepositTx extends TradeTask { - @SuppressWarnings({"unused"}) public SellerPublishesDepositTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendDelayedPayoutTxSignatureRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendDelayedPayoutTxSignatureRequest.java index b895c9c910c..fc6c86e22fc 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendDelayedPayoutTxSignatureRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendDelayedPayoutTxSignatureRequest.java @@ -36,7 +36,6 @@ @Slf4j public class SellerSendDelayedPayoutTxSignatureRequest extends TradeTask { - @SuppressWarnings({"unused"}) public SellerSendDelayedPayoutTxSignatureRequest(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendPayoutTxPublishedMessage.java index 6e7e23b8ae6..3bda43fa860 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendPayoutTxPublishedMessage.java @@ -34,7 +34,6 @@ @Slf4j public class SellerSendPayoutTxPublishedMessage extends SendPayoutTxPublishedMessage { - @SuppressWarnings({"unused"}) public SellerSendPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java index 81308b1cbff..9e549cb537f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java @@ -36,7 +36,6 @@ @Slf4j public class SellerSendsDepositTxAndDelayedPayoutTxMessage extends TradeTask { - @SuppressWarnings({"unused"}) public SellerSendsDepositTxAndDelayedPayoutTxMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignAndFinalizePayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignAndFinalizePayoutTx.java index 672a27ed37f..eb5bd3aa99f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignAndFinalizePayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignAndFinalizePayoutTx.java @@ -40,7 +40,6 @@ @Slf4j public class SellerSignAndFinalizePayoutTx extends TradeTask { - @SuppressWarnings({"unused"}) public SellerSignAndFinalizePayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignsDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignsDelayedPayoutTx.java index 1d885d888a0..ed47059bda2 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignsDelayedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignsDelayedPayoutTx.java @@ -36,7 +36,6 @@ @Slf4j public class SellerSignsDelayedPayoutTx extends TradeTask { - @SuppressWarnings({"unused"}) public SellerSignsDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerCreatesUnsignedDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerCreatesUnsignedDepositTx.java index 53724c56c8f..5caf031bfe2 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerCreatesUnsignedDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerCreatesUnsignedDepositTx.java @@ -43,7 +43,6 @@ @Slf4j public class SellerAsMakerCreatesUnsignedDepositTx extends TradeTask { - @SuppressWarnings({"unused"}) public SellerAsMakerCreatesUnsignedDepositTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerFinalizesDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerFinalizesDepositTx.java index 35f3962d368..0a130b17dcd 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerFinalizesDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerFinalizesDepositTx.java @@ -30,7 +30,6 @@ @Slf4j public class SellerAsMakerFinalizesDepositTx extends TradeTask { - @SuppressWarnings({"unused"}) public SellerAsMakerFinalizesDepositTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerProcessDepositTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerProcessDepositTxMessage.java index a66af65616a..26dfd96b240 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerProcessDepositTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerProcessDepositTxMessage.java @@ -30,7 +30,6 @@ @Slf4j public class SellerAsMakerProcessDepositTxMessage extends TradeTask { - @SuppressWarnings({"unused"}) public SellerAsMakerProcessDepositTxMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerSendsInputsForDepositTxResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerSendsInputsForDepositTxResponse.java index ffea7a392c6..c44adea75bd 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerSendsInputsForDepositTxResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerSendsInputsForDepositTxResponse.java @@ -29,7 +29,6 @@ @Slf4j public class SellerAsMakerSendsInputsForDepositTxResponse extends MakerSendsInputsForDepositTxResponse { - @SuppressWarnings({"unused"}) public SellerAsMakerSendsInputsForDepositTxResponse(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java index 2d5d782aaac..0aa4f72fc58 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java @@ -42,7 +42,6 @@ @Slf4j public class SellerAsTakerSignsDepositTx extends TradeTask { - @SuppressWarnings({"unused"}) public SellerAsTakerSignsDepositTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java index 4f9a023c070..69e47e76008 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java @@ -35,7 +35,6 @@ @Slf4j public class TakerProcessesInputsForDepositTxResponse extends TradeTask { - @SuppressWarnings({"unused"}) public TakerProcessesInputsForDepositTxResponse(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerPublishFeeTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerPublishFeeTx.java index 8cf9c550a09..9ca6bfc5135 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerPublishFeeTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerPublishFeeTx.java @@ -35,7 +35,6 @@ @Slf4j public class TakerPublishFeeTx extends TradeTask { - @SuppressWarnings({"unused"}) public TakerPublishFeeTx(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java index b7b742cb94b..83ec54b793f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java @@ -46,7 +46,6 @@ @Slf4j public class TakerSendInputsForDepositTxRequest extends TradeTask { - @SuppressWarnings({"unused"}) public TakerSendInputsForDepositTxRequest(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java index 7b36bee59d7..517d65f59ad 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java @@ -43,7 +43,6 @@ @Slf4j public class TakerVerifyAndSignContract extends TradeTask { - @SuppressWarnings({"unused"}) public TakerVerifyAndSignContract(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerAccount.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerAccount.java index beefc4a774a..971366d25ad 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerAccount.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerAccount.java @@ -27,7 +27,6 @@ @Slf4j public class TakerVerifyMakerAccount extends TradeTask { - @SuppressWarnings({"unused"}) public TakerVerifyMakerAccount(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerFeePayment.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerFeePayment.java index bdbc65824f6..7d8d208d4d7 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerFeePayment.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerFeePayment.java @@ -26,7 +26,6 @@ @Slf4j public class TakerVerifyMakerFeePayment extends TradeTask { - @SuppressWarnings({"unused"}) public TakerVerifyMakerFeePayment(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } From 6a835343776c42beb81ef727863e105e0d92a85c Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 19:29:15 -0500 Subject: [PATCH 006/143] Cleanups. Small functional change by removing wrapping into arraylist --- .../TakerSendInputsForDepositTxRequest.java | 76 +++++++++++-------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java index 83ec54b793f..84bb4e015ea 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java @@ -32,11 +32,14 @@ import bisq.common.crypto.Sig; import bisq.common.taskrunner.TaskRunner; +import org.bitcoinj.core.Coin; + import com.google.common.base.Charsets; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Optional; import java.util.UUID; import lombok.extern.slf4j.Slf4j; @@ -54,42 +57,51 @@ public TakerSendInputsForDepositTxRequest(TaskRunner taskHandler, Trade t protected void run() { try { runInterceptHook(); - checkNotNull(trade.getTradeAmount(), "TradeAmount must not be null"); - checkNotNull(trade.getTakerFeeTxId(), "TakeOfferFeeTxId must not be null"); - final User user = processModel.getUser(); - checkNotNull(user, "User must not be null"); - final List acceptedArbitratorAddresses = user.getAcceptedArbitratorAddresses(); - final List acceptedMediatorAddresses = user.getAcceptedMediatorAddresses(); - final List acceptedRefundAgentAddresses = user.getAcceptedRefundAgentAddresses(); + Coin tradeAmount = checkNotNull(trade.getTradeAmount(), "TradeAmount must not be null"); + String takerFeeTxId = checkNotNull(trade.getTakerFeeTxId(), "TakeOfferFeeTxId must not be null"); + User user = checkNotNull(processModel.getUser(), "User must not be null"); + List acceptedArbitratorAddresses = user.getAcceptedArbitratorAddresses() == null ? + new ArrayList<>() : + user.getAcceptedArbitratorAddresses(); + List acceptedMediatorAddresses = user.getAcceptedMediatorAddresses(); + List acceptedRefundAgentAddresses = user.getAcceptedRefundAgentAddresses() == null ? + new ArrayList<>() : + user.getAcceptedRefundAgentAddresses(); // We don't check for arbitrators as they should vanish soon checkNotNull(acceptedMediatorAddresses, "acceptedMediatorAddresses must not be null"); - // We also don't check for refund agents yet as we don't want to restict us too much. They are not mandatory. + // We also don't check for refund agents yet as we don't want to restrict us too much. They are not mandatory. BtcWalletService walletService = processModel.getBtcWalletService(); String id = processModel.getOffer().getId(); - checkArgument(walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG).isPresent(), + Optional optionalMultiSigAddressEntry = walletService.getAddressEntry(id, + AddressEntry.Context.MULTI_SIG); + checkArgument(optionalMultiSigAddressEntry.isPresent(), "MULTI_SIG addressEntry must have been already set here."); - AddressEntry addressEntry = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.MULTI_SIG); - byte[] takerMultiSigPubKey = addressEntry.getPubKey(); + AddressEntry multiSigAddressEntry = optionalMultiSigAddressEntry.get(); + byte[] takerMultiSigPubKey = multiSigAddressEntry.getPubKey(); processModel.setMyMultiSigPubKey(takerMultiSigPubKey); - checkArgument(walletService.getAddressEntry(id, AddressEntry.Context.TRADE_PAYOUT).isPresent(), - "TRADE_PAYOUT addressEntry must have been already set here."); - AddressEntry takerPayoutAddressEntry = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.TRADE_PAYOUT); - String takerPayoutAddressString = takerPayoutAddressEntry.getAddressString(); + Optional optionalPayoutAddressEntry = walletService.getAddressEntry(id, + AddressEntry.Context.TRADE_PAYOUT); + checkArgument(optionalPayoutAddressEntry.isPresent(), + "TRADE_PAYOUT multiSigAddressEntry must have been already set here."); + AddressEntry payoutAddressEntry = optionalPayoutAddressEntry.get(); + String takerPayoutAddressString = payoutAddressEntry.getAddressString(); - final String offerId = processModel.getOfferId(); + String offerId = processModel.getOfferId(); - // Taker has to use offerId as nonce (he cannot manipulate that - so we avoid to have a challenge protocol for passing the nonce we want to get signed) - // He cannot manipulate the offerId - so we avoid to have a challenge protocol for passing the nonce we want to get signed. - final PaymentAccountPayload paymentAccountPayload = checkNotNull(processModel.getPaymentAccountPayload(trade), "processModel.getPaymentAccountPayload(trade) must not be null"); - byte[] sig = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(), offerId.getBytes(Charsets.UTF_8)); + // Taker has to use offerId as nonce (he cannot manipulate that - so we avoid to have a challenge + // protocol for passing the nonce we want to get signed) + PaymentAccountPayload paymentAccountPayload = checkNotNull(processModel.getPaymentAccountPayload(trade), + "processModel.getPaymentAccountPayload(trade) must not be null"); + byte[] sig = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(), + offerId.getBytes(Charsets.UTF_8)); - InputsForDepositTxRequest message = new InputsForDepositTxRequest( + InputsForDepositTxRequest request = new InputsForDepositTxRequest( offerId, processModel.getMyNodeAddress(), - trade.getTradeAmount().value, + tradeAmount.value, trade.getTradePrice().getValue(), trade.getTxFee().getValue(), trade.getTakerFee().getValue(), @@ -102,10 +114,10 @@ protected void run() { processModel.getPubKeyRing(), paymentAccountPayload, processModel.getAccountId(), - trade.getTakerFeeTxId(), - acceptedArbitratorAddresses == null ? new ArrayList<>() : new ArrayList<>(acceptedArbitratorAddresses), - new ArrayList<>(acceptedMediatorAddresses), - acceptedRefundAgentAddresses == null ? new ArrayList<>() : new ArrayList<>(acceptedRefundAgentAddresses), + takerFeeTxId, + acceptedArbitratorAddresses, + acceptedMediatorAddresses, + acceptedRefundAgentAddresses, trade.getArbitratorNodeAddress(), trade.getMediatorNodeAddress(), trade.getRefundAgentNodeAddress(), @@ -114,25 +126,25 @@ protected void run() { sig, new Date().getTime()); log.info("Send {} with offerId {} and uid {} to peer {}", - message.getClass().getSimpleName(), message.getTradeId(), - message.getUid(), trade.getTradingPeerNodeAddress()); + request.getClass().getSimpleName(), request.getTradeId(), + request.getUid(), trade.getTradingPeerNodeAddress()); processModel.getP2PService().sendEncryptedDirectMessage( trade.getTradingPeerNodeAddress(), processModel.getTradingPeer().getPubKeyRing(), - message, + request, new SendDirectMessageListener() { public void onArrived() { log.info("{} arrived at peer: offerId={}; uid={}", - message.getClass().getSimpleName(), message.getTradeId(), message.getUid()); + request.getClass().getSimpleName(), request.getTradeId(), request.getUid()); complete(); } @Override public void onFault(String errorMessage) { log.error("Sending {} failed: uid={}; peer={}; error={}", - message.getClass().getSimpleName(), message.getUid(), + request.getClass().getSimpleName(), request.getUid(), trade.getTradingPeerNodeAddress(), errorMessage); - appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage); + appendToErrorMessage("Sending message failed: message=" + request + "\nerrorMessage=" + errorMessage); failed(); } } From 87c2ddf20015920780ab6850ffcaafe146bc83ac Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 19:48:01 -0500 Subject: [PATCH 007/143] Remove Nullable annotations. arbitratorNodeAddress is not null and accountAgeWitnessSignatureOfOfferId was added in v 0.6 so is with todays versions also not null --- .../trade/messages/InputsForDepositTxRequest.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/messages/InputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/messages/InputsForDepositTxRequest.java index 57df03a1b24..d0e8501a227 100644 --- a/core/src/main/java/bisq/core/trade/messages/InputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/messages/InputsForDepositTxRequest.java @@ -61,13 +61,10 @@ public final class InputsForDepositTxRequest extends TradeMessage implements Dir private final List acceptedArbitratorNodeAddresses; private final List acceptedMediatorNodeAddresses; private final List acceptedRefundAgentNodeAddresses; - @Nullable private final NodeAddress arbitratorNodeAddress; private final NodeAddress mediatorNodeAddress; private final NodeAddress refundAgentNodeAddress; - // added in v 0.6. can be null if we trade with an older peer - @Nullable private final byte[] accountAgeWitnessSignatureOfOfferId; private final long currentDate; @@ -95,7 +92,7 @@ public InputsForDepositTxRequest(String tradeId, NodeAddress refundAgentNodeAddress, String uid, int messageVersion, - @Nullable byte[] accountAgeWitnessSignatureOfOfferId, + byte[] accountAgeWitnessSignatureOfOfferId, long currentDate) { super(messageVersion, tradeId, uid); this.senderNodeAddress = senderNodeAddress; @@ -155,12 +152,12 @@ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() { .map(NodeAddress::toProtoMessage).collect(Collectors.toList())) .setMediatorNodeAddress(mediatorNodeAddress.toProtoMessage()) .setRefundAgentNodeAddress(refundAgentNodeAddress.toProtoMessage()) - .setUid(uid); + .setUid(uid) + .setAccountAgeWitnessSignatureOfOfferId(ByteString.copyFrom(accountAgeWitnessSignatureOfOfferId)) + .setArbitratorNodeAddress(arbitratorNodeAddress.toProtoMessage()) + .setCurrentDate(currentDate); Optional.ofNullable(changeOutputAddress).ifPresent(builder::setChangeOutputAddress); - Optional.ofNullable(accountAgeWitnessSignatureOfOfferId).ifPresent(e -> builder.setAccountAgeWitnessSignatureOfOfferId(ByteString.copyFrom(e))); - Optional.ofNullable(arbitratorNodeAddress).ifPresent(e -> builder.setArbitratorNodeAddress(arbitratorNodeAddress.toProtoMessage())); - builder.setCurrentDate(currentDate); return getNetworkEnvelopeBuilder().setInputsForDepositTxRequest(builder).build(); } @@ -203,7 +200,7 @@ public static InputsForDepositTxRequest fromProto(protobuf.InputsForDepositTxReq NodeAddress.fromProto(proto.getRefundAgentNodeAddress()), proto.getUid(), messageVersion, - ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessSignatureOfOfferId()), + proto.getAccountAgeWitnessSignatureOfOfferId().toByteArray(), proto.getCurrentDate()); } From a25dcf29faf112407dce450a2059ad180078cac1 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 19:48:35 -0500 Subject: [PATCH 008/143] Refactor: Rename sig to accountAgeWitnessSignatureOfOfferId to make context more clear --- .../tasks/taker/TakerSendInputsForDepositTxRequest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java index 84bb4e015ea..0db99b431ff 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java @@ -95,7 +95,7 @@ protected void run() { // protocol for passing the nonce we want to get signed) PaymentAccountPayload paymentAccountPayload = checkNotNull(processModel.getPaymentAccountPayload(trade), "processModel.getPaymentAccountPayload(trade) must not be null"); - byte[] sig = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(), + byte[] accountAgeWitnessSignatureOfOfferId = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(), offerId.getBytes(Charsets.UTF_8)); InputsForDepositTxRequest request = new InputsForDepositTxRequest( @@ -123,7 +123,7 @@ protected void run() { trade.getRefundAgentNodeAddress(), UUID.randomUUID().toString(), Version.getP2PMessageVersion(), - sig, + accountAgeWitnessSignatureOfOfferId, new Date().getTime()); log.info("Send {} with offerId {} and uid {} to peer {}", request.getClass().getSimpleName(), request.getTradeId(), From 19afb449d5d42e40abdb38c93857ad8cf4ebcc9f Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 19:49:36 -0500 Subject: [PATCH 009/143] Refactor: rename inputsForDepositTxRequest to request Remove final Cleanups --- ...kerProcessesInputsForDepositTxRequest.java | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java index e8a453df4dc..a6cd000dbec 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java @@ -51,35 +51,35 @@ public MakerProcessesInputsForDepositTxRequest(TaskRunner taskHandler, Tr protected void run() { try { runInterceptHook(); - log.debug("current trade state " + trade.getState()); - InputsForDepositTxRequest inputsForDepositTxRequest = (InputsForDepositTxRequest) processModel.getTradeMessage(); - checkNotNull(inputsForDepositTxRequest); - checkTradeId(processModel.getOfferId(), inputsForDepositTxRequest); + InputsForDepositTxRequest request = (InputsForDepositTxRequest) processModel.getTradeMessage(); + checkNotNull(request); + checkTradeId(processModel.getOfferId(), request); - final TradingPeer tradingPeer = processModel.getTradingPeer(); - tradingPeer.setPaymentAccountPayload(checkNotNull(inputsForDepositTxRequest.getTakerPaymentAccountPayload())); - tradingPeer.setRawTransactionInputs(checkNotNull(inputsForDepositTxRequest.getRawTransactionInputs())); - checkArgument(inputsForDepositTxRequest.getRawTransactionInputs().size() > 0); + TradingPeer tradingPeer = processModel.getTradingPeer(); + tradingPeer.setPaymentAccountPayload(checkNotNull(request.getTakerPaymentAccountPayload())); + tradingPeer.setRawTransactionInputs(checkNotNull(request.getRawTransactionInputs())); + checkArgument(request.getRawTransactionInputs().size() > 0); - tradingPeer.setChangeOutputValue(inputsForDepositTxRequest.getChangeOutputValue()); - tradingPeer.setChangeOutputAddress(inputsForDepositTxRequest.getChangeOutputAddress()); + tradingPeer.setChangeOutputValue(request.getChangeOutputValue()); + tradingPeer.setChangeOutputAddress(request.getChangeOutputAddress()); - tradingPeer.setMultiSigPubKey(checkNotNull(inputsForDepositTxRequest.getTakerMultiSigPubKey())); - tradingPeer.setPayoutAddressString(nonEmptyStringOf(inputsForDepositTxRequest.getTakerPayoutAddressString())); - tradingPeer.setPubKeyRing(checkNotNull(inputsForDepositTxRequest.getTakerPubKeyRing())); + tradingPeer.setMultiSigPubKey(checkNotNull(request.getTakerMultiSigPubKey())); + tradingPeer.setPayoutAddressString(nonEmptyStringOf(request.getTakerPayoutAddressString())); + tradingPeer.setPubKeyRing(checkNotNull(request.getTakerPubKeyRing())); - tradingPeer.setAccountId(nonEmptyStringOf(inputsForDepositTxRequest.getTakerAccountId())); - trade.setTakerFeeTxId(nonEmptyStringOf(inputsForDepositTxRequest.getTakerFeeTxId())); + tradingPeer.setAccountId(nonEmptyStringOf(request.getTakerAccountId())); + trade.setTakerFeeTxId(nonEmptyStringOf(request.getTakerFeeTxId())); - // Taker has to sign offerId (he cannot manipulate that - so we avoid to have a challenge protocol for passing the nonce we want to get signed) + // Taker has to sign offerId (he cannot manipulate that - so we avoid to have a challenge protocol for + // passing the nonce we want to get signed) tradingPeer.setAccountAgeWitnessNonce(trade.getId().getBytes(Charsets.UTF_8)); - tradingPeer.setAccountAgeWitnessSignature(inputsForDepositTxRequest.getAccountAgeWitnessSignatureOfOfferId()); - tradingPeer.setCurrentDate(inputsForDepositTxRequest.getCurrentDate()); + tradingPeer.setAccountAgeWitnessSignature(request.getAccountAgeWitnessSignatureOfOfferId()); + tradingPeer.setCurrentDate(request.getCurrentDate()); User user = checkNotNull(processModel.getUser(), "User must not be null"); - NodeAddress mediatorNodeAddress = checkNotNull(inputsForDepositTxRequest.getMediatorNodeAddress(), - "payDepositRequest.getMediatorNodeAddress() must not be null"); + NodeAddress mediatorNodeAddress = checkNotNull(request.getMediatorNodeAddress(), + "InputsForDepositTxRequest.getMediatorNodeAddress() must not be null"); trade.setMediatorNodeAddress(mediatorNodeAddress); Mediator mediator = checkNotNull(user.getAcceptedMediatorByAddress(mediatorNodeAddress), "user.getAcceptedMediatorByAddress(mediatorNodeAddress) must not be null"); @@ -88,7 +88,7 @@ protected void run() { Offer offer = checkNotNull(trade.getOffer(), "Offer must not be null"); try { - long takersTradePrice = inputsForDepositTxRequest.getTradePrice(); + long takersTradePrice = request.getTradePrice(); offer.checkTradePriceTolerance(takersTradePrice); trade.setTradePrice(takersTradePrice); } catch (TradePriceOutOfToleranceException e) { @@ -97,8 +97,8 @@ protected void run() { failed(e2); } - checkArgument(inputsForDepositTxRequest.getTradeAmount() > 0); - trade.setTradeAmount(Coin.valueOf(inputsForDepositTxRequest.getTradeAmount())); + checkArgument(request.getTradeAmount() > 0); + trade.setTradeAmount(Coin.valueOf(request.getTradeAmount())); trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress()); From c88135713e5bb00413cb1e6857b1320702830ccf Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 20:01:24 -0500 Subject: [PATCH 010/143] Revert removal of Nullable. arbitratorNodeAddress is null (confused it with acceptedArbitratorNodeAddresses) --- .../core/trade/messages/InputsForDepositTxRequest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/messages/InputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/messages/InputsForDepositTxRequest.java index d0e8501a227..a67a879e3db 100644 --- a/core/src/main/java/bisq/core/trade/messages/InputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/messages/InputsForDepositTxRequest.java @@ -61,6 +61,7 @@ public final class InputsForDepositTxRequest extends TradeMessage implements Dir private final List acceptedArbitratorNodeAddresses; private final List acceptedMediatorNodeAddresses; private final List acceptedRefundAgentNodeAddresses; + @Nullable private final NodeAddress arbitratorNodeAddress; private final NodeAddress mediatorNodeAddress; private final NodeAddress refundAgentNodeAddress; @@ -87,7 +88,7 @@ public InputsForDepositTxRequest(String tradeId, List acceptedArbitratorNodeAddresses, List acceptedMediatorNodeAddresses, List acceptedRefundAgentNodeAddresses, - NodeAddress arbitratorNodeAddress, + @Nullable NodeAddress arbitratorNodeAddress, NodeAddress mediatorNodeAddress, NodeAddress refundAgentNodeAddress, String uid, @@ -154,11 +155,10 @@ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() { .setRefundAgentNodeAddress(refundAgentNodeAddress.toProtoMessage()) .setUid(uid) .setAccountAgeWitnessSignatureOfOfferId(ByteString.copyFrom(accountAgeWitnessSignatureOfOfferId)) - .setArbitratorNodeAddress(arbitratorNodeAddress.toProtoMessage()) .setCurrentDate(currentDate); Optional.ofNullable(changeOutputAddress).ifPresent(builder::setChangeOutputAddress); - + Optional.ofNullable(arbitratorNodeAddress).ifPresent(e -> builder.setArbitratorNodeAddress(arbitratorNodeAddress.toProtoMessage())); return getNetworkEnvelopeBuilder().setInputsForDepositTxRequest(builder).build(); } @@ -200,7 +200,7 @@ public static InputsForDepositTxRequest fromProto(protobuf.InputsForDepositTxReq NodeAddress.fromProto(proto.getRefundAgentNodeAddress()), proto.getUid(), messageVersion, - proto.getAccountAgeWitnessSignatureOfOfferId().toByteArray(), + ProtoUtil.byteArrayOrNullFromProto(proto.getAccountAgeWitnessSignatureOfOfferId()), proto.getCurrentDate()); } From 525360c3ce671d8549b9664761922103cbc207ef Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 20:02:50 -0500 Subject: [PATCH 011/143] Use ApplyFilter at start at take offer process. Make paymentAccountPayload nullable Set TempTradingPeerNodeAddress with value from trade.getTradingPeerNodeAddress() --- .../core/trade/protocol/BuyerAsTakerProtocol.java | 2 ++ .../core/trade/protocol/SellerAsTakerProtocol.java | 2 ++ .../bisq/core/trade/protocol/tasks/ApplyFilter.java | 11 +++++++---- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 4d17d4c47fa..e478165f62d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -122,11 +122,13 @@ public void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress pe @Override public void takeAvailableOffer() { + processModel.setTempTradingPeerNodeAddress(trade.getTradingPeerNodeAddress()); TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, () -> handleTaskRunnerSuccess("takeAvailableOffer"), this::handleTaskRunnerFault); taskRunner.addTasks( + ApplyFilter.class, TakerVerifyMakerAccount.class, TakerVerifyMakerFeePayment.class, CreateTakerFeeTx.class, diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 8979a61b28c..5dd5486cbfd 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -98,11 +98,13 @@ public void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress pe @Override public void takeAvailableOffer() { + processModel.setTempTradingPeerNodeAddress(trade.getTradingPeerNodeAddress()); TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, () -> handleTaskRunnerSuccess("takeAvailableOffer"), this::handleTaskRunnerFault); taskRunner.addTasks( + ApplyFilter.class, TakerVerifyMakerAccount.class, TakerVerifyMakerFeePayment.class, CreateTakerFeeTx.class, diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/ApplyFilter.java b/core/src/main/java/bisq/core/trade/protocol/tasks/ApplyFilter.java index 2b546059064..f3a2d341593 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/ApplyFilter.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/ApplyFilter.java @@ -27,6 +27,8 @@ import lombok.extern.slf4j.Slf4j; +import javax.annotation.Nullable; + import static com.google.common.base.Preconditions.checkNotNull; @Slf4j @@ -40,11 +42,12 @@ protected void run() { try { runInterceptHook(); - NodeAddress nodeAddress = processModel.getTempTradingPeerNodeAddress(); - PaymentAccountPayload paymentAccountPayload = checkNotNull(processModel.getTradingPeer().getPaymentAccountPayload()); + NodeAddress nodeAddress = checkNotNull(processModel.getTempTradingPeerNodeAddress()); + @Nullable + PaymentAccountPayload paymentAccountPayload = processModel.getTradingPeer().getPaymentAccountPayload(); FilterManager filterManager = processModel.getFilterManager(); - if (nodeAddress != null && filterManager.isNodeAddressBanned(nodeAddress)) { + if (filterManager.isNodeAddressBanned(nodeAddress)) { failed("Other trader is banned by their node address.\n" + "tradingPeerNodeAddress=" + nodeAddress); } else if (filterManager.isOfferIdBanned(trade.getId())) { @@ -56,7 +59,7 @@ protected void run() { } else if (filterManager.isPaymentMethodBanned(checkNotNull(trade.getOffer()).getPaymentMethod())) { failed("Payment method is banned.\n" + "Payment method=" + trade.getOffer().getPaymentMethod().getId()); - } else if (filterManager.arePeersPaymentAccountDataBanned(paymentAccountPayload)) { + } else if (paymentAccountPayload != null && filterManager.arePeersPaymentAccountDataBanned(paymentAccountPayload)) { failed("Other trader is banned by their trading account data.\n" + "paymentAccountPayload=" + paymentAccountPayload.getPaymentDetails()); } else if (filterManager.requireUpdateToNewVersionForTrading()) { From a3864efe9aa21a391cca268567fee35d57cb4a0c Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 20:10:16 -0500 Subject: [PATCH 012/143] Refactor: Remove final --- .../bisq/core/account/witness/AccountAgeWitnessService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java index c1a55e2bb0b..c5264fc4eda 100644 --- a/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java +++ b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java @@ -562,9 +562,9 @@ boolean isDateAfterReleaseDate(long witnessDateAsLong, } private boolean verifyPeersCurrentDate(Date peersCurrentDate, ErrorMessageHandler errorMessageHandler) { - final boolean result = Math.abs(peersCurrentDate.getTime() - new Date().getTime()) <= TimeUnit.DAYS.toMillis(1); + boolean result = Math.abs(peersCurrentDate.getTime() - new Date().getTime()) <= TimeUnit.DAYS.toMillis(1); if (!result) { - final String msg = "Peers current date is further than 1 day off to our current date. " + + String msg = "Peers current date is further than 1 day off to our current date. " + "PeersCurrentDate=" + peersCurrentDate + "; myCurrentDate=" + new Date(); log.warn(msg); errorMessageHandler.handleErrorMessage(msg); From 3269e8c6f0482afa3b0aac83991fbbf0c407879e Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 20:11:06 -0500 Subject: [PATCH 013/143] Remove check that account age signature can be null. Such old versions are not supported anymore. Cleanups. --- .../tasks/VerifyPeersAccountAgeWitness.java | 66 ++++++++----------- 1 file changed, 29 insertions(+), 37 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/VerifyPeersAccountAgeWitness.java b/core/src/main/java/bisq/core/trade/protocol/tasks/VerifyPeersAccountAgeWitness.java index 3cf2985a0bd..68ea2d9eeba 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/VerifyPeersAccountAgeWitness.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/VerifyPeersAccountAgeWitness.java @@ -19,6 +19,7 @@ import bisq.core.account.witness.AccountAgeWitnessService; import bisq.core.locale.CurrencyUtil; +import bisq.core.offer.Offer; import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.trade.Trade; import bisq.core.trade.protocol.TradingPeer; @@ -27,6 +28,7 @@ import bisq.common.taskrunner.TaskRunner; import java.util.Date; +import java.util.concurrent.atomic.AtomicReference; import lombok.extern.slf4j.Slf4j; @@ -44,44 +46,34 @@ protected void run() { try { runInterceptHook(); - if (trade.getOffer() != null && CurrencyUtil.isFiatCurrency(trade.getOffer().getCurrencyCode())) { - final AccountAgeWitnessService accountAgeWitnessService = processModel.getAccountAgeWitnessService(); - final TradingPeer tradingPeer = processModel.getTradingPeer(); - final PaymentAccountPayload peersPaymentAccountPayload = checkNotNull(tradingPeer.getPaymentAccountPayload(), - "Peers peersPaymentAccountPayload must not be null"); - final PubKeyRing peersPubKeyRing = checkNotNull(tradingPeer.getPubKeyRing(), "peersPubKeyRing must not be null"); - byte[] nonce = tradingPeer.getAccountAgeWitnessNonce(); - byte[] signature = tradingPeer.getAccountAgeWitnessSignature(); - if (nonce != null && signature != null) { - final String[] errorMsg = new String[1]; - long currentDateAsLong = tradingPeer.getCurrentDate(); - // In case the peer has an older version we get 0, so we use our time instead - final Date peersCurrentDate = currentDateAsLong > 0 ? new Date(currentDateAsLong) : new Date(); - boolean result = accountAgeWitnessService.verifyAccountAgeWitness(trade, - peersPaymentAccountPayload, - peersCurrentDate, - peersPubKeyRing, - nonce, - signature, - errorMessage -> errorMsg[0] = errorMessage); - if (result) - complete(); - else - failed(errorMsg[0]); - } else { - String msg = "Seems that offer was created with an application before v0.6 which did not support the account age witness verification."; - msg += "\nTrade ID=" + trade.getId(); - if (new Date().after(AccountAgeWitnessService.FULL_ACTIVATION)) { - msg = "The account age witness verification failed.\nReason: " + msg + "\nAfter first of Feb. 2018 we don't support old offers without account age witness verification anymore."; - log.error(msg); - failed(msg); - } else { - log.warn(msg + "\nWe tolerate offers without account age witness until first of Feb. 2018"); - complete(); - } - } - } else { + Offer offer = checkNotNull(trade.getOffer()); + if (CurrencyUtil.isCryptoCurrency(offer.getCurrencyCode())) { complete(); + return; + } + + AccountAgeWitnessService accountAgeWitnessService = processModel.getAccountAgeWitnessService(); + TradingPeer tradingPeer = processModel.getTradingPeer(); + PaymentAccountPayload peersPaymentAccountPayload = checkNotNull(tradingPeer.getPaymentAccountPayload(), + "Peers peersPaymentAccountPayload must not be null"); + PubKeyRing peersPubKeyRing = checkNotNull(tradingPeer.getPubKeyRing(), "peersPubKeyRing must not be null"); + byte[] nonce = checkNotNull(tradingPeer.getAccountAgeWitnessNonce()); + byte[] signature = checkNotNull(tradingPeer.getAccountAgeWitnessSignature()); + AtomicReference errorMsg = new AtomicReference<>(); + long currentDateAsLong = tradingPeer.getCurrentDate(); + // In case the peer has an older version we get 0, so we use our time instead + Date peersCurrentDate = currentDateAsLong > 0 ? new Date(currentDateAsLong) : new Date(); + boolean isValid = accountAgeWitnessService.verifyAccountAgeWitness(trade, + peersPaymentAccountPayload, + peersCurrentDate, + peersPubKeyRing, + nonce, + signature, + errorMsg::set); + if (isValid) { + complete(); + } else { + failed(errorMsg.get()); } } catch (Throwable t) { failed(t); From 3a7af57a43a5a6af5ee0d55e5f405508aaf27945 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 20:18:47 -0500 Subject: [PATCH 014/143] Refactoring: cleanups, add more checkNotNull tests --- .../maker/MakerCreateAndSignContract.java | 20 +++++++------------ .../tasks/maker/MakerSetsLockTime.java | 8 ++++---- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java index d1033fa46d3..1c5694ab610 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java @@ -19,7 +19,6 @@ import bisq.core.btc.model.AddressEntry; import bisq.core.btc.wallet.BtcWalletService; -import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.trade.BuyerAsMakerTrade; import bisq.core.trade.Contract; import bisq.core.trade.Trade; @@ -52,11 +51,7 @@ protected void run() { Preconditions.checkNotNull(trade.getTakerFeeTxId(), "trade.getTakeOfferFeeTxId() must not be null"); TradingPeer taker = processModel.getTradingPeer(); - PaymentAccountPayload makerPaymentAccountPayload = processModel.getPaymentAccountPayload(trade); - checkNotNull(makerPaymentAccountPayload, "makerPaymentAccountPayload must not be null"); - PaymentAccountPayload takerPaymentAccountPayload = checkNotNull(taker.getPaymentAccountPayload()); boolean isBuyerMakerAndSellerTaker = trade instanceof BuyerAsMakerTrade; - NodeAddress buyerNodeAddress = isBuyerMakerAndSellerTaker ? processModel.getMyNodeAddress() : processModel.getTempTradingPeerNodeAddress(); NodeAddress sellerNodeAddress = isBuyerMakerAndSellerTaker ? @@ -70,10 +65,9 @@ protected void run() { byte[] makerMultiSigPubKey = makerAddressEntry.getPubKey(); AddressEntry takerAddressEntry = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.TRADE_PAYOUT); - checkNotNull(trade.getTradeAmount(), "trade.getTradeAmount() must not be null"); Contract contract = new Contract( processModel.getOffer().getOfferPayload(), - trade.getTradeAmount().value, + checkNotNull(trade.getTradeAmount()).value, trade.getTradePrice().getValue(), trade.getTakerFeeTxId(), buyerNodeAddress, @@ -81,15 +75,15 @@ protected void run() { trade.getMediatorNodeAddress(), isBuyerMakerAndSellerTaker, processModel.getAccountId(), - taker.getAccountId(), - makerPaymentAccountPayload, - takerPaymentAccountPayload, + checkNotNull(taker.getAccountId()), + checkNotNull(processModel.getPaymentAccountPayload(trade)), + checkNotNull(taker.getPaymentAccountPayload()), processModel.getPubKeyRing(), - taker.getPubKeyRing(), + checkNotNull(taker.getPubKeyRing()), takerAddressEntry.getAddressString(), - taker.getPayoutAddressString(), + checkNotNull(taker.getPayoutAddressString()), makerMultiSigPubKey, - taker.getMultiSigPubKey(), + checkNotNull(taker.getMultiSigPubKey()), trade.getLockTime(), trade.getRefundAgentNodeAddress() ); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSetsLockTime.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSetsLockTime.java index 068c4696448..3e55cee4813 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSetsLockTime.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSetsLockTime.java @@ -38,10 +38,10 @@ protected void run() { runInterceptHook(); // 10 days for altcoins, 20 days for other payment methods - int delay = Restrictions.getLockTime(processModel.getOffer().getPaymentMethod().isAsset()); - if (Config.baseCurrencyNetwork().isRegtest()) { - delay = 5; - } + // For regtest dev environment we use 5 blocks + int delay = Config.baseCurrencyNetwork().isRegtest() ? + 5 : + Restrictions.getLockTime(processModel.getOffer().getPaymentMethod().isAsset()); long lockTime = processModel.getBtcWalletService().getBestChainHeight() + delay; log.info("lockTime={}, delay={}", lockTime, delay); From dc8ddbd4ae0abe6cc8ed58cd2d3dc8865db619fd Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 20:31:22 -0500 Subject: [PATCH 015/143] Refactoring: cleanups --- .../buyer/BuyerSetupDepositTxListener.java | 28 +++++++++++-------- .../BuyerAsMakerCreatesAndSignsDepositTx.java | 15 ++++------ 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupDepositTxListener.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupDepositTxListener.java index 5c3536f7f5b..6a814c818e4 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupDepositTxListener.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupDepositTxListener.java @@ -55,18 +55,21 @@ protected void run() { if (trade.getDepositTx() == null && processModel.getPreparedDepositTx() != null) { BtcWalletService walletService = processModel.getBtcWalletService(); - final NetworkParameters params = walletService.getParams(); + NetworkParameters params = walletService.getParams(); Transaction preparedDepositTx = new Transaction(params, processModel.getPreparedDepositTx()); checkArgument(!preparedDepositTx.getOutputs().isEmpty(), "preparedDepositTx.getOutputs() must not be empty"); + + //TODO update to new bitcoinj API Address depositTxAddress = preparedDepositTx.getOutput(0).getAddressFromP2SH(params); - final TransactionConfidence confidence = walletService.getConfidenceForAddress(depositTxAddress); - if (isInNetwork(confidence)) { + + TransactionConfidence confidence = walletService.getConfidenceForAddress(depositTxAddress); + if (isVisibleInNetwork(confidence)) { applyConfidence(confidence); } else { confidenceListener = new AddressConfidenceListener(depositTxAddress) { @Override public void onTransactionConfidenceChanged(TransactionConfidence confidence) { - if (isInNetwork(confidence)) + if (isVisibleInNetwork(confidence)) applyConfidence(confidence); } }; @@ -77,7 +80,7 @@ public void onTransactionConfidenceChanged(TransactionConfidence confidence) { swapReservedForTradeEntry(); // hack to remove tradeStateSubscription at callback - UserThread.execute(this::unSubscribe); + UserThread.execute(this::unSubscribeAndRemoveListener); } }); } @@ -103,10 +106,10 @@ private void applyConfidence(TransactionConfidence confidence) { swapReservedForTradeEntry(); // need delay as it can be called inside the listener handler before listener and tradeStateSubscription are actually set. - UserThread.execute(this::unSubscribe); + UserThread.execute(this::unSubscribeAndRemoveListener); } - private boolean isInNetwork(TransactionConfidence confidence) { + private boolean isVisibleInNetwork(TransactionConfidence confidence) { return confidence != null && (confidence.getConfidenceType().equals(TransactionConfidence.ConfidenceType.BUILDING) || confidence.getConfidenceType().equals(TransactionConfidence.ConfidenceType.PENDING)); @@ -114,14 +117,17 @@ private boolean isInNetwork(TransactionConfidence confidence) { private void swapReservedForTradeEntry() { log.info("swapReservedForTradeEntry"); - processModel.getBtcWalletService().swapTradeEntryToAvailableEntry(trade.getId(), AddressEntry.Context.RESERVED_FOR_TRADE); + processModel.getBtcWalletService().swapTradeEntryToAvailableEntry(trade.getId(), + AddressEntry.Context.RESERVED_FOR_TRADE); } - private void unSubscribe() { - if (tradeStateSubscription != null) + private void unSubscribeAndRemoveListener() { + if (tradeStateSubscription != null) { tradeStateSubscription.unsubscribe(); + } - if (confidenceListener != null) + if (confidenceListener != null) { processModel.getBtcWalletService().removeAddressConfidenceListener(confidenceListener); + } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerCreatesAndSignsDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerCreatesAndSignsDepositTx.java index 5eca415e5c7..ae656b83fb6 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerCreatesAndSignsDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerCreatesAndSignsDepositTx.java @@ -38,6 +38,8 @@ import lombok.extern.slf4j.Slf4j; +import javax.annotation.Nullable; + import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @@ -51,20 +53,15 @@ public BuyerAsMakerCreatesAndSignsDepositTx(TaskRunner taskHandler, Trade protected void run() { try { runInterceptHook(); - checkNotNull(trade.getTradeAmount(), "trade.getTradeAmount() must not be null"); + Coin tradeAmount = checkNotNull(trade.getTradeAmount(), "trade.getTradeAmount() must not be null"); BtcWalletService walletService = processModel.getBtcWalletService(); String id = processModel.getOffer().getId(); TradingPeer tradingPeer = processModel.getTradingPeer(); Offer offer = checkNotNull(trade.getOffer()); - // params byte[] contractHash = Hash.getSha256Hash(checkNotNull(trade.getContractAsJson())); trade.setContractHash(contractHash); - log.debug("\n\n------------------------------------------------------------\n" - + "Contract as json\n" - + trade.getContractAsJson() - + "\n------------------------------------------------------------\n"); Coin makerInputAmount = offer.getBuyerSecurityDeposit(); Optional addressEntryOptional = walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG); @@ -76,15 +73,15 @@ protected void run() { Coin msOutputAmount = makerInputAmount .add(trade.getTxFee()) .add(offer.getSellerSecurityDeposit()) - .add(trade.getTradeAmount()); + .add(tradeAmount); List takerRawTransactionInputs = checkNotNull(tradingPeer.getRawTransactionInputs()); long takerChangeOutputValue = tradingPeer.getChangeOutputValue(); - String takerChangeAddressString = tradingPeer.getChangeOutputAddress(); + @Nullable String takerChangeAddressString = tradingPeer.getChangeOutputAddress(); Address makerAddress = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.RESERVED_FOR_TRADE).getAddress(); Address makerChangeAddress = walletService.getFreshAddressEntry().getAddress(); byte[] buyerPubKey = processModel.getMyMultiSigPubKey(); - byte[] sellerPubKey = tradingPeer.getMultiSigPubKey(); + byte[] sellerPubKey = checkNotNull(tradingPeer.getMultiSigPubKey()); checkArgument(Arrays.equals(buyerPubKey, makerMultiSigAddressEntry.getPubKey()), "buyerPubKey from AddressEntry must match the one from the trade data. trade id =" + id); From 03c2fbfb1d526f42fda52658b3eea64334c75701 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 20:45:52 -0500 Subject: [PATCH 016/143] Refactoring: cleanups --- .../MakerSendsInputsForDepositTxResponse.java | 24 +++++++++---------- .../TakerSendInputsForDepositTxRequest.java | 5 ++-- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java index c0f1081bf5b..8831d8eab00 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java @@ -19,7 +19,6 @@ import bisq.core.btc.model.AddressEntry; import bisq.core.btc.wallet.BtcWalletService; -import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.trade.Trade; import bisq.core.trade.messages.InputsForDepositTxResponse; import bisq.core.trade.protocol.tasks.TradeTask; @@ -30,6 +29,8 @@ import bisq.common.crypto.Sig; import bisq.common.taskrunner.TaskRunner; +import java.security.PrivateKey; + import java.util.Arrays; import java.util.Date; import java.util.Optional; @@ -55,26 +56,25 @@ protected void run() { BtcWalletService walletService = processModel.getBtcWalletService(); String id = processModel.getOffer().getId(); - Optional addressEntryOptional = walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG); - checkArgument(addressEntryOptional.isPresent(), "addressEntry must be set here."); + Optional optionalMultiSigAddressEntry = walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG); + checkArgument(optionalMultiSigAddressEntry.isPresent(), "addressEntry must be set here."); AddressEntry makerPayoutAddressEntry = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.TRADE_PAYOUT); byte[] makerMultiSigPubKey = processModel.getMyMultiSigPubKey(); checkArgument(Arrays.equals(makerMultiSigPubKey, - addressEntryOptional.get().getPubKey()), + optionalMultiSigAddressEntry.get().getPubKey()), "makerMultiSigPubKey from AddressEntry must match the one from the trade data. trade id =" + id); byte[] preparedDepositTx = getPreparedDepositTx(); // Maker has to use preparedDepositTx as nonce. - // He cannot manipulate the preparedDepositTx - so we avoid to have a challenge protocol for passing the nonce we want to get signed. - PaymentAccountPayload paymentAccountPayload = checkNotNull(processModel.getPaymentAccountPayload(trade), - "processModel.getPaymentAccountPayload(trade) must not be null"); - - byte[] sig = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(), preparedDepositTx); - + // He cannot manipulate the preparedDepositTx - so we avoid to have a challenge protocol for passing the + // nonce we want to get signed. + // This is used for verifying the peers account age witness + PrivateKey privateKey = processModel.getKeyRing().getSignatureKeyPair().getPrivate(); + byte[] signatureOfNonce = Sig.sign(privateKey, preparedDepositTx); InputsForDepositTxResponse message = new InputsForDepositTxResponse( processModel.getOfferId(), - paymentAccountPayload, + checkNotNull(processModel.getPaymentAccountPayload(trade)), processModel.getAccountId(), makerMultiSigPubKey, trade.getContractAsJson(), @@ -84,7 +84,7 @@ protected void run() { processModel.getRawTransactionInputs(), processModel.getMyNodeAddress(), UUID.randomUUID().toString(), - sig, + signatureOfNonce, new Date().getTime(), trade.getLockTime()); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java index 0db99b431ff..f7ec1e82ca9 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java @@ -93,9 +93,10 @@ protected void run() { // Taker has to use offerId as nonce (he cannot manipulate that - so we avoid to have a challenge // protocol for passing the nonce we want to get signed) + // This is used for verifying the peers account age witness PaymentAccountPayload paymentAccountPayload = checkNotNull(processModel.getPaymentAccountPayload(trade), "processModel.getPaymentAccountPayload(trade) must not be null"); - byte[] accountAgeWitnessSignatureOfOfferId = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(), + byte[] signatureOfNonce = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(), offerId.getBytes(Charsets.UTF_8)); InputsForDepositTxRequest request = new InputsForDepositTxRequest( @@ -123,7 +124,7 @@ protected void run() { trade.getRefundAgentNodeAddress(), UUID.randomUUID().toString(), Version.getP2PMessageVersion(), - accountAgeWitnessSignatureOfOfferId, + signatureOfNonce, new Date().getTime()); log.info("Send {} with offerId {} and uid {} to peer {}", request.getClass().getSimpleName(), request.getTradeId(), From e02355704ba7aea844576fbdfd1e7047d5ecc97a Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 21:53:45 -0500 Subject: [PATCH 017/143] Unsubscribe before state is set to avoid duplicate calls Cleanups --- .../tasks/buyer/BuyerSetupDepositTxListener.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupDepositTxListener.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupDepositTxListener.java index 6a814c818e4..2b765a76d0b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupDepositTxListener.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupDepositTxListener.java @@ -69,8 +69,9 @@ protected void run() { confidenceListener = new AddressConfidenceListener(depositTxAddress) { @Override public void onTransactionConfidenceChanged(TransactionConfidence confidence) { - if (isVisibleInNetwork(confidence)) + if (isVisibleInNetwork(confidence)) { applyConfidence(confidence); + } } }; walletService.addAddressConfidenceListener(confidenceListener); @@ -98,15 +99,15 @@ private void applyConfidence(TransactionConfidence confidence) { Transaction walletTx = processModel.getTradeWalletService().getWalletTx(confidence.getTransactionHash()); trade.applyDepositTx(walletTx); BtcWalletService.printTx("depositTx received from network", walletTx); + + // We don't want to trigger the tradeStateSubscription when setting the state, so we unsubscribe before + unSubscribeAndRemoveListener(); trade.setState(Trade.State.BUYER_SAW_DEPOSIT_TX_IN_NETWORK); } else { - log.info("We got the deposit tx already set from MakerProcessDepositTxPublishedMessage. tradeId={}, state={}", trade.getId(), trade.getState()); + unSubscribeAndRemoveListener(); } swapReservedForTradeEntry(); - - // need delay as it can be called inside the listener handler before listener and tradeStateSubscription are actually set. - UserThread.execute(this::unSubscribeAndRemoveListener); } private boolean isVisibleInNetwork(TransactionConfidence confidence) { @@ -116,7 +117,6 @@ private boolean isVisibleInNetwork(TransactionConfidence confidence) { } private void swapReservedForTradeEntry() { - log.info("swapReservedForTradeEntry"); processModel.getBtcWalletService().swapTradeEntryToAvailableEntry(trade.getId(), AddressEntry.Context.RESERVED_FOR_TRADE); } @@ -124,10 +124,12 @@ private void swapReservedForTradeEntry() { private void unSubscribeAndRemoveListener() { if (tradeStateSubscription != null) { tradeStateSubscription.unsubscribe(); + tradeStateSubscription = null; } if (confidenceListener != null) { processModel.getBtcWalletService().removeAddressConfidenceListener(confidenceListener); + confidenceListener = null; } } } From 5705d8e67ad68cc78a47266ce121d2af7061e15a Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 22:01:30 -0500 Subject: [PATCH 018/143] Refactoring: rename inputsForDepositTxResponse , add more checkNotNull checks --- ...erProcessesInputsForDepositTxResponse.java | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java index 69e47e76008..925e727b3da 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java @@ -43,42 +43,41 @@ public TakerProcessesInputsForDepositTxResponse(TaskRunner taskHandler, T protected void run() { try { runInterceptHook(); - log.debug("current trade state " + trade.getState()); - InputsForDepositTxResponse inputsForDepositTxResponse = (InputsForDepositTxResponse) processModel.getTradeMessage(); - checkTradeId(processModel.getOfferId(), inputsForDepositTxResponse); - checkNotNull(inputsForDepositTxResponse); + InputsForDepositTxResponse response = (InputsForDepositTxResponse) processModel.getTradeMessage(); + checkTradeId(processModel.getOfferId(), response); + checkNotNull(response); TradingPeer tradingPeer = processModel.getTradingPeer(); - tradingPeer.setPaymentAccountPayload(checkNotNull(inputsForDepositTxResponse.getMakerPaymentAccountPayload())); - tradingPeer.setAccountId(nonEmptyStringOf(inputsForDepositTxResponse.getMakerAccountId())); - tradingPeer.setMultiSigPubKey(checkNotNull(inputsForDepositTxResponse.getMakerMultiSigPubKey())); - tradingPeer.setContractAsJson(nonEmptyStringOf(inputsForDepositTxResponse.getMakerContractAsJson())); - tradingPeer.setContractSignature(nonEmptyStringOf(inputsForDepositTxResponse.getMakerContractSignature())); - tradingPeer.setPayoutAddressString(nonEmptyStringOf(inputsForDepositTxResponse.getMakerPayoutAddressString())); - tradingPeer.setRawTransactionInputs(checkNotNull(inputsForDepositTxResponse.getMakerInputs())); - byte[] preparedDepositTx = inputsForDepositTxResponse.getPreparedDepositTx(); - processModel.setPreparedDepositTx(checkNotNull(preparedDepositTx)); - long lockTime = inputsForDepositTxResponse.getLockTime(); + tradingPeer.setPaymentAccountPayload(checkNotNull(response.getMakerPaymentAccountPayload())); + tradingPeer.setAccountId(nonEmptyStringOf(response.getMakerAccountId())); + tradingPeer.setMultiSigPubKey(checkNotNull(response.getMakerMultiSigPubKey())); + tradingPeer.setContractAsJson(nonEmptyStringOf(response.getMakerContractAsJson())); + tradingPeer.setContractSignature(nonEmptyStringOf(response.getMakerContractSignature())); + tradingPeer.setPayoutAddressString(nonEmptyStringOf(response.getMakerPayoutAddressString())); + tradingPeer.setRawTransactionInputs(checkNotNull(response.getMakerInputs())); + processModel.setPreparedDepositTx(checkNotNull(response.getPreparedDepositTx())); + long lockTime = response.getLockTime(); if (Config.baseCurrencyNetwork().isMainnet()) { int myLockTime = processModel.getBtcWalletService().getBestChainHeight() + Restrictions.getLockTime(processModel.getOffer().getPaymentMethod().isAsset()); // We allow a tolerance of 3 blocks as BestChainHeight might be a bit different on maker and taker in case a new // block was just found checkArgument(Math.abs(lockTime - myLockTime) <= 3, - "Lock time of maker is more than 3 blocks different to the locktime I " + + "Lock time of maker is more than 3 blocks different to the lockTime I " + "calculated. Makers lockTime= " + lockTime + ", myLockTime=" + myLockTime); } trade.setLockTime(lockTime); - log.info("lockTime={}, delay={}", lockTime, (processModel.getBtcWalletService().getBestChainHeight() - lockTime)); + long delay = processModel.getBtcWalletService().getBestChainHeight() - lockTime; + log.info("lockTime={}, delay={}", lockTime, delay); // Maker has to sign preparedDepositTx. He cannot manipulate the preparedDepositTx - so we avoid to have a // challenge protocol for passing the nonce we want to get signed. - tradingPeer.setAccountAgeWitnessNonce(inputsForDepositTxResponse.getPreparedDepositTx()); - tradingPeer.setAccountAgeWitnessSignature(inputsForDepositTxResponse.getAccountAgeWitnessSignatureOfPreparedDepositTx()); + tradingPeer.setAccountAgeWitnessNonce(checkNotNull(response.getPreparedDepositTx())); + tradingPeer.setAccountAgeWitnessSignature(checkNotNull(response.getAccountAgeWitnessSignatureOfPreparedDepositTx())); - tradingPeer.setCurrentDate(inputsForDepositTxResponse.getCurrentDate()); + tradingPeer.setCurrentDate(response.getCurrentDate()); - checkArgument(inputsForDepositTxResponse.getMakerInputs().size() > 0); + checkArgument(response.getMakerInputs().size() > 0); // update to the latest peer address of our peer if the message is correct trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress()); From a8a3318f673ccf78b811dd04e28f442a9b27c47b Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 22:07:51 -0500 Subject: [PATCH 019/143] Refactoring: cleanups --- .../main/java/bisq/core/trade/Contract.java | 2 +- core/src/main/java/bisq/core/trade/Trade.java | 2 +- .../trade/protocol/BuyerAsMakerProtocol.java | 2 -- .../taker/TakerVerifyAndSignContract.java | 28 +++++++++---------- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/Contract.java b/core/src/main/java/bisq/core/trade/Contract.java index 65a8b00d9f7..9374eafb1f9 100644 --- a/core/src/main/java/bisq/core/trade/Contract.java +++ b/core/src/main/java/bisq/core/trade/Contract.java @@ -268,7 +268,7 @@ public boolean isMyRoleBuyer(PubKeyRing myPubKeyRing) { } public void printDiff(@Nullable String peersContractAsJson) { - final String json = Utilities.objectToJson(this); + String json = Utilities.objectToJson(this); String diff = StringUtils.difference(json, peersContractAsJson); if (!diff.isEmpty()) { log.warn("Diff of both contracts: \n" + diff); diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index 4f0f900a38c..030de7c358f 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -1146,7 +1146,7 @@ private void setupConfidenceListener() { setConfirmedState(); } else { ListenableFuture future = transactionConfidence.getDepthFuture(1); - Futures.addCallback(future, new FutureCallback() { + Futures.addCallback(future, new FutureCallback<>() { @Override public void onSuccess(TransactionConfidence result) { setConfirmedState(); diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 6f475f6734e..271c03de599 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -138,8 +138,6 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest tradeMessage, BuyerSetupDepositTxListener.class, BuyerAsMakerSendsInputsForDepositTxResponse.class ); - // We don't use a timeout here because if the DepositTxPublishedMessage does not arrive we - // get the deposit tx set at MakerSetupDepositTxListener once it is seen in the bitcoin network taskRunner.run(); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java index 517d65f59ad..29af6897530 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java @@ -52,18 +52,18 @@ protected void run() { try { runInterceptHook(); - checkNotNull(trade.getTakerFeeTxId(), "TakeOfferFeeTxId must not be null"); - + String takerFeeTxId = checkNotNull(trade.getTakerFeeTxId()); TradingPeer maker = processModel.getTradingPeer(); PaymentAccountPayload makerPaymentAccountPayload = checkNotNull(maker.getPaymentAccountPayload()); PaymentAccountPayload takerPaymentAccountPayload = checkNotNull(processModel.getPaymentAccountPayload(trade)); boolean isBuyerMakerAndSellerTaker = trade instanceof SellerAsTakerTrade; - NodeAddress buyerNodeAddress = isBuyerMakerAndSellerTaker ? processModel.getTempTradingPeerNodeAddress() : processModel.getMyNodeAddress(); - NodeAddress sellerNodeAddress = isBuyerMakerAndSellerTaker ? processModel.getMyNodeAddress() : processModel.getTempTradingPeerNodeAddress(); - log.debug("isBuyerMakerAndSellerTaker " + isBuyerMakerAndSellerTaker); - log.debug("buyerAddress " + buyerNodeAddress); - log.debug("sellerAddress " + sellerNodeAddress); + NodeAddress buyerNodeAddress = isBuyerMakerAndSellerTaker ? + processModel.getTempTradingPeerNodeAddress() : + processModel.getMyNodeAddress(); + NodeAddress sellerNodeAddress = isBuyerMakerAndSellerTaker ? + processModel.getMyNodeAddress() : + processModel.getTempTradingPeerNodeAddress(); BtcWalletService walletService = processModel.getBtcWalletService(); String id = processModel.getOffer().getId(); @@ -75,13 +75,12 @@ protected void run() { takerMultiSigAddressEntry.getPubKey()), "takerMultiSigPubKey from AddressEntry must match the one from the trade data. trade id =" + id); - final Coin tradeAmount = trade.getTradeAmount(); - checkNotNull(tradeAmount, "tradeAmount must not be null"); + Coin tradeAmount = checkNotNull(trade.getTradeAmount()); Contract contract = new Contract( processModel.getOffer().getOfferPayload(), tradeAmount.value, trade.getTradePrice().getValue(), - trade.getTakerFeeTxId(), + takerFeeTxId, buyerNodeAddress, sellerNodeAddress, trade.getMediatorNodeAddress(), @@ -100,10 +99,11 @@ protected void run() { trade.getRefundAgentNodeAddress() ); String contractAsJson = Utilities.objectToJson(contract); - log.trace("Contract as json:{}", contractAsJson); - contract.printDiff(processModel.getTradingPeer().getContractAsJson()); - checkArgument(contractAsJson.equals(processModel.getTradingPeer().getContractAsJson()), "Contracts are not matching"); + if (!contractAsJson.equals(processModel.getTradingPeer().getContractAsJson())) { + contract.printDiff(processModel.getTradingPeer().getContractAsJson()); + failed("Contracts are not matching"); + } String signature = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(), contractAsJson); trade.setContract(contract); @@ -117,7 +117,7 @@ protected void run() { complete(); } catch (Throwable t) { - failed("Signature verification failed. " + t.getMessage()); + failed("Contract signature verification failed. " + t.getMessage()); } } catch (Throwable t) { failed(t); From 53526e3c20c7b380e5177979a3e813d639ac59a7 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 22:08:24 -0500 Subject: [PATCH 020/143] Remove repeated TakerVerifyMakerAccount and TakerVerifyMakerFeePayment from taker protocol --- .../java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java | 2 -- .../java/bisq/core/trade/protocol/SellerAsTakerProtocol.java | 2 -- 2 files changed, 4 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index e478165f62d..879795e7733 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -160,9 +160,7 @@ private void handle(InputsForDepositTxResponse tradeMessage, NodeAddress sender) taskRunner.addTasks( TakerProcessesInputsForDepositTxResponse.class, ApplyFilter.class, - TakerVerifyMakerAccount.class, VerifyPeersAccountAgeWitness.class, - TakerVerifyMakerFeePayment.class, TakerVerifyAndSignContract.class, TakerPublishFeeTx.class, BuyerAsTakerSignsDepositTx.class, diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 5dd5486cbfd..851d60656e4 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -135,9 +135,7 @@ private void handle(InputsForDepositTxResponse tradeMessage, NodeAddress sender) taskRunner.addTasks( TakerProcessesInputsForDepositTxResponse.class, ApplyFilter.class, - TakerVerifyMakerAccount.class, VerifyPeersAccountAgeWitness.class, - TakerVerifyMakerFeePayment.class, TakerVerifyAndSignContract.class, TakerPublishFeeTx.class, SellerAsTakerSignsDepositTx.class, From a725227ff30bf8e9083d113b7d902bb7edfe819f Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 22:20:08 -0500 Subject: [PATCH 021/143] Refactor: set string at success handlers correctly --- .../bisq/core/trade/protocol/BuyerAsMakerProtocol.java | 3 +-- .../bisq/core/trade/protocol/BuyerAsTakerProtocol.java | 5 ++--- .../bisq/core/trade/protocol/SellerAsMakerProtocol.java | 6 +++--- .../bisq/core/trade/protocol/SellerAsTakerProtocol.java | 7 +++---- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 271c03de599..7672450b667 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -193,12 +193,11 @@ private void handle(PayoutTxPublishedMessage tradeMessage, NodeAddress peerNodeA } private void handle() { - log.debug("handle RefreshTradeStateRequest called"); // Resend CounterCurrencyTransferStartedMessage if it hasn't been acked yet and counterparty asked for a refresh if (trade.getState().getPhase() == Trade.Phase.FIAT_SENT && trade.getState().ordinal() >= Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG.ordinal()) { TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, - () -> handleTaskRunnerSuccess("onFiatPaymentStarted"), + () -> handleTaskRunnerSuccess("RefreshTradeStateRequest"), this::handleTaskRunnerFault); taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class); taskRunner.run(); diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 879795e7733..0f65b5971b5 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -154,7 +154,7 @@ private void handle(InputsForDepositTxResponse tradeMessage, NodeAddress sender) TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, () -> { stopTimeout(); - handleTaskRunnerSuccess(tradeMessage, "PublishDepositTxRequest"); + handleTaskRunnerSuccess(tradeMessage, "handle InputsForDepositTxResponse"); }, errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); taskRunner.addTasks( @@ -219,12 +219,11 @@ private void handle(PayoutTxPublishedMessage tradeMessage, NodeAddress peerNodeA } private void handle() { - log.debug("handle RefreshTradeStateRequest called"); // Resend CounterCurrencyTransferStartedMessage if it hasn't been acked yet and counterparty asked for a refresh if (trade.getState().getPhase() == Trade.Phase.FIAT_SENT && trade.getState().ordinal() >= Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG.ordinal()) { TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> handleTaskRunnerSuccess("onFiatPaymentStarted"), + () -> handleTaskRunnerSuccess("RefreshTradeStateRequest"), this::handleTaskRunnerFault); taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class); taskRunner.run(); diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index 29ecde1c005..259cfb53188 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -142,7 +142,7 @@ protected void handle(DepositTxMessage tradeMessage, NodeAddress sender) { processModel.setTempTradingPeerNodeAddress(sender); TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "DepositTxPublishedMessage"), + () -> handleTaskRunnerSuccess(tradeMessage, "handle DepositTxMessage"), errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); taskRunner.addTasks( @@ -161,7 +161,7 @@ private void handle(DelayedPayoutTxSignatureResponse tradeMessage, NodeAddress s TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, () -> { stopTimeout(); - handleTaskRunnerSuccess(tradeMessage, "PublishDepositTxRequest"); + handleTaskRunnerSuccess(tradeMessage, "handle DelayedPayoutTxSignatureResponse"); }, errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); @@ -187,7 +187,7 @@ private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddr processModel.setTempTradingPeerNodeAddress(sender); TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "CounterCurrencyTransferStartedMessage"), + () -> handleTaskRunnerSuccess(tradeMessage, "handle CounterCurrencyTransferStartedMessage"), errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); taskRunner.addTasks( diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 851d60656e4..8877b1e57b3 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -127,8 +127,7 @@ private void handle(InputsForDepositTxResponse tradeMessage, NodeAddress sender) TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, () -> { - stopTimeout(); - handleTaskRunnerSuccess(tradeMessage, "PublishDepositTxRequest"); + handleTaskRunnerSuccess(tradeMessage, "handle InputsForDepositTxResponse"); }, errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); @@ -152,7 +151,7 @@ private void handle(DelayedPayoutTxSignatureResponse tradeMessage, NodeAddress s TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, () -> { stopTimeout(); - handleTaskRunnerSuccess(tradeMessage, "PublishDepositTxRequest"); + handleTaskRunnerSuccess(tradeMessage, "handle DelayedPayoutTxSignatureResponse"); }, errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); @@ -178,7 +177,7 @@ private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddr processModel.setTempTradingPeerNodeAddress(sender); TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "CounterCurrencyTransferStartedMessage"), + () -> handleTaskRunnerSuccess(tradeMessage, "handle CounterCurrencyTransferStartedMessage"), errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); taskRunner.addTasks( From 2aa5feebc14ac1d0192f218fd9fc68704b3f98e6 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 22:23:01 -0500 Subject: [PATCH 022/143] Move stopTimeout to second message handler --- .../java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 0f65b5971b5..0f938724a12 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -153,7 +153,6 @@ private void handle(InputsForDepositTxResponse tradeMessage, NodeAddress sender) TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, () -> { - stopTimeout(); handleTaskRunnerSuccess(tradeMessage, "handle InputsForDepositTxResponse"); }, errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); @@ -175,7 +174,10 @@ private void handle(DelayedPayoutTxSignatureRequest tradeMessage, NodeAddress se processModel.setTempTradingPeerNodeAddress(sender); TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle DelayedPayoutTxSignatureRequest"), + () -> { + stopTimeout(); // We stop timeout here as last DepositTxAndDelayedPayoutTxMessage is not mandatory + handleTaskRunnerSuccess(tradeMessage, "handle DelayedPayoutTxSignatureRequest"); + }, errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); taskRunner.addTasks( BuyerProcessDelayedPayoutTxSignatureRequest.class, From 9966f9a9a880a7bfba193f567a1186f0dfc0355e Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 22:25:48 -0500 Subject: [PATCH 023/143] Move contractHash creation to TakerVerifyAndSignContract --- .../seller_as_taker/SellerAsTakerSignsDepositTx.java | 10 +--------- .../tasks/taker/TakerVerifyAndSignContract.java | 6 +++++- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java index 0aa4f72fc58..317863578ef 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java @@ -25,7 +25,6 @@ import bisq.core.trade.protocol.TradingPeer; import bisq.core.trade.protocol.tasks.TradeTask; -import bisq.common.crypto.Hash; import bisq.common.taskrunner.TaskRunner; import org.bitcoinj.core.Coin; @@ -50,13 +49,6 @@ public SellerAsTakerSignsDepositTx(TaskRunner taskHandler, Trade trade) { protected void run() { try { runInterceptHook(); - log.debug("\n\n------------------------------------------------------------\n" - + "Contract as json\n" - + trade.getContractAsJson() - + "\n------------------------------------------------------------\n"); - - byte[] contractHash = Hash.getSha256Hash(checkNotNull(trade.getContractAsJson())); - trade.setContractHash(contractHash); List sellerInputs = checkNotNull(processModel.getRawTransactionInputs(), "sellerInputs must not be null"); BtcWalletService walletService = processModel.getBtcWalletService(); @@ -79,7 +71,7 @@ protected void run() { Transaction depositTx = processModel.getTradeWalletService().takerSignsDepositTx( true, - contractHash, + trade.getContractHash(), processModel.getPreparedDepositTx(), checkNotNull(tradingPeer.getRawTransactionInputs()), sellerInputs, diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java index 29af6897530..ba3e42ede46 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java @@ -28,6 +28,7 @@ import bisq.network.p2p.NodeAddress; +import bisq.common.crypto.Hash; import bisq.common.crypto.Sig; import bisq.common.taskrunner.TaskRunner; import bisq.common.util.Utilities; @@ -108,13 +109,16 @@ protected void run() { String signature = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(), contractAsJson); trade.setContract(contract); trade.setContractAsJson(contractAsJson); + + byte[] contractHash = Hash.getSha256Hash(checkNotNull(contractAsJson)); + trade.setContractHash(contractHash); + trade.setTakerContractSignature(signature); try { checkNotNull(maker.getPubKeyRing(), "maker.getPubKeyRing() must nto be null"); Sig.verify(maker.getPubKeyRing().getSignaturePubKey(), contractAsJson, maker.getContractSignature()); - complete(); } catch (Throwable t) { failed("Contract signature verification failed. " + t.getMessage()); From fdde4b552cb4ff859bde968356e122edfd136ee6 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 22:29:13 -0500 Subject: [PATCH 024/143] Refactoring: cleanups --- .../seller_as_taker/SellerAsTakerSignsDepositTx.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java index 317863578ef..389c4ce040a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java @@ -50,13 +50,14 @@ protected void run() { try { runInterceptHook(); - List sellerInputs = checkNotNull(processModel.getRawTransactionInputs(), "sellerInputs must not be null"); + List sellerInputs = checkNotNull(processModel.getRawTransactionInputs(), + "sellerInputs must not be null"); BtcWalletService walletService = processModel.getBtcWalletService(); String id = processModel.getOffer().getId(); - Optional addressEntryOptional = walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG); - checkArgument(addressEntryOptional.isPresent(), "addressEntryOptional must be present"); - AddressEntry sellerMultiSigAddressEntry = addressEntryOptional.get(); + Optional optionalMultiSigAddressEntry = walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG); + checkArgument(optionalMultiSigAddressEntry.isPresent(), "addressEntryOptional must be present"); + AddressEntry sellerMultiSigAddressEntry = optionalMultiSigAddressEntry.get(); byte[] sellerMultiSigPubKey = processModel.getMyMultiSigPubKey(); checkArgument(Arrays.equals(sellerMultiSigPubKey, sellerMultiSigAddressEntry.getPubKey()), @@ -64,7 +65,8 @@ protected void run() { Coin sellerInput = Coin.valueOf(sellerInputs.stream().mapToLong(input -> input.value).sum()); - sellerMultiSigAddressEntry.setCoinLockedInMultiSig(sellerInput.subtract(trade.getTxFee().multiply(2))); + Coin totalFee = trade.getTxFee().multiply(2); // Fee for deposit and payout tx + sellerMultiSigAddressEntry.setCoinLockedInMultiSig(sellerInput.subtract(totalFee)); walletService.saveAddressEntryList(); TradingPeer tradingPeer = processModel.getTradingPeer(); From e960e1208470c6b76d15615d6abbd102bcecdbaf Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 22:58:13 -0500 Subject: [PATCH 025/143] Refactoring: cleanups --- .../core/trade/DelayedPayoutTxValidation.java | 4 + .../trade/protocol/BuyerAsMakerProtocol.java | 1 + .../tasks/PublishTradeStatistics.java | 50 ++++++----- ...rocessDelayedPayoutTxSignatureRequest.java | 9 +- ...essDepositTxAndDelayedPayoutTxMessage.java | 25 +++--- ...SendsDelayedPayoutTxSignatureResponse.java | 4 - .../buyer/BuyerSignsDelayedPayoutTx.java | 6 +- .../SellerFinalizesDelayedPayoutTx.java | 3 +- ...ocessDelayedPayoutTxSignatureResponse.java | 11 +-- .../seller/SellerPublishesDepositTx.java | 7 +- ...erSendDelayedPayoutTxSignatureRequest.java | 4 - ...ndsDepositTxAndDelayedPayoutTxMessage.java | 84 +++++++++---------- .../seller/SellerSignsDelayedPayoutTx.java | 3 +- 13 files changed, 101 insertions(+), 110 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/DelayedPayoutTxValidation.java b/core/src/main/java/bisq/core/trade/DelayedPayoutTxValidation.java index 088716b8060..8472fc2c0df 100644 --- a/core/src/main/java/bisq/core/trade/DelayedPayoutTxValidation.java +++ b/core/src/main/java/bisq/core/trade/DelayedPayoutTxValidation.java @@ -146,9 +146,13 @@ public static void validatePayoutTx(Trade trade, NetworkParameters params = btcWalletService.getParams(); + + //TODO update to BitcoinJ API changes Address address = output.getAddressFromP2PKHScript(params); + if (address == null) { // The donation address can be as well be a multisig address. + //TODO update to BitcoinJ API changes address = output.getAddressFromP2SH(params); if (address == null) { errorMsg = "Donation address cannot be resolved (not of type P2PKHScript or P2SH). Output: " + output; diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 7672450b667..3e0447b9aae 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -178,6 +178,7 @@ private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress processModel.logTrade(buyerAsMakerTrade); } + private void handle(PayoutTxPublishedMessage tradeMessage, NodeAddress peerNodeAddress) { processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(peerNodeAddress); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/PublishTradeStatistics.java b/core/src/main/java/bisq/core/trade/protocol/tasks/PublishTradeStatistics.java index 7a19d4f9177..8eb71ffdd87 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/PublishTradeStatistics.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/PublishTradeStatistics.java @@ -45,35 +45,33 @@ public PublishTradeStatistics(TaskRunner taskHandler, Trade trade) { protected void run() { try { runInterceptHook(); - if (trade.getDepositTx() != null) { - Map extraDataMap = new HashMap<>(); - if (processModel.getReferralIdService().getOptionalReferralId().isPresent()) { - extraDataMap.put(OfferPayload.REFERRAL_ID, processModel.getReferralIdService().getOptionalReferralId().get()); - } - NodeAddress mediatorNodeAddress = trade.getMediatorNodeAddress(); - if (mediatorNodeAddress != null) { - // The first 4 chars are sufficient to identify a mediator. - // For testing with regtest/localhost we use the full address as its localhost and would result in - // same values for multiple mediators. - NetworkNode networkNode = model.getProcessModel().getP2PService().getNetworkNode(); - String address = networkNode instanceof TorNetworkNode ? - mediatorNodeAddress.getFullAddress().substring(0, 4) : - mediatorNodeAddress.getFullAddress(); - extraDataMap.put(TradeStatistics2.MEDIATOR_ADDRESS, address); - } + checkNotNull(trade.getDepositTx()); - Offer offer = trade.getOffer(); - checkNotNull(offer, "offer must not ne null"); - checkNotNull(trade.getTradeAmount(), "trade.getTradeAmount() must not ne null"); - TradeStatistics2 tradeStatistics = new TradeStatistics2(offer.getOfferPayload(), - trade.getTradePrice(), - trade.getTradeAmount(), - trade.getDate(), - trade.getDepositTxId(), - extraDataMap); - processModel.getP2PService().addPersistableNetworkPayload(tradeStatistics, true); + Map extraDataMap = new HashMap<>(); + if (processModel.getReferralIdService().getOptionalReferralId().isPresent()) { + extraDataMap.put(OfferPayload.REFERRAL_ID, processModel.getReferralIdService().getOptionalReferralId().get()); } + + NodeAddress mediatorNodeAddress = checkNotNull(trade.getMediatorNodeAddress()); + // The first 4 chars are sufficient to identify a mediator. + // For testing with regtest/localhost we use the full address as its localhost and would result in + // same values for multiple mediators. + NetworkNode networkNode = model.getProcessModel().getP2PService().getNetworkNode(); + String address = networkNode instanceof TorNetworkNode ? + mediatorNodeAddress.getFullAddress().substring(0, 4) : + mediatorNodeAddress.getFullAddress(); + extraDataMap.put(TradeStatistics2.MEDIATOR_ADDRESS, address); + + Offer offer = checkNotNull(trade.getOffer()); + TradeStatistics2 tradeStatistics = new TradeStatistics2(offer.getOfferPayload(), + trade.getTradePrice(), + checkNotNull(trade.getTradeAmount()), + trade.getDate(), + trade.getDepositTxId(), + extraDataMap); + processModel.getP2PService().addPersistableNetworkPayload(tradeStatistics, true); + complete(); } catch (Throwable t) { failed(t); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDelayedPayoutTxSignatureRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDelayedPayoutTxSignatureRequest.java index e64e4355cf0..4ef0e01117e 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDelayedPayoutTxSignatureRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDelayedPayoutTxSignatureRequest.java @@ -40,14 +40,13 @@ public BuyerProcessDelayedPayoutTxSignatureRequest(TaskRunner taskHandler protected void run() { try { runInterceptHook(); - DelayedPayoutTxSignatureRequest message = (DelayedPayoutTxSignatureRequest) processModel.getTradeMessage(); - checkNotNull(message); - Validator.checkTradeId(processModel.getOfferId(), message); - byte[] delayedPayoutTxAsBytes = checkNotNull(message.getDelayedPayoutTx()); + DelayedPayoutTxSignatureRequest request = (DelayedPayoutTxSignatureRequest) processModel.getTradeMessage(); + checkNotNull(request); + Validator.checkTradeId(processModel.getOfferId(), request); + byte[] delayedPayoutTxAsBytes = checkNotNull(request.getDelayedPayoutTx()); Transaction preparedDelayedPayoutTx = processModel.getBtcWalletService().getTxFromSerializedTx(delayedPayoutTxAsBytes); processModel.setPreparedDelayedPayoutTx(preparedDelayedPayoutTx); - // update to the latest peer address of our peer if the message is correct trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress()); complete(); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java index 026102b8c03..60ac8048016 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java @@ -26,13 +26,12 @@ import bisq.core.util.Validator; import bisq.common.taskrunner.TaskRunner; -import bisq.common.util.Utilities; import org.bitcoinj.core.Transaction; +import org.bitcoinj.wallet.Wallet; import lombok.extern.slf4j.Slf4j; -import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @Slf4j @@ -45,34 +44,36 @@ public BuyerProcessDepositTxAndDelayedPayoutTxMessage(TaskRunner taskHand protected void run() { try { runInterceptHook(); - DepositTxAndDelayedPayoutTxMessage message = (DepositTxAndDelayedPayoutTxMessage) processModel.getTradeMessage(); + var message = (DepositTxAndDelayedPayoutTxMessage) processModel.getTradeMessage(); checkNotNull(message); Validator.checkTradeId(processModel.getOfferId(), message); - checkArgument(message.getDepositTx() != null); // To access tx confidence we need to add that tx into our wallet. - Transaction depositTx = processModel.getBtcWalletService().getTxFromSerializedTx(message.getDepositTx()); + byte[] depositTxBytes = checkNotNull(message.getDepositTx()); + Transaction depositTx = processModel.getBtcWalletService().getTxFromSerializedTx(depositTxBytes); // update with full tx - Transaction committedDepositTx = WalletService.maybeAddSelfTxToWallet(depositTx, processModel.getBtcWalletService().getWallet()); + Wallet wallet = processModel.getBtcWalletService().getWallet(); + Transaction committedDepositTx = WalletService.maybeAddSelfTxToWallet(depositTx, wallet); trade.applyDepositTx(committedDepositTx); BtcWalletService.printTx("depositTx received from peer", committedDepositTx); // To access tx confidence we need to add that tx into our wallet. - byte[] delayedPayoutTxBytes = message.getDelayedPayoutTx(); + byte[] delayedPayoutTxBytes = checkNotNull(message.getDelayedPayoutTx()); trade.applyDelayedPayoutTxBytes(delayedPayoutTxBytes); - BtcWalletService.printTx("delayedPayoutTx received from peer", trade.getDelayedPayoutTx()); - log.info("DelayedPayoutTxBytes = {}", Utilities.bytesAsHexString(trade.getDelayedPayoutTxBytes())); + BtcWalletService.printTx("delayedPayoutTx received from peer", + checkNotNull(trade.getDelayedPayoutTx())); - // update to the latest peer address of our peer if the message is correct trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress()); processModel.removeMailboxMessageAfterProcessing(trade); // If we got already the confirmation we don't want to apply an earlier state - if (trade.getState().ordinal() < Trade.State.BUYER_SAW_DEPOSIT_TX_IN_NETWORK.ordinal()) + if (trade.getState().ordinal() < Trade.State.BUYER_SAW_DEPOSIT_TX_IN_NETWORK.ordinal()) { trade.setState(Trade.State.BUYER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG); + } - processModel.getBtcWalletService().swapTradeEntryToAvailableEntry(trade.getId(), AddressEntry.Context.RESERVED_FOR_TRADE); + processModel.getBtcWalletService().swapTradeEntryToAvailableEntry(trade.getId(), + AddressEntry.Context.RESERVED_FOR_TRADE); complete(); } catch (Throwable t) { diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendsDelayedPayoutTxSignatureResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendsDelayedPayoutTxSignatureResponse.java index 1d4bc214ba4..1cf373e7889 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendsDelayedPayoutTxSignatureResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendsDelayedPayoutTxSignatureResponse.java @@ -49,8 +49,6 @@ protected void run() { processModel.getMyNodeAddress(), delayedPayoutTxSignature); - // todo trade.setState - NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress(); log.info("Send {} to peer {}. tradeId={}, uid={}", message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); @@ -63,7 +61,6 @@ protected void run() { public void onArrived() { log.info("{} arrived at peer {}. tradeId={}, uid={}", message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); - // todo trade.setState complete(); } @@ -71,7 +68,6 @@ public void onArrived() { public void onFault(String errorMessage) { log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}", message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage); - // todo trade.setState appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage); failed(errorMessage); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignsDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignsDelayedPayoutTx.java index 5e43f265674..2008b92b40a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignsDelayedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSignsDelayedPayoutTx.java @@ -56,7 +56,11 @@ protected void run() { btcWalletService.getOrCreateAddressEntry(id, AddressEntry.Context.MULTI_SIG).getPubKey()), "buyerMultiSigPubKey from AddressEntry must match the one from the trade data. trade id =" + id); byte[] sellerMultiSigPubKey = processModel.getTradingPeer().getMultiSigPubKey(); - byte[] delayedPayoutTxSignature = processModel.getTradeWalletService().signDelayedPayoutTx(preparedDelayedPayoutTx, myMultiSigKeyPair, buyerMultiSigPubKey, sellerMultiSigPubKey); + byte[] delayedPayoutTxSignature = processModel.getTradeWalletService().signDelayedPayoutTx( + preparedDelayedPayoutTx, + myMultiSigKeyPair, + buyerMultiSigPubKey, + sellerMultiSigPubKey); processModel.setDelayedPayoutTxSignature(delayedPayoutTxSignature); complete(); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerFinalizesDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerFinalizesDelayedPayoutTx.java index ca374974adb..720c1a9f048 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerFinalizesDelayedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerFinalizesDelayedPayoutTx.java @@ -58,7 +58,8 @@ protected void run() { byte[] buyerSignature = processModel.getTradingPeer().getDelayedPayoutTxSignature(); byte[] sellerSignature = processModel.getDelayedPayoutTxSignature(); - Transaction signedDelayedPayoutTx = processModel.getTradeWalletService().finalizeDelayedPayoutTx(preparedDelayedPayoutTx, + Transaction signedDelayedPayoutTx = processModel.getTradeWalletService().finalizeDelayedPayoutTx( + preparedDelayedPayoutTx, buyerMultiSigPubKey, sellerMultiSigPubKey, buyerSignature, diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessDelayedPayoutTxSignatureResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessDelayedPayoutTxSignatureResponse.java index cca5a552891..c47fd0be067 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessDelayedPayoutTxSignatureResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessDelayedPayoutTxSignatureResponse.java @@ -38,18 +38,15 @@ public SellerProcessDelayedPayoutTxSignatureResponse(TaskRunner taskHandl protected void run() { try { runInterceptHook(); - DelayedPayoutTxSignatureResponse delayedPayoutTxSignatureResponse = (DelayedPayoutTxSignatureResponse) processModel.getTradeMessage(); - checkNotNull(delayedPayoutTxSignatureResponse); - checkTradeId(processModel.getOfferId(), delayedPayoutTxSignatureResponse); + DelayedPayoutTxSignatureResponse response = (DelayedPayoutTxSignatureResponse) processModel.getTradeMessage(); + checkNotNull(response); + checkTradeId(processModel.getOfferId(), response); - byte[] delayedPayoutTxSignature = checkNotNull(delayedPayoutTxSignatureResponse.getDelayedPayoutTxSignature()); - processModel.getTradingPeer().setDelayedPayoutTxSignature(delayedPayoutTxSignature); + processModel.getTradingPeer().setDelayedPayoutTxSignature(checkNotNull(response.getDelayedPayoutTxSignature())); // update to the latest peer address of our peer if the message is correct trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress()); - // todo trade.setState - complete(); } catch (Throwable t) { failed(t); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerPublishesDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerPublishesDepositTx.java index 6295a7ecaeb..7f4aef9386b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerPublishesDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerPublishesDepositTx.java @@ -20,7 +20,6 @@ import bisq.core.btc.exceptions.TxBroadcastException; import bisq.core.btc.model.AddressEntry; import bisq.core.btc.wallet.TxBroadcaster; -import bisq.core.trade.Contract; import bisq.core.trade.Trade; import bisq.core.trade.protocol.tasks.TradeTask; @@ -48,7 +47,8 @@ public void onSuccess(Transaction transaction) { if (!completed) { trade.setState(Trade.State.SELLER_PUBLISHED_DEPOSIT_TX); - processModel.getBtcWalletService().swapTradeEntryToAvailableEntry(processModel.getOffer().getId(), AddressEntry.Context.RESERVED_FOR_TRADE); + processModel.getBtcWalletService().swapTradeEntryToAvailableEntry(processModel.getOffer().getId(), + AddressEntry.Context.RESERVED_FOR_TRADE); complete(); } else { @@ -66,9 +66,6 @@ public void onFailure(TxBroadcastException exception) { } }); } catch (Throwable t) { - Contract contract = trade.getContract(); - if (contract != null) - contract.printDiff(processModel.getTradingPeer().getContractAsJson()); failed(t); } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendDelayedPayoutTxSignatureRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendDelayedPayoutTxSignatureRequest.java index fc6c86e22fc..b914f1b1290 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendDelayedPayoutTxSignatureRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendDelayedPayoutTxSignatureRequest.java @@ -52,8 +52,6 @@ protected void run() { processModel.getMyNodeAddress(), preparedDelayedPayoutTx.bitcoinSerialize()); - // todo trade.setState - NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress(); log.info("Send {} to peer {}. tradeId={}, uid={}", message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); @@ -66,7 +64,6 @@ protected void run() { public void onArrived() { log.info("{} arrived at peer {}. tradeId={}, uid={}", message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); - // todo trade.setState complete(); } @@ -74,7 +71,6 @@ public void onArrived() { public void onFault(String errorMessage) { log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}", message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage); - // todo trade.setState appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage); failed(); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java index 9e549cb537f..7506f958af7 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java @@ -44,55 +44,51 @@ public SellerSendsDepositTxAndDelayedPayoutTxMessage(TaskRunner taskHandl protected void run() { try { runInterceptHook(); - if (trade.getDepositTx() != null) { - Transaction delayedPayoutTx = checkNotNull(trade.getDelayedPayoutTx()); - Transaction depositTx = checkNotNull(trade.getDepositTx()); - DepositTxAndDelayedPayoutTxMessage message = new DepositTxAndDelayedPayoutTxMessage(UUID.randomUUID().toString(), - processModel.getOfferId(), - processModel.getMyNodeAddress(), - depositTx.bitcoinSerialize(), - delayedPayoutTx.bitcoinSerialize()); - trade.setState(Trade.State.SELLER_SENT_DEPOSIT_TX_PUBLISHED_MSG); - NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress(); - log.info("Send {} to peer {}. tradeId={}, uid={}", - message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); - processModel.getP2PService().sendEncryptedMailboxMessage( - peersNodeAddress, - processModel.getTradingPeer().getPubKeyRing(), - message, - new SendMailboxMessageListener() { - @Override - public void onArrived() { - log.info("{} arrived at peer {}. tradeId={}, uid={}", - message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); - trade.setState(Trade.State.SELLER_SAW_ARRIVED_DEPOSIT_TX_PUBLISHED_MSG); - complete(); - } + Transaction depositTx = checkNotNull(trade.getDepositTx(), "DepositTx must not be null"); + Transaction delayedPayoutTx = checkNotNull(trade.getDelayedPayoutTx()); + DepositTxAndDelayedPayoutTxMessage message = new DepositTxAndDelayedPayoutTxMessage(UUID.randomUUID().toString(), + processModel.getOfferId(), + processModel.getMyNodeAddress(), + depositTx.bitcoinSerialize(), + delayedPayoutTx.bitcoinSerialize()); + trade.setState(Trade.State.SELLER_SENT_DEPOSIT_TX_PUBLISHED_MSG); - @Override - public void onStoredInMailbox() { - log.info("{} stored in mailbox for peer {}. tradeId={}, uid={}", - message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); + NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress(); + log.info("Send {} to peer {}. tradeId={}, uid={}", + message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); + processModel.getP2PService().sendEncryptedMailboxMessage( + peersNodeAddress, + processModel.getTradingPeer().getPubKeyRing(), + message, + new SendMailboxMessageListener() { + @Override + public void onArrived() { + log.info("{} arrived at peer {}. tradeId={}, uid={}", + message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); + trade.setState(Trade.State.SELLER_SAW_ARRIVED_DEPOSIT_TX_PUBLISHED_MSG); + complete(); + } + + @Override + public void onStoredInMailbox() { + log.info("{} stored in mailbox for peer {}. tradeId={}, uid={}", + message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); - trade.setState(Trade.State.SELLER_STORED_IN_MAILBOX_DEPOSIT_TX_PUBLISHED_MSG); - complete(); - } + trade.setState(Trade.State.SELLER_STORED_IN_MAILBOX_DEPOSIT_TX_PUBLISHED_MSG); + complete(); + } - @Override - public void onFault(String errorMessage) { - log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}", - message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage); - trade.setState(Trade.State.SELLER_SEND_FAILED_DEPOSIT_TX_PUBLISHED_MSG); - appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage); - failed(); - } + @Override + public void onFault(String errorMessage) { + log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}", + message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage); + trade.setState(Trade.State.SELLER_SEND_FAILED_DEPOSIT_TX_PUBLISHED_MSG); + appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage); + failed(); } - ); - } else { - log.error("trade.getDepositTx() = " + trade.getDepositTx()); - failed("DepositTx is null"); - } + } + ); } catch (Throwable t) { failed(t); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignsDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignsDelayedPayoutTx.java index ed47059bda2..0ae1a159201 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignsDelayedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSignsDelayedPayoutTx.java @@ -57,7 +57,8 @@ protected void run() { "sellerMultiSigPubKey from AddressEntry must match the one from the trade data. trade id =" + id); byte[] buyerMultiSigPubKey = processModel.getTradingPeer().getMultiSigPubKey(); - byte[] delayedPayoutTxSignature = processModel.getTradeWalletService().signDelayedPayoutTx(preparedDelayedPayoutTx, + byte[] delayedPayoutTxSignature = processModel.getTradeWalletService().signDelayedPayoutTx( + preparedDelayedPayoutTx, myMultiSigKeyPair, buyerMultiSigPubKey, sellerMultiSigPubKey); From 17baf18844ac75cc4abb21289a8f3f71cb94af1b Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 23:01:33 -0500 Subject: [PATCH 026/143] Refactoring: cleanups --- .../tasks/buyer/BuyerVerifiesFinalDelayedPayoutTx.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesFinalDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesFinalDelayedPayoutTx.java index adb301d6451..c00bd19861f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesFinalDelayedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerVerifiesFinalDelayedPayoutTx.java @@ -40,17 +40,14 @@ protected void run() { try { runInterceptHook(); - Transaction delayedPayoutTx = trade.getDelayedPayoutTx(); - checkNotNull(delayedPayoutTx, "trade.getDelayedPayoutTx() must not be null"); - // Check again tx + Transaction delayedPayoutTx = checkNotNull(trade.getDelayedPayoutTx()); DelayedPayoutTxValidation.validatePayoutTx(trade, delayedPayoutTx, processModel.getDaoFacade(), processModel.getBtcWalletService()); // Now as we know the deposit tx we can also verify the input - Transaction depositTx = trade.getDepositTx(); - checkNotNull(depositTx, "trade.getDepositTx() must not be null"); + Transaction depositTx = checkNotNull(trade.getDepositTx()); DelayedPayoutTxValidation.validatePayoutTxInput(depositTx, delayedPayoutTx); complete(); From 853dac75441ad5690931658f9dbe66ccdd21b2bf Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 23:04:45 -0500 Subject: [PATCH 027/143] Remove empty task runner --- .../bisq/core/trade/protocol/SellerAsMakerProtocol.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index 259cfb53188..b8f17cfdc09 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -72,15 +72,6 @@ public SellerAsMakerProtocol(SellerAsMakerTrade trade) { super(trade); this.sellerAsMakerTrade = trade; - - Trade.Phase phase = trade.getState().getPhase(); - if (phase == Trade.Phase.TAKER_FEE_PUBLISHED) { - TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess("MakerSetupDepositTxListener"), - this::handleTaskRunnerFault); - - taskRunner.run(); - } } From 0f36ae8928e1558be75d0825175faa9561179532 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 23:17:50 -0500 Subject: [PATCH 028/143] Refactoring: cleanups --- .../trade/protocol/BuyerAsMakerProtocol.java | 68 ++++++++++-------- .../trade/protocol/BuyerAsTakerProtocol.java | 70 +++++++++++-------- .../trade/protocol/SellerAsMakerProtocol.java | 7 +- .../trade/protocol/SellerAsTakerProtocol.java | 7 +- 4 files changed, 87 insertions(+), 65 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 3e0447b9aae..6803fe2d977 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -143,7 +143,7 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest tradeMessage, /////////////////////////////////////////////////////////////////////////////////////////// - // Incoming message handling + // Incoming messages Take offer process /////////////////////////////////////////////////////////////////////////////////////////// private void handle(DelayedPayoutTxSignatureRequest tradeMessage, NodeAddress peerNodeAddress) { @@ -162,6 +162,7 @@ private void handle(DelayedPayoutTxSignatureRequest tradeMessage, NodeAddress pe taskRunner.run(); } + // DepositTxAndDelayedPayoutTxMessage is a MailboxMessage private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress peerNodeAddress) { processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(peerNodeAddress); @@ -179,37 +180,10 @@ private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress } - private void handle(PayoutTxPublishedMessage tradeMessage, NodeAddress peerNodeAddress) { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(peerNodeAddress); - - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle PayoutTxPublishedMessage"), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); - - taskRunner.addTasks( - BuyerProcessPayoutTxPublishedMessage.class - ); - taskRunner.run(); - } - - private void handle() { - // Resend CounterCurrencyTransferStartedMessage if it hasn't been acked yet and counterparty asked for a refresh - if (trade.getState().getPhase() == Trade.Phase.FIAT_SENT && - trade.getState().ordinal() >= Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG.ordinal()) { - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, - () -> handleTaskRunnerSuccess("RefreshTradeStateRequest"), - this::handleTaskRunnerFault); - taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class); - taskRunner.run(); - } - } - /////////////////////////////////////////////////////////////////////////////////////////// - // Called from UI + // User interaction /////////////////////////////////////////////////////////////////////////////////////////// - // User clicked the "bank transfer started" button @Override public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { checkArgument(!wasDisputed(), "A call to onFiatPaymentStarted is not permitted once a " + @@ -241,6 +215,42 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle } + /////////////////////////////////////////////////////////////////////////////////////////// + // Incoming message Payout tx + /////////////////////////////////////////////////////////////////////////////////////////// + + private void handle(PayoutTxPublishedMessage tradeMessage, NodeAddress peerNodeAddress) { + processModel.setTradeMessage(tradeMessage); + processModel.setTempTradingPeerNodeAddress(peerNodeAddress); + + TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, + () -> handleTaskRunnerSuccess(tradeMessage, "handle PayoutTxPublishedMessage"), + errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + + taskRunner.addTasks( + BuyerProcessPayoutTxPublishedMessage.class + ); + taskRunner.run(); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Incoming message Handle missing messages + /////////////////////////////////////////////////////////////////////////////////////////// + + private void handle() { + // Resend CounterCurrencyTransferStartedMessage if it hasn't been acked yet and counterparty asked for a refresh + if (trade.getState().getPhase() == Trade.Phase.FIAT_SENT && + trade.getState().ordinal() >= Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG.ordinal()) { + TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, + () -> handleTaskRunnerSuccess("RefreshTradeStateRequest"), + this::handleTaskRunnerFault); + taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class); + taskRunner.run(); + } + } + + /////////////////////////////////////////////////////////////////////////////////////////// // Message dispatcher /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 0f938724a12..9698953624b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -144,7 +144,7 @@ public void takeAvailableOffer() { /////////////////////////////////////////////////////////////////////////////////////////// - // Incoming message handling + // Incoming messages Take offer process /////////////////////////////////////////////////////////////////////////////////////////// private void handle(InputsForDepositTxResponse tradeMessage, NodeAddress sender) { @@ -189,6 +189,7 @@ private void handle(DelayedPayoutTxSignatureRequest tradeMessage, NodeAddress se } + // DepositTxAndDelayedPayoutTxMessage is a MailboxMessage private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress peerNodeAddress) { processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(peerNodeAddress); @@ -205,35 +206,9 @@ private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress processModel.logTrade(buyerAsTakerTrade); } - private void handle(PayoutTxPublishedMessage tradeMessage, NodeAddress peerNodeAddress) { - log.debug("handle PayoutTxPublishedMessage called"); - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(peerNodeAddress); - - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle PayoutTxPublishedMessage"), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); - - taskRunner.addTasks( - BuyerProcessPayoutTxPublishedMessage.class - ); - taskRunner.run(); - } - - private void handle() { - // Resend CounterCurrencyTransferStartedMessage if it hasn't been acked yet and counterparty asked for a refresh - if (trade.getState().getPhase() == Trade.Phase.FIAT_SENT && - trade.getState().ordinal() >= Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG.ordinal()) { - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> handleTaskRunnerSuccess("RefreshTradeStateRequest"), - this::handleTaskRunnerFault); - taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class); - taskRunner.run(); - } - } /////////////////////////////////////////////////////////////////////////////////////////// - // Called from UI + // User interaction /////////////////////////////////////////////////////////////////////////////////////////// // User clicked the "bank transfer started" button @@ -267,6 +242,45 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle log.warn("onFiatPaymentStarted called twice. tradeState=" + trade.getState()); } } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Incoming message Payout tx + /////////////////////////////////////////////////////////////////////////////////////////// + + private void handle(PayoutTxPublishedMessage tradeMessage, NodeAddress peerNodeAddress) { + log.debug("handle PayoutTxPublishedMessage called"); + processModel.setTradeMessage(tradeMessage); + processModel.setTempTradingPeerNodeAddress(peerNodeAddress); + + TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, + () -> handleTaskRunnerSuccess(tradeMessage, "handle PayoutTxPublishedMessage"), + errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + + taskRunner.addTasks( + BuyerProcessPayoutTxPublishedMessage.class + ); + taskRunner.run(); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Incoming message Handle missing messages + /////////////////////////////////////////////////////////////////////////////////////////// + + private void handle() { + // Resend CounterCurrencyTransferStartedMessage if it hasn't been acked yet and counterparty asked for a refresh + if (trade.getState().getPhase() == Trade.Phase.FIAT_SENT && + trade.getState().ordinal() >= Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG.ordinal()) { + TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, + () -> handleTaskRunnerSuccess("RefreshTradeStateRequest"), + this::handleTaskRunnerFault); + taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class); + taskRunner.run(); + } + } + + /////////////////////////////////////////////////////////////////////////////////////////// // Message dispatcher /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index b8f17cfdc09..78f96b21141 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -125,7 +125,7 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest tradeMessage, /////////////////////////////////////////////////////////////////////////////////////////// - // Incoming message handling + // Incoming messages Take offer process /////////////////////////////////////////////////////////////////////////////////////////// protected void handle(DepositTxMessage tradeMessage, NodeAddress sender) { @@ -170,7 +170,7 @@ private void handle(DelayedPayoutTxSignatureResponse tradeMessage, NodeAddress s /////////////////////////////////////////////////////////////////////////////////////////// - // After peer has started Fiat tx + // Incoming message when buyer has clicked payment started button /////////////////////////////////////////////////////////////////////////////////////////// private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddress sender) { @@ -191,10 +191,9 @@ private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddr /////////////////////////////////////////////////////////////////////////////////////////// - // Called from UI + // User interaction /////////////////////////////////////////////////////////////////////////////////////////// - // User clicked the "bank transfer received" button, so we release the funds for payout @Override public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { checkArgument(!wasDisputed(), "A call to onFiatPaymentReceived is not permitted once a " + diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 8877b1e57b3..3b900a779b8 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -118,7 +118,7 @@ public void takeAvailableOffer() { /////////////////////////////////////////////////////////////////////////////////////////// - // Incoming message handling + // Incoming messages Take offer process /////////////////////////////////////////////////////////////////////////////////////////// private void handle(InputsForDepositTxResponse tradeMessage, NodeAddress sender) { @@ -169,7 +169,7 @@ private void handle(DelayedPayoutTxSignatureResponse tradeMessage, NodeAddress s /////////////////////////////////////////////////////////////////////////////////////////// - // After peer has started Fiat tx + // Incoming message when buyer has clicked payment started button /////////////////////////////////////////////////////////////////////////////////////////// private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddress sender) { @@ -190,10 +190,9 @@ private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddr /////////////////////////////////////////////////////////////////////////////////////////// - // Called from UI + // User interaction /////////////////////////////////////////////////////////////////////////////////////////// - // User clicked the "bank transfer received" button, so we release the funds for payout @Override public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { checkArgument(!wasDisputed(), "A call to onFiatPaymentReceived is not permitted once a " + From 538db2f36f6da33055773065ef8189c412134a21 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 23:26:51 -0500 Subject: [PATCH 029/143] Move contractHash creation to MakerCreateAndSignContract --- .../BuyerAsMakerCreatesAndSignsDepositTx.java | 6 +----- .../protocol/tasks/maker/MakerCreateAndSignContract.java | 5 +++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerCreatesAndSignsDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerCreatesAndSignsDepositTx.java index ae656b83fb6..29459b1c955 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerCreatesAndSignsDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_maker/BuyerAsMakerCreatesAndSignsDepositTx.java @@ -26,7 +26,6 @@ import bisq.core.trade.protocol.TradingPeer; import bisq.core.trade.protocol.tasks.TradeTask; -import bisq.common.crypto.Hash; import bisq.common.taskrunner.TaskRunner; import org.bitcoinj.core.Address; @@ -60,9 +59,6 @@ protected void run() { TradingPeer tradingPeer = processModel.getTradingPeer(); Offer offer = checkNotNull(trade.getOffer()); - byte[] contractHash = Hash.getSha256Hash(checkNotNull(trade.getContractAsJson())); - trade.setContractHash(contractHash); - Coin makerInputAmount = offer.getBuyerSecurityDeposit(); Optional addressEntryOptional = walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG); checkArgument(addressEntryOptional.isPresent(), "addressEntryOptional must be present"); @@ -87,7 +83,7 @@ protected void run() { "buyerPubKey from AddressEntry must match the one from the trade data. trade id =" + id); PreparedDepositTxAndMakerInputs result = processModel.getTradeWalletService().buyerAsMakerCreatesAndSignsDepositTx( - contractHash, + trade.getContractHash(), makerInputAmount, msOutputAmount, takerRawTransactionInputs, diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java index 1c5694ab610..77b154e99d7 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java @@ -27,6 +27,7 @@ import bisq.network.p2p.NodeAddress; +import bisq.common.crypto.Hash; import bisq.common.crypto.Sig; import bisq.common.taskrunner.TaskRunner; import bisq.common.util.Utilities; @@ -93,6 +94,10 @@ protected void run() { trade.setContract(contract); trade.setContractAsJson(contractAsJson); trade.setMakerContractSignature(signature); + + byte[] contractHash = Hash.getSha256Hash(checkNotNull(trade.getContractAsJson())); + trade.setContractHash(contractHash); + processModel.setMyMultiSigPubKey(makerMultiSigPubKey); complete(); From 971cd57984768bf38e3187754f877e0a8302d190 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 23:34:07 -0500 Subject: [PATCH 030/143] Refactoring: cleanups, rename cleanupTradableOnFault --- .../bisq/core/trade/protocol/TradeProtocol.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index 9b056672d92..be41e046f83 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -222,7 +222,6 @@ private void handle(PeerPublishedDelayedPayoutTxMessage tradeMessage, NodeAddres errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); taskRunner.addTasks( - //todo ProcessPeerPublishedDelayedPayoutTxMessage.class ); taskRunner.run(); @@ -309,7 +308,7 @@ protected void startTimeout() { timeoutTimer = UserThread.runAfter(() -> { log.error("Timeout reached. TradeID={}, state={}", trade.getId(), trade.stateProperty().get()); trade.setErrorMessage("A timeout occurred."); - cleanupTradableOnFault(); + cleanupTradeOnFault(); cleanup(); }, TIMEOUT); } @@ -340,7 +339,7 @@ protected void handleTaskRunnerFault(@Nullable TradeMessage tradeMessage, String sendAckMessage(tradeMessage, false, errorMessage); - cleanupTradableOnFault(); + cleanupTradeOnFault(); cleanup(); } @@ -396,8 +395,8 @@ public void onFault(String errorMessage) { ); } - private void cleanupTradableOnFault() { - final Trade.State state = trade.getState(); + private void cleanupTradeOnFault() { + Trade.State state = trade.getState(); log.warn("cleanupTradableOnFault tradeState={}", state); TradeManager tradeManager = processModel.getTradeManager(); if (trade.isInPreparation()) { @@ -405,10 +404,11 @@ private void cleanupTradableOnFault() { tradeManager.removePreparedTrade(trade); } else if (!trade.isFundsLockedIn()) { if (processModel.getPreparedDepositTx() == null) { - if (trade.isTakerFeePublished()) + if (trade.isTakerFeePublished()) { tradeManager.addTradeToFailedTrades(trade); - else + } else { tradeManager.addTradeToClosedTrades(trade); + } } else { log.error("We have already sent the prepared deposit tx to the peer but we did not received the reply " + "about the deposit tx nor saw it in the network. tradeId={}, tradeState={}", trade.getId(), trade.getState()); From 33c816acf645a3e49fc367d7e7435fc5d4535bae Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 21 Sep 2020 23:41:24 -0500 Subject: [PATCH 031/143] Move SellerPublishesDepositTx after SellerSendsDepositTxAndDelayedPayoutTxMessage This should help to avoid that the buyer does not get the delayed payout tx. If a timeout at deposit tx broadcast would prevent that it get out, the peer has at least both transactions. The timeout could be Bisq internal but the tx gets in reality published. With the previous code we would get interrupted at SellerPublishesDepositTx and then the SellerSendsDepositTxAndDelayedPayoutTxMessage would never get executed. --- .../java/bisq/core/trade/protocol/SellerAsMakerProtocol.java | 2 +- .../java/bisq/core/trade/protocol/SellerAsTakerProtocol.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index 78f96b21141..df962b6fccc 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -160,8 +160,8 @@ private void handle(DelayedPayoutTxSignatureResponse tradeMessage, NodeAddress s SellerProcessDelayedPayoutTxSignatureResponse.class, SellerSignsDelayedPayoutTx.class, SellerFinalizesDelayedPayoutTx.class, - SellerPublishesDepositTx.class, SellerSendsDepositTxAndDelayedPayoutTxMessage.class, + SellerPublishesDepositTx.class, PublishTradeStatistics.class ); taskRunner.run(); diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 3b900a779b8..36d3096085a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -159,8 +159,8 @@ private void handle(DelayedPayoutTxSignatureResponse tradeMessage, NodeAddress s SellerProcessDelayedPayoutTxSignatureResponse.class, SellerSignsDelayedPayoutTx.class, SellerFinalizesDelayedPayoutTx.class, - SellerPublishesDepositTx.class, SellerSendsDepositTxAndDelayedPayoutTxMessage.class, + SellerPublishesDepositTx.class, PublishTradeStatistics.class ); taskRunner.run(); From 527f1537a9e9525fcdc92b2931e5bd64f8965669 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Tue, 22 Sep 2020 00:32:28 -0500 Subject: [PATCH 032/143] Add listener on BuyerSendCounterCurrencyTransferStartedMessage to resend msg case it has not arrived Add signed witness to PayoutTxPublishedMessage Remove usage of RefreshTradeStateRequest but leave it for backward compatibility Move removeMailboxMessageAfterProcessing calls in finally branch Rename methods --- .../account/sign/SignedWitnessService.java | 45 +++--- .../witness/AccountAgeWitnessService.java | 60 +------- .../java/bisq/core/trade/TradeManager.java | 3 - .../messages/PayoutTxPublishedMessage.java | 43 ++++-- .../messages/RefreshTradeStateRequest.java | 24 +-- .../trade/protocol/BuyerAsMakerProtocol.java | 35 ++--- .../trade/protocol/BuyerAsTakerProtocol.java | 35 ++--- .../core/trade/protocol/TradeProtocol.java | 14 -- ...ssPeerPublishedDelayedPayoutTxMessage.java | 3 +- .../tasks/SendMailboxMessageTask.java | 92 +++++++++++ .../tasks/SendPayoutTxPublishedMessage.java | 97 ------------ ...essDepositTxAndDelayedPayoutTxMessage.java | 4 +- .../BuyerProcessPayoutTxPublishedMessage.java | 13 +- ...CounterCurrencyTransferStartedMessage.java | 145 +++++++++++------- ...ProcessMediatedPayoutSignatureMessage.java | 3 +- ...ocessMediatedPayoutTxPublishedMessage.java | 3 +- .../SendMediatedPayoutTxPublishedMessage.java | 10 +- ...CounterCurrencyTransferStartedMessage.java | 4 +- .../SellerSendPayoutTxPublishedMessage.java | 35 ++++- .../sign/SignedWitnessServiceTest.java | 4 +- .../witness/AccountAgeWitnessServiceTest.java | 2 +- .../fiataccounts/FiatAccountsDataModel.java | 2 +- .../pendingtrades/PendingTradesDataModel.java | 41 ----- .../pendingtrades/PendingTradesView.java | 2 - .../steps/seller/SellerStep2View.java | 60 -------- proto/src/main/proto/pb.proto | 19 ++- 26 files changed, 355 insertions(+), 443 deletions(-) create mode 100644 core/src/main/java/bisq/core/trade/protocol/tasks/SendMailboxMessageTask.java delete mode 100644 core/src/main/java/bisq/core/trade/protocol/tasks/SendPayoutTxPublishedMessage.java diff --git a/core/src/main/java/bisq/core/account/sign/SignedWitnessService.java b/core/src/main/java/bisq/core/account/sign/SignedWitnessService.java index e27bf2493cd..788c369eed6 100644 --- a/core/src/main/java/bisq/core/account/sign/SignedWitnessService.java +++ b/core/src/main/java/bisq/core/account/sign/SignedWitnessService.java @@ -216,20 +216,20 @@ public boolean publishOwnSignedWitness(SignedWitness signedWitness) { } // Arbitrators sign with EC key - public void signAccountAgeWitness(Coin tradeAmount, - AccountAgeWitness accountAgeWitness, - ECKey key, - PublicKey peersPubKey) { - signAccountAgeWitness(tradeAmount, accountAgeWitness, key, peersPubKey.getEncoded(), new Date().getTime()); + public void signAndPublishAccountAgeWitness(Coin tradeAmount, + AccountAgeWitness accountAgeWitness, + ECKey key, + PublicKey peersPubKey) { + signAndPublishAccountAgeWitness(tradeAmount, accountAgeWitness, key, peersPubKey.getEncoded(), new Date().getTime()); } // Arbitrators sign with EC key - public String signAccountAgeWitness(AccountAgeWitness accountAgeWitness, - ECKey key, - byte[] peersPubKey, - long time) { + public String signAndPublishAccountAgeWitness(AccountAgeWitness accountAgeWitness, + ECKey key, + byte[] peersPubKey, + long time) { var witnessPubKey = peersPubKey == null ? ownerPubKey(accountAgeWitness) : peersPubKey; - return signAccountAgeWitness(MINIMUM_TRADE_AMOUNT_FOR_SIGNING, accountAgeWitness, key, witnessPubKey, time); + return signAndPublishAccountAgeWitness(MINIMUM_TRADE_AMOUNT_FOR_SIGNING, accountAgeWitness, key, witnessPubKey, time); } // Arbitrators sign with EC key @@ -238,15 +238,15 @@ public String signTraderPubKey(ECKey key, long childSignTime) { var time = childSignTime - SIGNER_AGE - 1; var dummyAccountAgeWitness = new AccountAgeWitness(Hash.getRipemd160hash(peersPubKey), time); - return signAccountAgeWitness(MINIMUM_TRADE_AMOUNT_FOR_SIGNING, dummyAccountAgeWitness, key, peersPubKey, time); + return signAndPublishAccountAgeWitness(MINIMUM_TRADE_AMOUNT_FOR_SIGNING, dummyAccountAgeWitness, key, peersPubKey, time); } // Arbitrators sign with EC key - private String signAccountAgeWitness(Coin tradeAmount, - AccountAgeWitness accountAgeWitness, - ECKey key, - byte[] peersPubKey, - long time) { + private String signAndPublishAccountAgeWitness(Coin tradeAmount, + AccountAgeWitness accountAgeWitness, + ECKey key, + byte[] peersPubKey, + long time) { if (isSignedAccountAgeWitness(accountAgeWitness)) { var err = "Arbitrator trying to sign already signed accountagewitness " + accountAgeWitness.toString(); log.warn(err); @@ -272,16 +272,16 @@ private String signAccountAgeWitness(Coin tradeAmount, return ""; } - public void selfSignAccountAgeWitness(AccountAgeWitness accountAgeWitness) throws CryptoException { + public void selfSignAndPublishAccountAgeWitness(AccountAgeWitness accountAgeWitness) throws CryptoException { log.info("Sign own accountAgeWitness {}", accountAgeWitness); - signAccountAgeWitness(MINIMUM_TRADE_AMOUNT_FOR_SIGNING, accountAgeWitness, + signAndPublishAccountAgeWitness(MINIMUM_TRADE_AMOUNT_FOR_SIGNING, accountAgeWitness, keyRing.getSignatureKeyPair().getPublic()); } // Any peer can sign with DSA key - public Optional signAccountAgeWitness(Coin tradeAmount, - AccountAgeWitness accountAgeWitness, - PublicKey peersPubKey) throws CryptoException { + public Optional signAndPublishAccountAgeWitness(Coin tradeAmount, + AccountAgeWitness accountAgeWitness, + PublicKey peersPubKey) throws CryptoException { if (isSignedAccountAgeWitness(accountAgeWitness)) { log.warn("Trader trying to sign already signed accountagewitness {}", accountAgeWitness.toString()); return Optional.empty(); @@ -494,7 +494,8 @@ void addToMap(SignedWitness signedWitness) { private void publishSignedWitness(SignedWitness signedWitness) { if (!signedWitnessMap.containsKey(signedWitness.getHashAsByteArray())) { log.info("broadcast signed witness {}", signedWitness.toString()); - p2PService.addPersistableNetworkPayload(signedWitness, false); + // We set reBroadcast to true to achieve better resilience. + p2PService.addPersistableNetworkPayload(signedWitness, true); addToMap(signedWitness); } } diff --git a/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java index c5264fc4eda..ab8ad18e179 100644 --- a/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java +++ b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java @@ -35,14 +35,11 @@ import bisq.core.support.dispute.arbitration.TraderDataItem; import bisq.core.trade.Contract; import bisq.core.trade.Trade; -import bisq.core.trade.messages.TraderSignedWitnessMessage; import bisq.core.trade.protocol.TradingPeer; import bisq.core.user.User; import bisq.network.p2p.BootstrapListener; -import bisq.network.p2p.NodeAddress; import bisq.network.p2p.P2PService; -import bisq.network.p2p.SendMailboxMessageListener; import bisq.network.p2p.storage.P2PDataStorage; import bisq.network.p2p.storage.persistence.AppendOnlyDataStoreService; @@ -76,7 +73,6 @@ import java.util.Optional; import java.util.Random; import java.util.Set; -import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -202,7 +198,7 @@ public void onUpdatedDataReceived() { private void onBootStrapped() { republishAllFiatAccounts(); - signSameNameAccounts(); + signAndPublishSameNameAccounts(); } @@ -643,7 +639,7 @@ public void arbitratorSignAccountAgeWitness(Coin tradeAmount, AccountAgeWitness accountAgeWitness, ECKey key, PublicKey peersPubKey) { - signedWitnessService.signAccountAgeWitness(tradeAmount, accountAgeWitness, key, peersPubKey); + signedWitnessService.signAndPublishAccountAgeWitness(tradeAmount, accountAgeWitness, key, peersPubKey); } public String arbitratorSignOrphanWitness(AccountAgeWitness accountAgeWitness, @@ -655,7 +651,7 @@ public String arbitratorSignOrphanWitness(AccountAgeWitness accountAgeWitness, .findAny() .orElse(null); checkNotNull(signedWitness); - return signedWitnessService.signAccountAgeWitness(accountAgeWitness, key, signedWitness.getWitnessOwnerPubKey(), + return signedWitnessService.signAndPublishAccountAgeWitness(accountAgeWitness, key, signedWitness.getWitnessOwnerPubKey(), time); } @@ -669,10 +665,10 @@ public void arbitratorSignAccountAgeWitness(AccountAgeWitness accountAgeWitness, ECKey key, byte[] tradersPubKey, long time) { - signedWitnessService.signAccountAgeWitness(accountAgeWitness, key, tradersPubKey, time); + signedWitnessService.signAndPublishAccountAgeWitness(accountAgeWitness, key, tradersPubKey, time); } - public Optional traderSignPeersAccountAgeWitness(Trade trade) { + public Optional traderSignAndPublishPeersAccountAgeWitness(Trade trade) { AccountAgeWitness peersWitness = findTradePeerWitness(trade).orElse(null); Coin tradeAmount = trade.getTradeAmount(); checkNotNull(trade.getProcessModel().getTradingPeer().getPubKeyRing(), "Peer must have a keyring"); @@ -682,7 +678,7 @@ public Optional traderSignPeersAccountAgeWitness(Trade trade) { checkNotNull(peersPubKey, "Peers pub key must not be null"); try { - return signedWitnessService.signAccountAgeWitness(tradeAmount, peersWitness, peersPubKey); + return signedWitnessService.signAndPublishAccountAgeWitness(tradeAmount, peersWitness, peersPubKey); } catch (CryptoException e) { log.warn("Trader failed to sign witness, exception {}", e.toString()); } @@ -827,7 +823,7 @@ public Set getOrphanSignedWitnesses() { .collect(Collectors.toSet()); } - public void signSameNameAccounts() { + public void signAndPublishSameNameAccounts() { // Collect accounts that have ownerId to sign unsigned accounts with the same ownderId var signerAccounts = Objects.requireNonNull(user.getPaymentAccounts()).stream() .filter(account -> account.getOwnerId() != null && @@ -842,7 +838,7 @@ public void signSameNameAccounts() { signerAccounts.forEach(signer -> unsignedAccounts.forEach(unsigned -> { if (signer.getOwnerId().equals(unsigned.getOwnerId())) { try { - signedWitnessService.selfSignAccountAgeWitness( + signedWitnessService.selfSignAndPublishAccountAgeWitness( getMyWitness(unsigned.getPaymentAccountPayload())); } catch (CryptoException e) { log.warn("Self signing failed, exception {}", e.toString()); @@ -868,44 +864,4 @@ public boolean isSignWitnessTrade(Trade trade) { !peerHasSignedWitness(trade) && tradeAmountIsSufficient(trade.getTradeAmount()); } - - public void maybeSignWitness(Trade trade) { - if (isSignWitnessTrade(trade)) { - var signedWitnessOptional = traderSignPeersAccountAgeWitness(trade); - signedWitnessOptional.ifPresent(signedWitness -> sendSignedWitnessToPeer(signedWitness, trade)); - } - } - - private void sendSignedWitnessToPeer(SignedWitness signedWitness, Trade trade) { - if (trade == null) return; - - NodeAddress tradingPeerNodeAddress = trade.getTradingPeerNodeAddress(); - var traderSignedWitnessMessage = new TraderSignedWitnessMessage(UUID.randomUUID().toString(), trade.getId(), - tradingPeerNodeAddress, signedWitness); - - p2PService.sendEncryptedMailboxMessage( - tradingPeerNodeAddress, - trade.getProcessModel().getTradingPeer().getPubKeyRing(), - traderSignedWitnessMessage, - new SendMailboxMessageListener() { - @Override - public void onArrived() { - log.info("SendMailboxMessageListener onArrived tradeId={} at peer {} SignedWitness {}", - trade.getId(), tradingPeerNodeAddress, signedWitness); - } - - @Override - public void onStoredInMailbox() { - log.info("SendMailboxMessageListener onStoredInMailbox tradeId={} at peer {} SignedWitness {}", - trade.getId(), tradingPeerNodeAddress, signedWitness); - } - - @Override - public void onFault(String errorMessage) { - log.error("SendMailboxMessageListener onFault tradeId={} at peer {} SignedWitness {}", - trade.getId(), tradingPeerNodeAddress, signedWitness); - } - } - ); - } } diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 817dcfe0b86..018b1200ac0 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -350,9 +350,6 @@ public void onUserConfirmedFiatPaymentReceived(SellerTrade sellerTrade, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { sellerTrade.onFiatPaymentReceived(resultHandler, errorMessageHandler); - - //TODO move to trade protocol task - accountAgeWitnessService.maybeSignWitness(sellerTrade); } private void initPendingTrade(Trade trade) { 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 cae6469c1ea..6b6f38f9c1d 100644 --- a/core/src/main/java/bisq/core/trade/messages/PayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/messages/PayoutTxPublishedMessage.java @@ -17,6 +17,8 @@ package bisq.core.trade.messages; +import bisq.core.account.sign.SignedWitness; + import bisq.network.p2p.MailboxMessage; import bisq.network.p2p.NodeAddress; @@ -26,23 +28,35 @@ import com.google.protobuf.ByteString; +import java.util.Optional; +import java.util.UUID; + import lombok.EqualsAndHashCode; import lombok.Value; +import lombok.extern.slf4j.Slf4j; +import javax.annotation.Nullable; + +@Slf4j @EqualsAndHashCode(callSuper = true) @Value public final class PayoutTxPublishedMessage extends TradeMessage implements MailboxMessage { private final byte[] payoutTx; private final NodeAddress senderNodeAddress; + // Added in v1.4.0 + @Nullable + private final SignedWitness signedWitness; + public PayoutTxPublishedMessage(String tradeId, byte[] payoutTx, NodeAddress senderNodeAddress, - String uid) { + @Nullable SignedWitness signedWitness) { this(tradeId, payoutTx, senderNodeAddress, - uid, + signedWitness, + UUID.randomUUID().toString(), Version.getP2PMessageVersion()); } @@ -54,28 +68,37 @@ public PayoutTxPublishedMessage(String tradeId, private PayoutTxPublishedMessage(String tradeId, byte[] payoutTx, NodeAddress senderNodeAddress, + @Nullable SignedWitness signedWitness, String uid, int messageVersion) { super(messageVersion, tradeId, uid); this.payoutTx = payoutTx; this.senderNodeAddress = senderNodeAddress; + this.signedWitness = signedWitness; } @Override public protobuf.NetworkEnvelope toProtoNetworkEnvelope() { - return getNetworkEnvelopeBuilder() - .setPayoutTxPublishedMessage(protobuf.PayoutTxPublishedMessage.newBuilder() - .setTradeId(tradeId) - .setPayoutTx(ByteString.copyFrom(payoutTx)) - .setSenderNodeAddress(senderNodeAddress.toProtoMessage()) - .setUid(uid)) - .build(); + protobuf.PayoutTxPublishedMessage.Builder builder = protobuf.PayoutTxPublishedMessage.newBuilder() + .setTradeId(tradeId) + .setPayoutTx(ByteString.copyFrom(payoutTx)) + .setSenderNodeAddress(senderNodeAddress.toProtoMessage()) + .setUid(uid); + Optional.ofNullable(signedWitness).ifPresent(signedWitness -> builder.setSignedWitness(signedWitness.toProtoSignedWitness())); + return getNetworkEnvelopeBuilder().setPayoutTxPublishedMessage(builder).build(); } public static NetworkEnvelope fromProto(protobuf.PayoutTxPublishedMessage proto, int messageVersion) { + // There is no method to check for a nullable non-primitive data type object but we know that all fields + // are empty/null, so we check for the signature to see if we got a valid signedWitness. + protobuf.SignedWitness protoSignedWitness = proto.getSignedWitness(); + SignedWitness signedWitness = !protoSignedWitness.getSignature().isEmpty() ? + SignedWitness.fromProto(protoSignedWitness) : + null; return new PayoutTxPublishedMessage(proto.getTradeId(), proto.getPayoutTx().toByteArray(), NodeAddress.fromProto(proto.getSenderNodeAddress()), + signedWitness, proto.getUid(), messageVersion); } @@ -85,7 +108,7 @@ public String toString() { return "PayoutTxPublishedMessage{" + "\n payoutTx=" + Utilities.bytesAsHexString(payoutTx) + ",\n senderNodeAddress=" + senderNodeAddress + - ",\n uid='" + uid + '\'' + + ",\n signedWitness=" + signedWitness + "\n} " + super.toString(); } } diff --git a/core/src/main/java/bisq/core/trade/messages/RefreshTradeStateRequest.java b/core/src/main/java/bisq/core/trade/messages/RefreshTradeStateRequest.java index 907af09a652..ff5c82362ed 100644 --- a/core/src/main/java/bisq/core/trade/messages/RefreshTradeStateRequest.java +++ b/core/src/main/java/bisq/core/trade/messages/RefreshTradeStateRequest.java @@ -20,25 +20,19 @@ import bisq.network.p2p.MailboxMessage; import bisq.network.p2p.NodeAddress; -import bisq.common.app.Version; - import lombok.EqualsAndHashCode; import lombok.Value; +/** + * Not used anymore since v1.4.0 + * We do the re-sending of the payment sent message via the BuyerSendCounterCurrencyTransferStartedMessage task on the + * buyer side, so seller do not need to do anything interactively. + */ @EqualsAndHashCode(callSuper = true) @Value public class RefreshTradeStateRequest extends TradeMessage implements MailboxMessage { private final NodeAddress senderNodeAddress; - public RefreshTradeStateRequest(String uid, - String tradeId, - NodeAddress senderNodeAddress) { - this(Version.getP2PMessageVersion(), - uid, - tradeId, - senderNodeAddress); - } - /////////////////////////////////////////////////////////////////////////////////////////// // PROTO BUFFER @@ -67,12 +61,4 @@ public static RefreshTradeStateRequest fromProto(protobuf.RefreshTradeStateReque proto.getTradeId(), NodeAddress.fromProto(proto.getSenderNodeAddress())); } - - @Override - public String toString() { - return "RefreshTradeStateRequest{" + - "\n senderNodeAddress=" + senderNodeAddress + - "\n} " + super.toString(); - } - } diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 6803fe2d977..515572eff30 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -23,7 +23,6 @@ import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage; import bisq.core.trade.messages.InputsForDepositTxRequest; import bisq.core.trade.messages.PayoutTxPublishedMessage; -import bisq.core.trade.messages.RefreshTradeStateRequest; import bisq.core.trade.messages.TradeMessage; import bisq.core.trade.protocol.tasks.ApplyFilter; import bisq.core.trade.protocol.tasks.PublishTradeStatistics; @@ -87,6 +86,19 @@ public BuyerAsMakerProtocol(BuyerAsMakerTrade trade) { taskRunner.addTasks(BuyerSetupPayoutTxListener.class); taskRunner.run(); } + + // We might have 2 taskRunners as BuyerSetupPayoutTxListener might have been started as well + if (trade.getState() == Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG || + trade.getState() == Trade.State.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG) { + // In case we have not received an ACK from the CounterCurrencyTransferStartedMessage we re-send it + // periodically in BuyerSendCounterCurrencyTransferStartedMessage + TradeTaskRunner taskRunner = new TradeTaskRunner(trade, + () -> handleTaskRunnerSuccess("BuyerSendCounterCurrencyTransferStartedMessage"), + this::handleTaskRunnerFault); + + taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class); + taskRunner.run(); + } } @@ -102,8 +114,6 @@ public void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress pe handle((DepositTxAndDelayedPayoutTxMessage) tradeMessage, peerNodeAddress); } else if (tradeMessage instanceof PayoutTxPublishedMessage) { handle((PayoutTxPublishedMessage) tradeMessage, peerNodeAddress); - } else if (tradeMessage instanceof RefreshTradeStateRequest) { - handle(); } } @@ -234,23 +244,6 @@ private void handle(PayoutTxPublishedMessage tradeMessage, NodeAddress peerNodeA } - /////////////////////////////////////////////////////////////////////////////////////////// - // Incoming message Handle missing messages - /////////////////////////////////////////////////////////////////////////////////////////// - - private void handle() { - // Resend CounterCurrencyTransferStartedMessage if it hasn't been acked yet and counterparty asked for a refresh - if (trade.getState().getPhase() == Trade.Phase.FIAT_SENT && - trade.getState().ordinal() >= Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG.ordinal()) { - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, - () -> handleTaskRunnerSuccess("RefreshTradeStateRequest"), - this::handleTaskRunnerFault); - taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class); - taskRunner.run(); - } - } - - /////////////////////////////////////////////////////////////////////////////////////////// // Message dispatcher /////////////////////////////////////////////////////////////////////////////////////////// @@ -268,8 +261,6 @@ protected void doHandleDecryptedMessage(TradeMessage tradeMessage, NodeAddress s handle((DepositTxAndDelayedPayoutTxMessage) tradeMessage, sender); } else if (tradeMessage instanceof PayoutTxPublishedMessage) { handle((PayoutTxPublishedMessage) tradeMessage, sender); - } else if (tradeMessage instanceof RefreshTradeStateRequest) { - handle(); } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 9698953624b..4073167d13e 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -25,7 +25,6 @@ import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage; import bisq.core.trade.messages.InputsForDepositTxResponse; import bisq.core.trade.messages.PayoutTxPublishedMessage; -import bisq.core.trade.messages.RefreshTradeStateRequest; import bisq.core.trade.messages.TradeMessage; import bisq.core.trade.protocol.tasks.ApplyFilter; import bisq.core.trade.protocol.tasks.PublishTradeStatistics; @@ -95,6 +94,19 @@ public BuyerAsTakerProtocol(BuyerAsTakerTrade trade) { taskRunner.addTasks(BuyerSetupPayoutTxListener.class); taskRunner.run(); } + + // We might have 2 taskRunners as BuyerSetupPayoutTxListener might have been started as well + if (trade.getState() == Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG || + trade.getState() == Trade.State.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG) { + // In case we have not received an ACK from the CounterCurrencyTransferStartedMessage we re-send it + // periodically in BuyerSendCounterCurrencyTransferStartedMessage + TradeTaskRunner taskRunner = new TradeTaskRunner(trade, + () -> handleTaskRunnerSuccess("BuyerSendCounterCurrencyTransferStartedMessage"), + this::handleTaskRunnerFault); + + taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class); + taskRunner.run(); + } } @@ -110,8 +122,6 @@ public void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress pe handle((DepositTxAndDelayedPayoutTxMessage) tradeMessage, peerNodeAddress); } else if (tradeMessage instanceof PayoutTxPublishedMessage) { handle((PayoutTxPublishedMessage) tradeMessage, peerNodeAddress); - } else if (tradeMessage instanceof RefreshTradeStateRequest) { - handle(); } } @@ -264,23 +274,6 @@ private void handle(PayoutTxPublishedMessage tradeMessage, NodeAddress peerNodeA } - /////////////////////////////////////////////////////////////////////////////////////////// - // Incoming message Handle missing messages - /////////////////////////////////////////////////////////////////////////////////////////// - - private void handle() { - // Resend CounterCurrencyTransferStartedMessage if it hasn't been acked yet and counterparty asked for a refresh - if (trade.getState().getPhase() == Trade.Phase.FIAT_SENT && - trade.getState().ordinal() >= Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG.ordinal()) { - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> handleTaskRunnerSuccess("RefreshTradeStateRequest"), - this::handleTaskRunnerFault); - taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class); - taskRunner.run(); - } - } - - /////////////////////////////////////////////////////////////////////////////////////////// // Message dispatcher /////////////////////////////////////////////////////////////////////////////////////////// @@ -300,8 +293,6 @@ protected void doHandleDecryptedMessage(TradeMessage tradeMessage, NodeAddress s handle((DepositTxAndDelayedPayoutTxMessage) tradeMessage, sender); } else if (tradeMessage instanceof PayoutTxPublishedMessage) { handle((PayoutTxPublishedMessage) tradeMessage, sender); - } else if (tradeMessage instanceof RefreshTradeStateRequest) { - handle(); } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index be41e046f83..aafb8303d9f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -25,7 +25,6 @@ import bisq.core.trade.messages.MediatedPayoutTxSignatureMessage; import bisq.core.trade.messages.PeerPublishedDelayedPayoutTxMessage; import bisq.core.trade.messages.TradeMessage; -import bisq.core.trade.messages.TraderSignedWitnessMessage; import bisq.core.trade.protocol.tasks.ApplyFilter; import bisq.core.trade.protocol.tasks.ProcessPeerPublishedDelayedPayoutTxMessage; import bisq.core.trade.protocol.tasks.mediation.BroadcastMediatedPayoutTx; @@ -227,15 +226,6 @@ private void handle(PeerPublishedDelayedPayoutTxMessage tradeMessage, NodeAddres taskRunner.run(); } - /////////////////////////////////////////////////////////////////////////////////////////// - // Peer has sent a SignedWitness - /////////////////////////////////////////////////////////////////////////////////////////// - - private void handle(TraderSignedWitnessMessage tradeMessage) { - // Publish signed witness, if it is valid and ours - processModel.getAccountAgeWitnessService().publishOwnSignedWitness(tradeMessage.getSignedWitness()); - } - /////////////////////////////////////////////////////////////////////////////////////////// // Dispatcher @@ -248,8 +238,6 @@ protected void doHandleDecryptedMessage(TradeMessage tradeMessage, NodeAddress s handle((MediatedPayoutTxPublishedMessage) tradeMessage, sender); } else if (tradeMessage instanceof PeerPublishedDelayedPayoutTxMessage) { handle((PeerPublishedDelayedPayoutTxMessage) tradeMessage, sender); - } else if (tradeMessage instanceof TraderSignedWitnessMessage) { - handle((TraderSignedWitnessMessage) tradeMessage); } } @@ -297,8 +285,6 @@ protected void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress handle((MediatedPayoutTxPublishedMessage) tradeMessage, peerNodeAddress); } else if (tradeMessage instanceof PeerPublishedDelayedPayoutTxMessage) { handle((PeerPublishedDelayedPayoutTxMessage) tradeMessage, peerNodeAddress); - } else if (tradeMessage instanceof TraderSignedWitnessMessage) { - handle((TraderSignedWitnessMessage) tradeMessage); } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessPeerPublishedDelayedPayoutTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessPeerPublishedDelayedPayoutTxMessage.java index c4aae4dd382..385e8638507 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessPeerPublishedDelayedPayoutTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessPeerPublishedDelayedPayoutTxMessage.java @@ -47,7 +47,6 @@ protected void run() { // update to the latest peer address of our peer if the message is correct trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress()); - processModel.removeMailboxMessageAfterProcessing(trade); // We add the tx to our wallet. Transaction delayedPayoutTx = checkNotNull(trade.getDelayedPayoutTx()); @@ -58,6 +57,8 @@ protected void run() { complete(); } catch (Throwable t) { failed(t); + } finally { + processModel.removeMailboxMessageAfterProcessing(trade); } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/SendMailboxMessageTask.java b/core/src/main/java/bisq/core/trade/protocol/tasks/SendMailboxMessageTask.java new file mode 100644 index 00000000000..29aeb0d5cf3 --- /dev/null +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/SendMailboxMessageTask.java @@ -0,0 +1,92 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.trade.protocol.tasks; + +import bisq.core.trade.Trade; +import bisq.core.trade.messages.TradeMessage; + +import bisq.network.p2p.NodeAddress; +import bisq.network.p2p.SendMailboxMessageListener; + +import bisq.common.taskrunner.TaskRunner; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public abstract class SendMailboxMessageTask extends TradeTask { + public SendMailboxMessageTask(TaskRunner taskHandler, Trade trade) { + super(taskHandler, trade); + } + + protected abstract TradeMessage getMessage(String id); + + protected abstract void setStateSent(); + + protected abstract void setStateArrived(); + + protected abstract void setStateStoredInMailbox(); + + protected abstract void setStateFault(); + + @Override + protected void run() { + try { + runInterceptHook(); + String id = processModel.getOfferId(); + TradeMessage message = getMessage(id); + setStateSent(); + NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress(); + log.info("Send {} to peer {}. tradeId={}, uid={}", + message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); + + processModel.getP2PService().sendEncryptedMailboxMessage( + peersNodeAddress, + processModel.getTradingPeer().getPubKeyRing(), + message, + new SendMailboxMessageListener() { + @Override + public void onArrived() { + log.info("{} arrived at peer {}. tradeId={}, uid={}", + message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); + setStateArrived(); + complete(); + } + + @Override + public void onStoredInMailbox() { + log.info("{} stored in mailbox for peer {}. tradeId={}, uid={}", + message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); + setStateStoredInMailbox(); + complete(); + } + + @Override + public void onFault(String errorMessage) { + log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}", + message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage); + setStateFault(); + appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage); + failed(errorMessage); + } + } + ); + } catch (Throwable t) { + failed(t); + } + } +} diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/SendPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/SendPayoutTxPublishedMessage.java deleted file mode 100644 index ea85430c9a5..00000000000 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/SendPayoutTxPublishedMessage.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.core.trade.protocol.tasks; - -import bisq.core.trade.Trade; -import bisq.core.trade.messages.TradeMessage; - -import bisq.network.p2p.NodeAddress; -import bisq.network.p2p.SendMailboxMessageListener; - -import bisq.common.taskrunner.TaskRunner; - -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public abstract class SendPayoutTxPublishedMessage extends TradeTask { - public SendPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) { - super(taskHandler, trade); - } - - protected abstract TradeMessage getMessage(String id); - - protected abstract void setStateSent(); - - protected abstract void setStateArrived(); - - protected abstract void setStateStoredInMailbox(); - - protected abstract void setStateFault(); - - @Override - protected void run() { - try { - runInterceptHook(); - if (trade.getPayoutTx() != null) { - String id = processModel.getOfferId(); - TradeMessage message = getMessage(id); - setStateSent(); - NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress(); - log.info("Send {} to peer {}. tradeId={}, uid={}", - message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); - - processModel.getP2PService().sendEncryptedMailboxMessage( - peersNodeAddress, - processModel.getTradingPeer().getPubKeyRing(), - message, - new SendMailboxMessageListener() { - @Override - public void onArrived() { - log.info("{} arrived at peer {}. tradeId={}, uid={}", - message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); - setStateArrived(); - complete(); - } - - @Override - public void onStoredInMailbox() { - log.info("{} stored in mailbox for peer {}. tradeId={}, uid={}", - message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); - setStateStoredInMailbox(); - complete(); - } - - @Override - public void onFault(String errorMessage) { - log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}", - message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage); - setStateFault(); - appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage); - failed(errorMessage); - } - } - ); - } else { - log.error("trade.getPayoutTx() = " + trade.getPayoutTx()); - failed("PayoutTx is null"); - } - } catch (Throwable t) { - failed(t); - } - } -} diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java index 60ac8048016..09683d9d998 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java @@ -65,8 +65,6 @@ protected void run() { trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress()); - processModel.removeMailboxMessageAfterProcessing(trade); - // If we got already the confirmation we don't want to apply an earlier state if (trade.getState().ordinal() < Trade.State.BUYER_SAW_DEPOSIT_TX_IN_NETWORK.ordinal()) { trade.setState(Trade.State.BUYER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG); @@ -78,6 +76,8 @@ protected void run() { complete(); } catch (Throwable t) { failed(t); + } finally { + processModel.removeMailboxMessageAfterProcessing(trade); } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessPayoutTxPublishedMessage.java index ebcf85eaa26..f82bb916be4 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessPayoutTxPublishedMessage.java @@ -17,6 +17,7 @@ package bisq.core.trade.protocol.tasks.buyer; +import bisq.core.account.sign.SignedWitness; import bisq.core.btc.model.AddressEntry; import bisq.core.btc.wallet.BtcWalletService; import bisq.core.btc.wallet.WalletService; @@ -63,10 +64,20 @@ protected void run() { } else { log.info("We got the payout tx already set from BuyerSetupPayoutTxListener and do nothing here. trade ID={}", trade.getId()); } - processModel.removeMailboxMessageAfterProcessing(trade); + + SignedWitness signedWitness = message.getSignedWitness(); + if (signedWitness != null) { + // We received the signedWitness from the seller and publish the data to the network. + // The signer has published it as well but we prefer to re-do it on our side as well to achieve higher + // resilience. + processModel.getAccountAgeWitnessService().publishOwnSignedWitness(signedWitness); + } + complete(); } catch (Throwable t) { failed(t); + } finally { + processModel.removeMailboxMessageAfterProcessing(trade); } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java index 2804eb25ed3..922e0829b5c 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java @@ -18,81 +18,122 @@ package bisq.core.trade.protocol.tasks.buyer; import bisq.core.btc.model.AddressEntry; -import bisq.core.btc.wallet.BtcWalletService; +import bisq.core.network.MessageState; +import bisq.core.payment.payload.PaymentMethod; import bisq.core.trade.Trade; import bisq.core.trade.messages.CounterCurrencyTransferStartedMessage; -import bisq.core.trade.protocol.tasks.TradeTask; - -import bisq.network.p2p.NodeAddress; -import bisq.network.p2p.SendMailboxMessageListener; +import bisq.core.trade.messages.TradeMessage; +import bisq.core.trade.protocol.tasks.SendMailboxMessageTask; +import bisq.common.Timer; +import bisq.common.UserThread; import bisq.common.taskrunner.TaskRunner; -import java.util.UUID; +import javafx.beans.value.ChangeListener; + +import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; +import static com.google.common.base.Preconditions.checkNotNull; + @Slf4j -public class BuyerSendCounterCurrencyTransferStartedMessage extends TradeTask { +public class BuyerSendCounterCurrencyTransferStartedMessage extends SendMailboxMessageTask { + private static final long MAX_REFRESH_INTERVAL = TimeUnit.HOURS.toMillis(4); + + private ChangeListener listener; + private Timer timer; + private CounterCurrencyTransferStartedMessage counterCurrencyTransferStartedMessage; + public BuyerSendCounterCurrencyTransferStartedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } @Override - protected void run() { - try { - runInterceptHook(); - - BtcWalletService walletService = processModel.getBtcWalletService(); - final String id = processModel.getOfferId(); - AddressEntry payoutAddressEntry = walletService.getOrCreateAddressEntry(id, + protected TradeMessage getMessage(String tradeId) { + if (counterCurrencyTransferStartedMessage == null) { + AddressEntry payoutAddressEntry = processModel.getBtcWalletService().getOrCreateAddressEntry(tradeId, AddressEntry.Context.TRADE_PAYOUT); - final CounterCurrencyTransferStartedMessage message = new CounterCurrencyTransferStartedMessage( - id, + + // 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 + // 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 = tradeId + processModel.getMyNodeAddress().getFullAddress(); + counterCurrencyTransferStartedMessage = new CounterCurrencyTransferStartedMessage( + tradeId, payoutAddressEntry.getAddressString(), processModel.getMyNodeAddress(), processModel.getPayoutTxSignature(), trade.getCounterCurrencyTxId(), trade.getCounterCurrencyExtraData(), - UUID.randomUUID().toString() - ); - NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress(); - log.info("Send {} to peer {}. tradeId={}, uid={}", - message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); - trade.setState(Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG); - processModel.getP2PService().sendEncryptedMailboxMessage( - peersNodeAddress, - processModel.getTradingPeer().getPubKeyRing(), - message, - new SendMailboxMessageListener() { - @Override - public void onArrived() { - log.info("{} arrived at peer {}. tradeId={}, uid={}", - message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); - trade.setState(Trade.State.BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG); - complete(); - } - - @Override - public void onStoredInMailbox() { - log.info("{} stored in mailbox for peer {}. tradeId={}, uid={}", - message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); - trade.setState(Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG); - complete(); - } - - @Override - public void onFault(String errorMessage) { - log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}", - message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage); - trade.setState(Trade.State.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG); - appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage); - failed(errorMessage); - } - } + deterministicId ); + } + return counterCurrencyTransferStartedMessage; + } + + @Override + protected void setStateSent() { + trade.setState(Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG); + } + + @Override + protected void setStateArrived() { + trade.setState(Trade.State.BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG); + stop(); + } + + @Override + protected void setStateStoredInMailbox() { + trade.setState(Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG); + start(); + } + + @Override + protected void setStateFault() { + trade.setState(Trade.State.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG); + start(); + } + + @Override + protected void run() { + try { + runInterceptHook(); + + super.run(); } catch (Throwable t) { failed(t); } } + + private void stop() { + if (timer != null) { + timer.stop(); + processModel.getPaymentStartedMessageStateProperty().removeListener(listener); + } + } + + // The listeners ensure we don't get GCed even we have completed the task. + private void start() { + if (timer != null) { + return; + } + + PaymentMethod paymentMethod = checkNotNull(trade.getOffer()).getPaymentMethod(); + // For instant trades with 1 hour we want a short interval, otherwise a few hours should be ok. + long interval = Math.min(paymentMethod.getMaxTradePeriod() / 5, MAX_REFRESH_INTERVAL); + timer = UserThread.runPeriodically(this::run, interval, TimeUnit.MILLISECONDS); + + listener = (observable, oldValue, newValue) -> { + // Once we receive an ACK from our msg we know the peer has received the msg and we stop. + if (newValue == MessageState.ACKNOWLEDGED) { + // We treat a ACK like BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG + trade.setState(Trade.State.BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG); + // Ensure listener construction is completed before remove call + UserThread.execute(this::stop); + } + }; + processModel.getPaymentStartedMessageStateProperty().addListener(listener); + } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutSignatureMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutSignatureMessage.java index 3636dbcbfe7..a049d0932d9 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutSignatureMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutSignatureMessage.java @@ -48,13 +48,14 @@ protected void run() { // update to the latest peer address of our peer if the message is correct trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress()); - processModel.removeMailboxMessageAfterProcessing(trade); trade.setMediationResultState(MediationResultState.RECEIVED_SIG_MSG); complete(); } catch (Throwable t) { failed(t); + } finally { + processModel.removeMailboxMessageAfterProcessing(trade); } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutTxPublishedMessage.java index 6f0f5b3d69d..9fdcc4b75c9 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutTxPublishedMessage.java @@ -74,10 +74,11 @@ protected void run() { } else { log.info("We got the payout tx already set from BuyerSetupPayoutTxListener and do nothing here. trade ID={}", trade.getId()); } - processModel.removeMailboxMessageAfterProcessing(trade); complete(); } catch (Throwable t) { failed(t); + } finally { + processModel.removeMailboxMessageAfterProcessing(trade); } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutTxPublishedMessage.java index a67ba017a0d..8cadcbeaece 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/SendMediatedPayoutTxPublishedMessage.java @@ -21,7 +21,7 @@ import bisq.core.trade.Trade; import bisq.core.trade.messages.MediatedPayoutTxPublishedMessage; import bisq.core.trade.messages.TradeMessage; -import bisq.core.trade.protocol.tasks.SendPayoutTxPublishedMessage; +import bisq.core.trade.protocol.tasks.SendMailboxMessageTask; import bisq.common.taskrunner.TaskRunner; @@ -35,7 +35,7 @@ @Slf4j -public class SendMediatedPayoutTxPublishedMessage extends SendPayoutTxPublishedMessage { +public class SendMediatedPayoutTxPublishedMessage extends SendMailboxMessageTask { public SendMediatedPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } @@ -76,6 +76,12 @@ protected void run() { try { runInterceptHook(); + if (trade.getPayoutTx() == null) { + log.error("PayoutTx is null"); + failed("PayoutTx is null"); + return; + } + super.run(); } catch (Throwable t) { failed(t); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessCounterCurrencyTransferStartedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessCounterCurrencyTransferStartedMessage.java index cf1f5112948..d2a12964452 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessCounterCurrencyTransferStartedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessCounterCurrencyTransferStartedMessage.java @@ -59,13 +59,13 @@ protected void run() { trade.setCounterCurrencyExtraData(counterCurrencyExtraData); } - processModel.removeMailboxMessageAfterProcessing(trade); - trade.setState(Trade.State.SELLER_RECEIVED_FIAT_PAYMENT_INITIATED_MSG); complete(); } catch (Throwable t) { failed(t); + } finally { + processModel.removeMailboxMessageAfterProcessing(trade); } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendPayoutTxPublishedMessage.java index 3bda43fa860..db73f1910a6 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendPayoutTxPublishedMessage.java @@ -17,23 +17,27 @@ package bisq.core.trade.protocol.tasks.seller; +import bisq.core.account.sign.SignedWitness; +import bisq.core.account.witness.AccountAgeWitnessService; import bisq.core.trade.Trade; import bisq.core.trade.messages.PayoutTxPublishedMessage; import bisq.core.trade.messages.TradeMessage; -import bisq.core.trade.protocol.tasks.SendPayoutTxPublishedMessage; +import bisq.core.trade.protocol.tasks.SendMailboxMessageTask; import bisq.common.taskrunner.TaskRunner; import org.bitcoinj.core.Transaction; -import java.util.UUID; - +import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; import static com.google.common.base.Preconditions.checkNotNull; +@EqualsAndHashCode(callSuper = true) @Slf4j -public class SellerSendPayoutTxPublishedMessage extends SendPayoutTxPublishedMessage { +public class SellerSendPayoutTxPublishedMessage extends SendMailboxMessageTask { + SignedWitness signedWitness = null; + public SellerSendPayoutTxPublishedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } @@ -41,32 +45,47 @@ public SellerSendPayoutTxPublishedMessage(TaskRunner taskHandler, Trade t @Override protected TradeMessage getMessage(String id) { Transaction payoutTx = checkNotNull(trade.getPayoutTx(), "trade.getPayoutTx() must not be null"); + + AccountAgeWitnessService accountAgeWitnessService = processModel.getAccountAgeWitnessService(); + if (accountAgeWitnessService.isSignWitnessTrade(trade)) { + // Broadcast is done in accountAgeWitness domain. + accountAgeWitnessService.traderSignAndPublishPeersAccountAgeWitness(trade).ifPresent(witness -> signedWitness = witness); + } + return new PayoutTxPublishedMessage( id, payoutTx.bitcoinSerialize(), processModel.getMyNodeAddress(), - UUID.randomUUID().toString() + signedWitness ); } @Override protected void setStateSent() { trade.setState(Trade.State.SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG); + log.info("Sent PayoutTxPublishedMessage: tradeId={} at peer {} SignedWitness {}", + trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness); } @Override protected void setStateArrived() { trade.setState(Trade.State.SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG); + log.info("PayoutTxPublishedMessage arrived: tradeId={} at peer {} SignedWitness {}", + trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness); } @Override protected void setStateStoredInMailbox() { trade.setState(Trade.State.SELLER_STORED_IN_MAILBOX_PAYOUT_TX_PUBLISHED_MSG); + log.info("PayoutTxPublishedMessage storedInMailbox: tradeId={} at peer {} SignedWitness {}", + trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness); } @Override protected void setStateFault() { trade.setState(Trade.State.SELLER_SEND_FAILED_PAYOUT_TX_PUBLISHED_MSG); + log.error("PayoutTxPublishedMessage failed: tradeId={} at peer {} SignedWitness {}", + trade.getId(), trade.getTradingPeerNodeAddress(), signedWitness); } @Override @@ -74,6 +93,12 @@ protected void run() { try { runInterceptHook(); + if (trade.getPayoutTx() == null) { + log.error("PayoutTx is null"); + failed("PayoutTx is null"); + return; + } + super.run(); } catch (Throwable t) { failed(t); diff --git a/core/src/test/java/bisq/core/account/sign/SignedWitnessServiceTest.java b/core/src/test/java/bisq/core/account/sign/SignedWitnessServiceTest.java index 338a9b3a705..55a6e8879b9 100644 --- a/core/src/test/java/bisq/core/account/sign/SignedWitnessServiceTest.java +++ b/core/src/test/java/bisq/core/account/sign/SignedWitnessServiceTest.java @@ -354,7 +354,7 @@ public void testSignAccountAgeWitness_withTooLowTradeAmount() throws CryptoExcep when(keyRing.getSignatureKeyPair()).thenReturn(signerKeyPair); AccountAgeWitness accountAgeWitness = new AccountAgeWitness(account1DataHash, accountCreationTime); - signedWitnessService.signAccountAgeWitness(Coin.ZERO, accountAgeWitness, peerKeyPair.getPublic()); + signedWitnessService.signAndPublishAccountAgeWitness(Coin.ZERO, accountAgeWitness, peerKeyPair.getPublic()); verify(p2pService, never()).addPersistableNetworkPayload(any(PersistableNetworkPayload.class), anyBoolean()); } @@ -370,7 +370,7 @@ public void testSignAccountAgeWitness_withSufficientTradeAmount() throws CryptoE AccountAgeWitness accountAgeWitness = new AccountAgeWitness(account1DataHash, accountCreationTime); - signedWitnessService.signAccountAgeWitness(SignedWitnessService.MINIMUM_TRADE_AMOUNT_FOR_SIGNING, accountAgeWitness, peerKeyPair.getPublic()); + signedWitnessService.signAndPublishAccountAgeWitness(SignedWitnessService.MINIMUM_TRADE_AMOUNT_FOR_SIGNING, accountAgeWitness, peerKeyPair.getPublic()); verify(p2pService, times(1)).addPersistableNetworkPayload(any(PersistableNetworkPayload.class), anyBoolean()); } diff --git a/core/src/test/java/bisq/core/account/witness/AccountAgeWitnessServiceTest.java b/core/src/test/java/bisq/core/account/witness/AccountAgeWitnessServiceTest.java index 2b2d11e5621..10840861ddc 100644 --- a/core/src/test/java/bisq/core/account/witness/AccountAgeWitnessServiceTest.java +++ b/core/src/test/java/bisq/core/account/witness/AccountAgeWitnessServiceTest.java @@ -301,7 +301,7 @@ public void testArbitratorSignDummyWitness() throws CryptoException { signAccountAgeWitness(aew2, pubKeyRing2.getSignaturePubKey(), aew2.getDate(), user1KeyRing); // user2 signs user3 signAccountAgeWitness(aew3, pubKeyRing3.getSignaturePubKey(), aew3.getDate(), user2KeyRing); - signedWitnessService.signAccountAgeWitness(SignedWitnessService.MINIMUM_TRADE_AMOUNT_FOR_SIGNING, aew2, + signedWitnessService.signAndPublishAccountAgeWitness(SignedWitnessService.MINIMUM_TRADE_AMOUNT_FOR_SIGNING, aew2, pubKeyRing2.getSignaturePubKey()); assertTrue(service.accountIsSigner(aew1)); assertTrue(service.accountIsSigner(aew2)); diff --git a/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsDataModel.java b/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsDataModel.java index 2cd3dc1ff3d..a9b5f3baccf 100644 --- a/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsDataModel.java @@ -130,7 +130,7 @@ public void onSaveNewAccount(PaymentAccount paymentAccount) { user.addPaymentAccount(paymentAccount); accountAgeWitnessService.publishMyAccountAgeWitness(paymentAccount.getPaymentAccountPayload()); - accountAgeWitnessService.signSameNameAccounts(); + accountAgeWitnessService.signAndPublishSameNameAccounts(); } public boolean onDeleteAccount(PaymentAccount paymentAccount) { diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java index ab0d06c7ea9..2a4e584f795 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -50,13 +50,10 @@ import bisq.core.trade.SellerTrade; import bisq.core.trade.Trade; import bisq.core.trade.TradeManager; -import bisq.core.trade.messages.RefreshTradeStateRequest; import bisq.core.user.Preferences; import bisq.core.util.FormattingUtils; -import bisq.network.p2p.NodeAddress; import bisq.network.p2p.P2PService; -import bisq.network.p2p.SendMailboxMessageListener; import bisq.common.crypto.PubKeyRing; import bisq.common.handlers.ErrorMessageHandler; @@ -81,7 +78,6 @@ import org.bouncycastle.crypto.params.KeyParameter; -import java.util.UUID; import java.util.stream.Collectors; import lombok.Getter; @@ -237,43 +233,6 @@ public void onMoveToFailedTrades() { tradeManager.addTradeToFailedTrades(getTrade()); } - // Ask counterparty to resend last action (in case message was lost) - public void refreshTradeState() { - Trade trade = getTrade(); - if (trade == null || !trade.allowedRefresh()) return; - - trade.logRefresh(); - NodeAddress tradingPeerNodeAddress = trade.getTradingPeerNodeAddress(); - - RefreshTradeStateRequest refreshReq = new RefreshTradeStateRequest(UUID.randomUUID().toString(), - trade.getId(), - tradingPeerNodeAddress); - p2PService.sendEncryptedMailboxMessage( - tradingPeerNodeAddress, - trade.getProcessModel().getTradingPeer().getPubKeyRing(), - refreshReq, - new SendMailboxMessageListener() { - @Override - public void onArrived() { - log.info("SendMailboxMessageListener onArrived tradeId={} at peer {}", - trade.getId(), tradingPeerNodeAddress); - } - - @Override - public void onStoredInMailbox() { - log.info("SendMailboxMessageListener onStoredInMailbox tradeId={} at peer {}", - trade.getId(), tradingPeerNodeAddress); - } - - @Override - public void onFault(String errorMessage) { - log.error("SendMailboxMessageListener onFault tradeId={} at peer {}", - trade.getId(), tradingPeerNodeAddress); - } - } - ); - tradeManager.persistTrades(); - } /////////////////////////////////////////////////////////////////////////////////////////// // Getters diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java index 3776b3f1a7e..d211997f8a5 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java @@ -216,8 +216,6 @@ public void initialize() { new Popup().warning(Res.get("portfolio.pending.removeFailedTrade")) .onAction(model.dataModel::onMoveToFailedTrades) .show(); - } else if (Utilities.isAltOrCtrlPressed(KeyCode.R, keyEvent)) { - model.dataModel.refreshTradeState(); } }; diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep2View.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep2View.java index 425634d2fb3..e6b8506ce10 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep2View.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep2View.java @@ -24,27 +24,12 @@ import bisq.core.locale.Res; import bisq.core.payment.payload.F2FAccountPayload; -import bisq.core.trade.Trade; -import bisq.common.Timer; -import bisq.common.UserThread; - -import javafx.scene.control.Button; -import javafx.scene.layout.GridPane; - -import java.util.Date; -import java.util.concurrent.TimeUnit; - -import static bisq.desktop.util.FormBuilder.addButtonAfterGroup; -import static bisq.desktop.util.FormBuilder.addMultilineLabel; import static bisq.desktop.util.FormBuilder.addTitledGroupBg; import static com.google.common.base.Preconditions.checkNotNull; public class SellerStep2View extends TradeStepView { - private GridPane refreshButtonPane; - private Timer timer; - /////////////////////////////////////////////////////////////////////////////////////////// // Constructor, Initialisation /////////////////////////////////////////////////////////////////////////////////////////// @@ -65,61 +50,16 @@ protected void addContent() { gridRow = F2FForm.addFormForBuyer(gridPane, --gridRow, model.dataModel.getSellersPaymentAccountPayload(), model.dataModel.getTrade().getOffer(), Layout.COMPACT_FIRST_ROW_AND_GROUP_DISTANCE); } - - addRefreshBlock(); } - private void addRefreshBlock() { - refreshButtonPane = new GridPane(); - addTitledGroupBg(refreshButtonPane, 0, 1, - Res.get("portfolio.pending.step2_seller.refresh"), Layout.COMPACT_GROUP_DISTANCE); - addMultilineLabel(refreshButtonPane, 1, Res.get("portfolio.pending.step2_seller.refreshInfo"), - Layout.COMPACT_FIRST_ROW_DISTANCE); - Button refreshButton = addButtonAfterGroup(refreshButtonPane, 2, Res.get("portfolio.pending.step2_seller.refresh")); - refreshButton.setOnAction(event -> onRefreshButton()); - - GridPane.setRowIndex(refreshButtonPane, ++gridRow); - GridPane.setColumnIndex(refreshButtonPane, 0); - GridPane.setColumnSpan(refreshButtonPane, 2); - gridPane.getChildren().add(refreshButtonPane); - } - - @Override public void activate() { super.activate(); - activateRefreshButton(); } @Override public void deactivate() { super.deactivate(); - deActivateRefreshButtonTimer(); - } - - private void activateRefreshButton() { - checkNotNull(model.dataModel.getTrade(), "No trade found"); - - Trade trade = model.dataModel.getTrade(); - var timeToNextRefresh = - trade.getLastRefreshRequestDate() + trade.getRefreshInterval() - new Date().getTime(); - if (timeToNextRefresh <= 0) { - refreshButtonPane.setVisible(true); - } else { - refreshButtonPane.setVisible(false); - timer = UserThread.runAfter(this::activateRefreshButton, timeToNextRefresh, TimeUnit.MILLISECONDS); - } - } - - private void deActivateRefreshButtonTimer() { - if (timer != null) { - timer.stop(); - } - } - - private void onRefreshButton() { - model.dataModel.refreshTradeState(); - activateRefreshButton(); } diff --git a/proto/src/main/proto/pb.proto b/proto/src/main/proto/pb.proto index 2f334e06e03..1cb5dff3a86 100644 --- a/proto/src/main/proto/pb.proto +++ b/proto/src/main/proto/pb.proto @@ -76,7 +76,7 @@ message NetworkEnvelope { DepositTxAndDelayedPayoutTxMessage deposit_tx_and_delayed_payout_tx_message = 48; PeerPublishedDelayedPayoutTxMessage peer_published_delayed_payout_tx_message = 49; - RefreshTradeStateRequest refresh_trade_state_request = 50; + RefreshTradeStateRequest refresh_trade_state_request = 50 [deprecated = true]; TraderSignedWitnessMessage trader_signed_witness_message = 51; } } @@ -309,6 +309,7 @@ message PayoutTxPublishedMessage { bytes payout_tx = 2; NodeAddress sender_node_address = 3; string uid = 4; + SignedWitness signed_witness = 5; // Added in v1.4.0 } message MediatedPayoutTxPublishedMessage { @@ -325,17 +326,19 @@ message MediatedPayoutTxSignatureMessage { NodeAddress sender_node_address = 4; } +// Deprecated since 1.4.0 message RefreshTradeStateRequest { - string uid = 1; - string trade_id = 2; - NodeAddress sender_node_address = 3; + string uid = 1 [deprecated = true]; + string trade_id = 2 [deprecated = true]; + NodeAddress sender_node_address = 3 [deprecated = true]; } +// Deprecated since 1.4.0 message TraderSignedWitnessMessage { - string uid = 1; - string trade_id = 2; - NodeAddress sender_node_address = 3; - SignedWitness signed_witness = 4; + string uid = 1 [deprecated = true]; + string trade_id = 2 [deprecated = true]; + NodeAddress sender_node_address = 3 [deprecated = true]; + SignedWitness signed_witness = 4 [deprecated = true]; } // dispute From 2b747cc32385123fde4cbfbdc83ff62f879c7f9f Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Tue, 22 Sep 2020 18:48:47 -0500 Subject: [PATCH 033/143] Don't return null if name is null by try to use UNDEFINED. Only if that is not present we return null --- common/src/main/java/bisq/common/proto/ProtoUtil.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/common/src/main/java/bisq/common/proto/ProtoUtil.java b/common/src/main/java/bisq/common/proto/ProtoUtil.java index 5f79abe02a2..f734526534e 100644 --- a/common/src/main/java/bisq/common/proto/ProtoUtil.java +++ b/common/src/main/java/bisq/common/proto/ProtoUtil.java @@ -69,13 +69,10 @@ public static byte[] byteArrayOrNullFromProto(ByteString proto) { */ @Nullable public static > E enumFromProto(Class enumType, String name) { - if (name == null) { - return null; - } - - E result = Enums.getIfPresent(enumType, name).orNull(); + String enumName = name != null ? name : "UNDEFINED"; + E result = Enums.getIfPresent(enumType, enumName).orNull(); if (result == null) { - log.debug("Invalid value for enum " + enumType.getSimpleName() + ": " + name); + log.debug("Invalid value for enum " + enumType.getSimpleName() + ": " + enumName); result = Enums.getIfPresent(enumType, "UNDEFINED").orNull(); log.debug("We try to lookup for an enum entry with name 'UNDEFINED' and use that if available, " + "otherwise the enum is null. enum={}", result); From b13e1a3edbfa82326cddc5e7a9b208fbc161e806 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Tue, 22 Sep 2020 18:50:45 -0500 Subject: [PATCH 034/143] Resend DepositTxAndDelayedPayoutTxMessage at SellerSendsDepositTxAndDelayedPayoutTxMessage if no ACK received Add checks for valid trade state transitions --- .../witness/AccountAgeWitnessUtils.java | 2 +- .../core/trade/DelayedPayoutTxValidation.java | 15 +- .../java/bisq/core/trade/TradableList.java | 7 + core/src/main/java/bisq/core/trade/Trade.java | 38 +++- .../trade/protocol/BuyerAsMakerProtocol.java | 25 ++- .../trade/protocol/BuyerAsTakerProtocol.java | 25 ++- .../core/trade/protocol/ProcessModel.java | 58 +++--- .../trade/protocol/SellerAsMakerProtocol.java | 2 +- .../trade/protocol/SellerAsTakerProtocol.java | 2 +- .../core/trade/protocol/TradeProtocol.java | 37 +++- .../tasks/SendMailboxMessageTask.java | 18 +- ...essDepositTxAndDelayedPayoutTxMessage.java | 2 +- ...CounterCurrencyTransferStartedMessage.java | 4 +- ...ndsDepositTxAndDelayedPayoutTxMessage.java | 186 +++++++++++++----- 14 files changed, 314 insertions(+), 107 deletions(-) diff --git a/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessUtils.java b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessUtils.java index 56983fea866..c450e7e4aa0 100644 --- a/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessUtils.java +++ b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessUtils.java @@ -144,7 +144,7 @@ public void witnessDebugLog(Trade trade, @Nullable AccountAgeWitness myWitness) boolean isSignWitnessTrade = accountAgeWitnessService.accountIsSigner(witness) && !accountAgeWitnessService.peerHasSignedWitness(trade) && accountAgeWitnessService.tradeAmountIsSufficient(trade.getTradeAmount()); - log.info("AccountSigning: " + + log.info("AccountSigning debug log: " + "\ntradeId: {}" + "\nis buyer: {}" + "\nbuyer account age witness info: {}" + diff --git a/core/src/main/java/bisq/core/trade/DelayedPayoutTxValidation.java b/core/src/main/java/bisq/core/trade/DelayedPayoutTxValidation.java index 8472fc2c0df..629d7a31299 100644 --- a/core/src/main/java/bisq/core/trade/DelayedPayoutTxValidation.java +++ b/core/src/main/java/bisq/core/trade/DelayedPayoutTxValidation.java @@ -85,21 +85,21 @@ public static void validatePayoutTx(Trade trade, InvalidTxException, InvalidLockTimeException, AmountMismatchException { String errorMsg; if (delayedPayoutTx == null) { - errorMsg = "DelayedPayoutTx must not be null"; + errorMsg = "DelayedPayoutTx must not be null. tradeId=" + trade.getShortId(); log.error(errorMsg); - throw new MissingDelayedPayoutTxException("DelayedPayoutTx must not be null"); + throw new MissingDelayedPayoutTxException(errorMsg); } // Validate tx structure if (delayedPayoutTx.getInputs().size() != 1) { - errorMsg = "Number of delayedPayoutTx inputs must be 1"; + errorMsg = "Number of delayedPayoutTx inputs must be 1. tradeId=" + trade.getShortId(); log.error(errorMsg); log.error(delayedPayoutTx.toString()); throw new InvalidTxException(errorMsg); } if (delayedPayoutTx.getOutputs().size() != 1) { - errorMsg = "Number of delayedPayoutTx outputs must be 1"; + errorMsg = "Number of delayedPayoutTx outputs must be 1. tradeId=" + trade.getShortId(); log.error(errorMsg); log.error(delayedPayoutTx.toString()); throw new InvalidTxException(errorMsg); @@ -110,7 +110,7 @@ public static void validatePayoutTx(Trade trade, // Validate lock time if (delayedPayoutTx.getLockTime() != trade.getLockTime()) { - errorMsg = "delayedPayoutTx.getLockTime() must match trade.getLockTime()"; + errorMsg = "delayedPayoutTx.getLockTime() must match trade.getLockTime(). tradeId=" + trade.getShortId(); log.error(errorMsg); log.error(delayedPayoutTx.toString()); throw new InvalidLockTimeException(errorMsg); @@ -118,7 +118,7 @@ public static void validatePayoutTx(Trade trade, // Validate seq num if (delayedPayoutTx.getInput(0).getSequenceNumber() != TransactionInput.NO_SEQUENCE - 1) { - errorMsg = "Sequence number must be 0xFFFFFFFE"; + errorMsg = "Sequence number must be 0xFFFFFFFE. tradeId=" + trade.getShortId(); log.error(errorMsg); log.error(delayedPayoutTx.toString()); throw new InvalidLockTimeException(errorMsg); @@ -132,7 +132,8 @@ public static void validatePayoutTx(Trade trade, .add(checkNotNull(trade.getTradeAmount())); if (!output.getValue().equals(msOutputAmount)) { - errorMsg = "Output value of deposit tx and delayed payout tx is not matching. Output: " + output + " / msOutputAmount: " + msOutputAmount; + errorMsg = "Output value of deposit tx and delayed payout tx is not matching. Output: " + output + + " / msOutputAmount: " + msOutputAmount + ". tradeId=" + trade.getShortId(); log.error(errorMsg); log.error(delayedPayoutTx.toString()); throw new AmountMismatchException(errorMsg); diff --git a/core/src/main/java/bisq/core/trade/TradableList.java b/core/src/main/java/bisq/core/trade/TradableList.java index eae2c3a60b1..1b3b2dad224 100644 --- a/core/src/main/java/bisq/core/trade/TradableList.java +++ b/core/src/main/java/bisq/core/trade/TradableList.java @@ -143,4 +143,11 @@ public int size() { public boolean contains(T thing) { return list.contains(thing); } + + @Override + public String toString() { + return "TradableList{" + + ",\n list=" + list + + "\n}"; + } } diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index 030de7c358f..c71d353a32e 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -116,7 +116,7 @@ public enum State { // At first part maker/taker have different roles // taker perspective - // #################### Phase TAKER_FEE_PAID + // #################### Phase TAKER_FEE_PUBLISHED TAKER_PUBLISHED_TAKER_FEE_TX(Phase.TAKER_FEE_PUBLISHED), // PUBLISH_DEPOSIT_TX_REQUEST @@ -130,7 +130,10 @@ public enum State { TAKER_RECEIVED_PUBLISH_DEPOSIT_TX_REQUEST(Phase.TAKER_FEE_PUBLISHED), - // #################### Phase DEPOSIT_PAID + // #################### Phase DEPOSIT_PUBLISHED + // We changes order in trade protocol of publishing deposit tx and sending it to the peer. + // Now we send it first to the peer and only if that succeeds we publish it to avoid likelyhood of + // failed trades. We do not want to change the order of the enum though so we keep it here as it was originally. SELLER_PUBLISHED_DEPOSIT_TX(Phase.DEPOSIT_PUBLISHED), @@ -165,7 +168,7 @@ public enum State { // note that this state can also be triggered by auto confirmation feature SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT(Phase.FIAT_RECEIVED), - // #################### Phase PAYOUT_PAID + // #################### Phase PAYOUT_PUBLISHED SELLER_PUBLISHED_PAYOUT_TX(Phase.PAYOUT_PUBLISHED), SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG(Phase.PAYOUT_PUBLISHED), @@ -200,6 +203,15 @@ public static Trade.State fromProto(protobuf.Trade.State state) { public static protobuf.Trade.State toProtoMessage(Trade.State state) { return protobuf.Trade.State.valueOf(state.name()); } + + + // We allow a state change only if the phase is the next phase or if we do not change the phase by the + // state change (e.g. detail change inside the same phase) + public boolean isValidTransitionTo(State newState) { + Phase newPhase = newState.getPhase(); + Phase currentPhase = this.getPhase(); + return currentPhase.isValidTransitionTo(newPhase) || newPhase == currentPhase; + } } public enum Phase { @@ -219,6 +231,12 @@ public static Trade.Phase fromProto(protobuf.Trade.Phase phase) { public static protobuf.Trade.Phase toProtoMessage(Trade.Phase phase) { return protobuf.Trade.Phase.valueOf(phase.name()); } + + // We allow a phase change only if the phase is next phase + public boolean isValidTransitionTo(Phase newPhase) { + // this is current phase + return newPhase.ordinal() == this.ordinal() + 1; + } } public enum DisputeState { @@ -522,7 +540,7 @@ protected Trade(Offer offer, @Override public Message toProtoMessage() { - final protobuf.Trade.Builder builder = protobuf.Trade.newBuilder() + protobuf.Trade.Builder builder = protobuf.Trade.newBuilder() .setOffer(checkNotNull(offer).toProtoMessage()) .setIsCurrencyForTakerFeeBtc(isCurrencyForTakerFeeBtc) .setTxFeeAsLong(txFeeAsLong) @@ -811,6 +829,14 @@ public void onComplete() { // Setters /////////////////////////////////////////////////////////////////////////////////////////// + public void setStateIfValidTransitionTo(State newState) { + if (state.isValidTransitionTo(newState)) { + setState(newState); + } else { + log.warn("State change is not getting applied because it would cause an invalid transition."); + } + } + public void setState(State state) { log.info("Set new state at {} (id={}): {}", this.getClass().getSimpleName(), getShortId(), state); if (state.getPhase().ordinal() < this.state.getPhase().ordinal()) { @@ -903,6 +929,10 @@ public Date getTakeOfferDate() { return new Date(takeOfferDate); } + public Phase getPhase() { + return state.getPhase(); + } + @Nullable public Volume getTradeVolume() { if (getTradeAmount() != null && getTradePrice() != null) { diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 515572eff30..93b449fad2f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -172,11 +172,30 @@ private void handle(DelayedPayoutTxSignatureRequest tradeMessage, NodeAddress pe taskRunner.run(); } - // DepositTxAndDelayedPayoutTxMessage is a MailboxMessage + // The DepositTxAndDelayedPayoutTxMessage is a mailbox message as earlier we use only the deposit tx which can + // be also received from the network once published. + // Now we send the delayed payout tx as well and with that this message is mandatory for continuing the protocol. + // We do not support mailbox message handling during the take offer process as it is expected that both peers + // are online. + // For backward compatibility and extra resilience we still keep DepositTxAndDelayedPayoutTxMessage as a + // mailbox message but the stored in mailbox case is not expected and the seller would try to send the message again + // in the hope to reach the buyer directly. private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress peerNodeAddress) { + if (trade.getDepositTx() != null && trade.getDelayedPayoutTx() != null) { + log.warn("We received a DepositTxAndDelayedPayoutTxMessage but we have already processed the deposit and " + + "delayed payout tx so we ignore the message. This can happen if the ACK message to the peer did not " + + "arrive and the peer repeats sending us the message. We send another ACK msg."); + sendAckMessage(tradeMessage, true, null); + processModel.removeMailboxMessageAfterProcessing(trade); + return; + } + + if (!isTradeInPhase(Trade.Phase.TAKER_FEE_PUBLISHED, tradeMessage)) { + return; + } + processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(peerNodeAddress); - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, () -> handleTaskRunnerSuccess(tradeMessage, "handle DepositTxAndDelayedPayoutTxMessage"), errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); @@ -186,7 +205,7 @@ private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress PublishTradeStatistics.class ); taskRunner.run(); - processModel.logTrade(buyerAsMakerTrade); + processModel.witnessDebugLog(buyerAsMakerTrade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 4073167d13e..0a98b4dda7b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -199,11 +199,30 @@ private void handle(DelayedPayoutTxSignatureRequest tradeMessage, NodeAddress se } - // DepositTxAndDelayedPayoutTxMessage is a MailboxMessage + // The DepositTxAndDelayedPayoutTxMessage is a mailbox message as earlier we use only the deposit tx which can + // be also received from the network once published. + // Now we send the delayed payout tx as well and with that this message is mandatory for continuing the protocol. + // We do not support mailbox message handling during the take offer process as it is expected that both peers + // are online. + // For backward compatibility and extra resilience we still keep DepositTxAndDelayedPayoutTxMessage as a + // mailbox message but the stored in mailbox case is not expected and the seller would try to send the message again + // in the hope to reach the buyer directly. private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress peerNodeAddress) { + if (trade.getDepositTx() != null && trade.getDelayedPayoutTx() != null) { + log.warn("We received a DepositTxAndDelayedPayoutTxMessage but we have already processed the deposit and " + + "delayed payout tx so we ignore the message. This can happen if the ACK message to the peer did not " + + "arrive and the peer repeats sending us the message. We send another ACK msg."); + sendAckMessage(tradeMessage, true, null); + processModel.removeMailboxMessageAfterProcessing(trade); + return; + } + + if (!isTradeInPhase(Trade.Phase.TAKER_FEE_PUBLISHED, tradeMessage)) { + return; + } + processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(peerNodeAddress); - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, () -> handleTaskRunnerSuccess(tradeMessage, "handle DepositTxAndDelayedPayoutTxMessage"), errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); @@ -213,7 +232,7 @@ private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress PublishTradeStatistics.class ); taskRunner.run(); - processModel.logTrade(buyerAsTakerTrade); + processModel.witnessDebugLog(buyerAsTakerTrade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java b/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java index a09d93834e7..e60237def8a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java +++ b/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java @@ -112,15 +112,26 @@ public class ProcessModel implements Model, PersistablePayload { @Nullable transient private Transaction preparedDelayedPayoutTx; + // Added in v1.4.0 + // MessageState of the last message sent from the seller to the buyer in the take offer process. + // It is used only in a task which would not be executed after restart, so no need to persist it. + @Setter + transient private ObjectProperty depositTxMessageStateProperty = new SimpleObjectProperty<>(MessageState.UNDEFINED); + + // Persistable Immutable (private setter only used by PB method) + @Setter private TradingPeer tradingPeer = new TradingPeer(); + @Setter private String offerId; + @Setter private String accountId; + @Setter private PubKeyRing pubKeyRing; // Persistable Mutable @Nullable - @Setter() + @Setter private String takeOfferFeeTxId; @Nullable @Setter @@ -158,8 +169,9 @@ public class ProcessModel implements Model, PersistablePayload { @Setter private long sellerPayoutAmountFromMediation; - // The only trade message where we want to indicate the user the state of the message delivery is the - // CounterCurrencyTransferStartedMessage. We persist the state with the processModel. + // We want to indicate the user the state of the message delivery of the + // CounterCurrencyTransferStartedMessage. As well we do an automatic re-send in case it was not ACKed yet. + // To enable that even after restart we persist the state. @Setter private ObjectProperty paymentStartedMessageStateProperty = new SimpleObjectProperty<>(MessageState.UNDEFINED); @@ -173,7 +185,7 @@ public ProcessModel() { @Override public protobuf.ProcessModel toProtoMessage() { - final protobuf.ProcessModel.Builder builder = protobuf.ProcessModel.newBuilder() + protobuf.ProcessModel.Builder builder = protobuf.ProcessModel.newBuilder() .setTradingPeer((protobuf.TradingPeer) tradingPeer.toProtoMessage()) .setOfferId(offerId) .setAccountId(accountId) @@ -221,10 +233,12 @@ public static ProcessModel fromProto(protobuf.ProcessModel proto, CoreProtoResol processModel.setChangeOutputAddress(ProtoUtil.stringOrNullFromProto(proto.getChangeOutputAddress())); processModel.setMyMultiSigPubKey(ProtoUtil.byteArrayOrNullFromProto(proto.getMyMultiSigPubKey())); processModel.setTempTradingPeerNodeAddress(proto.hasTempTradingPeerNodeAddress() ? NodeAddress.fromProto(proto.getTempTradingPeerNodeAddress()) : null); - String paymentStartedMessageState = proto.getPaymentStartedMessageState().isEmpty() ? MessageState.UNDEFINED.name() : proto.getPaymentStartedMessageState(); - ObjectProperty paymentStartedMessageStateProperty = processModel.getPaymentStartedMessageStateProperty(); - paymentStartedMessageStateProperty.set(ProtoUtil.enumFromProto(MessageState.class, paymentStartedMessageState)); processModel.setMediatedPayoutTxSignature(ProtoUtil.byteArrayOrNullFromProto(proto.getMediatedPayoutTxSignature())); + + String paymentStartedMessageStateString = ProtoUtil.stringOrNullFromProto(proto.getPaymentStartedMessageState()); + MessageState paymentStartedMessageState = ProtoUtil.enumFromProto(MessageState.class, paymentStartedMessageStateString); + processModel.setPaymentStartedMessageState(paymentStartedMessageState); + return processModel; } @@ -330,34 +344,28 @@ public NodeAddress getMyNodeAddress() { } void setPaymentStartedAckMessage(AckMessage ackMessage) { - if (ackMessage.isSuccess()) { - setPaymentStartedMessageState(MessageState.ACKNOWLEDGED); - } else { - setPaymentStartedMessageState(MessageState.FAILED); - } + MessageState messageState = ackMessage.isSuccess() ? + MessageState.ACKNOWLEDGED : + MessageState.FAILED; + setPaymentStartedMessageState(messageState); } public void setPaymentStartedMessageState(MessageState paymentStartedMessageStateProperty) { this.paymentStartedMessageStateProperty.set(paymentStartedMessageStateProperty); } - private void setTradingPeer(TradingPeer tradingPeer) { - this.tradingPeer = tradingPeer; - } - - private void setOfferId(String offerId) { - this.offerId = offerId; - } - - private void setAccountId(String accountId) { - this.accountId = accountId; + void setDepositTxSentAckMessage(AckMessage ackMessage) { + MessageState messageState = ackMessage.isSuccess() ? + MessageState.ACKNOWLEDGED : + MessageState.FAILED; + setDepositTxMessageState(messageState); } - private void setPubKeyRing(PubKeyRing pubKeyRing) { - this.pubKeyRing = pubKeyRing; + public void setDepositTxMessageState(MessageState messageState) { + this.depositTxMessageStateProperty.set(messageState); } - void logTrade(Trade trade) { + void witnessDebugLog(Trade trade) { accountAgeWitnessService.getAccountAgeWitnessUtils().witnessDebugLog(trade, null); } } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index df962b6fccc..54d902fce91 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -165,7 +165,7 @@ private void handle(DelayedPayoutTxSignatureResponse tradeMessage, NodeAddress s PublishTradeStatistics.class ); taskRunner.run(); - processModel.logTrade(sellerAsMakerTrade); + processModel.witnessDebugLog(sellerAsMakerTrade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 36d3096085a..7d4f6f1e3b6 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -164,7 +164,7 @@ private void handle(DelayedPayoutTxSignatureResponse tradeMessage, NodeAddress s PublishTradeStatistics.class ); taskRunner.run(); - processModel.logTrade(sellerAsTakerTrade); + processModel.witnessDebugLog(sellerAsTakerTrade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index aafb8303d9f..a238835803d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -21,6 +21,7 @@ import bisq.core.trade.Trade; import bisq.core.trade.TradeManager; import bisq.core.trade.messages.CounterCurrencyTransferStartedMessage; +import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage; import bisq.core.trade.messages.MediatedPayoutTxPublishedMessage; import bisq.core.trade.messages.MediatedPayoutTxSignatureMessage; import bisq.core.trade.messages.PeerPublishedDelayedPayoutTxMessage; @@ -93,9 +94,13 @@ public TradeProtocol(Trade trade) { AckMessage ackMessage = (AckMessage) networkEnvelope; if (ackMessage.getSourceType() == AckMessageSourceType.TRADE_MESSAGE && ackMessage.getSourceId().equals(trade.getId())) { - // We only handle the ack for CounterCurrencyTransferStartedMessage - if (ackMessage.getSourceMsgClassName().equals(CounterCurrencyTransferStartedMessage.class.getSimpleName())) + // We handle the ack for CounterCurrencyTransferStartedMessage and DepositTxAndDelayedPayoutTxMessage + // as we support automatic re-send of the msg in case it was not ACKed after a certain time + if (ackMessage.getSourceMsgClassName().equals(CounterCurrencyTransferStartedMessage.class.getSimpleName())) { processModel.setPaymentStartedAckMessage(ackMessage); + } else if (ackMessage.getSourceMsgClassName().equals(DepositTxAndDelayedPayoutTxMessage.class.getSimpleName())) { + processModel.setDepositTxSentAckMessage(ackMessage); + } if (ackMessage.isSuccess()) { log.info("Received AckMessage for {} from {} with tradeId {} and uid {}", @@ -333,7 +338,7 @@ protected boolean wasDisputed() { return trade.getDisputeState() != Trade.DisputeState.NO_DISPUTE; } - private void sendAckMessage(@Nullable TradeMessage tradeMessage, boolean result, @Nullable String errorMessage) { + protected void sendAckMessage(@Nullable TradeMessage tradeMessage, boolean result, @Nullable String errorMessage) { // We complete at initial protocol setup with the setup listener tasks. // Other cases are if we start from an UI event the task runner (payment started, confirmed). // In such cases we have not set any tradeMessage and we ignore the sendAckMessage call. @@ -352,7 +357,9 @@ private void sendAckMessage(@Nullable TradeMessage tradeMessage, boolean result, errorMessage); // If there was an error during offer verification, the tradingPeerNodeAddress of the trade might not be set yet. // We can find the peer's node address in the processModel's tempTradingPeerNodeAddress in that case. - final NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress() != null ? trade.getTradingPeerNodeAddress() : processModel.getTempTradingPeerNodeAddress(); + NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress() != null ? + trade.getTradingPeerNodeAddress() : + processModel.getTempTradingPeerNodeAddress(); log.info("Send AckMessage for {} to peer {}. tradeId={}, sourceUid={}", ackMessage.getSourceMsgClassName(), peersNodeAddress, tradeId, sourceUid); processModel.getP2PService().sendEncryptedMailboxMessage( @@ -401,4 +408,26 @@ private void cleanupTradeOnFault() { } } } + + protected boolean isTradeInPhase(Trade.Phase phase) { + return isTradeInPhase(phase, null); + } + + protected boolean isTradeInPhase(Trade.Phase expectedPhase, + @Nullable TradeMessage tradeMessage) { + boolean isValidPhase = trade.getPhase() == expectedPhase; + if (!isValidPhase) { + if (tradeMessage != null) { + log.error("We received a {} but we are not in the correct phase. Phase={}, State= {} ", + tradeMessage.getClass().getSimpleName(), + trade.getPhase(), + trade.getState()); + } else { + log.error("We are not in the correct phase. Phase={}, State= {} ", + trade.getPhase(), + trade.getState()); + } + } + return isValidPhase; + } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/SendMailboxMessageTask.java b/core/src/main/java/bisq/core/trade/protocol/tasks/SendMailboxMessageTask.java index 29aeb0d5cf3..b8ef5f5f039 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/SendMailboxMessageTask.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/SendMailboxMessageTask.java @@ -71,17 +71,14 @@ public void onArrived() { public void onStoredInMailbox() { log.info("{} stored in mailbox for peer {}. tradeId={}, uid={}", message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); - setStateStoredInMailbox(); - complete(); + SendMailboxMessageTask.this.onStoredInMailbox(); } @Override public void onFault(String errorMessage) { log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}", message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage); - setStateFault(); - appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage); - failed(errorMessage); + SendMailboxMessageTask.this.onFault(errorMessage, message); } } ); @@ -89,4 +86,15 @@ public void onFault(String errorMessage) { failed(t); } } + + protected void onStoredInMailbox() { + setStateStoredInMailbox(); + complete(); + } + + protected void onFault(String errorMessage, TradeMessage message) { + setStateFault(); + appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage); + failed(errorMessage); + } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java index 09683d9d998..2bfea25a9cf 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java @@ -44,7 +44,7 @@ public BuyerProcessDepositTxAndDelayedPayoutTxMessage(TaskRunner taskHand protected void run() { try { runInterceptHook(); - var message = (DepositTxAndDelayedPayoutTxMessage) processModel.getTradeMessage(); + var message = checkNotNull((DepositTxAndDelayedPayoutTxMessage) processModel.getTradeMessage()); checkNotNull(message); Validator.checkTradeId(processModel.getOfferId(), message); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java index 922e0829b5c..be13fa07fb8 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java @@ -129,7 +129,9 @@ private void start() { // Once we receive an ACK from our msg we know the peer has received the msg and we stop. if (newValue == MessageState.ACKNOWLEDGED) { // We treat a ACK like BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG - trade.setState(Trade.State.BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG); + if (trade.getState().getPhase() == Trade.Phase.FIAT_SENT) { + trade.setState(Trade.State.BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG); + } // Ensure listener construction is completed before remove call UserThread.execute(this::stop); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java index 7506f958af7..a212390ac03 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java @@ -17,80 +17,164 @@ package bisq.core.trade.protocol.tasks.seller; +import bisq.core.network.MessageState; import bisq.core.trade.Trade; import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage; -import bisq.core.trade.protocol.tasks.TradeTask; - -import bisq.network.p2p.NodeAddress; -import bisq.network.p2p.SendMailboxMessageListener; +import bisq.core.trade.messages.TradeMessage; +import bisq.core.trade.protocol.tasks.SendMailboxMessageTask; +import bisq.common.Timer; +import bisq.common.UserThread; import bisq.common.taskrunner.TaskRunner; -import org.bitcoinj.core.Transaction; +import javafx.beans.value.ChangeListener; -import java.util.UUID; +import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import static com.google.common.base.Preconditions.checkNotNull; +/** + * We send the buyer the deposit and delayed payout tx. We wait to receive a ACK message back and resend the message + * in case that does not happen in 4 seconds or if the message was stored in mailbox or failed. We keep repeating that + * with doubling the interval each time and until the MAX_RESEND_ATTEMPTS is reached. If never successful we fail and + * do not continue the protocol with publishing the deposit tx. That way we avoid that a deposit tx is published but the + * buyer does not has the delayed payout tx and would not be able to open arbitration. + */ @Slf4j -public class SellerSendsDepositTxAndDelayedPayoutTxMessage extends TradeTask { +public class SellerSendsDepositTxAndDelayedPayoutTxMessage extends SendMailboxMessageTask { + private static final int MAX_RESEND_ATTEMPTS = 7; + private int delayInSec = 4; + private int resendCounter = 0; + private DepositTxAndDelayedPayoutTxMessage depositTxAndDelayedPayoutTxMessage; + private ChangeListener listener; + private Timer timer; + public SellerSendsDepositTxAndDelayedPayoutTxMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); } + @Override + protected TradeMessage getMessage(String tradeId) { + if (depositTxAndDelayedPayoutTxMessage == 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 + // 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 = tradeId + processModel.getMyNodeAddress().getFullAddress(); + depositTxAndDelayedPayoutTxMessage = new DepositTxAndDelayedPayoutTxMessage( + deterministicId, + processModel.getOfferId(), + processModel.getMyNodeAddress(), + checkNotNull(trade.getDepositTx()).bitcoinSerialize(), + checkNotNull(trade.getDelayedPayoutTx()).bitcoinSerialize()); + } + return depositTxAndDelayedPayoutTxMessage; + } + + @Override + protected void setStateSent() { + trade.setStateIfValidTransitionTo(Trade.State.SELLER_SENT_DEPOSIT_TX_PUBLISHED_MSG); + } + + @Override + protected void setStateArrived() { + trade.setStateIfValidTransitionTo(Trade.State.SELLER_SAW_ARRIVED_DEPOSIT_TX_PUBLISHED_MSG); + cleanup(); + // Complete is called in base class + } + + // We override the default behaviour for onStoredInMailbox and do not call complete + @Override + protected void onStoredInMailbox() { + setStateStoredInMailbox(); + } + + @Override + protected void setStateStoredInMailbox() { + trade.setStateIfValidTransitionTo(Trade.State.SELLER_STORED_IN_MAILBOX_DEPOSIT_TX_PUBLISHED_MSG); + // The DepositTxAndDelayedPayoutTxMessage is a mailbox message as earlier we use only the deposit tx which can + // be also received from the network once published. + // Now we send the delayed payout tx as well and with that this message is mandatory for continuing the protocol. + // We do not support mailbox message handling during the take offer process as it is expected that both peers + // are online. + // For backward compatibility and extra resilience we still keep DepositTxAndDelayedPayoutTxMessage as a + // mailbox message but the stored in mailbox case is not expected and the seller would try to send the message again + // in the hope to reach the buyer directly. + if (!trade.isDepositConfirmed()) { + tryToSendAgainLater(); + } + } + + // We override the default behaviour for onFault and do not call appendToErrorMessage and failed + @Override + protected void onFault(String errorMessage, TradeMessage message) { + setStateFault(); + } + + @Override + protected void setStateFault() { + trade.setStateIfValidTransitionTo(Trade.State.SELLER_SEND_FAILED_DEPOSIT_TX_PUBLISHED_MSG); + if (!trade.isDepositConfirmed()) { + tryToSendAgainLater(); + } + } + @Override protected void run() { try { runInterceptHook(); - Transaction depositTx = checkNotNull(trade.getDepositTx(), "DepositTx must not be null"); - Transaction delayedPayoutTx = checkNotNull(trade.getDelayedPayoutTx()); - DepositTxAndDelayedPayoutTxMessage message = new DepositTxAndDelayedPayoutTxMessage(UUID.randomUUID().toString(), - processModel.getOfferId(), - processModel.getMyNodeAddress(), - depositTx.bitcoinSerialize(), - delayedPayoutTx.bitcoinSerialize()); - trade.setState(Trade.State.SELLER_SENT_DEPOSIT_TX_PUBLISHED_MSG); - - NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress(); - log.info("Send {} to peer {}. tradeId={}, uid={}", - message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); - processModel.getP2PService().sendEncryptedMailboxMessage( - peersNodeAddress, - processModel.getTradingPeer().getPubKeyRing(), - message, - new SendMailboxMessageListener() { - @Override - public void onArrived() { - log.info("{} arrived at peer {}. tradeId={}, uid={}", - message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); - trade.setState(Trade.State.SELLER_SAW_ARRIVED_DEPOSIT_TX_PUBLISHED_MSG); - complete(); - } - - @Override - public void onStoredInMailbox() { - log.info("{} stored in mailbox for peer {}. tradeId={}, uid={}", - message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); - - trade.setState(Trade.State.SELLER_STORED_IN_MAILBOX_DEPOSIT_TX_PUBLISHED_MSG); - complete(); - } - - @Override - public void onFault(String errorMessage) { - log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}", - message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage); - trade.setState(Trade.State.SELLER_SEND_FAILED_DEPOSIT_TX_PUBLISHED_MSG); - appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage); - failed(); - } - } - ); + super.run(); } catch (Throwable t) { failed(t); + } finally { + cleanup(); + } + } + + private void cleanup() { + if (timer != null) { + timer.stop(); + } + if (listener != null) { + processModel.getPaymentStartedMessageStateProperty().removeListener(listener); + } + } + + private void tryToSendAgainLater() { + if (resendCounter >= MAX_RESEND_ATTEMPTS) { + cleanup(); + failed("We never received an ACK message when sending the msg to the peer. " + + "We fail here and do not publish the deposit tx."); + return; + } + + log.info("We send the message again to the peer after a delay of {} sec.", delayInSec); + if (timer != null) { + timer.stop(); + } + timer = UserThread.runAfter(this::run, delayInSec, TimeUnit.SECONDS); + + if (resendCounter == 0) { + // We want to register listener only once + listener = (observable, oldValue, newValue) -> onMessageStateChange(newValue); + processModel.getDepositTxMessageStateProperty().addListener(listener); + onMessageStateChange(processModel.getDepositTxMessageStateProperty().get()); + } + + delayInSec = delayInSec * 2; + resendCounter++; + } + + private void onMessageStateChange(MessageState newValue) { + // Once we receive an ACK from our msg we know the peer has received the msg and we stop. + if (newValue == MessageState.ACKNOWLEDGED) { + // We treat a ACK like SELLER_SAW_ARRIVED_DEPOSIT_TX_PUBLISHED_MSG + trade.setStateIfValidTransitionTo(Trade.State.SELLER_SAW_ARRIVED_DEPOSIT_TX_PUBLISHED_MSG); + cleanup(); + complete(); } } } From 96221317e2f474d53dddd946649b020be0ed2668 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Tue, 22 Sep 2020 19:01:51 -0500 Subject: [PATCH 035/143] Change order of tasks Call BuyerSetupPayoutTxListener before BuyerSendCounterCurrencyTransferStartedMessage We will change BuyerSendCounterCurrencyTransferStartedMessage so that it does not complete until the message has been ACKed by the peer. It is more transparent to leave the task uncompleted and if it is the last task we dont have issues. The caller would not get the result handler called though until all is completed. But the result handler in the UI was anyway empty. --- .../java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java | 4 ++-- .../java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 93b449fad2f..a0001a397b2 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -234,8 +234,8 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle MakerVerifyTakerAccount.class, MakerVerifyTakerFeePayment.class, BuyerSignPayoutTx.class, - BuyerSendCounterCurrencyTransferStartedMessage.class, - BuyerSetupPayoutTxListener.class + BuyerSetupPayoutTxListener.class, + BuyerSendCounterCurrencyTransferStartedMessage.class ); taskRunner.run(); } else { diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 0a98b4dda7b..549a8add707 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -198,7 +198,6 @@ private void handle(DelayedPayoutTxSignatureRequest tradeMessage, NodeAddress se taskRunner.run(); } - // The DepositTxAndDelayedPayoutTxMessage is a mailbox message as earlier we use only the deposit tx which can // be also received from the network once published. // Now we send the delayed payout tx as well and with that this message is mandatory for continuing the protocol. @@ -263,8 +262,8 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle TakerVerifyMakerAccount.class, TakerVerifyMakerFeePayment.class, BuyerSignPayoutTx.class, - BuyerSendCounterCurrencyTransferStartedMessage.class, - BuyerSetupPayoutTxListener.class + BuyerSetupPayoutTxListener.class, + BuyerSendCounterCurrencyTransferStartedMessage.class ); taskRunner.run(); } else { From c7e0c51875e98645ffcf94a2bb905951a4e5e6f5 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Tue, 22 Sep 2020 19:34:14 -0500 Subject: [PATCH 036/143] Use same model as in SellerSendsDepositTxAndDelayedPayoutTxMessage Reason: the other model was already tested quite a lot and seems to work correctly. We gain a lot of resiliance with min. costs (repeated mailbox messages - as they are the same they will not cause higher number of msg, just a bit more traffic) --- ...CounterCurrencyTransferStartedMessage.java | 113 ++++++++++++------ 1 file changed, 76 insertions(+), 37 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java index be13fa07fb8..5fd30322122 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSendCounterCurrencyTransferStartedMessage.java @@ -19,7 +19,6 @@ import bisq.core.btc.model.AddressEntry; import bisq.core.network.MessageState; -import bisq.core.payment.payload.PaymentMethod; import bisq.core.trade.Trade; import bisq.core.trade.messages.CounterCurrencyTransferStartedMessage; import bisq.core.trade.messages.TradeMessage; @@ -35,15 +34,23 @@ import lombok.extern.slf4j.Slf4j; -import static com.google.common.base.Preconditions.checkNotNull; - +/** + * We send the seller the BuyerSendCounterCurrencyTransferStartedMessage. + * We wait to receive a ACK message back and resend the message + * in case that does not happen in 10 minutes or if the message was stored in mailbox or failed. We keep repeating that + * with doubling the interval each time and until the MAX_RESEND_ATTEMPTS is reached. + * If never successful we give up and complete. It might be a valid case that the peer was not online for an extended + * time but we can be very sure that our message was stored as mailbox message in the network and one the peer goes + * online he will process it. + */ @Slf4j public class BuyerSendCounterCurrencyTransferStartedMessage extends SendMailboxMessageTask { - private static final long MAX_REFRESH_INTERVAL = TimeUnit.HOURS.toMillis(4); - + private static final int MAX_RESEND_ATTEMPTS = 10; + private int delayInMin = 15; + private int resendCounter = 0; + private CounterCurrencyTransferStartedMessage message; private ChangeListener listener; private Timer timer; - private CounterCurrencyTransferStartedMessage counterCurrencyTransferStartedMessage; public BuyerSendCounterCurrencyTransferStartedMessage(TaskRunner taskHandler, Trade trade) { super(taskHandler, trade); @@ -51,7 +58,7 @@ public BuyerSendCounterCurrencyTransferStartedMessage(TaskRunner taskHand @Override protected TradeMessage getMessage(String tradeId) { - if (counterCurrencyTransferStartedMessage == null) { + if (message == null) { AddressEntry payoutAddressEntry = processModel.getBtcWalletService().getOrCreateAddressEntry(tradeId, AddressEntry.Context.TRADE_PAYOUT); @@ -60,7 +67,7 @@ protected TradeMessage getMessage(String tradeId) { // 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 = tradeId + processModel.getMyNodeAddress().getFullAddress(); - counterCurrencyTransferStartedMessage = new CounterCurrencyTransferStartedMessage( + message = new CounterCurrencyTransferStartedMessage( tradeId, payoutAddressEntry.getAddressString(), processModel.getMyNodeAddress(), @@ -70,30 +77,47 @@ protected TradeMessage getMessage(String tradeId) { deterministicId ); } - return counterCurrencyTransferStartedMessage; + return message; } @Override protected void setStateSent() { - trade.setState(Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG); + trade.setStateIfValidTransitionTo(Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG); } @Override protected void setStateArrived() { - trade.setState(Trade.State.BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG); - stop(); + trade.setStateIfValidTransitionTo(Trade.State.BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG); + cleanup(); + // Complete is called in base class + } + + // We override the default behaviour for onStoredInMailbox and do not call complete + @Override + protected void onStoredInMailbox() { + setStateStoredInMailbox(); } @Override protected void setStateStoredInMailbox() { - trade.setState(Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG); - start(); + trade.setStateIfValidTransitionTo(Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG); + if (!trade.isPayoutPublished()) { + tryToSendAgainLater(); + } + } + + // We override the default behaviour for onFault and do not call appendToErrorMessage and failed + @Override + protected void onFault(String errorMessage, TradeMessage message) { + setStateFault(); } @Override protected void setStateFault() { - trade.setState(Trade.State.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG); - start(); + trade.setStateIfValidTransitionTo(Trade.State.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG); + if (!trade.isPayoutPublished()) { + tryToSendAgainLater(); + } } @Override @@ -104,38 +128,53 @@ protected void run() { super.run(); } catch (Throwable t) { failed(t); + } finally { + cleanup(); } } - private void stop() { + private void cleanup() { if (timer != null) { timer.stop(); + } + if (listener != null) { processModel.getPaymentStartedMessageStateProperty().removeListener(listener); } } - // The listeners ensure we don't get GCed even we have completed the task. - private void start() { - if (timer != null) { + private void tryToSendAgainLater() { + if (resendCounter >= MAX_RESEND_ATTEMPTS) { + cleanup(); + log.warn("We never received an ACK message when sending the CounterCurrencyTransferStartedMessage to the peer. " + + "We stop now and complete the protocol task."); + complete(); return; } - PaymentMethod paymentMethod = checkNotNull(trade.getOffer()).getPaymentMethod(); - // For instant trades with 1 hour we want a short interval, otherwise a few hours should be ok. - long interval = Math.min(paymentMethod.getMaxTradePeriod() / 5, MAX_REFRESH_INTERVAL); - timer = UserThread.runPeriodically(this::run, interval, TimeUnit.MILLISECONDS); - - listener = (observable, oldValue, newValue) -> { - // Once we receive an ACK from our msg we know the peer has received the msg and we stop. - if (newValue == MessageState.ACKNOWLEDGED) { - // We treat a ACK like BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG - if (trade.getState().getPhase() == Trade.Phase.FIAT_SENT) { - trade.setState(Trade.State.BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG); - } - // Ensure listener construction is completed before remove call - UserThread.execute(this::stop); - } - }; - processModel.getPaymentStartedMessageStateProperty().addListener(listener); + log.info("We send the message again to the peer after a delay of {} min.", delayInMin); + if (timer != null) { + timer.stop(); + } + timer = UserThread.runAfter(this::run, delayInMin, TimeUnit.MINUTES); + + if (resendCounter == 0) { + // We want to register listener only once + listener = (observable, oldValue, newValue) -> onMessageStateChange(newValue); + processModel.getPaymentStartedMessageStateProperty().addListener(listener); + onMessageStateChange(processModel.getPaymentStartedMessageStateProperty().get()); + } + + delayInMin = delayInMin * 2; + resendCounter++; + } + + private void onMessageStateChange(MessageState newValue) { + // Once we receive an ACK from our msg we know the peer has received the msg and we stop. + if (newValue == MessageState.ACKNOWLEDGED) { + // We treat a ACK like BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG + trade.setStateIfValidTransitionTo(Trade.State.BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG); + cleanup(); + complete(); + } } } From 4b7307e07fbb687e989414ddd38f72f3901f1bab Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Tue, 22 Sep 2020 19:35:01 -0500 Subject: [PATCH 037/143] Add checks for state at handle CounterCurrencyTransferStartedMessage Add ApplyFilter task --- .../core/trade/protocol/SellerAsMakerProtocol.java | 14 ++++++++++++++ .../core/trade/protocol/SellerAsTakerProtocol.java | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index 54d902fce91..a9f3bb29aa5 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -174,6 +174,19 @@ private void handle(DelayedPayoutTxSignatureResponse tradeMessage, NodeAddress s /////////////////////////////////////////////////////////////////////////////////////////// private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddress sender) { + if (trade.getPayoutTx() != null) { + log.warn("We received a CounterCurrencyTransferStartedMessage but we have already created the payout tx " + + "so we ignore the message. This can happen if the ACK message to the peer did not " + + "arrive and the peer repeats sending us the message. We send another ACK msg."); + sendAckMessage(tradeMessage, true, null); + processModel.removeMailboxMessageAfterProcessing(trade); + return; + } + + if (!isTradeInPhase(Trade.Phase.DEPOSIT_CONFIRMED, tradeMessage)) { + return; + } + processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(sender); @@ -184,6 +197,7 @@ private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddr taskRunner.addTasks( SellerProcessCounterCurrencyTransferStartedMessage.class, MakerVerifyTakerAccount.class, + ApplyFilter.class, MakerVerifyTakerFeePayment.class ); taskRunner.run(); diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 7d4f6f1e3b6..900fa6e6b87 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -173,6 +173,19 @@ private void handle(DelayedPayoutTxSignatureResponse tradeMessage, NodeAddress s /////////////////////////////////////////////////////////////////////////////////////////// private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddress sender) { + if (trade.getPayoutTx() != null) { + log.warn("We received a CounterCurrencyTransferStartedMessage but we have already created the payout tx " + + "so we ignore the message. This can happen if the ACK message to the peer did not " + + "arrive and the peer repeats sending us the message. We send another ACK msg."); + sendAckMessage(tradeMessage, true, null); + processModel.removeMailboxMessageAfterProcessing(trade); + return; + } + + if (!isTradeInPhase(Trade.Phase.DEPOSIT_CONFIRMED, tradeMessage)) { + return; + } + processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(sender); @@ -183,6 +196,7 @@ private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddr taskRunner.addTasks( SellerProcessCounterCurrencyTransferStartedMessage.class, TakerVerifyMakerAccount.class, + ApplyFilter.class, TakerVerifyMakerFeePayment.class ); taskRunner.run(); From 8ce5ebadeac03d34175d46029be46d0854d2899f Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Tue, 22 Sep 2020 19:35:24 -0500 Subject: [PATCH 038/143] Refactoring: rename, cleanups --- .../SellerSendsDepositTxAndDelayedPayoutTxMessage.java | 8 ++++---- .../pendingtrades/steps/buyer/BuyerStep2View.java | 7 ------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java index a212390ac03..20871176486 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java @@ -47,7 +47,7 @@ public class SellerSendsDepositTxAndDelayedPayoutTxMessage extends SendMailboxMe private static final int MAX_RESEND_ATTEMPTS = 7; private int delayInSec = 4; private int resendCounter = 0; - private DepositTxAndDelayedPayoutTxMessage depositTxAndDelayedPayoutTxMessage; + private DepositTxAndDelayedPayoutTxMessage message; private ChangeListener listener; private Timer timer; @@ -57,20 +57,20 @@ public SellerSendsDepositTxAndDelayedPayoutTxMessage(TaskRunner taskHandl @Override protected TradeMessage getMessage(String tradeId) { - if (depositTxAndDelayedPayoutTxMessage == null) { + if (message == 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 // 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 = tradeId + processModel.getMyNodeAddress().getFullAddress(); - depositTxAndDelayedPayoutTxMessage = new DepositTxAndDelayedPayoutTxMessage( + message = new DepositTxAndDelayedPayoutTxMessage( deterministicId, processModel.getOfferId(), processModel.getMyNodeAddress(), checkNotNull(trade.getDepositTx()).bitcoinSerialize(), checkNotNull(trade.getDelayedPayoutTx()).bitcoinSerialize()); } - return depositTxAndDelayedPayoutTxMessage; + return message; } @Override diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java index b60f682ce08..70d2718f08b 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java @@ -513,20 +513,13 @@ private void showConfirmPaymentStartedPopup() { } private void confirmPaymentStarted() { - // confirmButton.setDisable(true); busyAnimation.play(); statusLabel.setText(Res.get("shared.sendingConfirmation")); if (trade.isFiatSent()) trade.setState(Trade.State.DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN); model.dataModel.onPaymentStarted(() -> { - // In case the first send failed we got the support button displayed. - // If it succeeds at a second try we remove the support button again. - //TODO check for support. in case of a dispute we dont want to hide the button - //if (notificationGroup != null) - // notificationGroup.setButtonVisible(false); }, errorMessage -> { - // confirmButton.setDisable(false); busyAnimation.stop(); new Popup().warning(Res.get("popup.warning.sendMsgFailed")).show(); }); From 1abe6adac6a269e8e050f8baa363afc4c16002e1 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Tue, 22 Sep 2020 19:40:15 -0500 Subject: [PATCH 039/143] Remove empty tasks. --- .../trade/protocol/BuyerAsMakerProtocol.java | 3 -- .../trade/protocol/BuyerAsTakerProtocol.java | 3 -- .../trade/protocol/SellerAsMakerProtocol.java | 5 -- .../trade/protocol/SellerAsTakerProtocol.java | 5 -- .../tasks/maker/MakerVerifyTakerAccount.java | 51 ------------------- .../tasks/taker/TakerVerifyMakerAccount.java | 49 ------------------ .../bisq/desktop/main/debug/DebugView.java | 16 ------ 7 files changed, 132 deletions(-) delete mode 100644 core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerAccount.java delete mode 100644 core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerAccount.java diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index a0001a397b2..d398d0b3ceb 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -43,7 +43,6 @@ import bisq.core.trade.protocol.tasks.maker.MakerCreateAndSignContract; import bisq.core.trade.protocol.tasks.maker.MakerProcessesInputsForDepositTxRequest; import bisq.core.trade.protocol.tasks.maker.MakerSetsLockTime; -import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerAccount; import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment; import bisq.core.util.Validator; @@ -139,7 +138,6 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest tradeMessage, taskRunner.addTasks( MakerProcessesInputsForDepositTxRequest.class, ApplyFilter.class, - MakerVerifyTakerAccount.class, VerifyPeersAccountAgeWitness.class, MakerVerifyTakerFeePayment.class, MakerSetsLockTime.class, @@ -231,7 +229,6 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle }); taskRunner.addTasks( ApplyFilter.class, - MakerVerifyTakerAccount.class, MakerVerifyTakerFeePayment.class, BuyerSignPayoutTx.class, BuyerSetupPayoutTxListener.class, diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 549a8add707..d8bea312532 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -48,7 +48,6 @@ import bisq.core.trade.protocol.tasks.taker.TakerPublishFeeTx; import bisq.core.trade.protocol.tasks.taker.TakerSendInputsForDepositTxRequest; import bisq.core.trade.protocol.tasks.taker.TakerVerifyAndSignContract; -import bisq.core.trade.protocol.tasks.taker.TakerVerifyMakerAccount; import bisq.core.trade.protocol.tasks.taker.TakerVerifyMakerFeePayment; import bisq.network.p2p.NodeAddress; @@ -139,7 +138,6 @@ public void takeAvailableOffer() { taskRunner.addTasks( ApplyFilter.class, - TakerVerifyMakerAccount.class, TakerVerifyMakerFeePayment.class, CreateTakerFeeTx.class, BuyerAsTakerCreatesDepositTxInputs.class, @@ -259,7 +257,6 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle }); taskRunner.addTasks( ApplyFilter.class, - TakerVerifyMakerAccount.class, TakerVerifyMakerFeePayment.class, BuyerSignPayoutTx.class, BuyerSetupPayoutTxListener.class, diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index a9f3bb29aa5..03dd5f97ab1 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -31,7 +31,6 @@ import bisq.core.trade.protocol.tasks.maker.MakerCreateAndSignContract; import bisq.core.trade.protocol.tasks.maker.MakerProcessesInputsForDepositTxRequest; import bisq.core.trade.protocol.tasks.maker.MakerSetsLockTime; -import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerAccount; import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment; import bisq.core.trade.protocol.tasks.seller.SellerBroadcastPayoutTx; import bisq.core.trade.protocol.tasks.seller.SellerCreatesDelayedPayoutTx; @@ -111,7 +110,6 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest tradeMessage, taskRunner.addTasks( MakerProcessesInputsForDepositTxRequest.class, ApplyFilter.class, - MakerVerifyTakerAccount.class, VerifyPeersAccountAgeWitness.class, MakerVerifyTakerFeePayment.class, MakerSetsLockTime.class, @@ -196,7 +194,6 @@ private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddr taskRunner.addTasks( SellerProcessCounterCurrencyTransferStartedMessage.class, - MakerVerifyTakerAccount.class, ApplyFilter.class, MakerVerifyTakerFeePayment.class ); @@ -227,7 +224,6 @@ public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandl taskRunner.addTasks( ApplyFilter.class, - MakerVerifyTakerAccount.class, MakerVerifyTakerFeePayment.class, SellerSignAndFinalizePayoutTx.class, SellerBroadcastPayoutTx.class, @@ -252,7 +248,6 @@ public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandl taskRunner.addTasks( ApplyFilter.class, - MakerVerifyTakerAccount.class, MakerVerifyTakerFeePayment.class, SellerSendPayoutTxPublishedMessage.class ); diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 900fa6e6b87..9aa5760a907 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -46,7 +46,6 @@ import bisq.core.trade.protocol.tasks.taker.TakerPublishFeeTx; import bisq.core.trade.protocol.tasks.taker.TakerSendInputsForDepositTxRequest; import bisq.core.trade.protocol.tasks.taker.TakerVerifyAndSignContract; -import bisq.core.trade.protocol.tasks.taker.TakerVerifyMakerAccount; import bisq.core.trade.protocol.tasks.taker.TakerVerifyMakerFeePayment; import bisq.network.p2p.NodeAddress; @@ -105,7 +104,6 @@ public void takeAvailableOffer() { taskRunner.addTasks( ApplyFilter.class, - TakerVerifyMakerAccount.class, TakerVerifyMakerFeePayment.class, CreateTakerFeeTx.class, SellerAsTakerCreatesDepositTxInputs.class, @@ -195,7 +193,6 @@ private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddr taskRunner.addTasks( SellerProcessCounterCurrencyTransferStartedMessage.class, - TakerVerifyMakerAccount.class, ApplyFilter.class, TakerVerifyMakerFeePayment.class ); @@ -226,7 +223,6 @@ public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandl taskRunner.addTasks( ApplyFilter.class, - TakerVerifyMakerAccount.class, TakerVerifyMakerFeePayment.class, SellerSignAndFinalizePayoutTx.class, SellerBroadcastPayoutTx.class, @@ -251,7 +247,6 @@ public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandl taskRunner.addTasks( ApplyFilter.class, - TakerVerifyMakerAccount.class, TakerVerifyMakerFeePayment.class, SellerSendPayoutTxPublishedMessage.class ); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerAccount.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerAccount.java deleted file mode 100644 index adf0a1d7113..00000000000 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerVerifyTakerAccount.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.core.trade.protocol.tasks.maker; - -import bisq.core.trade.Trade; -import bisq.core.trade.protocol.tasks.TradeTask; - -import bisq.common.taskrunner.TaskRunner; - -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public class MakerVerifyTakerAccount extends TradeTask { - public MakerVerifyTakerAccount(TaskRunner taskHandler, Trade trade) { - super(taskHandler, trade); - } - - @Override - protected void run() { - try { - runInterceptHook(); - //TODO impl. missing - /* if (processModel.getBlockChainService().isAccountBlackListed(processModel.tradingPeer.getAccountId(), - processModel.tradingPeer.getPaymentAccountPayload())) { - log.error("Taker is blacklisted"); - failed("Taker is blacklisted"); - } - else {*/ - complete(); - //} - } catch (Throwable t) { - failed(t); - } - } -} - diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerAccount.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerAccount.java deleted file mode 100644 index 971366d25ad..00000000000 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyMakerAccount.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.core.trade.protocol.tasks.taker; - -import bisq.core.trade.Trade; -import bisq.core.trade.protocol.tasks.TradeTask; - -import bisq.common.taskrunner.TaskRunner; - -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public class TakerVerifyMakerAccount extends TradeTask { - - public TakerVerifyMakerAccount(TaskRunner taskHandler, Trade trade) { - super(taskHandler, trade); - } - - @Override - protected void run() { - try { - runInterceptHook(); - /* if (processModel.getBlockChainService().isAccountBlackListed(processModel.tradingPeer.getAccountId(), - processModel.tradingPeer.getPaymentAccountPayload())) { - failed("Taker is blacklisted."); - } - else {*/ - complete(); - // } - } catch (Throwable t) { - failed(t); - } - } -} diff --git a/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java b/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java index 7f9008b256f..1b75096665f 100644 --- a/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java +++ b/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java @@ -37,7 +37,6 @@ import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerSignsDepositTx; import bisq.core.trade.protocol.tasks.maker.MakerCreateAndSignContract; import bisq.core.trade.protocol.tasks.maker.MakerProcessesInputsForDepositTxRequest; -import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerAccount; import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment; import bisq.core.trade.protocol.tasks.seller.SellerBroadcastPayoutTx; import bisq.core.trade.protocol.tasks.seller.SellerProcessCounterCurrencyTransferStartedMessage; @@ -51,7 +50,6 @@ import bisq.core.trade.protocol.tasks.taker.TakerProcessesInputsForDepositTxResponse; import bisq.core.trade.protocol.tasks.taker.TakerSendInputsForDepositTxRequest; import bisq.core.trade.protocol.tasks.taker.TakerVerifyAndSignContract; -import bisq.core.trade.protocol.tasks.taker.TakerVerifyMakerAccount; import bisq.core.trade.protocol.tasks.taker.TakerVerifyMakerFeePayment; import bisq.common.taskrunner.Task; @@ -106,18 +104,15 @@ public void initialize() { FXCollections.observableArrayList(Arrays.asList( MakerProcessesInputsForDepositTxRequest.class, ApplyFilter.class, - MakerVerifyTakerAccount.class, MakerVerifyTakerFeePayment.class, MakerCreateAndSignContract.class, BuyerAsMakerCreatesAndSignsDepositTx.class, BuyerSetupDepositTxListener.class, - MakerVerifyTakerAccount.class, MakerVerifyTakerFeePayment.class, PublishTradeStatistics.class, ApplyFilter.class, - MakerVerifyTakerAccount.class, MakerVerifyTakerFeePayment.class, BuyerSignPayoutTx.class, BuyerSendCounterCurrencyTransferStartedMessage.class, @@ -125,7 +120,6 @@ public void initialize() { )); addGroup("SellerAsTakerProtocol", FXCollections.observableArrayList(Arrays.asList( - TakerVerifyMakerAccount.class, TakerVerifyMakerFeePayment.class, CreateTakerFeeTx.class, SellerAsTakerCreatesDepositTxInputs.class, @@ -133,18 +127,15 @@ public void initialize() { TakerProcessesInputsForDepositTxResponse.class, ApplyFilter.class, - TakerVerifyMakerAccount.class, TakerVerifyMakerFeePayment.class, TakerVerifyAndSignContract.class, SellerAsTakerSignsDepositTx.class, SellerSendsDepositTxAndDelayedPayoutTxMessage.class, SellerProcessCounterCurrencyTransferStartedMessage.class, - TakerVerifyMakerAccount.class, TakerVerifyMakerFeePayment.class, ApplyFilter.class, - TakerVerifyMakerAccount.class, TakerVerifyMakerFeePayment.class, SellerSignAndFinalizePayoutTx.class, SellerBroadcastPayoutTx.class, @@ -152,7 +143,6 @@ public void initialize() { )); addGroup("BuyerAsTakerProtocol", FXCollections.observableArrayList(Arrays.asList( - TakerVerifyMakerAccount.class, TakerVerifyMakerFeePayment.class, CreateTakerFeeTx.class, BuyerAsTakerCreatesDepositTxInputs.class, @@ -160,14 +150,12 @@ public void initialize() { TakerProcessesInputsForDepositTxResponse.class, ApplyFilter.class, - TakerVerifyMakerAccount.class, TakerVerifyMakerFeePayment.class, TakerVerifyAndSignContract.class, BuyerAsTakerSignsDepositTx.class, SellerSendsDepositTxAndDelayedPayoutTxMessage.class, ApplyFilter.class, - TakerVerifyMakerAccount.class, TakerVerifyMakerFeePayment.class, BuyerSignPayoutTx.class, BuyerSendCounterCurrencyTransferStartedMessage.class, @@ -177,22 +165,18 @@ public void initialize() { FXCollections.observableArrayList(Arrays.asList( MakerProcessesInputsForDepositTxRequest.class, ApplyFilter.class, - MakerVerifyTakerAccount.class, MakerVerifyTakerFeePayment.class, MakerCreateAndSignContract.class, SellerAsMakerCreatesUnsignedDepositTx.class, BuyerSetupDepositTxListener.class, PublishTradeStatistics.class, - MakerVerifyTakerAccount.class, MakerVerifyTakerFeePayment.class, SellerProcessCounterCurrencyTransferStartedMessage.class, - MakerVerifyTakerAccount.class, MakerVerifyTakerFeePayment.class, ApplyFilter.class, - MakerVerifyTakerAccount.class, MakerVerifyTakerFeePayment.class, SellerSignAndFinalizePayoutTx.class, SellerBroadcastPayoutTx.class, From 5f8f30a8b3e37c55c1d028b01152121c1a5906d4 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Tue, 22 Sep 2020 19:53:19 -0500 Subject: [PATCH 040/143] Add BuyerSendCounterCurrencyTransferStartedMessage as second optional task instead of starting a new task runner --- .../trade/protocol/BuyerAsMakerProtocol.java | 23 +++++++------------ .../trade/protocol/BuyerAsTakerProtocol.java | 22 +++++++----------- 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index d398d0b3ceb..0924a9b08c2 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -72,30 +72,23 @@ public BuyerAsMakerProtocol(BuyerAsMakerTrade trade) { Trade.Phase phase = trade.getState().getPhase(); if (phase == Trade.Phase.TAKER_FEE_PUBLISHED) { TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess("BuyerSetupDepositTxListener"), + () -> handleTaskRunnerSuccess("BuyerSetupDepositTxListener at startup"), this::handleTaskRunnerFault); taskRunner.addTasks(BuyerSetupDepositTxListener.class); taskRunner.run(); } else if (trade.isFiatSent() && !trade.isPayoutPublished()) { TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess("BuyerSetupPayoutTxListener"), + () -> handleTaskRunnerSuccess("BuyerSetupPayoutTxListener at startup"), this::handleTaskRunnerFault); taskRunner.addTasks(BuyerSetupPayoutTxListener.class); - taskRunner.run(); - } - - // We might have 2 taskRunners as BuyerSetupPayoutTxListener might have been started as well - if (trade.getState() == Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG || - trade.getState() == Trade.State.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG) { - // In case we have not received an ACK from the CounterCurrencyTransferStartedMessage we re-send it - // periodically in BuyerSendCounterCurrencyTransferStartedMessage - TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess("BuyerSendCounterCurrencyTransferStartedMessage"), - this::handleTaskRunnerFault); - - taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class); + if (trade.getState() == Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG || + trade.getState() == Trade.State.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG) { + // In case we have not received an ACK from the CounterCurrencyTransferStartedMessage we re-send it + // periodically in BuyerSendCounterCurrencyTransferStartedMessage + taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class); + } taskRunner.run(); } } diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index d8bea312532..922d1d6b351 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -80,30 +80,24 @@ public BuyerAsTakerProtocol(BuyerAsTakerTrade trade) { Trade.Phase phase = trade.getState().getPhase(); if (phase == Trade.Phase.TAKER_FEE_PUBLISHED) { TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess("BuyerSetupDepositTxListener"), + () -> handleTaskRunnerSuccess("BuyerSetupDepositTxListener at startup"), this::handleTaskRunnerFault); taskRunner.addTasks(BuyerSetupDepositTxListener.class); taskRunner.run(); } else if (trade.isFiatSent() && !trade.isPayoutPublished()) { TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess("BuyerSetupPayoutTxListener"), + () -> handleTaskRunnerSuccess("BuyerSetupPayoutTxListener at startup"), this::handleTaskRunnerFault); taskRunner.addTasks(BuyerSetupPayoutTxListener.class); - taskRunner.run(); - } - - // We might have 2 taskRunners as BuyerSetupPayoutTxListener might have been started as well - if (trade.getState() == Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG || - trade.getState() == Trade.State.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG) { - // In case we have not received an ACK from the CounterCurrencyTransferStartedMessage we re-send it - // periodically in BuyerSendCounterCurrencyTransferStartedMessage - TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess("BuyerSendCounterCurrencyTransferStartedMessage"), - this::handleTaskRunnerFault); - taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class); + if (trade.getState() == Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG || + trade.getState() == Trade.State.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG) { + // In case we have not received an ACK from the CounterCurrencyTransferStartedMessage we re-send it + // periodically in BuyerSendCounterCurrencyTransferStartedMessage + taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class); + } taskRunner.run(); } } From 48241af31660efdf699df17273cbbb20a3e6ed8f Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Tue, 22 Sep 2020 20:18:59 -0500 Subject: [PATCH 041/143] Change isTradeInPhase APi to fluent interface with ifInPhase --- .../trade/protocol/BuyerAsMakerProtocol.java | 31 ++++++----- .../trade/protocol/BuyerAsTakerProtocol.java | 33 +++++------ .../trade/protocol/SellerAsMakerProtocol.java | 33 ++++++----- .../trade/protocol/SellerAsTakerProtocol.java | 33 ++++++----- .../core/trade/protocol/TradeProtocol.java | 55 +++++++++++++------ .../buyer/BuyerSetupPayoutTxListener.java | 3 +- 6 files changed, 105 insertions(+), 83 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 0924a9b08c2..aad9838856c 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -181,22 +181,23 @@ private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress return; } - if (!isTradeInPhase(Trade.Phase.TAKER_FEE_PUBLISHED, tradeMessage)) { - return; - } + ifInPhase(Trade.Phase.TAKER_FEE_PUBLISHED, tradeMessage) + .run(() -> { + processModel.setTradeMessage(tradeMessage); + processModel.setTempTradingPeerNodeAddress(peerNodeAddress); + TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, + () -> handleTaskRunnerSuccess(tradeMessage, "handle DepositTxAndDelayedPayoutTxMessage"), + errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + taskRunner.addTasks( + BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, + BuyerVerifiesFinalDelayedPayoutTx.class, + PublishTradeStatistics.class + ); + taskRunner.run(); + processModel.witnessDebugLog(buyerAsMakerTrade); + }); + - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(peerNodeAddress); - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle DepositTxAndDelayedPayoutTxMessage"), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); - taskRunner.addTasks( - BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, - BuyerVerifiesFinalDelayedPayoutTx.class, - PublishTradeStatistics.class - ); - taskRunner.run(); - processModel.witnessDebugLog(buyerAsMakerTrade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 922d1d6b351..901f77aee65 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -208,22 +208,23 @@ private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress return; } - if (!isTradeInPhase(Trade.Phase.TAKER_FEE_PUBLISHED, tradeMessage)) { - return; - } - - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(peerNodeAddress); - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle DepositTxAndDelayedPayoutTxMessage"), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); - taskRunner.addTasks( - BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, - BuyerVerifiesFinalDelayedPayoutTx.class, - PublishTradeStatistics.class - ); - taskRunner.run(); - processModel.witnessDebugLog(buyerAsTakerTrade); + ifInPhase(Trade.Phase.TAKER_FEE_PUBLISHED, tradeMessage) + .run(() -> { + processModel.setTradeMessage(tradeMessage); + processModel.setTempTradingPeerNodeAddress(peerNodeAddress); + TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, + () -> handleTaskRunnerSuccess(tradeMessage, "handle DepositTxAndDelayedPayoutTxMessage"), + errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + taskRunner.addTasks( + BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, + BuyerVerifiesFinalDelayedPayoutTx.class, + PublishTradeStatistics.class + ); + taskRunner.run(); + processModel.witnessDebugLog(buyerAsTakerTrade); + }).otherWise(() -> { + log.warn(""); + }); } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index 03dd5f97ab1..75bcb32926d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -181,23 +181,22 @@ private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddr return; } - if (!isTradeInPhase(Trade.Phase.DEPOSIT_CONFIRMED, tradeMessage)) { - return; - } - - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle CounterCurrencyTransferStartedMessage"), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); - - taskRunner.addTasks( - SellerProcessCounterCurrencyTransferStartedMessage.class, - ApplyFilter.class, - MakerVerifyTakerFeePayment.class - ); - taskRunner.run(); + ifInPhase(Trade.Phase.DEPOSIT_CONFIRMED, tradeMessage) + .run(() -> { + processModel.setTradeMessage(tradeMessage); + processModel.setTempTradingPeerNodeAddress(sender); + + TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, + () -> handleTaskRunnerSuccess(tradeMessage, "handle CounterCurrencyTransferStartedMessage"), + errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + + taskRunner.addTasks( + SellerProcessCounterCurrencyTransferStartedMessage.class, + ApplyFilter.class, + MakerVerifyTakerFeePayment.class + ); + taskRunner.run(); + }); } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 9aa5760a907..94a0fb6b35d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -180,23 +180,22 @@ private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddr return; } - if (!isTradeInPhase(Trade.Phase.DEPOSIT_CONFIRMED, tradeMessage)) { - return; - } - - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle CounterCurrencyTransferStartedMessage"), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); - - taskRunner.addTasks( - SellerProcessCounterCurrencyTransferStartedMessage.class, - ApplyFilter.class, - TakerVerifyMakerFeePayment.class - ); - taskRunner.run(); + ifInPhase(Trade.Phase.DEPOSIT_CONFIRMED, tradeMessage) + .run(() -> { + processModel.setTradeMessage(tradeMessage); + processModel.setTempTradingPeerNodeAddress(sender); + + TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, + () -> handleTaskRunnerSuccess(tradeMessage, "handle CounterCurrencyTransferStartedMessage"), + errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + + taskRunner.addTasks( + SellerProcessCounterCurrencyTransferStartedMessage.class, + ApplyFilter.class, + TakerVerifyMakerFeePayment.class + ); + taskRunner.run(); + }); } diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index a238835803d..f2504726a75 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -56,6 +56,7 @@ import java.security.PublicKey; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import javax.annotation.Nullable; @@ -409,25 +410,47 @@ private void cleanupTradeOnFault() { } } - protected boolean isTradeInPhase(Trade.Phase phase) { - return isTradeInPhase(phase, null); + protected TradeStateValidation ifInPhase(Trade.Phase phase) { + return new TradeStateValidation(trade, phase, null); } - protected boolean isTradeInPhase(Trade.Phase expectedPhase, - @Nullable TradeMessage tradeMessage) { - boolean isValidPhase = trade.getPhase() == expectedPhase; - if (!isValidPhase) { - if (tradeMessage != null) { - log.error("We received a {} but we are not in the correct phase. Phase={}, State= {} ", - tradeMessage.getClass().getSimpleName(), - trade.getPhase(), - trade.getState()); - } else { - log.error("We are not in the correct phase. Phase={}, State= {} ", - trade.getPhase(), - trade.getState()); + protected TradeStateValidation ifInPhase(Trade.Phase phase, + @Nullable TradeMessage tradeMessage) { + return new TradeStateValidation(trade, phase, tradeMessage); + } + + static class TradeStateValidation { + @Getter + private final boolean isValidPhase; + + protected TradeStateValidation run(Runnable runnable) { + if (isValidPhase) { + runnable.run(); + } + return this; + } + + protected void otherWise(Runnable runnable) { + runnable.run(); + } + + public TradeStateValidation(Trade trade, + Trade.Phase expectedPhase, + @Nullable TradeMessage tradeMessage) { + isValidPhase = trade.getPhase() == expectedPhase; + if (!isValidPhase) { + if (tradeMessage != null) { + log.error("We received a {} but we are not in the correct phase. Phase={}, State= {} ", + tradeMessage.getClass().getSimpleName(), + trade.getPhase(), + trade.getState()); + } else { + log.error("We are not in the correct phase. Phase={}, State= {} ", + trade.getPhase(), + trade.getState()); + } } } - return isValidPhase; } + } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupPayoutTxListener.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupPayoutTxListener.java index befa919c47f..8f06c187bae 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupPayoutTxListener.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerSetupPayoutTxListener.java @@ -44,7 +44,6 @@ protected void run() { @Override protected void setState() { - trade.setState(Trade.State.BUYER_SAW_PAYOUT_TX_IN_NETWORK); + trade.setStateIfValidTransitionTo(Trade.State.BUYER_SAW_PAYOUT_TX_IN_NETWORK); } - } From 7c6f0ac9b20c81b6975bc44df79d2069de4d9196 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Tue, 22 Sep 2020 21:09:09 -0500 Subject: [PATCH 042/143] Use ifInPhase APi for testing expected phase(s) Add ifInPhase method to allow alternative phases. We can have parallel branches how we reach a new state, e.g. receiving the tx from network or receiving it from the peer. no guarantee which will happen first. Allow phase transition to skip a future phase as we have phases only relevant for one role. This is not good for treading it as a state machine state, we need to redesign the state/phase handling... --- core/src/main/java/bisq/core/trade/Trade.java | 10 +- .../trade/protocol/BuyerAsMakerProtocol.java | 140 ++++++------- .../trade/protocol/BuyerAsTakerProtocol.java | 185 +++++++++--------- .../core/trade/protocol/TradeProtocol.java | 36 +++- ...erProcessesInputsForDepositTxResponse.java | 1 - 5 files changed, 205 insertions(+), 167 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index c71d353a32e..58ac1744880 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -127,7 +127,7 @@ public enum State { MAKER_SEND_FAILED_PUBLISH_DEPOSIT_TX_REQUEST(Phase.TAKER_FEE_PUBLISHED), // taker perspective - TAKER_RECEIVED_PUBLISH_DEPOSIT_TX_REQUEST(Phase.TAKER_FEE_PUBLISHED), + TAKER_RECEIVED_PUBLISH_DEPOSIT_TX_REQUEST(Phase.TAKER_FEE_PUBLISHED), // Not used anymore // #################### Phase DEPOSIT_PUBLISHED @@ -232,10 +232,11 @@ public static protobuf.Trade.Phase toProtoMessage(Trade.Phase phase) { return protobuf.Trade.Phase.valueOf(phase.name()); } - // We allow a phase change only if the phase is next phase + // We allow a phase change only if the phase a future phase (we cannot limit it to next phase as we have cases where + // we skip a phase as it is only relevant to one role -> states and phases need a redesign ;-( ) public boolean isValidTransitionTo(Phase newPhase) { // this is current phase - return newPhase.ordinal() == this.ordinal() + 1; + return newPhase.ordinal() > this.ordinal(); } } @@ -833,7 +834,8 @@ public void setStateIfValidTransitionTo(State newState) { if (state.isValidTransitionTo(newState)) { setState(newState); } else { - log.warn("State change is not getting applied because it would cause an invalid transition."); + log.warn("State change is not getting applied because it would cause an invalid transition. " + + "Trade state={}, intended state={}", state, newState); } } diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index aad9838856c..1b9bbdae49a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -118,28 +118,31 @@ public void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress pe public void handleTakeOfferRequest(InputsForDepositTxRequest tradeMessage, NodeAddress peerNodeAddress, ErrorMessageHandler errorMessageHandler) { - Validator.checkTradeId(processModel.getOfferId(), tradeMessage); - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(peerNodeAddress); - - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handleTakeOfferRequest"), - errorMessage -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(errorMessage); + ifInPhase(Trade.Phase.INIT, tradeMessage) + .run(() -> { + Validator.checkTradeId(processModel.getOfferId(), tradeMessage); + processModel.setTradeMessage(tradeMessage); + processModel.setTempTradingPeerNodeAddress(peerNodeAddress); + + TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, + () -> handleTaskRunnerSuccess(tradeMessage, "handleTakeOfferRequest"), + errorMessage -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(errorMessage); + }); + taskRunner.addTasks( + MakerProcessesInputsForDepositTxRequest.class, + ApplyFilter.class, + VerifyPeersAccountAgeWitness.class, + MakerVerifyTakerFeePayment.class, + MakerSetsLockTime.class, + MakerCreateAndSignContract.class, + BuyerAsMakerCreatesAndSignsDepositTx.class, + BuyerSetupDepositTxListener.class, + BuyerAsMakerSendsInputsForDepositTxResponse.class + ); + taskRunner.run(); }); - taskRunner.addTasks( - MakerProcessesInputsForDepositTxRequest.class, - ApplyFilter.class, - VerifyPeersAccountAgeWitness.class, - MakerVerifyTakerFeePayment.class, - MakerSetsLockTime.class, - MakerCreateAndSignContract.class, - BuyerAsMakerCreatesAndSignsDepositTx.class, - BuyerSetupDepositTxListener.class, - BuyerAsMakerSendsInputsForDepositTxResponse.class - ); - taskRunner.run(); } @@ -148,19 +151,22 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest tradeMessage, /////////////////////////////////////////////////////////////////////////////////////////// private void handle(DelayedPayoutTxSignatureRequest tradeMessage, NodeAddress peerNodeAddress) { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(peerNodeAddress); - - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle DelayedPayoutTxSignatureRequest"), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); - taskRunner.addTasks( - BuyerProcessDelayedPayoutTxSignatureRequest.class, - BuyerVerifiesPreparedDelayedPayoutTx.class, - BuyerSignsDelayedPayoutTx.class, - BuyerSendsDelayedPayoutTxSignatureResponse.class - ); - taskRunner.run(); + ifInPhase(Trade.Phase.TAKER_FEE_PUBLISHED, tradeMessage) + .run(() -> { + processModel.setTradeMessage(tradeMessage); + processModel.setTempTradingPeerNodeAddress(peerNodeAddress); + + TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, + () -> handleTaskRunnerSuccess(tradeMessage, "handle DelayedPayoutTxSignatureRequest"), + errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + taskRunner.addTasks( + BuyerProcessDelayedPayoutTxSignatureRequest.class, + BuyerVerifiesPreparedDelayedPayoutTx.class, + BuyerSignsDelayedPayoutTx.class, + BuyerSendsDelayedPayoutTxSignatureResponse.class + ); + taskRunner.run(); + }); } // The DepositTxAndDelayedPayoutTxMessage is a mailbox message as earlier we use only the deposit tx which can @@ -181,7 +187,7 @@ private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress return; } - ifInPhase(Trade.Phase.TAKER_FEE_PUBLISHED, tradeMessage) + ifInPhase(Trade.Phase.TAKER_FEE_PUBLISHED, tradeMessage).orInPhase(Trade.Phase.DEPOSIT_PUBLISHED) .run(() -> { processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(peerNodeAddress); @@ -210,28 +216,27 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle checkArgument(!wasDisputed(), "A call to onFiatPaymentStarted is not permitted once a " + "dispute has been opened."); - if (trade.isDepositConfirmed() && !trade.isFiatSent()) { - buyerAsMakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess("onFiatPaymentStarted"); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(errorMessage); - }); - taskRunner.addTasks( - ApplyFilter.class, - MakerVerifyTakerFeePayment.class, - BuyerSignPayoutTx.class, - BuyerSetupPayoutTxListener.class, - BuyerSendCounterCurrencyTransferStartedMessage.class - ); - taskRunner.run(); - } else { - log.warn("onFiatPaymentStarted called twice. tradeState=" + trade.getState()); - } + ifInPhase(Trade.Phase.DEPOSIT_CONFIRMED) + .run(() -> { + buyerAsMakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); + TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess("onFiatPaymentStarted"); + }, + (errorMessage) -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(errorMessage); + }); + taskRunner.addTasks( + ApplyFilter.class, + MakerVerifyTakerFeePayment.class, + BuyerSignPayoutTx.class, + BuyerSetupPayoutTxListener.class, + BuyerSendCounterCurrencyTransferStartedMessage.class + ); + taskRunner.run(); + }); } @@ -240,17 +245,20 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle /////////////////////////////////////////////////////////////////////////////////////////// private void handle(PayoutTxPublishedMessage tradeMessage, NodeAddress peerNodeAddress) { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(peerNodeAddress); + ifInPhase(Trade.Phase.FIAT_SENT, tradeMessage).orInPhase(Trade.Phase.PAYOUT_PUBLISHED) + .run(() -> { + processModel.setTradeMessage(tradeMessage); + processModel.setTempTradingPeerNodeAddress(peerNodeAddress); - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle PayoutTxPublishedMessage"), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, + () -> handleTaskRunnerSuccess(tradeMessage, "handle PayoutTxPublishedMessage"), + errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); - taskRunner.addTasks( - BuyerProcessPayoutTxPublishedMessage.class - ); - taskRunner.run(); + taskRunner.addTasks( + BuyerProcessPayoutTxPublishedMessage.class + ); + taskRunner.run(); + }); } diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 901f77aee65..fabdc84a548 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -125,23 +125,26 @@ public void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress pe @Override public void takeAvailableOffer() { - processModel.setTempTradingPeerNodeAddress(trade.getTradingPeerNodeAddress()); - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> handleTaskRunnerSuccess("takeAvailableOffer"), - this::handleTaskRunnerFault); - - taskRunner.addTasks( - ApplyFilter.class, - TakerVerifyMakerFeePayment.class, - CreateTakerFeeTx.class, - BuyerAsTakerCreatesDepositTxInputs.class, - TakerSendInputsForDepositTxRequest.class - ); - - //TODO if peer does get an error he does not respond and all we get is the timeout now knowing why it failed. - // We should add an error message the peer sends us in such cases. - startTimeout(); - taskRunner.run(); + ifInPhase(Trade.Phase.INIT) + .run(() -> { + processModel.setTempTradingPeerNodeAddress(trade.getTradingPeerNodeAddress()); + TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, + () -> handleTaskRunnerSuccess("takeAvailableOffer"), + this::handleTaskRunnerFault); + + taskRunner.addTasks( + ApplyFilter.class, + TakerVerifyMakerFeePayment.class, + CreateTakerFeeTx.class, + BuyerAsTakerCreatesDepositTxInputs.class, + TakerSendInputsForDepositTxRequest.class + ); + + //TODO if peer does get an error he does not respond and all we get is the timeout now knowing why it failed. + // We should add an error message the peer sends us in such cases. + startTimeout(); + taskRunner.run(); + }); } @@ -150,44 +153,50 @@ public void takeAvailableOffer() { /////////////////////////////////////////////////////////////////////////////////////////// private void handle(InputsForDepositTxResponse tradeMessage, NodeAddress sender) { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> { - handleTaskRunnerSuccess(tradeMessage, "handle InputsForDepositTxResponse"); - }, - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); - taskRunner.addTasks( - TakerProcessesInputsForDepositTxResponse.class, - ApplyFilter.class, - VerifyPeersAccountAgeWitness.class, - TakerVerifyAndSignContract.class, - TakerPublishFeeTx.class, - BuyerAsTakerSignsDepositTx.class, - BuyerSetupDepositTxListener.class, - BuyerAsTakerSendsDepositTxMessage.class - ); - taskRunner.run(); + ifInPhase(Trade.Phase.INIT, tradeMessage) + .run(() -> { + processModel.setTradeMessage(tradeMessage); + processModel.setTempTradingPeerNodeAddress(sender); + + TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, + () -> { + handleTaskRunnerSuccess(tradeMessage, "handle InputsForDepositTxResponse"); + }, + errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + taskRunner.addTasks( + TakerProcessesInputsForDepositTxResponse.class, + ApplyFilter.class, + VerifyPeersAccountAgeWitness.class, + TakerVerifyAndSignContract.class, + TakerPublishFeeTx.class, + BuyerAsTakerSignsDepositTx.class, + BuyerSetupDepositTxListener.class, + BuyerAsTakerSendsDepositTxMessage.class + ); + taskRunner.run(); + }); } private void handle(DelayedPayoutTxSignatureRequest tradeMessage, NodeAddress sender) { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> { - stopTimeout(); // We stop timeout here as last DepositTxAndDelayedPayoutTxMessage is not mandatory - handleTaskRunnerSuccess(tradeMessage, "handle DelayedPayoutTxSignatureRequest"); - }, - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); - taskRunner.addTasks( - BuyerProcessDelayedPayoutTxSignatureRequest.class, - BuyerVerifiesPreparedDelayedPayoutTx.class, - BuyerSignsDelayedPayoutTx.class, - BuyerSendsDelayedPayoutTxSignatureResponse.class - ); - taskRunner.run(); + ifInPhase(Trade.Phase.TAKER_FEE_PUBLISHED, tradeMessage) + .run(() -> { + processModel.setTradeMessage(tradeMessage); + processModel.setTempTradingPeerNodeAddress(sender); + + TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, + () -> { + stopTimeout(); // We stop timeout here as last DepositTxAndDelayedPayoutTxMessage is not mandatory + handleTaskRunnerSuccess(tradeMessage, "handle DelayedPayoutTxSignatureRequest"); + }, + errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + taskRunner.addTasks( + BuyerProcessDelayedPayoutTxSignatureRequest.class, + BuyerVerifiesPreparedDelayedPayoutTx.class, + BuyerSignsDelayedPayoutTx.class, + BuyerSendsDelayedPayoutTxSignatureResponse.class + ); + taskRunner.run(); + }); } // The DepositTxAndDelayedPayoutTxMessage is a mailbox message as earlier we use only the deposit tx which can @@ -208,7 +217,7 @@ private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress return; } - ifInPhase(Trade.Phase.TAKER_FEE_PUBLISHED, tradeMessage) + ifInPhase(Trade.Phase.TAKER_FEE_PUBLISHED, tradeMessage).orInPhase(Trade.Phase.DEPOSIT_PUBLISHED) .run(() -> { processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(peerNodeAddress); @@ -238,29 +247,27 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle checkArgument(!wasDisputed(), "A call to onFiatPaymentStarted is not permitted once a " + "dispute has been opened."); - if (!trade.isFiatSent()) { - buyerAsTakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); - - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess("onFiatPaymentStarted"); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(errorMessage); - }); - taskRunner.addTasks( - ApplyFilter.class, - TakerVerifyMakerFeePayment.class, - BuyerSignPayoutTx.class, - BuyerSetupPayoutTxListener.class, - BuyerSendCounterCurrencyTransferStartedMessage.class - ); - taskRunner.run(); - } else { - log.warn("onFiatPaymentStarted called twice. tradeState=" + trade.getState()); - } + ifInPhase(Trade.Phase.DEPOSIT_CONFIRMED) + .run(() -> { + buyerAsTakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); + TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess("onFiatPaymentStarted"); + }, + (errorMessage) -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(errorMessage); + }); + taskRunner.addTasks( + ApplyFilter.class, + TakerVerifyMakerFeePayment.class, + BuyerSignPayoutTx.class, + BuyerSetupPayoutTxListener.class, + BuyerSendCounterCurrencyTransferStartedMessage.class + ); + taskRunner.run(); + }); } @@ -269,18 +276,20 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle /////////////////////////////////////////////////////////////////////////////////////////// private void handle(PayoutTxPublishedMessage tradeMessage, NodeAddress peerNodeAddress) { - log.debug("handle PayoutTxPublishedMessage called"); - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(peerNodeAddress); - - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle PayoutTxPublishedMessage"), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); - - taskRunner.addTasks( - BuyerProcessPayoutTxPublishedMessage.class - ); - taskRunner.run(); + ifInPhase(Trade.Phase.FIAT_SENT, tradeMessage).orInPhase(Trade.Phase.PAYOUT_PUBLISHED) + .run(() -> { + processModel.setTradeMessage(tradeMessage); + processModel.setTempTradingPeerNodeAddress(peerNodeAddress); + + TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, + () -> handleTaskRunnerSuccess(tradeMessage, "handle PayoutTxPublishedMessage"), + errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + + taskRunner.addTasks( + BuyerProcessPayoutTxPublishedMessage.class + ); + taskRunner.run(); + }); } diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index f2504726a75..36a59fa627c 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -56,7 +56,9 @@ import java.security.PublicKey; -import lombok.Getter; +import java.util.HashSet; +import java.util.Set; + import lombok.extern.slf4j.Slf4j; import javax.annotation.Nullable; @@ -420,11 +422,14 @@ protected TradeStateValidation ifInPhase(Trade.Phase phase, } static class TradeStateValidation { - @Getter - private final boolean isValidPhase; + private final Trade trade; + private final Trade.Phase expectedPhase; + @Nullable + private final TradeMessage tradeMessage; + private Set alternativePhase = new HashSet<>(); protected TradeStateValidation run(Runnable runnable) { - if (isValidPhase) { + if (isValidPhase()) { runnable.run(); } return this; @@ -437,20 +442,35 @@ protected void otherWise(Runnable runnable) { public TradeStateValidation(Trade trade, Trade.Phase expectedPhase, @Nullable TradeMessage tradeMessage) { - isValidPhase = trade.getPhase() == expectedPhase; + this.trade = trade; + this.expectedPhase = expectedPhase; + this.tradeMessage = tradeMessage; + } + + public boolean isValidPhase() { + boolean isValidPhase = trade.getPhase() == expectedPhase || + (alternativePhase.stream().anyMatch(e -> e == trade.getPhase())); + if (!isValidPhase) { if (tradeMessage != null) { - log.error("We received a {} but we are not in the correct phase. Phase={}, State= {} ", + log.error("We received a {} but we are not in the correct phase. Expected phase={}, Trade phase={}, Trade state= {} ", tradeMessage.getClass().getSimpleName(), + expectedPhase, trade.getPhase(), trade.getState()); } else { - log.error("We are not in the correct phase. Phase={}, State= {} ", + log.error("We are not in the correct phase. Expected phase={}, Trade phase={}, Trade state= {} ", + expectedPhase, trade.getPhase(), trade.getState()); } } + return isValidPhase; } - } + public TradeStateValidation orInPhase(Trade.Phase phase) { + alternativePhase.add(phase); + return this; + } + } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java index 925e727b3da..1aa4c5d213d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java @@ -81,7 +81,6 @@ protected void run() { // update to the latest peer address of our peer if the message is correct trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress()); - trade.setState(Trade.State.TAKER_RECEIVED_PUBLISH_DEPOSIT_TX_REQUEST); complete(); } catch (Throwable t) { From 6fa2225b652684e354df0ad2fb615c94ccd1fc17 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 23 Sep 2020 01:48:02 -0500 Subject: [PATCH 043/143] Use fluent interface for checking state and conditions --- .../trade/protocol/BuyerAsMakerProtocol.java | 48 ++-- .../trade/protocol/BuyerAsTakerProtocol.java | 56 ++--- .../core/trade/protocol/BuyerProtocol.java | 4 + .../core/trade/protocol/MakerProtocol.java | 4 +- .../trade/protocol/SellerAsMakerProtocol.java | 218 ++++++++--------- .../trade/protocol/SellerAsTakerProtocol.java | 222 +++++++++--------- .../core/trade/protocol/SellerProtocol.java | 4 + .../core/trade/protocol/TakerProtocol.java | 4 + .../core/trade/protocol/TradeProtocol.java | 114 ++++++--- .../SellerSendPayoutTxPublishedMessage.java | 1 + .../steps/seller/SellerStep3View.java | 3 - 11 files changed, 357 insertions(+), 321 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 1b9bbdae49a..779d9b3c298 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -53,8 +53,6 @@ import lombok.extern.slf4j.Slf4j; -import static com.google.common.base.Preconditions.checkArgument; - @Slf4j public class BuyerAsMakerProtocol extends TradeProtocol implements BuyerProtocol, MakerProtocol { private final BuyerAsMakerTrade buyerAsMakerTrade; @@ -118,8 +116,9 @@ public void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress pe public void handleTakeOfferRequest(InputsForDepositTxRequest tradeMessage, NodeAddress peerNodeAddress, ErrorMessageHandler errorMessageHandler) { - ifInPhase(Trade.Phase.INIT, tradeMessage) - .run(() -> { + from(Trade.Phase.INIT) + .onMessage(tradeMessage) + .process(() -> { Validator.checkTradeId(processModel.getOfferId(), tradeMessage); processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(peerNodeAddress); @@ -151,8 +150,9 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest tradeMessage, /////////////////////////////////////////////////////////////////////////////////////////// private void handle(DelayedPayoutTxSignatureRequest tradeMessage, NodeAddress peerNodeAddress) { - ifInPhase(Trade.Phase.TAKER_FEE_PUBLISHED, tradeMessage) - .run(() -> { + from(Trade.Phase.TAKER_FEE_PUBLISHED) + .onMessage(tradeMessage) + .process(() -> { processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(peerNodeAddress); @@ -178,17 +178,17 @@ private void handle(DelayedPayoutTxSignatureRequest tradeMessage, NodeAddress pe // mailbox message but the stored in mailbox case is not expected and the seller would try to send the message again // in the hope to reach the buyer directly. private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress peerNodeAddress) { - if (trade.getDepositTx() != null && trade.getDelayedPayoutTx() != null) { - log.warn("We received a DepositTxAndDelayedPayoutTxMessage but we have already processed the deposit and " + - "delayed payout tx so we ignore the message. This can happen if the ACK message to the peer did not " + - "arrive and the peer repeats sending us the message. We send another ACK msg."); - sendAckMessage(tradeMessage, true, null); - processModel.removeMailboxMessageAfterProcessing(trade); - return; - } - - ifInPhase(Trade.Phase.TAKER_FEE_PUBLISHED, tradeMessage).orInPhase(Trade.Phase.DEPOSIT_PUBLISHED) - .run(() -> { + fromAny(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) + .onMessage(tradeMessage) + .condition(trade.getDepositTx() == null || trade.getDelayedPayoutTx() == null, + () -> { + log.warn("We received a DepositTxAndDelayedPayoutTxMessage but we have already processed the deposit and " + + "delayed payout tx so we ignore the message. This can happen if the ACK message to the peer did not " + + "arrive and the peer repeats sending us the message. We send another ACK msg."); + sendAckMessage(tradeMessage, true, null); + processModel.removeMailboxMessageAfterProcessing(trade); + }) + .process(() -> { processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(peerNodeAddress); TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, @@ -213,11 +213,10 @@ private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress @Override public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - checkArgument(!wasDisputed(), "A call to onFiatPaymentStarted is not permitted once a " + - "dispute has been opened."); - - ifInPhase(Trade.Phase.DEPOSIT_CONFIRMED) - .run(() -> { + from(Trade.Phase.DEPOSIT_CONFIRMED) + .onEvent(BuyerEvent.PAYMENT_SENT) + .condition(!wasDisputed()) + .process(() -> { buyerAsMakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, () -> { @@ -245,8 +244,9 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle /////////////////////////////////////////////////////////////////////////////////////////// private void handle(PayoutTxPublishedMessage tradeMessage, NodeAddress peerNodeAddress) { - ifInPhase(Trade.Phase.FIAT_SENT, tradeMessage).orInPhase(Trade.Phase.PAYOUT_PUBLISHED) - .run(() -> { + fromAny(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) + .onMessage(tradeMessage) + .process(() -> { processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(peerNodeAddress); diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index fabdc84a548..b331a215fa9 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -57,7 +57,6 @@ import lombok.extern.slf4j.Slf4j; -import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @Slf4j @@ -125,8 +124,9 @@ public void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress pe @Override public void takeAvailableOffer() { - ifInPhase(Trade.Phase.INIT) - .run(() -> { + from(Trade.Phase.INIT) + .onEvent(TakerEvent.TAKE_OFFER) + .process(() -> { processModel.setTempTradingPeerNodeAddress(trade.getTradingPeerNodeAddress()); TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, () -> handleTaskRunnerSuccess("takeAvailableOffer"), @@ -153,8 +153,9 @@ public void takeAvailableOffer() { /////////////////////////////////////////////////////////////////////////////////////////// private void handle(InputsForDepositTxResponse tradeMessage, NodeAddress sender) { - ifInPhase(Trade.Phase.INIT, tradeMessage) - .run(() -> { + from(Trade.Phase.INIT) + .onMessage(tradeMessage) + .process(() -> { processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(sender); @@ -178,8 +179,9 @@ private void handle(InputsForDepositTxResponse tradeMessage, NodeAddress sender) } private void handle(DelayedPayoutTxSignatureRequest tradeMessage, NodeAddress sender) { - ifInPhase(Trade.Phase.TAKER_FEE_PUBLISHED, tradeMessage) - .run(() -> { + from(Trade.Phase.TAKER_FEE_PUBLISHED) + .onMessage(tradeMessage) + .process(() -> { processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(sender); @@ -208,17 +210,17 @@ private void handle(DelayedPayoutTxSignatureRequest tradeMessage, NodeAddress se // mailbox message but the stored in mailbox case is not expected and the seller would try to send the message again // in the hope to reach the buyer directly. private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress peerNodeAddress) { - if (trade.getDepositTx() != null && trade.getDelayedPayoutTx() != null) { - log.warn("We received a DepositTxAndDelayedPayoutTxMessage but we have already processed the deposit and " + - "delayed payout tx so we ignore the message. This can happen if the ACK message to the peer did not " + - "arrive and the peer repeats sending us the message. We send another ACK msg."); - sendAckMessage(tradeMessage, true, null); - processModel.removeMailboxMessageAfterProcessing(trade); - return; - } - - ifInPhase(Trade.Phase.TAKER_FEE_PUBLISHED, tradeMessage).orInPhase(Trade.Phase.DEPOSIT_PUBLISHED) - .run(() -> { + fromAny(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) + .onMessage(tradeMessage) + .condition(trade.getDepositTx() == null || trade.getDelayedPayoutTx() == null, + () -> { + log.warn("We received a DepositTxAndDelayedPayoutTxMessage but we have already processed the deposit and " + + "delayed payout tx so we ignore the message. This can happen if the ACK message to the peer did not " + + "arrive and the peer repeats sending us the message. We send another ACK msg."); + sendAckMessage(tradeMessage, true, null); + processModel.removeMailboxMessageAfterProcessing(trade); + }) + .process(() -> { processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(peerNodeAddress); TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, @@ -231,9 +233,7 @@ private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress ); taskRunner.run(); processModel.witnessDebugLog(buyerAsTakerTrade); - }).otherWise(() -> { - log.warn(""); - }); + }); } @@ -244,11 +244,10 @@ private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress // User clicked the "bank transfer started" button @Override public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - checkArgument(!wasDisputed(), "A call to onFiatPaymentStarted is not permitted once a " + - "dispute has been opened."); - - ifInPhase(Trade.Phase.DEPOSIT_CONFIRMED) - .run(() -> { + from(Trade.Phase.DEPOSIT_CONFIRMED) + .onEvent(BuyerEvent.PAYMENT_SENT) + .condition(!wasDisputed()) + .process(() -> { buyerAsTakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, () -> { @@ -276,8 +275,9 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle /////////////////////////////////////////////////////////////////////////////////////////// private void handle(PayoutTxPublishedMessage tradeMessage, NodeAddress peerNodeAddress) { - ifInPhase(Trade.Phase.FIAT_SENT, tradeMessage).orInPhase(Trade.Phase.PAYOUT_PUBLISHED) - .run(() -> { + fromAny(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) + .onMessage(tradeMessage) + .process(() -> { processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(peerNodeAddress); 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 a93b8e6931b..96c3f62b916 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java @@ -22,4 +22,8 @@ public interface BuyerProtocol { void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler); + + enum BuyerEvent implements TradeProtocol.Event { + PAYMENT_SENT + } } diff --git a/core/src/main/java/bisq/core/trade/protocol/MakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/MakerProtocol.java index d460289e3fc..349e677a702 100644 --- a/core/src/main/java/bisq/core/trade/protocol/MakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/MakerProtocol.java @@ -25,5 +25,7 @@ import bisq.common.handlers.ErrorMessageHandler; public interface MakerProtocol { - void handleTakeOfferRequest(InputsForDepositTxRequest message, NodeAddress taker, ErrorMessageHandler errorMessageHandler); + void handleTakeOfferRequest(InputsForDepositTxRequest message, + NodeAddress taker, + ErrorMessageHandler errorMessageHandler); } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index 75bcb32926d..ddb17ca23fb 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -56,8 +56,6 @@ import lombok.extern.slf4j.Slf4j; -import static com.google.common.base.Preconditions.checkArgument; - @Slf4j public class SellerAsMakerProtocol extends TradeProtocol implements SellerProtocol, MakerProtocol { private final SellerAsMakerTrade sellerAsMakerTrade; @@ -96,29 +94,33 @@ public void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress pe public void handleTakeOfferRequest(InputsForDepositTxRequest tradeMessage, NodeAddress sender, ErrorMessageHandler errorMessageHandler) { - Validator.checkTradeId(processModel.getOfferId(), tradeMessage); - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handleTakeOfferRequest"), - errorMessage -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(tradeMessage, errorMessage); - }); + from(Trade.Phase.INIT) + .onMessage(tradeMessage) + .process(() -> { + Validator.checkTradeId(processModel.getOfferId(), tradeMessage); + processModel.setTradeMessage(tradeMessage); + processModel.setTempTradingPeerNodeAddress(sender); + + TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, + () -> handleTaskRunnerSuccess(tradeMessage, "handleTakeOfferRequest"), + errorMessage -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(tradeMessage, errorMessage); + }); - taskRunner.addTasks( - MakerProcessesInputsForDepositTxRequest.class, - ApplyFilter.class, - VerifyPeersAccountAgeWitness.class, - MakerVerifyTakerFeePayment.class, - MakerSetsLockTime.class, - MakerCreateAndSignContract.class, - SellerAsMakerCreatesUnsignedDepositTx.class, - SellerAsMakerSendsInputsForDepositTxResponse.class - ); - - taskRunner.run(); + taskRunner.addTasks( + MakerProcessesInputsForDepositTxRequest.class, + ApplyFilter.class, + VerifyPeersAccountAgeWitness.class, + MakerVerifyTakerFeePayment.class, + MakerSetsLockTime.class, + MakerCreateAndSignContract.class, + SellerAsMakerCreatesUnsignedDepositTx.class, + SellerAsMakerSendsInputsForDepositTxResponse.class + ); + + taskRunner.run(); + }); } @@ -127,43 +129,51 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest tradeMessage, /////////////////////////////////////////////////////////////////////////////////////////// protected void handle(DepositTxMessage tradeMessage, NodeAddress sender) { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle DepositTxMessage"), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); - - taskRunner.addTasks( - SellerAsMakerProcessDepositTxMessage.class, - SellerAsMakerFinalizesDepositTx.class, - SellerCreatesDelayedPayoutTx.class, - SellerSendDelayedPayoutTxSignatureRequest.class - ); - taskRunner.run(); + from(Trade.Phase.TAKER_FEE_PUBLISHED) + .onMessage(tradeMessage) + .process(() -> { + processModel.setTradeMessage(tradeMessage); + processModel.setTempTradingPeerNodeAddress(sender); + + TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, + () -> handleTaskRunnerSuccess(tradeMessage, "handle DepositTxMessage"), + errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + + taskRunner.addTasks( + SellerAsMakerProcessDepositTxMessage.class, + SellerAsMakerFinalizesDepositTx.class, + SellerCreatesDelayedPayoutTx.class, + SellerSendDelayedPayoutTxSignatureRequest.class + ); + taskRunner.run(); + }); } private void handle(DelayedPayoutTxSignatureResponse tradeMessage, NodeAddress sender) { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, - () -> { - stopTimeout(); - handleTaskRunnerSuccess(tradeMessage, "handle DelayedPayoutTxSignatureResponse"); - }, - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); - - taskRunner.addTasks( - SellerProcessDelayedPayoutTxSignatureResponse.class, - SellerSignsDelayedPayoutTx.class, - SellerFinalizesDelayedPayoutTx.class, - SellerSendsDepositTxAndDelayedPayoutTxMessage.class, - SellerPublishesDepositTx.class, - PublishTradeStatistics.class - ); - taskRunner.run(); - processModel.witnessDebugLog(sellerAsMakerTrade); + from(Trade.Phase.TAKER_FEE_PUBLISHED) + .onMessage(tradeMessage) + .process(() -> { + processModel.setTradeMessage(tradeMessage); + processModel.setTempTradingPeerNodeAddress(sender); + + TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, + () -> { + stopTimeout(); + handleTaskRunnerSuccess(tradeMessage, "handle DelayedPayoutTxSignatureResponse"); + }, + errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + + taskRunner.addTasks( + SellerProcessDelayedPayoutTxSignatureResponse.class, + SellerSignsDelayedPayoutTx.class, + SellerFinalizesDelayedPayoutTx.class, + SellerSendsDepositTxAndDelayedPayoutTxMessage.class, + SellerPublishesDepositTx.class, + PublishTradeStatistics.class + ); + taskRunner.run(); + processModel.witnessDebugLog(sellerAsMakerTrade); + }); } @@ -172,17 +182,17 @@ private void handle(DelayedPayoutTxSignatureResponse tradeMessage, NodeAddress s /////////////////////////////////////////////////////////////////////////////////////////// private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddress sender) { - if (trade.getPayoutTx() != null) { - log.warn("We received a CounterCurrencyTransferStartedMessage but we have already created the payout tx " + - "so we ignore the message. This can happen if the ACK message to the peer did not " + - "arrive and the peer repeats sending us the message. We send another ACK msg."); - sendAckMessage(tradeMessage, true, null); - processModel.removeMailboxMessageAfterProcessing(trade); - return; - } - - ifInPhase(Trade.Phase.DEPOSIT_CONFIRMED, tradeMessage) - .run(() -> { + from(Trade.Phase.DEPOSIT_CONFIRMED) + .onMessage(tradeMessage) + .condition(trade.getPayoutTx() == null, + () -> { + log.warn("We received a CounterCurrencyTransferStartedMessage but we have already created the payout tx " + + "so we ignore the message. This can happen if the ACK message to the peer did not " + + "arrive and the peer repeats sending us the message. We send another ACK msg."); + sendAckMessage(tradeMessage, true, null); + processModel.removeMailboxMessageAfterProcessing(trade); + }) + .process(() -> { processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(sender); @@ -206,52 +216,30 @@ private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddr @Override public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - checkArgument(!wasDisputed(), "A call to onFiatPaymentReceived is not permitted once a " + - "dispute has been opened."); - - if (trade.getPayoutTx() == null) { - sellerAsMakerTrade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess("onFiatPaymentReceived 1"); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(errorMessage); - }); - - taskRunner.addTasks( - ApplyFilter.class, - MakerVerifyTakerFeePayment.class, - SellerSignAndFinalizePayoutTx.class, - SellerBroadcastPayoutTx.class, - SellerSendPayoutTxPublishedMessage.class - ); - taskRunner.run(); - } else { - // we don't set the state as we have already a later phase reached - log.info("onFiatPaymentReceived called twice. " + - "That can happen if message did not arrive the first time and we send msg again.\n" + - "state=" + sellerAsMakerTrade.getState()); - - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess("onFiatPaymentReceived 2"); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(errorMessage); - }); - - taskRunner.addTasks( - ApplyFilter.class, - MakerVerifyTakerFeePayment.class, - SellerSendPayoutTxPublishedMessage.class - ); - taskRunner.run(); - } + from(Trade.Phase.FIAT_SENT) + .onEvent(SellerEvent.PAYMENT_RECEIVED) + .condition(!wasDisputed()) + .process(() -> { + sellerAsMakerTrade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); + TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess("onFiatPaymentReceived"); + }, + (errorMessage) -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(errorMessage); + }); + + taskRunner.addTasks( + ApplyFilter.class, + MakerVerifyTakerFeePayment.class, + SellerSignAndFinalizePayoutTx.class, + SellerBroadcastPayoutTx.class, + SellerSendPayoutTxPublishedMessage.class + ); + taskRunner.run(); + }); } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 94a0fb6b35d..4bf7ea63381 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -55,7 +55,6 @@ import lombok.extern.slf4j.Slf4j; -import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @Slf4j @@ -97,21 +96,25 @@ public void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress pe @Override public void takeAvailableOffer() { - processModel.setTempTradingPeerNodeAddress(trade.getTradingPeerNodeAddress()); - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, - () -> handleTaskRunnerSuccess("takeAvailableOffer"), - this::handleTaskRunnerFault); - - taskRunner.addTasks( - ApplyFilter.class, - TakerVerifyMakerFeePayment.class, - CreateTakerFeeTx.class, - SellerAsTakerCreatesDepositTxInputs.class, - TakerSendInputsForDepositTxRequest.class - ); - - startTimeout(); - taskRunner.run(); + from(Trade.Phase.INIT) + .onEvent(TakerEvent.TAKE_OFFER) + .process(() -> { + processModel.setTempTradingPeerNodeAddress(trade.getTradingPeerNodeAddress()); + TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, + () -> handleTaskRunnerSuccess("takeAvailableOffer"), + this::handleTaskRunnerFault); + + taskRunner.addTasks( + ApplyFilter.class, + TakerVerifyMakerFeePayment.class, + CreateTakerFeeTx.class, // + SellerAsTakerCreatesDepositTxInputs.class, + TakerSendInputsForDepositTxRequest.class + ); + + startTimeout(); + taskRunner.run(); + }); } @@ -120,49 +123,57 @@ public void takeAvailableOffer() { /////////////////////////////////////////////////////////////////////////////////////////// private void handle(InputsForDepositTxResponse tradeMessage, NodeAddress sender) { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, - () -> { - handleTaskRunnerSuccess(tradeMessage, "handle InputsForDepositTxResponse"); - }, - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); - - taskRunner.addTasks( - TakerProcessesInputsForDepositTxResponse.class, - ApplyFilter.class, - VerifyPeersAccountAgeWitness.class, - TakerVerifyAndSignContract.class, - TakerPublishFeeTx.class, - SellerAsTakerSignsDepositTx.class, - SellerCreatesDelayedPayoutTx.class, - SellerSendDelayedPayoutTxSignatureRequest.class - ); - taskRunner.run(); + from(Trade.Phase.INIT) + .onMessage(tradeMessage) + .process(() -> { + processModel.setTradeMessage(tradeMessage); + processModel.setTempTradingPeerNodeAddress(sender); + + TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, + () -> { + handleTaskRunnerSuccess(tradeMessage, "handle InputsForDepositTxResponse"); + }, + errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + + taskRunner.addTasks( + TakerProcessesInputsForDepositTxResponse.class, + ApplyFilter.class, + VerifyPeersAccountAgeWitness.class, + TakerVerifyAndSignContract.class, + TakerPublishFeeTx.class, + SellerAsTakerSignsDepositTx.class, + SellerCreatesDelayedPayoutTx.class, + SellerSendDelayedPayoutTxSignatureRequest.class + ); + taskRunner.run(); + }); } private void handle(DelayedPayoutTxSignatureResponse tradeMessage, NodeAddress sender) { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, - () -> { - stopTimeout(); - handleTaskRunnerSuccess(tradeMessage, "handle DelayedPayoutTxSignatureResponse"); - }, - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); - - taskRunner.addTasks( - SellerProcessDelayedPayoutTxSignatureResponse.class, - SellerSignsDelayedPayoutTx.class, - SellerFinalizesDelayedPayoutTx.class, - SellerSendsDepositTxAndDelayedPayoutTxMessage.class, - SellerPublishesDepositTx.class, - PublishTradeStatistics.class - ); - taskRunner.run(); - processModel.witnessDebugLog(sellerAsTakerTrade); + from(Trade.Phase.TAKER_FEE_PUBLISHED) + .onMessage(tradeMessage) + .process(() -> { + processModel.setTradeMessage(tradeMessage); + processModel.setTempTradingPeerNodeAddress(sender); + + TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, + () -> { + stopTimeout(); + handleTaskRunnerSuccess(tradeMessage, "handle DelayedPayoutTxSignatureResponse"); + }, + errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + + taskRunner.addTasks( + SellerProcessDelayedPayoutTxSignatureResponse.class, + SellerSignsDelayedPayoutTx.class, + SellerFinalizesDelayedPayoutTx.class, + SellerSendsDepositTxAndDelayedPayoutTxMessage.class, // SEND_MSG(DepositTxAndDelayedPayoutTxMessage) + SellerPublishesDepositTx.class, // PUBLISH_DEPOSIT_TX + PublishTradeStatistics.class + ); + taskRunner.run(); + processModel.witnessDebugLog(sellerAsTakerTrade); + }); } @@ -171,17 +182,26 @@ private void handle(DelayedPayoutTxSignatureResponse tradeMessage, NodeAddress s /////////////////////////////////////////////////////////////////////////////////////////// private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddress sender) { - if (trade.getPayoutTx() != null) { - log.warn("We received a CounterCurrencyTransferStartedMessage but we have already created the payout tx " + - "so we ignore the message. This can happen if the ACK message to the peer did not " + - "arrive and the peer repeats sending us the message. We send another ACK msg."); - sendAckMessage(tradeMessage, true, null); - processModel.removeMailboxMessageAfterProcessing(trade); - return; - } + from(Trade.Phase.DEPOSIT_CONFIRMED) + .onMessage(tradeMessage) + .condition(trade.getPayoutTx() == null, + () -> { + log.warn("We received a CounterCurrencyTransferStartedMessage but we have already created the payout tx " + + "so we ignore the message. This can happen if the ACK message to the peer did not " + + "arrive and the peer repeats sending us the message. We send another ACK msg."); + sendAckMessage(tradeMessage, true, null); + processModel.removeMailboxMessageAfterProcessing(trade); + }) + .process(() -> { + if (trade.getPayoutTx() != null) { + log.warn("We received a CounterCurrencyTransferStartedMessage but we have already created the payout tx " + + "so we ignore the message. This can happen if the ACK message to the peer did not " + + "arrive and the peer repeats sending us the message. We send another ACK msg."); + sendAckMessage(tradeMessage, true, null); + processModel.removeMailboxMessageAfterProcessing(trade); + return; + } - ifInPhase(Trade.Phase.DEPOSIT_CONFIRMED, tradeMessage) - .run(() -> { processModel.setTradeMessage(tradeMessage); processModel.setTempTradingPeerNodeAddress(sender); @@ -205,52 +225,30 @@ private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddr @Override public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - checkArgument(!wasDisputed(), "A call to onFiatPaymentReceived is not permitted once a " + - "dispute has been opened."); - - if (trade.getPayoutTx() == null) { - sellerAsTakerTrade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess("onFiatPaymentReceived 1"); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(errorMessage); - }); - - taskRunner.addTasks( - ApplyFilter.class, - TakerVerifyMakerFeePayment.class, - SellerSignAndFinalizePayoutTx.class, - SellerBroadcastPayoutTx.class, - SellerSendPayoutTxPublishedMessage.class - ); - taskRunner.run(); - } else { - // we don't set the state as we have already a higher phase reached - log.info("onFiatPaymentReceived called twice. " + - "That can happen if message did not arrive the first time and we send msg again.\n" + - "state=" + sellerAsTakerTrade.getState()); - - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess("onFiatPaymentReceived 2"); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(errorMessage); - }); - - taskRunner.addTasks( - ApplyFilter.class, - TakerVerifyMakerFeePayment.class, - SellerSendPayoutTxPublishedMessage.class - ); - taskRunner.run(); - } + from(Trade.Phase.FIAT_SENT) + .onEvent(SellerEvent.PAYMENT_RECEIVED) + .condition(!wasDisputed()) + .process(() -> { + sellerAsTakerTrade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); + TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess("onFiatPaymentReceived"); + }, + (errorMessage) -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(errorMessage); + }); + + taskRunner.addTasks( + ApplyFilter.class, + TakerVerifyMakerFeePayment.class, + SellerSignAndFinalizePayoutTx.class, + SellerBroadcastPayoutTx.class, + SellerSendPayoutTxPublishedMessage.class //TODO add repeated msg send, check UI + ); + taskRunner.run(); + }); } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java index 7c54686b585..958534936dd 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java @@ -22,4 +22,8 @@ public interface SellerProtocol { void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler); + + enum SellerEvent implements TradeProtocol.Event { + PAYMENT_RECEIVED + } } diff --git a/core/src/main/java/bisq/core/trade/protocol/TakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TakerProtocol.java index 37e3d18c914..a9576db8a33 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TakerProtocol.java @@ -19,4 +19,8 @@ public interface TakerProtocol { void takeAvailableOffer(); + + enum TakerEvent implements TradeProtocol.Event { + TAKE_OFFER + } } diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index 36a59fa627c..2b01b78db69 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -68,6 +68,10 @@ @Slf4j public abstract class TradeProtocol { + interface Event { + String name(); + } + private static final long TIMEOUT = 180; protected final ProcessModel processModel; @@ -412,64 +416,98 @@ private void cleanupTradeOnFault() { } } - protected TradeStateValidation ifInPhase(Trade.Phase phase) { - return new TradeStateValidation(trade, phase, null); + + /////////////////////////////////////////////////////////////////////////////////////////// + // FluentProcess + /////////////////////////////////////////////////////////////////////////////////////////// + + protected FluentProcess from(Trade.Phase phase) { + return new FluentProcess(trade, phase); } - protected TradeStateValidation ifInPhase(Trade.Phase phase, - @Nullable TradeMessage tradeMessage) { - return new TradeStateValidation(trade, phase, tradeMessage); + protected FluentProcess fromAny(Trade.Phase... phase) { + return new FluentProcess(trade, phase); } - static class TradeStateValidation { + static class FluentProcess { private final Trade trade; - private final Trade.Phase expectedPhase; @Nullable - private final TradeMessage tradeMessage; - private Set alternativePhase = new HashSet<>(); + private TradeMessage tradeMessage; + private final Set expectedPhases = new HashSet<>(); + @Nullable + private Event event; + private boolean condition = true; + private Runnable conditionFailedHandler; - protected TradeStateValidation run(Runnable runnable) { - if (isValidPhase()) { + protected FluentProcess process(Runnable runnable) { + if (isPhaseValid() && condition) { runnable.run(); } + if (!condition && conditionFailedHandler != null) { + conditionFailedHandler.run(); + } return this; } - protected void otherWise(Runnable runnable) { - runnable.run(); + public FluentProcess(Trade trade, + Trade.Phase expectedPhase) { + this.trade = trade; + this.expectedPhases.add(expectedPhase); } - public TradeStateValidation(Trade trade, - Trade.Phase expectedPhase, - @Nullable TradeMessage tradeMessage) { + public FluentProcess(Trade trade, + Trade.Phase... expectedPhases) { this.trade = trade; - this.expectedPhase = expectedPhase; - this.tradeMessage = tradeMessage; + this.expectedPhases.addAll(Set.of(expectedPhases)); } - public boolean isValidPhase() { - boolean isValidPhase = trade.getPhase() == expectedPhase || - (alternativePhase.stream().anyMatch(e -> e == trade.getPhase())); - - if (!isValidPhase) { - if (tradeMessage != null) { - log.error("We received a {} but we are not in the correct phase. Expected phase={}, Trade phase={}, Trade state= {} ", - tradeMessage.getClass().getSimpleName(), - expectedPhase, - trade.getPhase(), - trade.getState()); - } else { - log.error("We are not in the correct phase. Expected phase={}, Trade phase={}, Trade state= {} ", - expectedPhase, - trade.getPhase(), - trade.getState()); - } + private boolean isPhaseValid() { + boolean isPhaseValid = expectedPhases.stream().anyMatch(e -> e == trade.getPhase()); + String trigger = tradeMessage != null ? + tradeMessage.getClass().getSimpleName() : + event != null ? + event.name() + " event" : + ""; + if (isPhaseValid) { + log.info("We received {} at phase {} and state {}", + trigger, + trade.getPhase(), + trade.getState()); + } else { + log.error("We received {} but we are are not in the correct phase. Expected phases={}, " + + "Trade phase={}, Trade state= {} ", + trigger, + expectedPhases, + trade.getPhase(), + trade.getState()); } - return isValidPhase; + + return isPhaseValid; + } + + public FluentProcess orInPhase(Trade.Phase phase) { + expectedPhases.add(phase); + return this; + } + + public FluentProcess onEvent(Event event) { + this.event = event; + return this; + } + + public FluentProcess onMessage(TradeMessage tradeMessage) { + this.tradeMessage = tradeMessage; + return this; + } + + public FluentProcess condition(boolean condition) { + this.condition = condition; + return this; } - public TradeStateValidation orInPhase(Trade.Phase phase) { - alternativePhase.add(phase); + public FluentProcess condition(boolean condition, Runnable conditionFailedHandler) { + this.condition = condition; + this.conditionFailedHandler = conditionFailedHandler; return this; } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendPayoutTxPublishedMessage.java index db73f1910a6..80599ef7b66 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendPayoutTxPublishedMessage.java @@ -33,6 +33,7 @@ import static com.google.common.base.Preconditions.checkNotNull; +//TODO add repeated msg send @EqualsAndHashCode(callSuper = true) @Slf4j public class SellerSendPayoutTxPublishedMessage extends SendMailboxMessageTask { diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java index e9136153b1e..eb0ef46b91d 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java @@ -45,7 +45,6 @@ import bisq.core.payment.payload.USPostalMoneyOrderAccountPayload; import bisq.core.payment.payload.WesternUnionAccountPayload; import bisq.core.trade.Contract; -import bisq.core.trade.Trade; import bisq.core.trade.txproof.AssetTxProofResult; import bisq.core.user.DontShowAgainLookup; @@ -458,8 +457,6 @@ private void confirmPaymentReceived() { log.info("User pressed the [Confirm payment receipt] button for Trade {}", trade.getShortId()); busyAnimation.play(); statusLabel.setText(Res.get("shared.sendingConfirmation")); - if (!trade.isPayoutPublished()) - trade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); model.dataModel.onFiatPaymentReceived(() -> { // In case the first send failed we got the support button displayed. From de008457cb22cbfc91f345b3ade976d776dd6890 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 23 Sep 2020 08:28:04 -0500 Subject: [PATCH 044/143] Remove empty file (from merge) --- core/src/main/java/bisq/core/trade/DelayedPayoutTxValidation.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 core/src/main/java/bisq/core/trade/DelayedPayoutTxValidation.java diff --git a/core/src/main/java/bisq/core/trade/DelayedPayoutTxValidation.java b/core/src/main/java/bisq/core/trade/DelayedPayoutTxValidation.java deleted file mode 100644 index e69de29bb2d..00000000000 From 2b53312af9ca102a46532baee7b331c00a8d9de2 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 23 Sep 2020 12:07:38 -0500 Subject: [PATCH 045/143] Various improvements - Add time outs per request/response cycle. - Use custom timeouts - Stop timeout if condition not met - Allow multiple condition calls (all need to be true) - Move processModel.setTradeMessage(tradeMessage); and processModel.setTempTradingPeerNodeAddress(peerNodeAddress); calls to FluentProcess - Add Validator.isTradeIdValid method - Replace Validator.checkTradeId(processModel.getOfferId(), tradeMessage); by isTradeIdValid in FluentProcess - Add DisputeEvent - Derive info string from message or event at handleTaskRunnerSuccess - Add from method - Add withTimeout method - Add BuyerEvent.STARTUP - Rename onMessage to on - Rename onEvent to on - Rename tradeMesage to message - Rename sener/peerNodeAddress to peer --- .../trade/protocol/BuyerAsMakerProtocol.java | 98 +++++++-------- .../trade/protocol/BuyerAsTakerProtocol.java | 115 ++++++++---------- .../core/trade/protocol/BuyerProtocol.java | 1 + .../trade/protocol/SellerAsMakerProtocol.java | 88 ++++++-------- .../trade/protocol/SellerAsTakerProtocol.java | 87 ++++++------- .../core/trade/protocol/TradeProtocol.java | 112 ++++++++++++----- .../BuyerAsTakerCreatesDepositTxInputs.java | 2 +- .../main/java/bisq/core/util/Validator.java | 6 +- 8 files changed, 273 insertions(+), 236 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 779d9b3c298..7dcc253f65d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -44,7 +44,6 @@ import bisq.core.trade.protocol.tasks.maker.MakerProcessesInputsForDepositTxRequest; import bisq.core.trade.protocol.tasks.maker.MakerSetsLockTime; import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment; -import bisq.core.util.Validator; import bisq.network.p2p.NodeAddress; @@ -70,14 +69,14 @@ public BuyerAsMakerProtocol(BuyerAsMakerTrade trade) { Trade.Phase phase = trade.getState().getPhase(); if (phase == Trade.Phase.TAKER_FEE_PUBLISHED) { TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess("BuyerSetupDepositTxListener at startup"), + () -> handleTaskRunnerSuccess(BuyerEvent.STARTUP), this::handleTaskRunnerFault); taskRunner.addTasks(BuyerSetupDepositTxListener.class); taskRunner.run(); } else if (trade.isFiatSent() && !trade.isPayoutPublished()) { TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess("BuyerSetupPayoutTxListener at startup"), + () -> handleTaskRunnerSuccess(BuyerEvent.STARTUP), this::handleTaskRunnerFault); taskRunner.addTasks(BuyerSetupPayoutTxListener.class); @@ -97,13 +96,13 @@ public BuyerAsMakerProtocol(BuyerAsMakerTrade trade) { /////////////////////////////////////////////////////////////////////////////////////////// @Override - public void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress peerNodeAddress) { - super.doApplyMailboxTradeMessage(tradeMessage, peerNodeAddress); + public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peer) { + super.doApplyMailboxTradeMessage(message, peer); - if (tradeMessage instanceof DepositTxAndDelayedPayoutTxMessage) { - handle((DepositTxAndDelayedPayoutTxMessage) tradeMessage, peerNodeAddress); - } else if (tradeMessage instanceof PayoutTxPublishedMessage) { - handle((PayoutTxPublishedMessage) tradeMessage, peerNodeAddress); + if (message instanceof DepositTxAndDelayedPayoutTxMessage) { + handle((DepositTxAndDelayedPayoutTxMessage) message, peer); + } else if (message instanceof PayoutTxPublishedMessage) { + handle((PayoutTxPublishedMessage) message, peer); } } @@ -113,18 +112,16 @@ public void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress pe /////////////////////////////////////////////////////////////////////////////////////////// @Override - public void handleTakeOfferRequest(InputsForDepositTxRequest tradeMessage, - NodeAddress peerNodeAddress, + public void handleTakeOfferRequest(InputsForDepositTxRequest message, + NodeAddress peer, ErrorMessageHandler errorMessageHandler) { from(Trade.Phase.INIT) - .onMessage(tradeMessage) + .on(message) + .from(peer) + .withTimeout(30) .process(() -> { - Validator.checkTradeId(processModel.getOfferId(), tradeMessage); - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(peerNodeAddress); - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handleTakeOfferRequest"), + () -> handleTaskRunnerSuccess(message), errorMessage -> { errorMessageHandler.handleErrorMessage(errorMessage); handleTaskRunnerFault(errorMessage); @@ -149,16 +146,15 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest tradeMessage, // Incoming messages Take offer process /////////////////////////////////////////////////////////////////////////////////////////// - private void handle(DelayedPayoutTxSignatureRequest tradeMessage, NodeAddress peerNodeAddress) { + private void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { from(Trade.Phase.TAKER_FEE_PUBLISHED) - .onMessage(tradeMessage) + .on(message) + .from(peer) + .withTimeout(30) .process(() -> { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(peerNodeAddress); - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle DelayedPayoutTxSignatureRequest"), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + () -> handleTaskRunnerSuccess(message), + errorMessage -> handleTaskRunnerFault(message, errorMessage)); taskRunner.addTasks( BuyerProcessDelayedPayoutTxSignatureRequest.class, BuyerVerifiesPreparedDelayedPayoutTx.class, @@ -177,23 +173,26 @@ private void handle(DelayedPayoutTxSignatureRequest tradeMessage, NodeAddress pe // For backward compatibility and extra resilience we still keep DepositTxAndDelayedPayoutTxMessage as a // mailbox message but the stored in mailbox case is not expected and the seller would try to send the message again // in the hope to reach the buyer directly. - private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress peerNodeAddress) { + private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer) { fromAny(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) - .onMessage(tradeMessage) + .on(message) + .from(peer) .condition(trade.getDepositTx() == null || trade.getDelayedPayoutTx() == null, () -> { log.warn("We received a DepositTxAndDelayedPayoutTxMessage but we have already processed the deposit and " + "delayed payout tx so we ignore the message. This can happen if the ACK message to the peer did not " + "arrive and the peer repeats sending us the message. We send another ACK msg."); - sendAckMessage(tradeMessage, true, null); + stopTimeout(); + sendAckMessage(message, true, null); processModel.removeMailboxMessageAfterProcessing(trade); }) .process(() -> { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(peerNodeAddress); TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle DepositTxAndDelayedPayoutTxMessage"), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + () -> { + stopTimeout(); + handleTaskRunnerSuccess(message); + }, + errorMessage -> handleTaskRunnerFault(message, errorMessage)); taskRunner.addTasks( BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, BuyerVerifiesFinalDelayedPayoutTx.class, @@ -214,14 +213,14 @@ private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress @Override public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { from(Trade.Phase.DEPOSIT_CONFIRMED) - .onEvent(BuyerEvent.PAYMENT_SENT) + .on(BuyerEvent.PAYMENT_SENT) .condition(!wasDisputed()) .process(() -> { buyerAsMakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, () -> { resultHandler.handleResult(); - handleTaskRunnerSuccess("onFiatPaymentStarted"); + handleTaskRunnerSuccess(BuyerEvent.PAYMENT_SENT); }, (errorMessage) -> { errorMessageHandler.handleErrorMessage(errorMessage); @@ -243,16 +242,17 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle // Incoming message Payout tx /////////////////////////////////////////////////////////////////////////////////////////// - private void handle(PayoutTxPublishedMessage tradeMessage, NodeAddress peerNodeAddress) { + private void handle(PayoutTxPublishedMessage message, NodeAddress peer) { fromAny(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) - .onMessage(tradeMessage) + .on(message) + .from(peer) .process(() -> { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(peerNodeAddress); + processModel.setTradeMessage(message); + processModel.setTempTradingPeerNodeAddress(peer); TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle PayoutTxPublishedMessage"), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + () -> handleTaskRunnerSuccess(message), + errorMessage -> handleTaskRunnerFault(message, errorMessage)); taskRunner.addTasks( BuyerProcessPayoutTxPublishedMessage.class @@ -267,18 +267,18 @@ private void handle(PayoutTxPublishedMessage tradeMessage, NodeAddress peerNodeA /////////////////////////////////////////////////////////////////////////////////////////// @Override - protected void doHandleDecryptedMessage(TradeMessage tradeMessage, NodeAddress sender) { - super.doHandleDecryptedMessage(tradeMessage, sender); + protected void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer) { + super.doHandleDecryptedMessage(message, peer); log.info("Received {} from {} with tradeId {} and uid {}", - tradeMessage.getClass().getSimpleName(), sender, tradeMessage.getTradeId(), tradeMessage.getUid()); - - if (tradeMessage instanceof DelayedPayoutTxSignatureRequest) { - handle((DelayedPayoutTxSignatureRequest) tradeMessage, sender); - } else if (tradeMessage instanceof DepositTxAndDelayedPayoutTxMessage) { - handle((DepositTxAndDelayedPayoutTxMessage) tradeMessage, sender); - } else if (tradeMessage instanceof PayoutTxPublishedMessage) { - handle((PayoutTxPublishedMessage) tradeMessage, sender); + message.getClass().getSimpleName(), peer, message.getTradeId(), message.getUid()); + + if (message instanceof DelayedPayoutTxSignatureRequest) { + handle((DelayedPayoutTxSignatureRequest) message, peer); + } else if (message instanceof DepositTxAndDelayedPayoutTxMessage) { + handle((DepositTxAndDelayedPayoutTxMessage) message, peer); + } else if (message instanceof PayoutTxPublishedMessage) { + handle((PayoutTxPublishedMessage) message, peer); } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index b331a215fa9..a00023a0851 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -79,14 +79,14 @@ public BuyerAsTakerProtocol(BuyerAsTakerTrade trade) { Trade.Phase phase = trade.getState().getPhase(); if (phase == Trade.Phase.TAKER_FEE_PUBLISHED) { TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess("BuyerSetupDepositTxListener at startup"), + () -> handleTaskRunnerSuccess(BuyerEvent.STARTUP), this::handleTaskRunnerFault); taskRunner.addTasks(BuyerSetupDepositTxListener.class); taskRunner.run(); } else if (trade.isFiatSent() && !trade.isPayoutPublished()) { TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess("BuyerSetupPayoutTxListener at startup"), + () -> handleTaskRunnerSuccess(BuyerEvent.STARTUP), this::handleTaskRunnerFault); taskRunner.addTasks(BuyerSetupPayoutTxListener.class); @@ -107,13 +107,13 @@ public BuyerAsTakerProtocol(BuyerAsTakerTrade trade) { /////////////////////////////////////////////////////////////////////////////////////////// @Override - public void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress peerNodeAddress) { - super.doApplyMailboxTradeMessage(tradeMessage, peerNodeAddress); + public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peerNodeAddress) { + super.doApplyMailboxTradeMessage(message, peerNodeAddress); - if (tradeMessage instanceof DepositTxAndDelayedPayoutTxMessage) { - handle((DepositTxAndDelayedPayoutTxMessage) tradeMessage, peerNodeAddress); - } else if (tradeMessage instanceof PayoutTxPublishedMessage) { - handle((PayoutTxPublishedMessage) tradeMessage, peerNodeAddress); + if (message instanceof DepositTxAndDelayedPayoutTxMessage) { + handle((DepositTxAndDelayedPayoutTxMessage) message, peerNodeAddress); + } else if (message instanceof PayoutTxPublishedMessage) { + handle((PayoutTxPublishedMessage) message, peerNodeAddress); } } @@ -125,11 +125,12 @@ public void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress pe @Override public void takeAvailableOffer() { from(Trade.Phase.INIT) - .onEvent(TakerEvent.TAKE_OFFER) + .on(TakerEvent.TAKE_OFFER) + .withTimeout(30) .process(() -> { processModel.setTempTradingPeerNodeAddress(trade.getTradingPeerNodeAddress()); TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> handleTaskRunnerSuccess("takeAvailableOffer"), + () -> handleTaskRunnerSuccess(TakerEvent.TAKE_OFFER), this::handleTaskRunnerFault); taskRunner.addTasks( @@ -139,10 +140,6 @@ public void takeAvailableOffer() { BuyerAsTakerCreatesDepositTxInputs.class, TakerSendInputsForDepositTxRequest.class ); - - //TODO if peer does get an error he does not respond and all we get is the timeout now knowing why it failed. - // We should add an error message the peer sends us in such cases. - startTimeout(); taskRunner.run(); }); } @@ -152,18 +149,15 @@ public void takeAvailableOffer() { // Incoming messages Take offer process /////////////////////////////////////////////////////////////////////////////////////////// - private void handle(InputsForDepositTxResponse tradeMessage, NodeAddress sender) { + private void handle(InputsForDepositTxResponse message, NodeAddress peer) { from(Trade.Phase.INIT) - .onMessage(tradeMessage) + .on(message) + .from(peer) + .withTimeout(30) .process(() -> { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> { - handleTaskRunnerSuccess(tradeMessage, "handle InputsForDepositTxResponse"); - }, - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + () -> handleTaskRunnerSuccess(message), + errorMessage -> handleTaskRunnerFault(message, errorMessage)); taskRunner.addTasks( TakerProcessesInputsForDepositTxResponse.class, ApplyFilter.class, @@ -178,19 +172,15 @@ private void handle(InputsForDepositTxResponse tradeMessage, NodeAddress sender) }); } - private void handle(DelayedPayoutTxSignatureRequest tradeMessage, NodeAddress sender) { + private void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { from(Trade.Phase.TAKER_FEE_PUBLISHED) - .onMessage(tradeMessage) + .on(message) + .from(peer) + .withTimeout(30) .process(() -> { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> { - stopTimeout(); // We stop timeout here as last DepositTxAndDelayedPayoutTxMessage is not mandatory - handleTaskRunnerSuccess(tradeMessage, "handle DelayedPayoutTxSignatureRequest"); - }, - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + () -> handleTaskRunnerSuccess(message), + errorMessage -> handleTaskRunnerFault(message, errorMessage)); taskRunner.addTasks( BuyerProcessDelayedPayoutTxSignatureRequest.class, BuyerVerifiesPreparedDelayedPayoutTx.class, @@ -209,23 +199,26 @@ private void handle(DelayedPayoutTxSignatureRequest tradeMessage, NodeAddress se // For backward compatibility and extra resilience we still keep DepositTxAndDelayedPayoutTxMessage as a // mailbox message but the stored in mailbox case is not expected and the seller would try to send the message again // in the hope to reach the buyer directly. - private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress peerNodeAddress) { + private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer) { fromAny(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) - .onMessage(tradeMessage) + .on(message) + .from(peer) .condition(trade.getDepositTx() == null || trade.getDelayedPayoutTx() == null, () -> { log.warn("We received a DepositTxAndDelayedPayoutTxMessage but we have already processed the deposit and " + "delayed payout tx so we ignore the message. This can happen if the ACK message to the peer did not " + "arrive and the peer repeats sending us the message. We send another ACK msg."); - sendAckMessage(tradeMessage, true, null); + stopTimeout(); + sendAckMessage(message, true, null); processModel.removeMailboxMessageAfterProcessing(trade); }) .process(() -> { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(peerNodeAddress); TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle DepositTxAndDelayedPayoutTxMessage"), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + () -> { + stopTimeout(); + handleTaskRunnerSuccess(message); + }, + errorMessage -> handleTaskRunnerFault(message, errorMessage)); taskRunner.addTasks( BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, BuyerVerifiesFinalDelayedPayoutTx.class, @@ -245,14 +238,16 @@ private void handle(DepositTxAndDelayedPayoutTxMessage tradeMessage, NodeAddress @Override public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { from(Trade.Phase.DEPOSIT_CONFIRMED) - .onEvent(BuyerEvent.PAYMENT_SENT) + .on(BuyerEvent.PAYMENT_SENT) .condition(!wasDisputed()) .process(() -> { + //todo buyerAsTakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); + TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, () -> { resultHandler.handleResult(); - handleTaskRunnerSuccess("onFiatPaymentStarted"); + handleTaskRunnerSuccess(BuyerEvent.PAYMENT_SENT); }, (errorMessage) -> { errorMessageHandler.handleErrorMessage(errorMessage); @@ -274,16 +269,14 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle // Incoming message Payout tx /////////////////////////////////////////////////////////////////////////////////////////// - private void handle(PayoutTxPublishedMessage tradeMessage, NodeAddress peerNodeAddress) { + private void handle(PayoutTxPublishedMessage message, NodeAddress peer) { fromAny(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) - .onMessage(tradeMessage) + .on(message) + .from(peer) .process(() -> { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(peerNodeAddress); - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle PayoutTxPublishedMessage"), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + () -> handleTaskRunnerSuccess(message), + errorMessage -> handleTaskRunnerFault(message, errorMessage)); taskRunner.addTasks( BuyerProcessPayoutTxPublishedMessage.class @@ -298,20 +291,20 @@ private void handle(PayoutTxPublishedMessage tradeMessage, NodeAddress peerNodeA /////////////////////////////////////////////////////////////////////////////////////////// @Override - protected void doHandleDecryptedMessage(TradeMessage tradeMessage, NodeAddress sender) { - super.doHandleDecryptedMessage(tradeMessage, sender); + protected void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer) { + super.doHandleDecryptedMessage(message, peer); log.info("Received {} from {} with tradeId {} and uid {}", - tradeMessage.getClass().getSimpleName(), sender, tradeMessage.getTradeId(), tradeMessage.getUid()); - - if (tradeMessage instanceof InputsForDepositTxResponse) { - handle((InputsForDepositTxResponse) tradeMessage, sender); - } else if (tradeMessage instanceof DelayedPayoutTxSignatureRequest) { - handle((DelayedPayoutTxSignatureRequest) tradeMessage, sender); - } else if (tradeMessage instanceof DepositTxAndDelayedPayoutTxMessage) { - handle((DepositTxAndDelayedPayoutTxMessage) tradeMessage, sender); - } else if (tradeMessage instanceof PayoutTxPublishedMessage) { - handle((PayoutTxPublishedMessage) tradeMessage, sender); + message.getClass().getSimpleName(), peer, message.getTradeId(), message.getUid()); + + if (message instanceof InputsForDepositTxResponse) { + handle((InputsForDepositTxResponse) message, peer); + } else if (message instanceof DelayedPayoutTxSignatureRequest) { + handle((DelayedPayoutTxSignatureRequest) message, peer); + } else if (message instanceof DepositTxAndDelayedPayoutTxMessage) { + handle((DepositTxAndDelayedPayoutTxMessage) message, peer); + } else if (message instanceof PayoutTxPublishedMessage) { + handle((PayoutTxPublishedMessage) message, peer); } } } 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 96c3f62b916..19c195a2ef8 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java @@ -24,6 +24,7 @@ public interface BuyerProtocol { void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler); enum BuyerEvent implements TradeProtocol.Event { + STARTUP, PAYMENT_SENT } } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index ddb17ca23fb..ee34a40f7fd 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -47,7 +47,6 @@ import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerFinalizesDepositTx; import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerProcessDepositTxMessage; import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerSendsInputsForDepositTxResponse; -import bisq.core.util.Validator; import bisq.network.p2p.NodeAddress; @@ -77,11 +76,11 @@ public SellerAsMakerProtocol(SellerAsMakerTrade trade) { /////////////////////////////////////////////////////////////////////////////////////////// @Override - public void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress peerNodeAddress) { - super.doApplyMailboxTradeMessage(tradeMessage, peerNodeAddress); + public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peerNodeAddress) { + super.doApplyMailboxTradeMessage(message, peerNodeAddress); - if (tradeMessage instanceof CounterCurrencyTransferStartedMessage) { - handle((CounterCurrencyTransferStartedMessage) tradeMessage, peerNodeAddress); + if (message instanceof CounterCurrencyTransferStartedMessage) { + handle((CounterCurrencyTransferStartedMessage) message, peerNodeAddress); } } @@ -91,21 +90,19 @@ public void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress pe /////////////////////////////////////////////////////////////////////////////////////////// @Override - public void handleTakeOfferRequest(InputsForDepositTxRequest tradeMessage, - NodeAddress sender, + public void handleTakeOfferRequest(InputsForDepositTxRequest message, + NodeAddress peer, ErrorMessageHandler errorMessageHandler) { from(Trade.Phase.INIT) - .onMessage(tradeMessage) + .on(message) + .from(peer) + .withTimeout(30) .process(() -> { - Validator.checkTradeId(processModel.getOfferId(), tradeMessage); - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handleTakeOfferRequest"), + () -> handleTaskRunnerSuccess(message), errorMessage -> { errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(tradeMessage, errorMessage); + handleTaskRunnerFault(message, errorMessage); }); taskRunner.addTasks( @@ -128,16 +125,15 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest tradeMessage, // Incoming messages Take offer process /////////////////////////////////////////////////////////////////////////////////////////// - protected void handle(DepositTxMessage tradeMessage, NodeAddress sender) { + protected void handle(DepositTxMessage message, NodeAddress peer) { from(Trade.Phase.TAKER_FEE_PUBLISHED) - .onMessage(tradeMessage) + .on(message) + .from(peer) + .withTimeout(30) .process(() -> { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle DepositTxMessage"), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + () -> handleTaskRunnerSuccess(message), + errorMessage -> handleTaskRunnerFault(message, errorMessage)); taskRunner.addTasks( SellerAsMakerProcessDepositTxMessage.class, @@ -149,19 +145,17 @@ protected void handle(DepositTxMessage tradeMessage, NodeAddress sender) { }); } - private void handle(DelayedPayoutTxSignatureResponse tradeMessage, NodeAddress sender) { + private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) { from(Trade.Phase.TAKER_FEE_PUBLISHED) - .onMessage(tradeMessage) + .on(message) + .from(peer) .process(() -> { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, () -> { stopTimeout(); - handleTaskRunnerSuccess(tradeMessage, "handle DelayedPayoutTxSignatureResponse"); + handleTaskRunnerSuccess(message); }, - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + errorMessage -> handleTaskRunnerFault(message, errorMessage)); taskRunner.addTasks( SellerProcessDelayedPayoutTxSignatureResponse.class, @@ -181,24 +175,22 @@ private void handle(DelayedPayoutTxSignatureResponse tradeMessage, NodeAddress s // Incoming message when buyer has clicked payment started button /////////////////////////////////////////////////////////////////////////////////////////// - private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddress sender) { + private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress peer) { from(Trade.Phase.DEPOSIT_CONFIRMED) - .onMessage(tradeMessage) + .on(message) + .from(peer) .condition(trade.getPayoutTx() == null, () -> { log.warn("We received a CounterCurrencyTransferStartedMessage but we have already created the payout tx " + "so we ignore the message. This can happen if the ACK message to the peer did not " + "arrive and the peer repeats sending us the message. We send another ACK msg."); - sendAckMessage(tradeMessage, true, null); + sendAckMessage(message, true, null); processModel.removeMailboxMessageAfterProcessing(trade); }) .process(() -> { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle CounterCurrencyTransferStartedMessage"), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + () -> handleTaskRunnerSuccess(message), + errorMessage -> handleTaskRunnerFault(message, errorMessage)); taskRunner.addTasks( SellerProcessCounterCurrencyTransferStartedMessage.class, @@ -217,14 +209,14 @@ private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddr @Override public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { from(Trade.Phase.FIAT_SENT) - .onEvent(SellerEvent.PAYMENT_RECEIVED) + .on(SellerEvent.PAYMENT_RECEIVED) .condition(!wasDisputed()) .process(() -> { sellerAsMakerTrade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, () -> { resultHandler.handleResult(); - handleTaskRunnerSuccess("onFiatPaymentReceived"); + handleTaskRunnerSuccess(SellerEvent.PAYMENT_RECEIVED); }, (errorMessage) -> { errorMessageHandler.handleErrorMessage(errorMessage); @@ -248,18 +240,18 @@ public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandl /////////////////////////////////////////////////////////////////////////////////////////// @Override - protected void doHandleDecryptedMessage(TradeMessage tradeMessage, NodeAddress sender) { - super.doHandleDecryptedMessage(tradeMessage, sender); + protected void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer) { + super.doHandleDecryptedMessage(message, peer); log.info("Received {} from {} with tradeId {} and uid {}", - tradeMessage.getClass().getSimpleName(), sender, tradeMessage.getTradeId(), tradeMessage.getUid()); - - if (tradeMessage instanceof DepositTxMessage) { - handle((DepositTxMessage) tradeMessage, sender); - } else if (tradeMessage instanceof DelayedPayoutTxSignatureResponse) { - handle((DelayedPayoutTxSignatureResponse) tradeMessage, sender); - } else if (tradeMessage instanceof CounterCurrencyTransferStartedMessage) { - handle((CounterCurrencyTransferStartedMessage) tradeMessage, sender); + message.getClass().getSimpleName(), peer, message.getTradeId(), message.getUid()); + + if (message instanceof DepositTxMessage) { + handle((DepositTxMessage) message, peer); + } else if (message instanceof DelayedPayoutTxSignatureResponse) { + handle((DelayedPayoutTxSignatureResponse) message, peer); + } else if (message instanceof CounterCurrencyTransferStartedMessage) { + handle((CounterCurrencyTransferStartedMessage) message, peer); } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 4bf7ea63381..1d6f638728e 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -81,11 +81,11 @@ public SellerAsTakerProtocol(SellerAsTakerTrade trade) { /////////////////////////////////////////////////////////////////////////////////////////// @Override - public void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress peerNodeAddress) { - super.doApplyMailboxTradeMessage(tradeMessage, peerNodeAddress); + public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peerNodeAddress) { + super.doApplyMailboxTradeMessage(message, peerNodeAddress); - if (tradeMessage instanceof CounterCurrencyTransferStartedMessage) { - handle((CounterCurrencyTransferStartedMessage) tradeMessage, peerNodeAddress); + if (message instanceof CounterCurrencyTransferStartedMessage) { + handle((CounterCurrencyTransferStartedMessage) message, peerNodeAddress); } } @@ -97,11 +97,12 @@ public void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress pe @Override public void takeAvailableOffer() { from(Trade.Phase.INIT) - .onEvent(TakerEvent.TAKE_OFFER) + .on(TakerEvent.TAKE_OFFER) + .withTimeout(30) .process(() -> { processModel.setTempTradingPeerNodeAddress(trade.getTradingPeerNodeAddress()); TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, - () -> handleTaskRunnerSuccess("takeAvailableOffer"), + () -> handleTaskRunnerSuccess(TakerEvent.TAKE_OFFER), this::handleTaskRunnerFault); taskRunner.addTasks( @@ -122,18 +123,17 @@ public void takeAvailableOffer() { // Incoming messages Take offer process /////////////////////////////////////////////////////////////////////////////////////////// - private void handle(InputsForDepositTxResponse tradeMessage, NodeAddress sender) { + private void handle(InputsForDepositTxResponse message, NodeAddress peer) { from(Trade.Phase.INIT) - .onMessage(tradeMessage) + .on(message) + .from(peer) + .withTimeout(30) .process(() -> { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, () -> { - handleTaskRunnerSuccess(tradeMessage, "handle InputsForDepositTxResponse"); + handleTaskRunnerSuccess(message); }, - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + errorMessage -> handleTaskRunnerFault(message, errorMessage)); taskRunner.addTasks( TakerProcessesInputsForDepositTxResponse.class, @@ -149,26 +149,29 @@ private void handle(InputsForDepositTxResponse tradeMessage, NodeAddress sender) }); } - private void handle(DelayedPayoutTxSignatureResponse tradeMessage, NodeAddress sender) { + private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) { from(Trade.Phase.TAKER_FEE_PUBLISHED) - .onMessage(tradeMessage) + .on(message) + .from(peer) .process(() -> { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); + // We stop timeout here and don't start a new one as the + // SellerSendsDepositTxAndDelayedPayoutTxMessage repeats the send the message and has it's own + // timeout if it never succeeds. + stopTimeout(); TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, () -> { - stopTimeout(); - handleTaskRunnerSuccess(tradeMessage, "handle DelayedPayoutTxSignatureResponse"); + + handleTaskRunnerSuccess(message); }, - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + errorMessage -> handleTaskRunnerFault(message, errorMessage)); taskRunner.addTasks( SellerProcessDelayedPayoutTxSignatureResponse.class, SellerSignsDelayedPayoutTx.class, SellerFinalizesDelayedPayoutTx.class, - SellerSendsDepositTxAndDelayedPayoutTxMessage.class, // SEND_MSG(DepositTxAndDelayedPayoutTxMessage) - SellerPublishesDepositTx.class, // PUBLISH_DEPOSIT_TX + SellerSendsDepositTxAndDelayedPayoutTxMessage.class, + SellerPublishesDepositTx.class, PublishTradeStatistics.class ); taskRunner.run(); @@ -181,15 +184,16 @@ private void handle(DelayedPayoutTxSignatureResponse tradeMessage, NodeAddress s // Incoming message when buyer has clicked payment started button /////////////////////////////////////////////////////////////////////////////////////////// - private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddress sender) { + private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress peer) { from(Trade.Phase.DEPOSIT_CONFIRMED) - .onMessage(tradeMessage) + .on(message) + .from(peer) .condition(trade.getPayoutTx() == null, () -> { log.warn("We received a CounterCurrencyTransferStartedMessage but we have already created the payout tx " + "so we ignore the message. This can happen if the ACK message to the peer did not " + "arrive and the peer repeats sending us the message. We send another ACK msg."); - sendAckMessage(tradeMessage, true, null); + sendAckMessage(message, true, null); processModel.removeMailboxMessageAfterProcessing(trade); }) .process(() -> { @@ -197,17 +201,14 @@ private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddr log.warn("We received a CounterCurrencyTransferStartedMessage but we have already created the payout tx " + "so we ignore the message. This can happen if the ACK message to the peer did not " + "arrive and the peer repeats sending us the message. We send another ACK msg."); - sendAckMessage(tradeMessage, true, null); + sendAckMessage(message, true, null); processModel.removeMailboxMessageAfterProcessing(trade); return; } - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle CounterCurrencyTransferStartedMessage"), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); + () -> handleTaskRunnerSuccess(message), + errorMessage -> handleTaskRunnerFault(message, errorMessage)); taskRunner.addTasks( SellerProcessCounterCurrencyTransferStartedMessage.class, @@ -226,14 +227,14 @@ private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddr @Override public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { from(Trade.Phase.FIAT_SENT) - .onEvent(SellerEvent.PAYMENT_RECEIVED) + .on(SellerEvent.PAYMENT_RECEIVED) .condition(!wasDisputed()) .process(() -> { sellerAsTakerTrade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, () -> { resultHandler.handleResult(); - handleTaskRunnerSuccess("onFiatPaymentReceived"); + handleTaskRunnerSuccess(SellerEvent.PAYMENT_RECEIVED); }, (errorMessage) -> { errorMessageHandler.handleErrorMessage(errorMessage); @@ -257,18 +258,18 @@ public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandl /////////////////////////////////////////////////////////////////////////////////////////// @Override - protected void doHandleDecryptedMessage(TradeMessage tradeMessage, NodeAddress sender) { - super.doHandleDecryptedMessage(tradeMessage, sender); + protected void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer) { + super.doHandleDecryptedMessage(message, peer); log.info("Received {} from {} with tradeId {} and uid {}", - tradeMessage.getClass().getSimpleName(), sender, tradeMessage.getTradeId(), tradeMessage.getUid()); - - if (tradeMessage instanceof InputsForDepositTxResponse) { - handle((InputsForDepositTxResponse) tradeMessage, sender); - } else if (tradeMessage instanceof DelayedPayoutTxSignatureResponse) { - handle((DelayedPayoutTxSignatureResponse) tradeMessage, sender); - } else if (tradeMessage instanceof CounterCurrencyTransferStartedMessage) { - handle((CounterCurrencyTransferStartedMessage) tradeMessage, sender); + message.getClass().getSimpleName(), peer, message.getTradeId(), message.getUid()); + + if (message instanceof InputsForDepositTxResponse) { + handle((InputsForDepositTxResponse) message, peer); + } else if (message instanceof DelayedPayoutTxSignatureResponse) { + handle((DelayedPayoutTxSignatureResponse) message, peer); + } else if (message instanceof CounterCurrencyTransferStartedMessage) { + handle((CounterCurrencyTransferStartedMessage) message, peer); } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index 2b01b78db69..bd05445dc91 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -63,6 +63,7 @@ import javax.annotation.Nullable; +import static bisq.core.util.Validator.isTradeIdValid; import static bisq.core.util.Validator.nonEmptyStringOf; import static com.google.common.base.Preconditions.checkNotNull; @@ -72,7 +73,12 @@ interface Event { String name(); } - private static final long TIMEOUT = 180; + enum DisputeEvent implements TradeProtocol.Event { + MEDIATION_RESULT_ACCEPTED, + MEDIATION_RESULT_REJECTED + } + + private static final long DEFAULT_TIMEOUT_SEC = 180; protected final ProcessModel processModel; private final DecryptedDirectMessageListener decryptedDirectMessageListener; @@ -134,6 +140,8 @@ public TradeProtocol(Trade trade) { // Mediation: Called from UI if trader accepts mediation result /////////////////////////////////////////////////////////////////////////////////////////// + //TODO + // Trader has not yet received the peer's signature but has clicked the accept button. public void onAcceptMediationResult(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { if (trade.getProcessModel().getTradingPeer().getMediatedPayoutTxSignature() != null) { @@ -144,7 +152,7 @@ public void onAcceptMediationResult(ResultHandler resultHandler, ErrorMessageHan TradeTaskRunner taskRunner = new TradeTaskRunner(trade, () -> { resultHandler.handleResult(); - handleTaskRunnerSuccess("onAcceptMediationResult"); + handleTaskRunnerSuccess(DisputeEvent.MEDIATION_RESULT_ACCEPTED); }, (errorMessage) -> { errorMessageHandler.handleErrorMessage(errorMessage); @@ -170,7 +178,7 @@ public void onFinalizeMediationResultPayout(ResultHandler resultHandler, ErrorMe TradeTaskRunner taskRunner = new TradeTaskRunner(trade, () -> { resultHandler.handleResult(); - handleTaskRunnerSuccess("onAcceptMediationResult"); + handleTaskRunnerSuccess(DisputeEvent.MEDIATION_RESULT_ACCEPTED); }, (errorMessage) -> { errorMessageHandler.handleErrorMessage(errorMessage); @@ -196,7 +204,7 @@ protected void handle(MediatedPayoutTxSignatureMessage tradeMessage, NodeAddress processModel.setTempTradingPeerNodeAddress(sender); TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(tradeMessage, "MediatedPayoutSignatureMessage"), + () -> handleTaskRunnerSuccess(tradeMessage), errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); taskRunner.addTasks( @@ -210,7 +218,7 @@ protected void handle(MediatedPayoutTxPublishedMessage tradeMessage, NodeAddress processModel.setTempTradingPeerNodeAddress(sender); TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(tradeMessage, "handle PayoutTxPublishedMessage"), + () -> handleTaskRunnerSuccess(tradeMessage), errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); taskRunner.addTasks( @@ -229,7 +237,7 @@ private void handle(PeerPublishedDelayedPayoutTxMessage tradeMessage, NodeAddres processModel.setTempTradingPeerNodeAddress(sender); TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(tradeMessage, "PeerPublishedDelayedPayoutTxMessage"), + () -> handleTaskRunnerSuccess(tradeMessage), errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); taskRunner.addTasks( @@ -301,14 +309,19 @@ protected void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress } protected void startTimeout() { + startTimeout(DEFAULT_TIMEOUT_SEC); + } + + protected void startTimeout(long timeoutSec) { stopTimeout(); timeoutTimer = UserThread.runAfter(() -> { - log.error("Timeout reached. TradeID={}, state={}", trade.getId(), trade.stateProperty().get()); - trade.setErrorMessage("A timeout occurred."); + log.error("Timeout reached. TradeID={}, state={}, timeoutSec={}", + trade.getId(), trade.stateProperty().get(), timeoutSec); + trade.setErrorMessage("Timeout reached. Protocol did not complete in " + timeoutSec + " sec."); cleanupTradeOnFault(); cleanup(); - }, TIMEOUT); + }, timeoutSec); } protected void stopTimeout() { @@ -318,12 +331,18 @@ protected void stopTimeout() { } } - protected void handleTaskRunnerSuccess(String info) { - handleTaskRunnerSuccess(null, info); + protected void handleTaskRunnerSuccess(TradeMessage tradeMessage) { + handleTaskRunnerSuccess(tradeMessage, null); } - protected void handleTaskRunnerSuccess(@Nullable TradeMessage tradeMessage, String info) { - log.debug("handleTaskRunnerSuccess {}", info); + protected void handleTaskRunnerSuccess(Event event) { + handleTaskRunnerSuccess(null, event.name()); + } + + private void handleTaskRunnerSuccess(@Nullable TradeMessage tradeMessage, @Nullable String trigger) { + String triggerEvent = trigger != null ? trigger : + tradeMessage != null ? tradeMessage.getClass().getSimpleName() : "N/A"; + log.info("TaskRunner successfully completed. {}", "Triggered from message " + triggerEvent); sendAckMessage(tradeMessage, true, null); } @@ -429,25 +448,17 @@ protected FluentProcess fromAny(Trade.Phase... phase) { return new FluentProcess(trade, phase); } - static class FluentProcess { + class FluentProcess { private final Trade trade; @Nullable private TradeMessage tradeMessage; private final Set expectedPhases = new HashSet<>(); + private final Set preConditions = new HashSet<>(); @Nullable private Event event; - private boolean condition = true; - private Runnable conditionFailedHandler; - - protected FluentProcess process(Runnable runnable) { - if (isPhaseValid() && condition) { - runnable.run(); - } - if (!condition && conditionFailedHandler != null) { - conditionFailedHandler.run(); - } - return this; - } + private Runnable preConditionFailedHandler; + private int timeoutSec; + private NodeAddress peersNodeAddress; public FluentProcess(Trade trade, Trade.Phase expectedPhase) { @@ -461,6 +472,31 @@ public FluentProcess(Trade trade, this.expectedPhases.addAll(Set.of(expectedPhases)); } + protected FluentProcess process(Runnable runnable) { + boolean allPreConditionsMet = preConditions.stream().allMatch(e -> e); + boolean isTradeIdValid = tradeMessage == null || isTradeIdValid(processModel.getOfferId(), tradeMessage); + + if (isPhaseValid() && allPreConditionsMet && isTradeIdValid) { + if (timeoutSec > 0) { + startTimeout(timeoutSec); + } + + if (peersNodeAddress != null) { + processModel.setTempTradingPeerNodeAddress(peersNodeAddress); + } + + if (tradeMessage != null) { + processModel.setTradeMessage(tradeMessage); + } + + runnable.run(); + } + if (!allPreConditionsMet && preConditionFailedHandler != null) { + preConditionFailedHandler.run(); + } + return this; + } + private boolean isPhaseValid() { boolean isPhaseValid = expectedPhases.stream().anyMatch(e -> e == trade.getPhase()); String trigger = tradeMessage != null ? @@ -490,24 +526,34 @@ public FluentProcess orInPhase(Trade.Phase phase) { return this; } - public FluentProcess onEvent(Event event) { + public FluentProcess on(Event event) { this.event = event; return this; } - public FluentProcess onMessage(TradeMessage tradeMessage) { + public FluentProcess on(TradeMessage tradeMessage) { this.tradeMessage = tradeMessage; return this; } - public FluentProcess condition(boolean condition) { - this.condition = condition; + public FluentProcess condition(boolean preCondition) { + preConditions.add(preCondition); + return this; + } + + public FluentProcess condition(boolean preCondition, Runnable conditionFailedHandler) { + preConditions.add(preCondition); + this.preConditionFailedHandler = conditionFailedHandler; + return this; + } + + public FluentProcess withTimeout(int timeoutSec) { + this.timeoutSec = timeoutSec; return this; } - public FluentProcess condition(boolean condition, Runnable conditionFailedHandler) { - this.condition = condition; - this.conditionFailedHandler = conditionFailedHandler; + public FluentProcess from(NodeAddress peersNodeAddress) { + this.peersNodeAddress = peersNodeAddress; return this; } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerCreatesDepositTxInputs.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerCreatesDepositTxInputs.java index 5732ebe15f1..0e911516436 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerCreatesDepositTxInputs.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerCreatesDepositTxInputs.java @@ -44,7 +44,7 @@ protected void run() { Coin txFee = trade.getTxFee(); Coin takerInputAmount = checkNotNull(trade.getOffer()).getBuyerSecurityDeposit() .add(txFee) - .add(txFee); + .add(txFee); // 2 times the fee as we need it for payout tx as well InputsAndChangeOutput result = processModel.getTradeWalletService().takerCreatesDepositTxInputs( processModel.getTakeOfferFeeTx(), takerInputAmount, diff --git a/core/src/main/java/bisq/core/util/Validator.java b/core/src/main/java/bisq/core/util/Validator.java index 2de194f9857..52da4927745 100644 --- a/core/src/main/java/bisq/core/util/Validator.java +++ b/core/src/main/java/bisq/core/util/Validator.java @@ -53,6 +53,10 @@ public static Coin positiveCoinOf(Coin value) { } public static void checkTradeId(String tradeId, TradeMessage tradeMessage) { - checkArgument(tradeId.equals(tradeMessage.getTradeId())); + checkArgument(isTradeIdValid(tradeId, tradeMessage)); + } + + public static boolean isTradeIdValid(String tradeId, TradeMessage tradeMessage) { + return tradeId.equals(tradeMessage.getTradeId()); } } From 3f80d1b1ea1037c6e2c828eb9444ce00733f7c45 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 23 Sep 2020 12:13:07 -0500 Subject: [PATCH 046/143] Refactor: Rename condition to preCondition --- .../java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java | 4 ++-- .../java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java | 4 ++-- .../java/bisq/core/trade/protocol/SellerAsMakerProtocol.java | 4 ++-- .../java/bisq/core/trade/protocol/SellerAsTakerProtocol.java | 4 ++-- .../src/main/java/bisq/core/trade/protocol/TradeProtocol.java | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 7dcc253f65d..36d8b3fdf7a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -177,7 +177,7 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer fromAny(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) .on(message) .from(peer) - .condition(trade.getDepositTx() == null || trade.getDelayedPayoutTx() == null, + .preCondition(trade.getDepositTx() == null || trade.getDelayedPayoutTx() == null, () -> { log.warn("We received a DepositTxAndDelayedPayoutTxMessage but we have already processed the deposit and " + "delayed payout tx so we ignore the message. This can happen if the ACK message to the peer did not " + @@ -214,7 +214,7 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { from(Trade.Phase.DEPOSIT_CONFIRMED) .on(BuyerEvent.PAYMENT_SENT) - .condition(!wasDisputed()) + .preCondition(!wasDisputed()) .process(() -> { buyerAsMakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index a00023a0851..ead71a382be 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -203,7 +203,7 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer fromAny(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) .on(message) .from(peer) - .condition(trade.getDepositTx() == null || trade.getDelayedPayoutTx() == null, + .preCondition(trade.getDepositTx() == null || trade.getDelayedPayoutTx() == null, () -> { log.warn("We received a DepositTxAndDelayedPayoutTxMessage but we have already processed the deposit and " + "delayed payout tx so we ignore the message. This can happen if the ACK message to the peer did not " + @@ -239,7 +239,7 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { from(Trade.Phase.DEPOSIT_CONFIRMED) .on(BuyerEvent.PAYMENT_SENT) - .condition(!wasDisputed()) + .preCondition(!wasDisputed()) .process(() -> { //todo buyerAsTakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index ee34a40f7fd..919e862b670 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -179,7 +179,7 @@ private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress p from(Trade.Phase.DEPOSIT_CONFIRMED) .on(message) .from(peer) - .condition(trade.getPayoutTx() == null, + .preCondition(trade.getPayoutTx() == null, () -> { log.warn("We received a CounterCurrencyTransferStartedMessage but we have already created the payout tx " + "so we ignore the message. This can happen if the ACK message to the peer did not " + @@ -210,7 +210,7 @@ private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress p public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { from(Trade.Phase.FIAT_SENT) .on(SellerEvent.PAYMENT_RECEIVED) - .condition(!wasDisputed()) + .preCondition(!wasDisputed()) .process(() -> { sellerAsMakerTrade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 1d6f638728e..bd2f8c12f10 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -188,7 +188,7 @@ private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress p from(Trade.Phase.DEPOSIT_CONFIRMED) .on(message) .from(peer) - .condition(trade.getPayoutTx() == null, + .preCondition(trade.getPayoutTx() == null, () -> { log.warn("We received a CounterCurrencyTransferStartedMessage but we have already created the payout tx " + "so we ignore the message. This can happen if the ACK message to the peer did not " + @@ -228,7 +228,7 @@ private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress p public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { from(Trade.Phase.FIAT_SENT) .on(SellerEvent.PAYMENT_RECEIVED) - .condition(!wasDisputed()) + .preCondition(!wasDisputed()) .process(() -> { sellerAsTakerTrade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index bd05445dc91..bbe7230dac9 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -536,12 +536,12 @@ public FluentProcess on(TradeMessage tradeMessage) { return this; } - public FluentProcess condition(boolean preCondition) { + public FluentProcess preCondition(boolean preCondition) { preConditions.add(preCondition); return this; } - public FluentProcess condition(boolean preCondition, Runnable conditionFailedHandler) { + public FluentProcess preCondition(boolean preCondition, Runnable conditionFailedHandler) { preConditions.add(preCondition); this.preConditionFailedHandler = conditionFailedHandler; return this; From d91e44c9ab757e4379f8c30913677bc9eb06898e Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 23 Sep 2020 12:14:18 -0500 Subject: [PATCH 047/143] Refactor: Rename from to expectedPhase --- .../bisq/core/trade/protocol/BuyerAsMakerProtocol.java | 6 +++--- .../bisq/core/trade/protocol/BuyerAsTakerProtocol.java | 8 ++++---- .../core/trade/protocol/SellerAsMakerProtocol.java | 10 +++++----- .../core/trade/protocol/SellerAsTakerProtocol.java | 10 +++++----- .../java/bisq/core/trade/protocol/TradeProtocol.java | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 36d8b3fdf7a..e6a431a5220 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -115,7 +115,7 @@ public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peer) { public void handleTakeOfferRequest(InputsForDepositTxRequest message, NodeAddress peer, ErrorMessageHandler errorMessageHandler) { - from(Trade.Phase.INIT) + expectedPhase(Trade.Phase.INIT) .on(message) .from(peer) .withTimeout(30) @@ -147,7 +147,7 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message, /////////////////////////////////////////////////////////////////////////////////////////// private void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { - from(Trade.Phase.TAKER_FEE_PUBLISHED) + expectedPhase(Trade.Phase.TAKER_FEE_PUBLISHED) .on(message) .from(peer) .withTimeout(30) @@ -212,7 +212,7 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer @Override public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - from(Trade.Phase.DEPOSIT_CONFIRMED) + expectedPhase(Trade.Phase.DEPOSIT_CONFIRMED) .on(BuyerEvent.PAYMENT_SENT) .preCondition(!wasDisputed()) .process(() -> { diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index ead71a382be..21135290d64 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -124,7 +124,7 @@ public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peerNod @Override public void takeAvailableOffer() { - from(Trade.Phase.INIT) + expectedPhase(Trade.Phase.INIT) .on(TakerEvent.TAKE_OFFER) .withTimeout(30) .process(() -> { @@ -150,7 +150,7 @@ public void takeAvailableOffer() { /////////////////////////////////////////////////////////////////////////////////////////// private void handle(InputsForDepositTxResponse message, NodeAddress peer) { - from(Trade.Phase.INIT) + expectedPhase(Trade.Phase.INIT) .on(message) .from(peer) .withTimeout(30) @@ -173,7 +173,7 @@ private void handle(InputsForDepositTxResponse message, NodeAddress peer) { } private void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { - from(Trade.Phase.TAKER_FEE_PUBLISHED) + expectedPhase(Trade.Phase.TAKER_FEE_PUBLISHED) .on(message) .from(peer) .withTimeout(30) @@ -237,7 +237,7 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer // User clicked the "bank transfer started" button @Override public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - from(Trade.Phase.DEPOSIT_CONFIRMED) + expectedPhase(Trade.Phase.DEPOSIT_CONFIRMED) .on(BuyerEvent.PAYMENT_SENT) .preCondition(!wasDisputed()) .process(() -> { diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index 919e862b670..b569e03696f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -93,7 +93,7 @@ public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peerNod public void handleTakeOfferRequest(InputsForDepositTxRequest message, NodeAddress peer, ErrorMessageHandler errorMessageHandler) { - from(Trade.Phase.INIT) + expectedPhase(Trade.Phase.INIT) .on(message) .from(peer) .withTimeout(30) @@ -126,7 +126,7 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message, /////////////////////////////////////////////////////////////////////////////////////////// protected void handle(DepositTxMessage message, NodeAddress peer) { - from(Trade.Phase.TAKER_FEE_PUBLISHED) + expectedPhase(Trade.Phase.TAKER_FEE_PUBLISHED) .on(message) .from(peer) .withTimeout(30) @@ -146,7 +146,7 @@ protected void handle(DepositTxMessage message, NodeAddress peer) { } private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) { - from(Trade.Phase.TAKER_FEE_PUBLISHED) + expectedPhase(Trade.Phase.TAKER_FEE_PUBLISHED) .on(message) .from(peer) .process(() -> { @@ -176,7 +176,7 @@ private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) /////////////////////////////////////////////////////////////////////////////////////////// private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress peer) { - from(Trade.Phase.DEPOSIT_CONFIRMED) + expectedPhase(Trade.Phase.DEPOSIT_CONFIRMED) .on(message) .from(peer) .preCondition(trade.getPayoutTx() == null, @@ -208,7 +208,7 @@ private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress p @Override public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - from(Trade.Phase.FIAT_SENT) + expectedPhase(Trade.Phase.FIAT_SENT) .on(SellerEvent.PAYMENT_RECEIVED) .preCondition(!wasDisputed()) .process(() -> { diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index bd2f8c12f10..7e6417b4b56 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -96,7 +96,7 @@ public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peerNod @Override public void takeAvailableOffer() { - from(Trade.Phase.INIT) + expectedPhase(Trade.Phase.INIT) .on(TakerEvent.TAKE_OFFER) .withTimeout(30) .process(() -> { @@ -124,7 +124,7 @@ public void takeAvailableOffer() { /////////////////////////////////////////////////////////////////////////////////////////// private void handle(InputsForDepositTxResponse message, NodeAddress peer) { - from(Trade.Phase.INIT) + expectedPhase(Trade.Phase.INIT) .on(message) .from(peer) .withTimeout(30) @@ -150,7 +150,7 @@ private void handle(InputsForDepositTxResponse message, NodeAddress peer) { } private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) { - from(Trade.Phase.TAKER_FEE_PUBLISHED) + expectedPhase(Trade.Phase.TAKER_FEE_PUBLISHED) .on(message) .from(peer) .process(() -> { @@ -185,7 +185,7 @@ private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) /////////////////////////////////////////////////////////////////////////////////////////// private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress peer) { - from(Trade.Phase.DEPOSIT_CONFIRMED) + expectedPhase(Trade.Phase.DEPOSIT_CONFIRMED) .on(message) .from(peer) .preCondition(trade.getPayoutTx() == null, @@ -226,7 +226,7 @@ private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress p @Override public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - from(Trade.Phase.FIAT_SENT) + expectedPhase(Trade.Phase.FIAT_SENT) .on(SellerEvent.PAYMENT_RECEIVED) .preCondition(!wasDisputed()) .process(() -> { diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index bbe7230dac9..26409d711ef 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -440,7 +440,7 @@ private void cleanupTradeOnFault() { // FluentProcess /////////////////////////////////////////////////////////////////////////////////////////// - protected FluentProcess from(Trade.Phase phase) { + protected FluentProcess expectedPhase(Trade.Phase phase) { return new FluentProcess(trade, phase); } From faf07f623fe4674827a6094487678ccb3f89db72 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 23 Sep 2020 12:14:40 -0500 Subject: [PATCH 048/143] Refactor: Rename fromAny to expectedPhases --- .../java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java | 4 ++-- .../java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java | 4 ++-- .../src/main/java/bisq/core/trade/protocol/TradeProtocol.java | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index e6a431a5220..aff3c8e8110 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -174,7 +174,7 @@ private void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { // mailbox message but the stored in mailbox case is not expected and the seller would try to send the message again // in the hope to reach the buyer directly. private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer) { - fromAny(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) + expectedPhases(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) .on(message) .from(peer) .preCondition(trade.getDepositTx() == null || trade.getDelayedPayoutTx() == null, @@ -243,7 +243,7 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle /////////////////////////////////////////////////////////////////////////////////////////// private void handle(PayoutTxPublishedMessage message, NodeAddress peer) { - fromAny(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) + expectedPhases(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) .on(message) .from(peer) .process(() -> { diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 21135290d64..8f513d73185 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -200,7 +200,7 @@ private void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { // mailbox message but the stored in mailbox case is not expected and the seller would try to send the message again // in the hope to reach the buyer directly. private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer) { - fromAny(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) + expectedPhases(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) .on(message) .from(peer) .preCondition(trade.getDepositTx() == null || trade.getDelayedPayoutTx() == null, @@ -270,7 +270,7 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle /////////////////////////////////////////////////////////////////////////////////////////// private void handle(PayoutTxPublishedMessage message, NodeAddress peer) { - fromAny(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) + expectedPhases(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) .on(message) .from(peer) .process(() -> { diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index 26409d711ef..3ac39074338 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -444,7 +444,7 @@ protected FluentProcess expectedPhase(Trade.Phase phase) { return new FluentProcess(trade, phase); } - protected FluentProcess fromAny(Trade.Phase... phase) { + protected FluentProcess expectedPhases(Trade.Phase... phase) { return new FluentProcess(trade, phase); } From 9505179bed6e80c4bbdbf9aeddf3202efffa5d33 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 23 Sep 2020 12:49:42 -0500 Subject: [PATCH 049/143] Use FluentProcess for boilerplate code (WIP - some custom code is commented out atm, will be fixed in follow up commits) Add setTaskRunner method Add addTasks method Add run method --- .../trade/protocol/BuyerAsMakerProtocol.java | 149 ++++++++--------- .../trade/protocol/BuyerAsTakerProtocol.java | 155 +++++++----------- .../trade/protocol/SellerAsMakerProtocol.java | 153 ++++++++--------- .../trade/protocol/SellerAsTakerProtocol.java | 136 +++++++-------- .../core/trade/protocol/TradeProtocol.java | 81 ++++++--- 5 files changed, 310 insertions(+), 364 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index aff3c8e8110..d6ddbad5ae4 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -70,14 +70,14 @@ public BuyerAsMakerProtocol(BuyerAsMakerTrade trade) { if (phase == Trade.Phase.TAKER_FEE_PUBLISHED) { TradeTaskRunner taskRunner = new TradeTaskRunner(trade, () -> handleTaskRunnerSuccess(BuyerEvent.STARTUP), - this::handleTaskRunnerFault); + errorMessage -> handleTaskRunnerFault(BuyerEvent.STARTUP, errorMessage)); taskRunner.addTasks(BuyerSetupDepositTxListener.class); taskRunner.run(); } else if (trade.isFiatSent() && !trade.isPayoutPublished()) { TradeTaskRunner taskRunner = new TradeTaskRunner(trade, () -> handleTaskRunnerSuccess(BuyerEvent.STARTUP), - this::handleTaskRunnerFault); + errorMessage -> handleTaskRunnerFault(BuyerEvent.STARTUP, errorMessage)); taskRunner.addTasks(BuyerSetupPayoutTxListener.class); if (trade.getState() == Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG || @@ -119,26 +119,24 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message, .on(message) .from(peer) .withTimeout(30) - .process(() -> { - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, - () -> handleTaskRunnerSuccess(message), - errorMessage -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(errorMessage); - }); - taskRunner.addTasks( - MakerProcessesInputsForDepositTxRequest.class, - ApplyFilter.class, - VerifyPeersAccountAgeWitness.class, - MakerVerifyTakerFeePayment.class, - MakerSetsLockTime.class, - MakerCreateAndSignContract.class, - BuyerAsMakerCreatesAndSignsDepositTx.class, - BuyerSetupDepositTxListener.class, - BuyerAsMakerSendsInputsForDepositTxResponse.class - ); - taskRunner.run(); - }); + .setTaskRunner(new TradeTaskRunner(buyerAsMakerTrade, + () -> handleTaskRunnerSuccess(message), + errorMessage -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(message, errorMessage); + })) + .addTasks( + MakerProcessesInputsForDepositTxRequest.class, + ApplyFilter.class, + VerifyPeersAccountAgeWitness.class, + MakerVerifyTakerFeePayment.class, + MakerSetsLockTime.class, + MakerCreateAndSignContract.class, + BuyerAsMakerCreatesAndSignsDepositTx.class, + BuyerSetupDepositTxListener.class, + BuyerAsMakerSendsInputsForDepositTxResponse.class + ) + .run(); } @@ -151,18 +149,12 @@ private void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { .on(message) .from(peer) .withTimeout(30) - .process(() -> { - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, - () -> handleTaskRunnerSuccess(message), - errorMessage -> handleTaskRunnerFault(message, errorMessage)); - taskRunner.addTasks( - BuyerProcessDelayedPayoutTxSignatureRequest.class, - BuyerVerifiesPreparedDelayedPayoutTx.class, - BuyerSignsDelayedPayoutTx.class, - BuyerSendsDelayedPayoutTxSignatureResponse.class - ); - taskRunner.run(); - }); + .addTasks( + BuyerProcessDelayedPayoutTxSignatureRequest.class, + BuyerVerifiesPreparedDelayedPayoutTx.class, + BuyerSignsDelayedPayoutTx.class, + BuyerSendsDelayedPayoutTxSignatureResponse.class + ).run(); } // The DepositTxAndDelayedPayoutTxMessage is a mailbox message as earlier we use only the deposit tx which can @@ -186,22 +178,20 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer sendAckMessage(message, true, null); processModel.removeMailboxMessageAfterProcessing(trade); }) - .process(() -> { - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, - () -> { - stopTimeout(); - handleTaskRunnerSuccess(message); - }, - errorMessage -> handleTaskRunnerFault(message, errorMessage)); - taskRunner.addTasks( - BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, - BuyerVerifiesFinalDelayedPayoutTx.class, - PublishTradeStatistics.class - ); - taskRunner.run(); - processModel.witnessDebugLog(buyerAsMakerTrade); - }); - + .setTaskRunner(new TradeTaskRunner(buyerAsMakerTrade, + () -> { + stopTimeout(); + handleTaskRunnerSuccess(message); + }, + errorMessage -> handleTaskRunnerFault(message, errorMessage))) + .addTasks( + BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, + BuyerVerifiesFinalDelayedPayoutTx.class, + PublishTradeStatistics.class + ) + .run(); + +//processModel.witnessDebugLog(buyerAsMakerTrade); } @@ -212,29 +202,29 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer @Override public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + BuyerEvent event = BuyerEvent.PAYMENT_SENT; expectedPhase(Trade.Phase.DEPOSIT_CONFIRMED) - .on(BuyerEvent.PAYMENT_SENT) + .on(event) .preCondition(!wasDisputed()) - .process(() -> { - buyerAsMakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess(BuyerEvent.PAYMENT_SENT); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(errorMessage); - }); - taskRunner.addTasks( - ApplyFilter.class, - MakerVerifyTakerFeePayment.class, - BuyerSignPayoutTx.class, - BuyerSetupPayoutTxListener.class, - BuyerSendCounterCurrencyTransferStartedMessage.class - ); - taskRunner.run(); - }); + .setTaskRunner(new TradeTaskRunner(buyerAsMakerTrade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess(event); + }, + (errorMessage) -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(event, errorMessage); + })) + .addTasks( + ApplyFilter.class, + MakerVerifyTakerFeePayment.class, + BuyerSignPayoutTx.class, + BuyerSetupPayoutTxListener.class, + BuyerSendCounterCurrencyTransferStartedMessage.class + ) + .run(); + + // buyerAsMakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); } @@ -246,19 +236,10 @@ private void handle(PayoutTxPublishedMessage message, NodeAddress peer) { expectedPhases(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) .on(message) .from(peer) - .process(() -> { - processModel.setTradeMessage(message); - processModel.setTempTradingPeerNodeAddress(peer); - - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, - () -> handleTaskRunnerSuccess(message), - errorMessage -> handleTaskRunnerFault(message, errorMessage)); - - taskRunner.addTasks( - BuyerProcessPayoutTxPublishedMessage.class - ); - taskRunner.run(); - }); + .addTasks( + BuyerProcessPayoutTxPublishedMessage.class + ) + .run(); } diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 8f513d73185..f198f5f339b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -80,14 +80,14 @@ public BuyerAsTakerProtocol(BuyerAsTakerTrade trade) { if (phase == Trade.Phase.TAKER_FEE_PUBLISHED) { TradeTaskRunner taskRunner = new TradeTaskRunner(trade, () -> handleTaskRunnerSuccess(BuyerEvent.STARTUP), - this::handleTaskRunnerFault); + errorMessage -> handleTaskRunnerFault(BuyerEvent.STARTUP, errorMessage)); taskRunner.addTasks(BuyerSetupDepositTxListener.class); taskRunner.run(); } else if (trade.isFiatSent() && !trade.isPayoutPublished()) { TradeTaskRunner taskRunner = new TradeTaskRunner(trade, () -> handleTaskRunnerSuccess(BuyerEvent.STARTUP), - this::handleTaskRunnerFault); + errorMessage -> handleTaskRunnerFault(BuyerEvent.STARTUP, errorMessage)); taskRunner.addTasks(BuyerSetupPayoutTxListener.class); @@ -127,21 +127,13 @@ public void takeAvailableOffer() { expectedPhase(Trade.Phase.INIT) .on(TakerEvent.TAKE_OFFER) .withTimeout(30) - .process(() -> { - processModel.setTempTradingPeerNodeAddress(trade.getTradingPeerNodeAddress()); - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> handleTaskRunnerSuccess(TakerEvent.TAKE_OFFER), - this::handleTaskRunnerFault); - - taskRunner.addTasks( - ApplyFilter.class, - TakerVerifyMakerFeePayment.class, - CreateTakerFeeTx.class, - BuyerAsTakerCreatesDepositTxInputs.class, - TakerSendInputsForDepositTxRequest.class - ); - taskRunner.run(); - }); + .addTasks( + ApplyFilter.class, + TakerVerifyMakerFeePayment.class, + CreateTakerFeeTx.class, + BuyerAsTakerCreatesDepositTxInputs.class, + TakerSendInputsForDepositTxRequest.class + ).run(); } @@ -154,22 +146,15 @@ private void handle(InputsForDepositTxResponse message, NodeAddress peer) { .on(message) .from(peer) .withTimeout(30) - .process(() -> { - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> handleTaskRunnerSuccess(message), - errorMessage -> handleTaskRunnerFault(message, errorMessage)); - taskRunner.addTasks( - TakerProcessesInputsForDepositTxResponse.class, - ApplyFilter.class, - VerifyPeersAccountAgeWitness.class, - TakerVerifyAndSignContract.class, - TakerPublishFeeTx.class, - BuyerAsTakerSignsDepositTx.class, - BuyerSetupDepositTxListener.class, - BuyerAsTakerSendsDepositTxMessage.class - ); - taskRunner.run(); - }); + .addTasks(TakerProcessesInputsForDepositTxResponse.class, + ApplyFilter.class, + VerifyPeersAccountAgeWitness.class, + TakerVerifyAndSignContract.class, + TakerPublishFeeTx.class, + BuyerAsTakerSignsDepositTx.class, + BuyerSetupDepositTxListener.class, + BuyerAsTakerSendsDepositTxMessage.class) + .run(); } private void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { @@ -177,18 +162,13 @@ private void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { .on(message) .from(peer) .withTimeout(30) - .process(() -> { - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> handleTaskRunnerSuccess(message), - errorMessage -> handleTaskRunnerFault(message, errorMessage)); - taskRunner.addTasks( - BuyerProcessDelayedPayoutTxSignatureRequest.class, - BuyerVerifiesPreparedDelayedPayoutTx.class, - BuyerSignsDelayedPayoutTx.class, - BuyerSendsDelayedPayoutTxSignatureResponse.class - ); - taskRunner.run(); - }); + .addTasks( + BuyerProcessDelayedPayoutTxSignatureRequest.class, + BuyerVerifiesPreparedDelayedPayoutTx.class, + BuyerSignsDelayedPayoutTx.class, + BuyerSendsDelayedPayoutTxSignatureResponse.class + ) + .run(); } // The DepositTxAndDelayedPayoutTxMessage is a mailbox message as earlier we use only the deposit tx which can @@ -212,21 +192,17 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer sendAckMessage(message, true, null); processModel.removeMailboxMessageAfterProcessing(trade); }) - .process(() -> { - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> { - stopTimeout(); - handleTaskRunnerSuccess(message); - }, - errorMessage -> handleTaskRunnerFault(message, errorMessage)); - taskRunner.addTasks( - BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, - BuyerVerifiesFinalDelayedPayoutTx.class, - PublishTradeStatistics.class - ); - taskRunner.run(); - processModel.witnessDebugLog(buyerAsTakerTrade); - }); + .setTaskRunner(new TradeTaskRunner(buyerAsTakerTrade, + () -> { + stopTimeout(); + handleTaskRunnerSuccess(message); + }, + errorMessage -> handleTaskRunnerFault(message, errorMessage))) + .addTasks(BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, + BuyerVerifiesFinalDelayedPayoutTx.class, + PublishTradeStatistics.class) + .run(); + //processModel.witnessDebugLog(buyerAsTakerTrade); } @@ -237,31 +213,29 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer // User clicked the "bank transfer started" button @Override public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + BuyerEvent event = BuyerEvent.PAYMENT_SENT; expectedPhase(Trade.Phase.DEPOSIT_CONFIRMED) - .on(BuyerEvent.PAYMENT_SENT) + .on(event) .preCondition(!wasDisputed()) - .process(() -> { - //todo - buyerAsTakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); - - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess(BuyerEvent.PAYMENT_SENT); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(errorMessage); - }); - taskRunner.addTasks( - ApplyFilter.class, - TakerVerifyMakerFeePayment.class, - BuyerSignPayoutTx.class, - BuyerSetupPayoutTxListener.class, - BuyerSendCounterCurrencyTransferStartedMessage.class - ); - taskRunner.run(); - }); + .setTaskRunner(new TradeTaskRunner(buyerAsTakerTrade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess(event); + }, + (errorMessage) -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(event, errorMessage); + })) + .addTasks(ApplyFilter.class, + TakerVerifyMakerFeePayment.class, + BuyerSignPayoutTx.class, + BuyerSetupPayoutTxListener.class, + BuyerSendCounterCurrencyTransferStartedMessage.class + ) + .run(); + + //todo + // buyerAsTakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); } @@ -273,16 +247,11 @@ private void handle(PayoutTxPublishedMessage message, NodeAddress peer) { expectedPhases(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) .on(message) .from(peer) - .process(() -> { - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, - () -> handleTaskRunnerSuccess(message), - errorMessage -> handleTaskRunnerFault(message, errorMessage)); - - taskRunner.addTasks( - BuyerProcessPayoutTxPublishedMessage.class - ); - taskRunner.run(); - }); + .addTasks( + BuyerProcessPayoutTxPublishedMessage.class + ) + .run(); + } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index b569e03696f..4d46184dc06 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -97,27 +97,23 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message, .on(message) .from(peer) .withTimeout(30) - .process(() -> { - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, - () -> handleTaskRunnerSuccess(message), - errorMessage -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(message, errorMessage); - }); - - taskRunner.addTasks( - MakerProcessesInputsForDepositTxRequest.class, - ApplyFilter.class, - VerifyPeersAccountAgeWitness.class, - MakerVerifyTakerFeePayment.class, - MakerSetsLockTime.class, - MakerCreateAndSignContract.class, - SellerAsMakerCreatesUnsignedDepositTx.class, - SellerAsMakerSendsInputsForDepositTxResponse.class - ); - - taskRunner.run(); - }); + .setTaskRunner(new TradeTaskRunner(sellerAsMakerTrade, + () -> handleTaskRunnerSuccess(message), + errorMessage -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(message, errorMessage); + })) + .addTasks( + MakerProcessesInputsForDepositTxRequest.class, + ApplyFilter.class, + VerifyPeersAccountAgeWitness.class, + MakerVerifyTakerFeePayment.class, + MakerSetsLockTime.class, + MakerCreateAndSignContract.class, + SellerAsMakerCreatesUnsignedDepositTx.class, + SellerAsMakerSendsInputsForDepositTxResponse.class + ) + .run(); } @@ -130,44 +126,36 @@ protected void handle(DepositTxMessage message, NodeAddress peer) { .on(message) .from(peer) .withTimeout(30) - .process(() -> { - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, - () -> handleTaskRunnerSuccess(message), - errorMessage -> handleTaskRunnerFault(message, errorMessage)); - - taskRunner.addTasks( - SellerAsMakerProcessDepositTxMessage.class, - SellerAsMakerFinalizesDepositTx.class, - SellerCreatesDelayedPayoutTx.class, - SellerSendDelayedPayoutTxSignatureRequest.class - ); - taskRunner.run(); - }); + .addTasks( + SellerAsMakerProcessDepositTxMessage.class, + SellerAsMakerFinalizesDepositTx.class, + SellerCreatesDelayedPayoutTx.class, + SellerSendDelayedPayoutTxSignatureRequest.class + ) + .run(); } private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) { expectedPhase(Trade.Phase.TAKER_FEE_PUBLISHED) .on(message) .from(peer) - .process(() -> { - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, - () -> { - stopTimeout(); - handleTaskRunnerSuccess(message); - }, - errorMessage -> handleTaskRunnerFault(message, errorMessage)); - - taskRunner.addTasks( - SellerProcessDelayedPayoutTxSignatureResponse.class, - SellerSignsDelayedPayoutTx.class, - SellerFinalizesDelayedPayoutTx.class, - SellerSendsDepositTxAndDelayedPayoutTxMessage.class, - SellerPublishesDepositTx.class, - PublishTradeStatistics.class - ); - taskRunner.run(); - processModel.witnessDebugLog(sellerAsMakerTrade); - }); + .setTaskRunner(new TradeTaskRunner(sellerAsMakerTrade, + () -> { + stopTimeout(); + handleTaskRunnerSuccess(message); + }, + errorMessage -> handleTaskRunnerFault(message, errorMessage))) + .addTasks( + SellerProcessDelayedPayoutTxSignatureResponse.class, + SellerSignsDelayedPayoutTx.class, + SellerFinalizesDelayedPayoutTx.class, + SellerSendsDepositTxAndDelayedPayoutTxMessage.class, + SellerPublishesDepositTx.class, + PublishTradeStatistics.class + ) + .run(); + + //processModel.witnessDebugLog(sellerAsMakerTrade); } @@ -187,18 +175,12 @@ private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress p sendAckMessage(message, true, null); processModel.removeMailboxMessageAfterProcessing(trade); }) - .process(() -> { - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, - () -> handleTaskRunnerSuccess(message), - errorMessage -> handleTaskRunnerFault(message, errorMessage)); - - taskRunner.addTasks( - SellerProcessCounterCurrencyTransferStartedMessage.class, - ApplyFilter.class, - MakerVerifyTakerFeePayment.class - ); - taskRunner.run(); - }); + .addTasks( + SellerProcessCounterCurrencyTransferStartedMessage.class, + ApplyFilter.class, + MakerVerifyTakerFeePayment.class + ) + .run(); } @@ -208,30 +190,27 @@ private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress p @Override public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + SellerEvent event = SellerEvent.PAYMENT_RECEIVED; expectedPhase(Trade.Phase.FIAT_SENT) - .on(SellerEvent.PAYMENT_RECEIVED) + .on(event) .preCondition(!wasDisputed()) - .process(() -> { - sellerAsMakerTrade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess(SellerEvent.PAYMENT_RECEIVED); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(errorMessage); - }); - - taskRunner.addTasks( - ApplyFilter.class, - MakerVerifyTakerFeePayment.class, - SellerSignAndFinalizePayoutTx.class, - SellerBroadcastPayoutTx.class, - SellerSendPayoutTxPublishedMessage.class - ); - taskRunner.run(); - }); + .setTaskRunner(new TradeTaskRunner(sellerAsMakerTrade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess(event); + }, + (errorMessage) -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(event, errorMessage); + })) + .addTasks( + ApplyFilter.class, + MakerVerifyTakerFeePayment.class, + SellerSignAndFinalizePayoutTx.class, + SellerBroadcastPayoutTx.class, + SellerSendPayoutTxPublishedMessage.class + ).run(); + // sellerAsMakerTrade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 7e6417b4b56..f910c2afa3a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -99,23 +99,13 @@ public void takeAvailableOffer() { expectedPhase(Trade.Phase.INIT) .on(TakerEvent.TAKE_OFFER) .withTimeout(30) - .process(() -> { - processModel.setTempTradingPeerNodeAddress(trade.getTradingPeerNodeAddress()); - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, - () -> handleTaskRunnerSuccess(TakerEvent.TAKE_OFFER), - this::handleTaskRunnerFault); - - taskRunner.addTasks( - ApplyFilter.class, - TakerVerifyMakerFeePayment.class, - CreateTakerFeeTx.class, // - SellerAsTakerCreatesDepositTxInputs.class, - TakerSendInputsForDepositTxRequest.class - ); - - startTimeout(); - taskRunner.run(); - }); + .addTasks( + ApplyFilter.class, + TakerVerifyMakerFeePayment.class, + CreateTakerFeeTx.class, // + SellerAsTakerCreatesDepositTxInputs.class, + TakerSendInputsForDepositTxRequest.class + ).run(); } @@ -128,32 +118,34 @@ private void handle(InputsForDepositTxResponse message, NodeAddress peer) { .on(message) .from(peer) .withTimeout(30) - .process(() -> { - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, - () -> { - handleTaskRunnerSuccess(message); - }, - errorMessage -> handleTaskRunnerFault(message, errorMessage)); - - taskRunner.addTasks( - TakerProcessesInputsForDepositTxResponse.class, - ApplyFilter.class, - VerifyPeersAccountAgeWitness.class, - TakerVerifyAndSignContract.class, - TakerPublishFeeTx.class, - SellerAsTakerSignsDepositTx.class, - SellerCreatesDelayedPayoutTx.class, - SellerSendDelayedPayoutTxSignatureRequest.class - ); - taskRunner.run(); - }); + .addTasks( + TakerProcessesInputsForDepositTxResponse.class, + ApplyFilter.class, + VerifyPeersAccountAgeWitness.class, + TakerVerifyAndSignContract.class, + TakerPublishFeeTx.class, + SellerAsTakerSignsDepositTx.class, + SellerCreatesDelayedPayoutTx.class, + SellerSendDelayedPayoutTxSignatureRequest.class + ) + .run(); } private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) { expectedPhase(Trade.Phase.TAKER_FEE_PUBLISHED) .on(message) .from(peer) - .process(() -> { + .addTasks( + SellerProcessDelayedPayoutTxSignatureResponse.class, + SellerSignsDelayedPayoutTx.class, + SellerFinalizesDelayedPayoutTx.class, + SellerSendsDepositTxAndDelayedPayoutTxMessage.class, + SellerPublishesDepositTx.class, + PublishTradeStatistics.class + ) + .run(); + /* + .addTasks(() -> { // We stop timeout here and don't start a new one as the // SellerSendsDepositTxAndDelayedPayoutTxMessage repeats the send the message and has it's own // timeout if it never succeeds. @@ -176,7 +168,7 @@ private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) ); taskRunner.run(); processModel.witnessDebugLog(sellerAsTakerTrade); - }); + });*/ } @@ -196,27 +188,12 @@ private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress p sendAckMessage(message, true, null); processModel.removeMailboxMessageAfterProcessing(trade); }) - .process(() -> { - if (trade.getPayoutTx() != null) { - log.warn("We received a CounterCurrencyTransferStartedMessage but we have already created the payout tx " + - "so we ignore the message. This can happen if the ACK message to the peer did not " + - "arrive and the peer repeats sending us the message. We send another ACK msg."); - sendAckMessage(message, true, null); - processModel.removeMailboxMessageAfterProcessing(trade); - return; - } - - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, - () -> handleTaskRunnerSuccess(message), - errorMessage -> handleTaskRunnerFault(message, errorMessage)); - - taskRunner.addTasks( - SellerProcessCounterCurrencyTransferStartedMessage.class, - ApplyFilter.class, - TakerVerifyMakerFeePayment.class - ); - taskRunner.run(); - }); + .addTasks( + SellerProcessCounterCurrencyTransferStartedMessage.class, + ApplyFilter.class, + TakerVerifyMakerFeePayment.class + ) + .run(); } @@ -226,30 +203,27 @@ private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress p @Override public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + SellerEvent event = SellerEvent.PAYMENT_RECEIVED; expectedPhase(Trade.Phase.FIAT_SENT) - .on(SellerEvent.PAYMENT_RECEIVED) + .on(event) .preCondition(!wasDisputed()) - .process(() -> { - sellerAsTakerTrade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess(SellerEvent.PAYMENT_RECEIVED); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(errorMessage); - }); - - taskRunner.addTasks( - ApplyFilter.class, - TakerVerifyMakerFeePayment.class, - SellerSignAndFinalizePayoutTx.class, - SellerBroadcastPayoutTx.class, - SellerSendPayoutTxPublishedMessage.class //TODO add repeated msg send, check UI - ); - taskRunner.run(); - }); + .setTaskRunner(new TradeTaskRunner(sellerAsTakerTrade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess(event); + }, + (errorMessage) -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(event, errorMessage); + })) + .addTasks( + ApplyFilter.class, + TakerVerifyMakerFeePayment.class, + SellerSignAndFinalizePayoutTx.class, + SellerBroadcastPayoutTx.class, + SellerSendPayoutTxPublishedMessage.class //TODO add repeated msg send, check UI + ).run(); + //sellerAsTakerTrade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); } diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index 3ac39074338..7aa3ea1044e 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -51,6 +51,7 @@ import bisq.common.handlers.ErrorMessageHandler; import bisq.common.handlers.ResultHandler; import bisq.common.proto.network.NetworkEnvelope; +import bisq.common.taskrunner.Task; import javafx.beans.value.ChangeListener; @@ -148,15 +149,15 @@ public void onAcceptMediationResult(ResultHandler resultHandler, ErrorMessageHan errorMessageHandler.handleErrorMessage("We have received already the signature from the peer."); return; } - + DisputeEvent event = DisputeEvent.MEDIATION_RESULT_ACCEPTED; TradeTaskRunner taskRunner = new TradeTaskRunner(trade, () -> { resultHandler.handleResult(); - handleTaskRunnerSuccess(DisputeEvent.MEDIATION_RESULT_ACCEPTED); + handleTaskRunnerSuccess(event); }, (errorMessage) -> { errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(errorMessage); + handleTaskRunnerFault(event, errorMessage); }); taskRunner.addTasks( ApplyFilter.class, @@ -175,14 +176,15 @@ public void onFinalizeMediationResultPayout(ResultHandler resultHandler, ErrorMe return; } + DisputeEvent event = DisputeEvent.MEDIATION_RESULT_ACCEPTED; TradeTaskRunner taskRunner = new TradeTaskRunner(trade, () -> { resultHandler.handleResult(); - handleTaskRunnerSuccess(DisputeEvent.MEDIATION_RESULT_ACCEPTED); + handleTaskRunnerSuccess(event); }, (errorMessage) -> { errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(errorMessage); + handleTaskRunnerFault(event, errorMessage); }); taskRunner.addTasks( ApplyFilter.class, @@ -347,12 +349,8 @@ private void handleTaskRunnerSuccess(@Nullable TradeMessage tradeMessage, @Nulla sendAckMessage(tradeMessage, true, null); } - protected void handleTaskRunnerFault(String errorMessage) { - handleTaskRunnerFault(null, errorMessage); - } - protected void handleTaskRunnerFault(@Nullable TradeMessage tradeMessage, String errorMessage) { - log.error(errorMessage); + log.error("Task runner failed on {} with error {}", tradeMessage, errorMessage); sendAckMessage(tradeMessage, false, errorMessage); @@ -360,6 +358,13 @@ protected void handleTaskRunnerFault(@Nullable TradeMessage tradeMessage, String cleanup(); } + protected void handleTaskRunnerFault(@Nullable Event event, String errorMessage) { + log.error("Task runner failed on {} with error {}", event, errorMessage); + + cleanupTradeOnFault(); + cleanup(); + } + protected boolean wasDisputed() { return trade.getDisputeState() != Trade.DisputeState.NO_DISPUTE; } @@ -451,7 +456,7 @@ protected FluentProcess expectedPhases(Trade.Phase... phase) { class FluentProcess { private final Trade trade; @Nullable - private TradeMessage tradeMessage; + private TradeMessage message; private final Set expectedPhases = new HashSet<>(); private final Set preConditions = new HashSet<>(); @Nullable @@ -459,6 +464,7 @@ class FluentProcess { private Runnable preConditionFailedHandler; private int timeoutSec; private NodeAddress peersNodeAddress; + private TradeTaskRunner taskRunner; public FluentProcess(Trade trade, Trade.Phase expectedPhase) { @@ -472,9 +478,9 @@ public FluentProcess(Trade trade, this.expectedPhases.addAll(Set.of(expectedPhases)); } - protected FluentProcess process(Runnable runnable) { + public FluentProcess run() { boolean allPreConditionsMet = preConditions.stream().allMatch(e -> e); - boolean isTradeIdValid = tradeMessage == null || isTradeIdValid(processModel.getOfferId(), tradeMessage); + boolean isTradeIdValid = message == null || isTradeIdValid(processModel.getOfferId(), message); if (isPhaseValid() && allPreConditionsMet && isTradeIdValid) { if (timeoutSec > 0) { @@ -485,22 +491,54 @@ protected FluentProcess process(Runnable runnable) { processModel.setTempTradingPeerNodeAddress(peersNodeAddress); } - if (tradeMessage != null) { - processModel.setTradeMessage(tradeMessage); + if (message != null) { + processModel.setTradeMessage(message); } - runnable.run(); + taskRunner.run(); } + if (!allPreConditionsMet && preConditionFailedHandler != null) { preConditionFailedHandler.run(); } + + return this; + } + + /* protected FluentProcess defaultTaskRunner(Consumer consumer) { + taskRunner = new TradeTaskRunner(trade, + () -> handleTaskRunnerSuccess(message), + errorMessage -> handleTaskRunnerFault(message, errorMessage)); + + consumer.accept(taskRunner); + + return this; + }*/ + + @SafeVarargs + public final FluentProcess addTasks(Class>... tasks) { + if (taskRunner == null) { + if (message != null) { + taskRunner = new TradeTaskRunner(trade, + () -> handleTaskRunnerSuccess(message), + errorMessage -> handleTaskRunnerFault(message, errorMessage)); + } else if (event != null) { + taskRunner = new TradeTaskRunner(trade, + () -> handleTaskRunnerSuccess(event), + errorMessage -> handleTaskRunnerFault(event, errorMessage)); + } else { + throw new IllegalStateException("addTasks must not be called without message or event " + + "set in case no taskRunner has been created yet"); + } + } + taskRunner.addTasks(tasks); return this; } private boolean isPhaseValid() { boolean isPhaseValid = expectedPhases.stream().anyMatch(e -> e == trade.getPhase()); - String trigger = tradeMessage != null ? - tradeMessage.getClass().getSimpleName() : + String trigger = message != null ? + message.getClass().getSimpleName() : event != null ? event.name() + " event" : ""; @@ -532,7 +570,7 @@ public FluentProcess on(Event event) { } public FluentProcess on(TradeMessage tradeMessage) { - this.tradeMessage = tradeMessage; + this.message = tradeMessage; return this; } @@ -556,5 +594,10 @@ public FluentProcess from(NodeAddress peersNodeAddress) { this.peersNodeAddress = peersNodeAddress; return this; } + + public FluentProcess setTaskRunner(TradeTaskRunner taskRunner) { + this.taskRunner = taskRunner; + return this; + } } } From 968a6df550c0cdfe7504c624944162b1c4c2303f Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 23 Sep 2020 12:50:22 -0500 Subject: [PATCH 050/143] Refactor: Rename run to runTasks --- .../core/trade/protocol/BuyerAsMakerProtocol.java | 10 +++++----- .../core/trade/protocol/BuyerAsTakerProtocol.java | 12 ++++++------ .../core/trade/protocol/SellerAsMakerProtocol.java | 10 +++++----- .../core/trade/protocol/SellerAsTakerProtocol.java | 10 +++++----- .../java/bisq/core/trade/protocol/TradeProtocol.java | 2 +- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index d6ddbad5ae4..e5a6d690056 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -136,7 +136,7 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message, BuyerSetupDepositTxListener.class, BuyerAsMakerSendsInputsForDepositTxResponse.class ) - .run(); + .runTasks(); } @@ -154,7 +154,7 @@ private void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { BuyerVerifiesPreparedDelayedPayoutTx.class, BuyerSignsDelayedPayoutTx.class, BuyerSendsDelayedPayoutTxSignatureResponse.class - ).run(); + ).runTasks(); } // The DepositTxAndDelayedPayoutTxMessage is a mailbox message as earlier we use only the deposit tx which can @@ -189,7 +189,7 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer BuyerVerifiesFinalDelayedPayoutTx.class, PublishTradeStatistics.class ) - .run(); + .runTasks(); //processModel.witnessDebugLog(buyerAsMakerTrade); @@ -222,7 +222,7 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle BuyerSetupPayoutTxListener.class, BuyerSendCounterCurrencyTransferStartedMessage.class ) - .run(); + .runTasks(); // buyerAsMakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); } @@ -239,7 +239,7 @@ private void handle(PayoutTxPublishedMessage message, NodeAddress peer) { .addTasks( BuyerProcessPayoutTxPublishedMessage.class ) - .run(); + .runTasks(); } diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index f198f5f339b..927056878d7 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -133,7 +133,7 @@ public void takeAvailableOffer() { CreateTakerFeeTx.class, BuyerAsTakerCreatesDepositTxInputs.class, TakerSendInputsForDepositTxRequest.class - ).run(); + ).runTasks(); } @@ -154,7 +154,7 @@ private void handle(InputsForDepositTxResponse message, NodeAddress peer) { BuyerAsTakerSignsDepositTx.class, BuyerSetupDepositTxListener.class, BuyerAsTakerSendsDepositTxMessage.class) - .run(); + .runTasks(); } private void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { @@ -168,7 +168,7 @@ private void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { BuyerSignsDelayedPayoutTx.class, BuyerSendsDelayedPayoutTxSignatureResponse.class ) - .run(); + .runTasks(); } // The DepositTxAndDelayedPayoutTxMessage is a mailbox message as earlier we use only the deposit tx which can @@ -201,7 +201,7 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer .addTasks(BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, BuyerVerifiesFinalDelayedPayoutTx.class, PublishTradeStatistics.class) - .run(); + .runTasks(); //processModel.witnessDebugLog(buyerAsTakerTrade); } @@ -232,7 +232,7 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle BuyerSetupPayoutTxListener.class, BuyerSendCounterCurrencyTransferStartedMessage.class ) - .run(); + .runTasks(); //todo // buyerAsTakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); @@ -250,7 +250,7 @@ private void handle(PayoutTxPublishedMessage message, NodeAddress peer) { .addTasks( BuyerProcessPayoutTxPublishedMessage.class ) - .run(); + .runTasks(); } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index 4d46184dc06..2e8269c9e2b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -113,7 +113,7 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message, SellerAsMakerCreatesUnsignedDepositTx.class, SellerAsMakerSendsInputsForDepositTxResponse.class ) - .run(); + .runTasks(); } @@ -132,7 +132,7 @@ protected void handle(DepositTxMessage message, NodeAddress peer) { SellerCreatesDelayedPayoutTx.class, SellerSendDelayedPayoutTxSignatureRequest.class ) - .run(); + .runTasks(); } private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) { @@ -153,7 +153,7 @@ private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) SellerPublishesDepositTx.class, PublishTradeStatistics.class ) - .run(); + .runTasks(); //processModel.witnessDebugLog(sellerAsMakerTrade); } @@ -180,7 +180,7 @@ private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress p ApplyFilter.class, MakerVerifyTakerFeePayment.class ) - .run(); + .runTasks(); } @@ -209,7 +209,7 @@ public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandl SellerSignAndFinalizePayoutTx.class, SellerBroadcastPayoutTx.class, SellerSendPayoutTxPublishedMessage.class - ).run(); + ).runTasks(); // sellerAsMakerTrade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index f910c2afa3a..25ac1e1f345 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -105,7 +105,7 @@ public void takeAvailableOffer() { CreateTakerFeeTx.class, // SellerAsTakerCreatesDepositTxInputs.class, TakerSendInputsForDepositTxRequest.class - ).run(); + ).runTasks(); } @@ -128,7 +128,7 @@ private void handle(InputsForDepositTxResponse message, NodeAddress peer) { SellerCreatesDelayedPayoutTx.class, SellerSendDelayedPayoutTxSignatureRequest.class ) - .run(); + .runTasks(); } private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) { @@ -143,7 +143,7 @@ private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) SellerPublishesDepositTx.class, PublishTradeStatistics.class ) - .run(); + .runTasks(); /* .addTasks(() -> { // We stop timeout here and don't start a new one as the @@ -193,7 +193,7 @@ private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress p ApplyFilter.class, TakerVerifyMakerFeePayment.class ) - .run(); + .runTasks(); } @@ -222,7 +222,7 @@ public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandl SellerSignAndFinalizePayoutTx.class, SellerBroadcastPayoutTx.class, SellerSendPayoutTxPublishedMessage.class //TODO add repeated msg send, check UI - ).run(); + ).runTasks(); //sellerAsTakerTrade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); } diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index 7aa3ea1044e..543bf0df8b3 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -478,7 +478,7 @@ public FluentProcess(Trade trade, this.expectedPhases.addAll(Set.of(expectedPhases)); } - public FluentProcess run() { + public FluentProcess runTasks() { boolean allPreConditionsMet = preConditions.stream().allMatch(e -> e); boolean isTradeIdValid = message == null || isTradeIdValid(processModel.getOfferId(), message); From 54d625e564be952ff88a03070a33638d1c44ca8f Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 23 Sep 2020 13:08:26 -0500 Subject: [PATCH 051/143] Add run method to accept runnable which is execute before run tasks Add isValid method in FluentProcess Add more logs if invalid Add toString Refactor: - Remove custom trade fields and use trade from base class instead --- .../trade/protocol/BuyerAsMakerProtocol.java | 17 ++---- .../trade/protocol/BuyerAsTakerProtocol.java | 12 ++--- .../trade/protocol/SellerAsMakerProtocol.java | 18 +++---- .../trade/protocol/SellerAsTakerProtocol.java | 37 ++++--------- .../core/trade/protocol/TradeProtocol.java | 54 +++++++++++++------ 5 files changed, 63 insertions(+), 75 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index e5a6d690056..28f4985835b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -54,8 +54,6 @@ @Slf4j public class BuyerAsMakerProtocol extends TradeProtocol implements BuyerProtocol, MakerProtocol { - private final BuyerAsMakerTrade buyerAsMakerTrade; - /////////////////////////////////////////////////////////////////////////////////////////// // Constructor @@ -64,8 +62,6 @@ public class BuyerAsMakerProtocol extends TradeProtocol implements BuyerProtocol public BuyerAsMakerProtocol(BuyerAsMakerTrade trade) { super(trade); - this.buyerAsMakerTrade = trade; - Trade.Phase phase = trade.getState().getPhase(); if (phase == Trade.Phase.TAKER_FEE_PUBLISHED) { TradeTaskRunner taskRunner = new TradeTaskRunner(trade, @@ -119,7 +115,7 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message, .on(message) .from(peer) .withTimeout(30) - .setTaskRunner(new TradeTaskRunner(buyerAsMakerTrade, + .setTaskRunner(new TradeTaskRunner(trade, () -> handleTaskRunnerSuccess(message), errorMessage -> { errorMessageHandler.handleErrorMessage(errorMessage); @@ -178,7 +174,7 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer sendAckMessage(message, true, null); processModel.removeMailboxMessageAfterProcessing(trade); }) - .setTaskRunner(new TradeTaskRunner(buyerAsMakerTrade, + .setTaskRunner(new TradeTaskRunner(trade, () -> { stopTimeout(); handleTaskRunnerSuccess(message); @@ -189,10 +185,8 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer BuyerVerifiesFinalDelayedPayoutTx.class, PublishTradeStatistics.class ) + .run(() -> processModel.witnessDebugLog(trade)) .runTasks(); - -//processModel.witnessDebugLog(buyerAsMakerTrade); - } @@ -206,7 +200,7 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle expectedPhase(Trade.Phase.DEPOSIT_CONFIRMED) .on(event) .preCondition(!wasDisputed()) - .setTaskRunner(new TradeTaskRunner(buyerAsMakerTrade, + .setTaskRunner(new TradeTaskRunner(trade, () -> { resultHandler.handleResult(); handleTaskRunnerSuccess(event); @@ -222,9 +216,8 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle BuyerSetupPayoutTxListener.class, BuyerSendCounterCurrencyTransferStartedMessage.class ) + .run(() -> trade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED)) .runTasks(); - - // buyerAsMakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); } diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 927056878d7..5b142ed6709 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -61,8 +61,6 @@ @Slf4j public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol, TakerProtocol { - private final BuyerAsTakerTrade buyerAsTakerTrade; - /////////////////////////////////////////////////////////////////////////////////////////// // Constructor @@ -71,8 +69,6 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol public BuyerAsTakerProtocol(BuyerAsTakerTrade trade) { super(trade); - this.buyerAsTakerTrade = trade; - Offer offer = checkNotNull(trade.getOffer()); processModel.getTradingPeer().setPubKeyRing(offer.getPubKeyRing()); @@ -192,7 +188,7 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer sendAckMessage(message, true, null); processModel.removeMailboxMessageAfterProcessing(trade); }) - .setTaskRunner(new TradeTaskRunner(buyerAsTakerTrade, + .setTaskRunner(new TradeTaskRunner(trade, () -> { stopTimeout(); handleTaskRunnerSuccess(message); @@ -217,7 +213,7 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle expectedPhase(Trade.Phase.DEPOSIT_CONFIRMED) .on(event) .preCondition(!wasDisputed()) - .setTaskRunner(new TradeTaskRunner(buyerAsTakerTrade, + .setTaskRunner(new TradeTaskRunner(trade, () -> { resultHandler.handleResult(); handleTaskRunnerSuccess(event); @@ -232,10 +228,8 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle BuyerSetupPayoutTxListener.class, BuyerSendCounterCurrencyTransferStartedMessage.class ) + .run(() -> trade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED)) .runTasks(); - - //todo - // buyerAsTakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index 2e8269c9e2b..3124b2ccf80 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -57,8 +57,6 @@ @Slf4j public class SellerAsMakerProtocol extends TradeProtocol implements SellerProtocol, MakerProtocol { - private final SellerAsMakerTrade sellerAsMakerTrade; - /////////////////////////////////////////////////////////////////////////////////////////// // Constructor @@ -66,8 +64,6 @@ public class SellerAsMakerProtocol extends TradeProtocol implements SellerProtoc public SellerAsMakerProtocol(SellerAsMakerTrade trade) { super(trade); - - this.sellerAsMakerTrade = trade; } @@ -97,7 +93,7 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message, .on(message) .from(peer) .withTimeout(30) - .setTaskRunner(new TradeTaskRunner(sellerAsMakerTrade, + .setTaskRunner(new TradeTaskRunner(trade, () -> handleTaskRunnerSuccess(message), errorMessage -> { errorMessageHandler.handleErrorMessage(errorMessage); @@ -139,7 +135,7 @@ private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) expectedPhase(Trade.Phase.TAKER_FEE_PUBLISHED) .on(message) .from(peer) - .setTaskRunner(new TradeTaskRunner(sellerAsMakerTrade, + .setTaskRunner(new TradeTaskRunner(trade, () -> { stopTimeout(); handleTaskRunnerSuccess(message); @@ -153,9 +149,8 @@ private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) SellerPublishesDepositTx.class, PublishTradeStatistics.class ) + .run(() -> processModel.witnessDebugLog(trade)) //TODO still needed? If so move to witness domain .runTasks(); - - //processModel.witnessDebugLog(sellerAsMakerTrade); } @@ -194,7 +189,7 @@ public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandl expectedPhase(Trade.Phase.FIAT_SENT) .on(event) .preCondition(!wasDisputed()) - .setTaskRunner(new TradeTaskRunner(sellerAsMakerTrade, + .setTaskRunner(new TradeTaskRunner(trade, () -> { resultHandler.handleResult(); handleTaskRunnerSuccess(event); @@ -209,8 +204,9 @@ public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandl SellerSignAndFinalizePayoutTx.class, SellerBroadcastPayoutTx.class, SellerSendPayoutTxPublishedMessage.class - ).runTasks(); - // sellerAsMakerTrade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); + ) + .run(() -> trade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT)) + .runTasks(); } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 25ac1e1f345..baf59f61a99 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -59,8 +59,6 @@ @Slf4j public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtocol, TakerProtocol { - private final SellerAsTakerTrade sellerAsTakerTrade; - /////////////////////////////////////////////////////////////////////////////////////////// // Constructor @@ -69,8 +67,6 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc public SellerAsTakerProtocol(SellerAsTakerTrade trade) { super(trade); - this.sellerAsTakerTrade = trade; - Offer offer = checkNotNull(trade.getOffer()); processModel.getTradingPeer().setPubKeyRing(offer.getPubKeyRing()); } @@ -143,32 +139,16 @@ private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) SellerPublishesDepositTx.class, PublishTradeStatistics.class ) - .runTasks(); - /* - .addTasks(() -> { + .run(() -> { // We stop timeout here and don't start a new one as the // SellerSendsDepositTxAndDelayedPayoutTxMessage repeats the send the message and has it's own // timeout if it never succeeds. stopTimeout(); - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, - () -> { - - handleTaskRunnerSuccess(message); - }, - errorMessage -> handleTaskRunnerFault(message, errorMessage)); - - taskRunner.addTasks( - SellerProcessDelayedPayoutTxSignatureResponse.class, - SellerSignsDelayedPayoutTx.class, - SellerFinalizesDelayedPayoutTx.class, - SellerSendsDepositTxAndDelayedPayoutTxMessage.class, - SellerPublishesDepositTx.class, - PublishTradeStatistics.class - ); - taskRunner.run(); - processModel.witnessDebugLog(sellerAsTakerTrade); - });*/ + //TODO still needed? If so move to witness domain + processModel.witnessDebugLog(trade); + }) + .runTasks(); } @@ -207,7 +187,7 @@ public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandl expectedPhase(Trade.Phase.FIAT_SENT) .on(event) .preCondition(!wasDisputed()) - .setTaskRunner(new TradeTaskRunner(sellerAsTakerTrade, + .setTaskRunner(new TradeTaskRunner(trade, () -> { resultHandler.handleResult(); handleTaskRunnerSuccess(event); @@ -222,8 +202,9 @@ public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandl SellerSignAndFinalizePayoutTx.class, SellerBroadcastPayoutTx.class, SellerSendPayoutTxPublishedMessage.class //TODO add repeated msg send, check UI - ).runTasks(); - //sellerAsTakerTrade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); + ) + .run(() -> trade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT)) + .runTasks(); } diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index 543bf0df8b3..8b36a2b05b4 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -478,11 +478,15 @@ public FluentProcess(Trade trade, this.expectedPhases.addAll(Set.of(expectedPhases)); } - public FluentProcess runTasks() { - boolean allPreConditionsMet = preConditions.stream().allMatch(e -> e); - boolean isTradeIdValid = message == null || isTradeIdValid(processModel.getOfferId(), message); + public FluentProcess run(Runnable runnable) { + if (isValid()) { + runnable.run(); + } + return this; + } - if (isPhaseValid() && allPreConditionsMet && isTradeIdValid) { + public FluentProcess runTasks() { + if (isValid()) { if (timeoutSec > 0) { startTimeout(timeoutSec); } @@ -498,22 +502,27 @@ public FluentProcess runTasks() { taskRunner.run(); } - if (!allPreConditionsMet && preConditionFailedHandler != null) { - preConditionFailedHandler.run(); - } - return this; } - /* protected FluentProcess defaultTaskRunner(Consumer consumer) { - taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(message), - errorMessage -> handleTaskRunnerFault(message, errorMessage)); + private boolean isValid() { + boolean isPhaseValid = isPhaseValid(); + boolean allPreConditionsMet = preConditions.stream().allMatch(e -> e); + boolean isTradeIdValid = message == null || isTradeIdValid(processModel.getOfferId(), message); - consumer.accept(taskRunner); + if (!allPreConditionsMet) { + log.error("PreConditions not met. preConditions={}, this={}", preConditions, this); + if (preConditionFailedHandler != null) { + preConditionFailedHandler.run(); + } + } + if (!isTradeIdValid) { + log.error("TradeId does not match tradeId in message, TradeId={}, tradeId in message={}", + trade.getId(), message.getTradeId()); + } - return this; - }*/ + return isPhaseValid && allPreConditionsMet && isTradeIdValid; + } @SafeVarargs public final FluentProcess addTasks(Class>... tasks) { @@ -599,5 +608,20 @@ public FluentProcess setTaskRunner(TradeTaskRunner taskRunner) { this.taskRunner = taskRunner; return this; } + + @Override + public String toString() { + return "FluentProcess{" + + "\n trade=" + trade + + ",\n message=" + message + + ",\n expectedPhases=" + expectedPhases + + ",\n preConditions=" + preConditions + + ",\n event=" + event + + ",\n preConditionFailedHandler=" + preConditionFailedHandler + + ",\n timeoutSec=" + timeoutSec + + ",\n peersNodeAddress=" + peersNodeAddress + + ",\n taskRunner=" + taskRunner + + "\n}"; + } } } From cdbd6cdfa8189a58f74518505209da447801f57e Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 23 Sep 2020 16:21:29 -0500 Subject: [PATCH 052/143] Redesigned fluent API again... Move code duplication to Buyer protocol --- .../trade/protocol/BuyerAsMakerProtocol.java | 140 ++++----- .../trade/protocol/BuyerAsTakerProtocol.java | 153 ++++------ .../core/trade/protocol/BuyerProtocol.java | 31 ++ .../trade/protocol/SellerAsMakerProtocol.java | 115 ++++--- .../trade/protocol/SellerAsTakerProtocol.java | 89 +++--- .../core/trade/protocol/TradeProtocol.java | 285 +++++++++++------- 6 files changed, 429 insertions(+), 384 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 28f4985835b..1e015215e95 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -11,7 +11,7 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public * License for more details. * - * You should have received a copy of the GNU Affero General Public License + * You should have with a copy of the GNU Affero General Public License * along with Bisq. If not, see . */ @@ -62,28 +62,7 @@ public class BuyerAsMakerProtocol extends TradeProtocol implements BuyerProtocol public BuyerAsMakerProtocol(BuyerAsMakerTrade trade) { super(trade); - Trade.Phase phase = trade.getState().getPhase(); - if (phase == Trade.Phase.TAKER_FEE_PUBLISHED) { - TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(BuyerEvent.STARTUP), - errorMessage -> handleTaskRunnerFault(BuyerEvent.STARTUP, errorMessage)); - - taskRunner.addTasks(BuyerSetupDepositTxListener.class); - taskRunner.run(); - } else if (trade.isFiatSent() && !trade.isPayoutPublished()) { - TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(BuyerEvent.STARTUP), - errorMessage -> handleTaskRunnerFault(BuyerEvent.STARTUP, errorMessage)); - - taskRunner.addTasks(BuyerSetupPayoutTxListener.class); - if (trade.getState() == Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG || - trade.getState() == Trade.State.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG) { - // In case we have not received an ACK from the CounterCurrencyTransferStartedMessage we re-send it - // periodically in BuyerSendCounterCurrencyTransferStartedMessage - taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class); - } - taskRunner.run(); - } + maybeSetupTaskRunners(trade, processModel, this); } @@ -104,24 +83,17 @@ public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peer) { /////////////////////////////////////////////////////////////////////////////////////////// - // Start trade + // Handle take offer request /////////////////////////////////////////////////////////////////////////////////////////// @Override public void handleTakeOfferRequest(InputsForDepositTxRequest message, NodeAddress peer, ErrorMessageHandler errorMessageHandler) { - expectedPhase(Trade.Phase.INIT) - .on(message) - .from(peer) - .withTimeout(30) - .setTaskRunner(new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(message), - errorMessage -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(message, errorMessage); - })) - .addTasks( + given(phase(Trade.Phase.INIT) + .with(message) + .from(peer)) + .setup(tasks( MakerProcessesInputsForDepositTxRequest.class, ApplyFilter.class, VerifyPeersAccountAgeWitness.class, @@ -130,9 +102,15 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message, MakerCreateAndSignContract.class, BuyerAsMakerCreatesAndSignsDepositTx.class, BuyerSetupDepositTxListener.class, - BuyerAsMakerSendsInputsForDepositTxResponse.class - ) - .runTasks(); + BuyerAsMakerSendsInputsForDepositTxResponse.class). + using(new TradeTaskRunner(trade, + () -> handleTaskRunnerSuccess(message), + errorMessage -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(message, errorMessage); + })) + .withTimeout(30)) + .executeTasks(); } @@ -141,20 +119,20 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message, /////////////////////////////////////////////////////////////////////////////////////////// private void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { - expectedPhase(Trade.Phase.TAKER_FEE_PUBLISHED) - .on(message) - .from(peer) - .withTimeout(30) - .addTasks( + given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) + .with(message) + .from(peer)) + .setup(tasks( BuyerProcessDelayedPayoutTxSignatureRequest.class, BuyerVerifiesPreparedDelayedPayoutTx.class, BuyerSignsDelayedPayoutTx.class, - BuyerSendsDelayedPayoutTxSignatureResponse.class - ).runTasks(); + BuyerSendsDelayedPayoutTxSignatureResponse.class) + .withTimeout(30)) + .executeTasks(); } // The DepositTxAndDelayedPayoutTxMessage is a mailbox message as earlier we use only the deposit tx which can - // be also received from the network once published. + // be also with from the network once published. // Now we send the delayed payout tx as well and with that this message is mandatory for continuing the protocol. // We do not support mailbox message handling during the take offer process as it is expected that both peers // are online. @@ -162,31 +140,30 @@ private void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { // mailbox message but the stored in mailbox case is not expected and the seller would try to send the message again // in the hope to reach the buyer directly. private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer) { - expectedPhases(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) - .on(message) + given(anyPhase(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) + .with(message) .from(peer) .preCondition(trade.getDepositTx() == null || trade.getDelayedPayoutTx() == null, () -> { - log.warn("We received a DepositTxAndDelayedPayoutTxMessage but we have already processed the deposit and " + + log.warn("We with a DepositTxAndDelayedPayoutTxMessage but we have already processed the deposit and " + "delayed payout tx so we ignore the message. This can happen if the ACK message to the peer did not " + "arrive and the peer repeats sending us the message. We send another ACK msg."); stopTimeout(); sendAckMessage(message, true, null); processModel.removeMailboxMessageAfterProcessing(trade); - }) - .setTaskRunner(new TradeTaskRunner(trade, - () -> { - stopTimeout(); - handleTaskRunnerSuccess(message); - }, - errorMessage -> handleTaskRunnerFault(message, errorMessage))) - .addTasks( + })) + .setup(tasks( BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, BuyerVerifiesFinalDelayedPayoutTx.class, - PublishTradeStatistics.class - ) + PublishTradeStatistics.class) + .using(new TradeTaskRunner(trade, + () -> { + stopTimeout(); + handleTaskRunnerSuccess(message); + }, + errorMessage -> handleTaskRunnerFault(message, errorMessage)))) .run(() -> processModel.witnessDebugLog(trade)) - .runTasks(); + .executeTasks(); } @@ -197,27 +174,26 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer @Override public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { BuyerEvent event = BuyerEvent.PAYMENT_SENT; - expectedPhase(Trade.Phase.DEPOSIT_CONFIRMED) - .on(event) - .preCondition(!wasDisputed()) - .setTaskRunner(new TradeTaskRunner(trade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess(event); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(event, errorMessage); - })) - .addTasks( + given(phase(Trade.Phase.DEPOSIT_CONFIRMED) + .with(event) + .preCondition(!wasDisputed())) + .setup(tasks( ApplyFilter.class, MakerVerifyTakerFeePayment.class, BuyerSignPayoutTx.class, BuyerSetupPayoutTxListener.class, - BuyerSendCounterCurrencyTransferStartedMessage.class - ) + BuyerSendCounterCurrencyTransferStartedMessage.class) + .using(new TradeTaskRunner(trade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess(event); + }, + (errorMessage) -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(event, errorMessage); + }))) .run(() -> trade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED)) - .runTasks(); + .executeTasks(); } @@ -226,13 +202,11 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle /////////////////////////////////////////////////////////////////////////////////////////// private void handle(PayoutTxPublishedMessage message, NodeAddress peer) { - expectedPhases(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) - .on(message) - .from(peer) - .addTasks( - BuyerProcessPayoutTxPublishedMessage.class - ) - .runTasks(); + given(anyPhase(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) + .with(message) + .from(peer)) + .setup(tasks(BuyerProcessPayoutTxPublishedMessage.class)) + .executeTasks(); } diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 5b142ed6709..f4e042a335a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -11,14 +11,13 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public * License for more details. * - * You should have received a copy of the GNU Affero General Public License + * You should have with a copy of the GNU Affero General Public License * along with Bisq. If not, see . */ package bisq.core.trade.protocol; -import bisq.core.offer.Offer; import bisq.core.trade.BuyerAsTakerTrade; import bisq.core.trade.Trade; import bisq.core.trade.messages.DelayedPayoutTxSignatureRequest; @@ -57,8 +56,6 @@ import lombok.extern.slf4j.Slf4j; -import static com.google.common.base.Preconditions.checkNotNull; - @Slf4j public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol, TakerProtocol { @@ -69,32 +66,7 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol public BuyerAsTakerProtocol(BuyerAsTakerTrade trade) { super(trade); - Offer offer = checkNotNull(trade.getOffer()); - processModel.getTradingPeer().setPubKeyRing(offer.getPubKeyRing()); - - Trade.Phase phase = trade.getState().getPhase(); - if (phase == Trade.Phase.TAKER_FEE_PUBLISHED) { - TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(BuyerEvent.STARTUP), - errorMessage -> handleTaskRunnerFault(BuyerEvent.STARTUP, errorMessage)); - - taskRunner.addTasks(BuyerSetupDepositTxListener.class); - taskRunner.run(); - } else if (trade.isFiatSent() && !trade.isPayoutPublished()) { - TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(BuyerEvent.STARTUP), - errorMessage -> handleTaskRunnerFault(BuyerEvent.STARTUP, errorMessage)); - - taskRunner.addTasks(BuyerSetupPayoutTxListener.class); - - if (trade.getState() == Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG || - trade.getState() == Trade.State.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG) { - // In case we have not received an ACK from the CounterCurrencyTransferStartedMessage we re-send it - // periodically in BuyerSendCounterCurrencyTransferStartedMessage - taskRunner.addTasks(BuyerSendCounterCurrencyTransferStartedMessage.class); - } - taskRunner.run(); - } + maybeSetupTaskRunners(trade, processModel, this); } @@ -103,33 +75,34 @@ public BuyerAsTakerProtocol(BuyerAsTakerTrade trade) { /////////////////////////////////////////////////////////////////////////////////////////// @Override - public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peerNodeAddress) { - super.doApplyMailboxTradeMessage(message, peerNodeAddress); + public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peer) { + super.doApplyMailboxTradeMessage(message, peer); if (message instanceof DepositTxAndDelayedPayoutTxMessage) { - handle((DepositTxAndDelayedPayoutTxMessage) message, peerNodeAddress); + handle((DepositTxAndDelayedPayoutTxMessage) message, peer); } else if (message instanceof PayoutTxPublishedMessage) { - handle((PayoutTxPublishedMessage) message, peerNodeAddress); + handle((PayoutTxPublishedMessage) message, peer); } } /////////////////////////////////////////////////////////////////////////////////////////// - // Start trade + // Take offer /////////////////////////////////////////////////////////////////////////////////////////// @Override public void takeAvailableOffer() { - expectedPhase(Trade.Phase.INIT) - .on(TakerEvent.TAKE_OFFER) - .withTimeout(30) - .addTasks( + given(phase(Trade.Phase.INIT) + .with(TakerEvent.TAKE_OFFER)) + .setup(tasks( ApplyFilter.class, TakerVerifyMakerFeePayment.class, CreateTakerFeeTx.class, BuyerAsTakerCreatesDepositTxInputs.class, - TakerSendInputsForDepositTxRequest.class - ).runTasks(); + TakerSendInputsForDepositTxRequest.class) + .withTimeout(30)) + .run(() -> processModel.setTempTradingPeerNodeAddress(trade.getTradingPeerNodeAddress())) + .executeTasks(); } @@ -138,11 +111,10 @@ public void takeAvailableOffer() { /////////////////////////////////////////////////////////////////////////////////////////// private void handle(InputsForDepositTxResponse message, NodeAddress peer) { - expectedPhase(Trade.Phase.INIT) - .on(message) - .from(peer) - .withTimeout(30) - .addTasks(TakerProcessesInputsForDepositTxResponse.class, + given(phase(Trade.Phase.INIT) + .with(message) + .from(peer)) + .setup(tasks(TakerProcessesInputsForDepositTxResponse.class, ApplyFilter.class, VerifyPeersAccountAgeWitness.class, TakerVerifyAndSignContract.class, @@ -150,25 +122,25 @@ private void handle(InputsForDepositTxResponse message, NodeAddress peer) { BuyerAsTakerSignsDepositTx.class, BuyerSetupDepositTxListener.class, BuyerAsTakerSendsDepositTxMessage.class) - .runTasks(); + .withTimeout(30)) + .executeTasks(); } private void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { - expectedPhase(Trade.Phase.TAKER_FEE_PUBLISHED) - .on(message) - .from(peer) - .withTimeout(30) - .addTasks( + given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) + .with(message) + .from(peer)) + .setup(tasks( BuyerProcessDelayedPayoutTxSignatureRequest.class, BuyerVerifiesPreparedDelayedPayoutTx.class, BuyerSignsDelayedPayoutTx.class, - BuyerSendsDelayedPayoutTxSignatureResponse.class - ) - .runTasks(); + BuyerSendsDelayedPayoutTxSignatureResponse.class) + .withTimeout(30)) + .executeTasks(); } // The DepositTxAndDelayedPayoutTxMessage is a mailbox message as earlier we use only the deposit tx which can - // be also received from the network once published. + // be also with from the network once published. // Now we send the delayed payout tx as well and with that this message is mandatory for continuing the protocol. // We do not support mailbox message handling during the take offer process as it is expected that both peers // are online. @@ -176,29 +148,29 @@ private void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { // mailbox message but the stored in mailbox case is not expected and the seller would try to send the message again // in the hope to reach the buyer directly. private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer) { - expectedPhases(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) - .on(message) + given(anyPhase(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) + .with(message) .from(peer) .preCondition(trade.getDepositTx() == null || trade.getDelayedPayoutTx() == null, () -> { - log.warn("We received a DepositTxAndDelayedPayoutTxMessage but we have already processed the deposit and " + + log.warn("We with a DepositTxAndDelayedPayoutTxMessage but we have already processed the deposit and " + "delayed payout tx so we ignore the message. This can happen if the ACK message to the peer did not " + "arrive and the peer repeats sending us the message. We send another ACK msg."); stopTimeout(); sendAckMessage(message, true, null); processModel.removeMailboxMessageAfterProcessing(trade); - }) - .setTaskRunner(new TradeTaskRunner(trade, - () -> { - stopTimeout(); - handleTaskRunnerSuccess(message); - }, - errorMessage -> handleTaskRunnerFault(message, errorMessage))) - .addTasks(BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, + })) + .setup(tasks(BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, BuyerVerifiesFinalDelayedPayoutTx.class, PublishTradeStatistics.class) - .runTasks(); - //processModel.witnessDebugLog(buyerAsTakerTrade); + .using(new TradeTaskRunner(trade, + () -> { + stopTimeout(); + handleTaskRunnerSuccess(message); + }, + errorMessage -> handleTaskRunnerFault(message, errorMessage)))) + .run(() -> processModel.witnessDebugLog(trade)) + .executeTasks(); } @@ -210,26 +182,25 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer @Override public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { BuyerEvent event = BuyerEvent.PAYMENT_SENT; - expectedPhase(Trade.Phase.DEPOSIT_CONFIRMED) - .on(event) - .preCondition(!wasDisputed()) - .setTaskRunner(new TradeTaskRunner(trade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess(event); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(event, errorMessage); - })) - .addTasks(ApplyFilter.class, + given(phase(Trade.Phase.DEPOSIT_CONFIRMED) + .with(event) + .preCondition(!wasDisputed())) + .setup(tasks(ApplyFilter.class, TakerVerifyMakerFeePayment.class, BuyerSignPayoutTx.class, BuyerSetupPayoutTxListener.class, - BuyerSendCounterCurrencyTransferStartedMessage.class - ) + BuyerSendCounterCurrencyTransferStartedMessage.class) + .using(new TradeTaskRunner(trade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess(event); + }, + (errorMessage) -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(event, errorMessage); + }))) .run(() -> trade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED)) - .runTasks(); + .executeTasks(); } @@ -238,13 +209,11 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle /////////////////////////////////////////////////////////////////////////////////////////// private void handle(PayoutTxPublishedMessage message, NodeAddress peer) { - expectedPhases(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) - .on(message) - .from(peer) - .addTasks( - BuyerProcessPayoutTxPublishedMessage.class - ) - .runTasks(); + given(anyPhase(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) + .with(message) + .from(peer)) + .setup(tasks(BuyerProcessPayoutTxPublishedMessage.class)) + .executeTasks(); } 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 19c195a2ef8..da37e2755f2 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java @@ -17,9 +17,17 @@ package bisq.core.trade.protocol; +import bisq.core.offer.Offer; +import bisq.core.trade.Trade; +import bisq.core.trade.protocol.tasks.buyer.BuyerSendCounterCurrencyTransferStartedMessage; +import bisq.core.trade.protocol.tasks.buyer.BuyerSetupDepositTxListener; +import bisq.core.trade.protocol.tasks.buyer.BuyerSetupPayoutTxListener; + import bisq.common.handlers.ErrorMessageHandler; import bisq.common.handlers.ResultHandler; +import static com.google.common.base.Preconditions.checkNotNull; + public interface BuyerProtocol { void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler); @@ -27,4 +35,27 @@ enum BuyerEvent implements TradeProtocol.Event { STARTUP, PAYMENT_SENT } + + default void maybeSetupTaskRunners(Trade trade, ProcessModel processModel, TradeProtocol tradeProtocol) { + Offer offer = checkNotNull(trade.getOffer()); + processModel.getTradingPeer().setPubKeyRing(offer.getPubKeyRing()); + + + tradeProtocol.given(tradeProtocol.phase(Trade.Phase.TAKER_FEE_PUBLISHED) + .with(BuyerEvent.STARTUP)) + .setup(tradeProtocol.tasks(BuyerSetupDepositTxListener.class)) + .executeTasks(); + + tradeProtocol.given(tradeProtocol.anyPhase(Trade.Phase.FIAT_SENT, Trade.Phase.FIAT_RECEIVED) + .with(BuyerEvent.STARTUP)) + .setup(tradeProtocol.tasks(BuyerSetupPayoutTxListener.class)) + .executeTasks(); + + tradeProtocol.given(tradeProtocol.anyPhase(Trade.Phase.FIAT_SENT, Trade.Phase.FIAT_RECEIVED) + .anyState(Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG, + Trade.State.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG) + .with(BuyerEvent.STARTUP)) + .setup(tradeProtocol.tasks(BuyerSendCounterCurrencyTransferStartedMessage.class)) + .executeTasks(); + } } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index 3124b2ccf80..752c2420966 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -82,24 +82,17 @@ public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peerNod /////////////////////////////////////////////////////////////////////////////////////////// - // Start trade + // Handle take offer request /////////////////////////////////////////////////////////////////////////////////////////// @Override public void handleTakeOfferRequest(InputsForDepositTxRequest message, NodeAddress peer, ErrorMessageHandler errorMessageHandler) { - expectedPhase(Trade.Phase.INIT) - .on(message) - .from(peer) - .withTimeout(30) - .setTaskRunner(new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(message), - errorMessage -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(message, errorMessage); - })) - .addTasks( + given(phase(Trade.Phase.INIT) + .with(message) + .from(peer)) + .setup(tasks( MakerProcessesInputsForDepositTxRequest.class, ApplyFilter.class, VerifyPeersAccountAgeWitness.class, @@ -107,9 +100,15 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message, MakerSetsLockTime.class, MakerCreateAndSignContract.class, SellerAsMakerCreatesUnsignedDepositTx.class, - SellerAsMakerSendsInputsForDepositTxResponse.class - ) - .runTasks(); + SellerAsMakerSendsInputsForDepositTxResponse.class) + .using(new TradeTaskRunner(trade, + () -> handleTaskRunnerSuccess(message), + errorMessage -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(message, errorMessage); + })) + .withTimeout(30)) + .executeTasks(); } @@ -118,39 +117,37 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message, /////////////////////////////////////////////////////////////////////////////////////////// protected void handle(DepositTxMessage message, NodeAddress peer) { - expectedPhase(Trade.Phase.TAKER_FEE_PUBLISHED) - .on(message) - .from(peer) - .withTimeout(30) - .addTasks( + given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) + .with(message) + .from(peer)) + .setup(tasks( SellerAsMakerProcessDepositTxMessage.class, SellerAsMakerFinalizesDepositTx.class, SellerCreatesDelayedPayoutTx.class, - SellerSendDelayedPayoutTxSignatureRequest.class - ) - .runTasks(); + SellerSendDelayedPayoutTxSignatureRequest.class) + .withTimeout(30)) + .executeTasks(); } private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) { - expectedPhase(Trade.Phase.TAKER_FEE_PUBLISHED) - .on(message) - .from(peer) - .setTaskRunner(new TradeTaskRunner(trade, - () -> { - stopTimeout(); - handleTaskRunnerSuccess(message); - }, - errorMessage -> handleTaskRunnerFault(message, errorMessage))) - .addTasks( + given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) + .with(message) + .from(peer)) + .setup(tasks( SellerProcessDelayedPayoutTxSignatureResponse.class, SellerSignsDelayedPayoutTx.class, SellerFinalizesDelayedPayoutTx.class, SellerSendsDepositTxAndDelayedPayoutTxMessage.class, SellerPublishesDepositTx.class, - PublishTradeStatistics.class - ) + PublishTradeStatistics.class) + .using(new TradeTaskRunner(trade, + () -> { + stopTimeout(); + handleTaskRunnerSuccess(message); + }, + errorMessage -> handleTaskRunnerFault(message, errorMessage)))) .run(() -> processModel.witnessDebugLog(trade)) //TODO still needed? If so move to witness domain - .runTasks(); + .executeTasks(); } @@ -159,23 +156,22 @@ private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) /////////////////////////////////////////////////////////////////////////////////////////// private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress peer) { - expectedPhase(Trade.Phase.DEPOSIT_CONFIRMED) - .on(message) + given(phase(Trade.Phase.DEPOSIT_CONFIRMED) + .with(message) .from(peer) .preCondition(trade.getPayoutTx() == null, () -> { - log.warn("We received a CounterCurrencyTransferStartedMessage but we have already created the payout tx " + + log.warn("We with a CounterCurrencyTransferStartedMessage but we have already created the payout tx " + "so we ignore the message. This can happen if the ACK message to the peer did not " + "arrive and the peer repeats sending us the message. We send another ACK msg."); sendAckMessage(message, true, null); processModel.removeMailboxMessageAfterProcessing(trade); - }) - .addTasks( + })) + .setup(tasks( SellerProcessCounterCurrencyTransferStartedMessage.class, ApplyFilter.class, - MakerVerifyTakerFeePayment.class - ) - .runTasks(); + MakerVerifyTakerFeePayment.class)) + .executeTasks(); } @@ -186,27 +182,26 @@ private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress p @Override public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { SellerEvent event = SellerEvent.PAYMENT_RECEIVED; - expectedPhase(Trade.Phase.FIAT_SENT) - .on(event) - .preCondition(!wasDisputed()) - .setTaskRunner(new TradeTaskRunner(trade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess(event); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(event, errorMessage); - })) - .addTasks( + given(phase(Trade.Phase.FIAT_SENT) + .with(event) + .preCondition(!wasDisputed())) + .setup(tasks( ApplyFilter.class, MakerVerifyTakerFeePayment.class, SellerSignAndFinalizePayoutTx.class, SellerBroadcastPayoutTx.class, - SellerSendPayoutTxPublishedMessage.class - ) + SellerSendPayoutTxPublishedMessage.class) + .using(new TradeTaskRunner(trade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess(event); + }, + (errorMessage) -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(event, errorMessage); + }))) .run(() -> trade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT)) - .runTasks(); + .executeTasks(); } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index baf59f61a99..3a5090f06a6 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -87,21 +87,22 @@ public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peerNod /////////////////////////////////////////////////////////////////////////////////////////// - // Start trade + // Take offer /////////////////////////////////////////////////////////////////////////////////////////// @Override public void takeAvailableOffer() { - expectedPhase(Trade.Phase.INIT) - .on(TakerEvent.TAKE_OFFER) - .withTimeout(30) - .addTasks( + given(phase(Trade.Phase.INIT) + .with(TakerEvent.TAKE_OFFER)) + .setup(tasks( ApplyFilter.class, TakerVerifyMakerFeePayment.class, CreateTakerFeeTx.class, // SellerAsTakerCreatesDepositTxInputs.class, - TakerSendInputsForDepositTxRequest.class - ).runTasks(); + TakerSendInputsForDepositTxRequest.class) + .withTimeout(30)) + .run(() -> processModel.setTempTradingPeerNodeAddress(trade.getTradingPeerNodeAddress())) + .executeTasks(); } @@ -110,11 +111,10 @@ public void takeAvailableOffer() { /////////////////////////////////////////////////////////////////////////////////////////// private void handle(InputsForDepositTxResponse message, NodeAddress peer) { - expectedPhase(Trade.Phase.INIT) - .on(message) - .from(peer) - .withTimeout(30) - .addTasks( + given(phase(Trade.Phase.INIT) + .with(message) + .from(peer)) + .setup(tasks( TakerProcessesInputsForDepositTxResponse.class, ApplyFilter.class, VerifyPeersAccountAgeWitness.class, @@ -122,23 +122,21 @@ private void handle(InputsForDepositTxResponse message, NodeAddress peer) { TakerPublishFeeTx.class, SellerAsTakerSignsDepositTx.class, SellerCreatesDelayedPayoutTx.class, - SellerSendDelayedPayoutTxSignatureRequest.class - ) - .runTasks(); + SellerSendDelayedPayoutTxSignatureRequest.class) + .withTimeout(30)) + .executeTasks(); } private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) { - expectedPhase(Trade.Phase.TAKER_FEE_PUBLISHED) - .on(message) - .from(peer) - .addTasks( - SellerProcessDelayedPayoutTxSignatureResponse.class, + given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) + .with(message) + .from(peer)) + .setup(tasks(SellerProcessDelayedPayoutTxSignatureResponse.class, SellerSignsDelayedPayoutTx.class, SellerFinalizesDelayedPayoutTx.class, SellerSendsDepositTxAndDelayedPayoutTxMessage.class, SellerPublishesDepositTx.class, - PublishTradeStatistics.class - ) + PublishTradeStatistics.class)) .run(() -> { // We stop timeout here and don't start a new one as the // SellerSendsDepositTxAndDelayedPayoutTxMessage repeats the send the message and has it's own @@ -148,7 +146,7 @@ private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) //TODO still needed? If so move to witness domain processModel.witnessDebugLog(trade); }) - .runTasks(); + .executeTasks(); } @@ -157,8 +155,8 @@ private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) /////////////////////////////////////////////////////////////////////////////////////////// private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress peer) { - expectedPhase(Trade.Phase.DEPOSIT_CONFIRMED) - .on(message) + given(phase(Trade.Phase.DEPOSIT_CONFIRMED) + .with(message) .from(peer) .preCondition(trade.getPayoutTx() == null, () -> { @@ -167,13 +165,12 @@ private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress p "arrive and the peer repeats sending us the message. We send another ACK msg."); sendAckMessage(message, true, null); processModel.removeMailboxMessageAfterProcessing(trade); - }) - .addTasks( + })) + .setup(tasks( SellerProcessCounterCurrencyTransferStartedMessage.class, ApplyFilter.class, - TakerVerifyMakerFeePayment.class - ) - .runTasks(); + TakerVerifyMakerFeePayment.class)) + .executeTasks(); } @@ -184,27 +181,27 @@ private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress p @Override public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { SellerEvent event = SellerEvent.PAYMENT_RECEIVED; - expectedPhase(Trade.Phase.FIAT_SENT) - .on(event) - .preCondition(!wasDisputed()) - .setTaskRunner(new TradeTaskRunner(trade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess(event); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(event, errorMessage); - })) - .addTasks( + given(phase(Trade.Phase.FIAT_SENT) + .with(event) + .preCondition(!wasDisputed())) + .setup(tasks( ApplyFilter.class, TakerVerifyMakerFeePayment.class, SellerSignAndFinalizePayoutTx.class, SellerBroadcastPayoutTx.class, - SellerSendPayoutTxPublishedMessage.class //TODO add repeated msg send, check UI - ) + //TODO add repeated msg send, check UI + SellerSendPayoutTxPublishedMessage.class) + .using(new TradeTaskRunner(trade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess(event); + }, + (errorMessage) -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(event, errorMessage); + }))) .run(() -> trade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT)) - .runTasks(); + .executeTasks(); } diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index 8b36a2b05b4..06f09b58a57 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -60,12 +60,14 @@ import java.util.HashSet; import java.util.Set; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import javax.annotation.Nullable; import static bisq.core.util.Validator.isTradeIdValid; import static bisq.core.util.Validator.nonEmptyStringOf; +import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @Slf4j @@ -442,109 +444,171 @@ private void cleanupTradeOnFault() { /////////////////////////////////////////////////////////////////////////////////////////// - // FluentProcess + // FluentProtocol /////////////////////////////////////////////////////////////////////////////////////////// - protected FluentProcess expectedPhase(Trade.Phase phase) { - return new FluentProcess(trade, phase); + protected FluentProtocol given(Condition condition) { + return new FluentProtocol(condition); } - protected FluentProcess expectedPhases(Trade.Phase... phase) { - return new FluentProcess(trade, phase); + protected Condition phase(Trade.Phase expectedPhase) { + return new Condition(trade, expectedPhase); } - class FluentProcess { + protected Condition anyPhase(Trade.Phase... expectedPhases) { + return new Condition(trade, expectedPhases); + } + + @SafeVarargs + public final Setup tasks(Class>... tasks) { + return new Setup(trade, tasks); + } + + // Main class. Contains the condition and setup, if condition is valid it will execute the + // taskRunner and the optional runnable. + class FluentProtocol { + private final Condition condition; + private Setup setup; + + public FluentProtocol(Condition condition) { + this.condition = condition; + } + + protected FluentProtocol setup(Setup setup) { + this.setup = setup; + return this; + } + + // Can be used before or after executeTasks + public FluentProtocol run(Runnable runnable) { + if (condition.isValid()) { + runnable.run(); + } + return this; + } + + public FluentProtocol executeTasks() { + if (condition.isValid()) { + if (setup.getTimeoutSec() > 0) { + startTimeout(setup.getTimeoutSec()); + } + + NodeAddress peer = condition.getPeersNodeAddress(); + if (peer != null) { + processModel.setTempTradingPeerNodeAddress(peer); + } + + TradeMessage message = condition.getMessage(); + if (message != null) { + processModel.setTradeMessage(message); + } + TradeTaskRunner taskRunner = setup.getTaskRunner(message, condition.getEvent()); + taskRunner.addTasks(setup.getTasks()); + taskRunner.run(); + } + return this; + } + } + + // + static class Condition { private final Trade trade; @Nullable + @Getter private TradeMessage message; private final Set expectedPhases = new HashSet<>(); + private final Set expectedStates = new HashSet<>(); private final Set preConditions = new HashSet<>(); @Nullable + @Getter private Event event; - private Runnable preConditionFailedHandler; - private int timeoutSec; + @Getter private NodeAddress peersNodeAddress; - private TradeTaskRunner taskRunner; + private boolean isValid; + private boolean isValidated; + private Runnable preConditionFailedHandler; - public FluentProcess(Trade trade, - Trade.Phase expectedPhase) { - this.trade = trade; + public Condition(Trade trade, Trade.Phase expectedPhase) { this.expectedPhases.add(expectedPhase); + this.trade = trade; } - public FluentProcess(Trade trade, - Trade.Phase... expectedPhases) { - this.trade = trade; + public Condition(Trade trade, Trade.Phase... expectedPhases) { this.expectedPhases.addAll(Set.of(expectedPhases)); + this.trade = trade; } - public FluentProcess run(Runnable runnable) { - if (isValid()) { - runnable.run(); - } + public Condition state(Trade.State state) { + this.expectedStates.add(state); return this; } - public FluentProcess runTasks() { - if (isValid()) { - if (timeoutSec > 0) { - startTimeout(timeoutSec); - } + public Condition anyState(Trade.State... states) { + this.expectedStates.addAll(Set.of(states)); + return this; + } - if (peersNodeAddress != null) { - processModel.setTempTradingPeerNodeAddress(peersNodeAddress); - } + public Condition with(Event event) { + checkArgument(!isValidated); + this.event = event; + return this; + } - if (message != null) { - processModel.setTradeMessage(message); - } + public Condition with(TradeMessage tradeMessage) { + checkArgument(!isValidated); + this.message = tradeMessage; + return this; + } - taskRunner.run(); - } + public Condition from(NodeAddress peersNodeAddress) { + checkArgument(!isValidated); + this.peersNodeAddress = peersNodeAddress; + return this; + } + public Condition preCondition(boolean preCondition) { + checkArgument(!isValidated); + preConditions.add(preCondition); + return this; + } + + public Condition preCondition(boolean preCondition, Runnable conditionFailedHandler) { + checkArgument(!isValidated); + preConditions.add(preCondition); + this.preConditionFailedHandler = conditionFailedHandler; return this; } private boolean isValid() { - boolean isPhaseValid = isPhaseValid(); - boolean allPreConditionsMet = preConditions.stream().allMatch(e -> e); - boolean isTradeIdValid = message == null || isTradeIdValid(processModel.getOfferId(), message); - - if (!allPreConditionsMet) { - log.error("PreConditions not met. preConditions={}, this={}", preConditions, this); - if (preConditionFailedHandler != null) { - preConditionFailedHandler.run(); - } - } - if (!isTradeIdValid) { - log.error("TradeId does not match tradeId in message, TradeId={}, tradeId in message={}", - trade.getId(), message.getTradeId()); - } + if (!isValidated) { + boolean isPhaseValid = isPhaseValid(); + boolean isStateValid = isStateValid(); - return isPhaseValid && allPreConditionsMet && isTradeIdValid; - } + boolean allPreConditionsMet = preConditions.stream().allMatch(e -> e); + boolean isTradeIdValid = message == null || isTradeIdValid(trade.getId(), message); - @SafeVarargs - public final FluentProcess addTasks(Class>... tasks) { - if (taskRunner == null) { - if (message != null) { - taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(message), - errorMessage -> handleTaskRunnerFault(message, errorMessage)); - } else if (event != null) { - taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(event), - errorMessage -> handleTaskRunnerFault(event, errorMessage)); - } else { - throw new IllegalStateException("addTasks must not be called without message or event " + - "set in case no taskRunner has been created yet"); + if (!allPreConditionsMet) { + log.error("PreConditions not met. preConditions={}, this={}", preConditions, this); + if (preConditionFailedHandler != null) { + preConditionFailedHandler.run(); + } + } + if (!isTradeIdValid) { + log.error("TradeId does not match tradeId in message, TradeId={}, tradeId in message={}", + trade.getId(), message.getTradeId()); } + + isValid = isPhaseValid && isStateValid && allPreConditionsMet && isTradeIdValid; + isValidated = true; } - taskRunner.addTasks(tasks); - return this; + return isValid; } private boolean isPhaseValid() { + if (expectedPhases.isEmpty()) { + return true; + } + boolean isPhaseValid = expectedPhases.stream().anyMatch(e -> e == trade.getPhase()); String trigger = message != null ? message.getClass().getSimpleName() : @@ -568,60 +632,75 @@ private boolean isPhaseValid() { return isPhaseValid; } - public FluentProcess orInPhase(Trade.Phase phase) { - expectedPhases.add(phase); - return this; - } + private boolean isStateValid() { + if (expectedStates.isEmpty()) { + return true; + } - public FluentProcess on(Event event) { - this.event = event; - return this; - } + boolean isStateValid = expectedStates.stream().anyMatch(e -> e == trade.getState()); + String trigger = message != null ? + message.getClass().getSimpleName() : + event != null ? + event.name() + " event" : + ""; + if (isStateValid) { + log.info("We received {} at state {}", + trigger, + trade.getState()); + } else { + log.error("We received {} but we are are not in the correct state. Expected states={}, " + + "Trade state= {} ", + trigger, + expectedStates, + trade.getState()); + } - public FluentProcess on(TradeMessage tradeMessage) { - this.message = tradeMessage; - return this; + return isStateValid; } + } - public FluentProcess preCondition(boolean preCondition) { - preConditions.add(preCondition); - return this; - } + // Setup for task runner + class Setup { + private final Trade trade; + @Getter + private final Class>[] tasks; + @Getter + private int timeoutSec; + @Nullable + private TradeTaskRunner taskRunner; - public FluentProcess preCondition(boolean preCondition, Runnable conditionFailedHandler) { - preConditions.add(preCondition); - this.preConditionFailedHandler = conditionFailedHandler; - return this; + @SafeVarargs + public Setup(Trade trade, Class>... tasks) { + this.trade = trade; + this.tasks = tasks; } - public FluentProcess withTimeout(int timeoutSec) { + public Setup withTimeout(int timeoutSec) { this.timeoutSec = timeoutSec; return this; } - public FluentProcess from(NodeAddress peersNodeAddress) { - this.peersNodeAddress = peersNodeAddress; - return this; - } - - public FluentProcess setTaskRunner(TradeTaskRunner taskRunner) { + public Setup using(TradeTaskRunner taskRunner) { this.taskRunner = taskRunner; return this; } - @Override - public String toString() { - return "FluentProcess{" + - "\n trade=" + trade + - ",\n message=" + message + - ",\n expectedPhases=" + expectedPhases + - ",\n preConditions=" + preConditions + - ",\n event=" + event + - ",\n preConditionFailedHandler=" + preConditionFailedHandler + - ",\n timeoutSec=" + timeoutSec + - ",\n peersNodeAddress=" + peersNodeAddress + - ",\n taskRunner=" + taskRunner + - "\n}"; + private TradeTaskRunner getTaskRunner(@Nullable TradeMessage message, @Nullable Event event) { + if (taskRunner == null) { + if (message != null) { + taskRunner = new TradeTaskRunner(trade, + () -> handleTaskRunnerSuccess(message), + errorMessage -> handleTaskRunnerFault(message, errorMessage)); + } else if (event != null) { + taskRunner = new TradeTaskRunner(trade, + () -> handleTaskRunnerSuccess(event), + errorMessage -> handleTaskRunnerFault(event, errorMessage)); + } else { + throw new IllegalStateException("addTasks must not be called without message or event " + + "set in case no taskRunner has been created yet"); + } + } + return taskRunner; } } } From e59b5b3cf52cef9b55907ada048943ce065dac14 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 23 Sep 2020 17:20:10 -0500 Subject: [PATCH 053/143] Change BuyerProtocol from interface to abstract class Move all common code of buyer protocol classes to BuyerProtocol --- .../trade/protocol/BuyerAsMakerProtocol.java | 139 ++------------- .../trade/protocol/BuyerAsTakerProtocol.java | 133 +++----------- .../core/trade/protocol/BuyerProtocol.java | 167 ++++++++++++++++-- 3 files changed, 198 insertions(+), 241 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 1e015215e95..dee6ffe8acf 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -23,21 +23,10 @@ import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage; import bisq.core.trade.messages.InputsForDepositTxRequest; import bisq.core.trade.messages.PayoutTxPublishedMessage; -import bisq.core.trade.messages.TradeMessage; import bisq.core.trade.protocol.tasks.ApplyFilter; -import bisq.core.trade.protocol.tasks.PublishTradeStatistics; +import bisq.core.trade.protocol.tasks.TradeTask; import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness; -import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest; -import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDepositTxAndDelayedPayoutTxMessage; -import bisq.core.trade.protocol.tasks.buyer.BuyerProcessPayoutTxPublishedMessage; -import bisq.core.trade.protocol.tasks.buyer.BuyerSendCounterCurrencyTransferStartedMessage; -import bisq.core.trade.protocol.tasks.buyer.BuyerSendsDelayedPayoutTxSignatureResponse; import bisq.core.trade.protocol.tasks.buyer.BuyerSetupDepositTxListener; -import bisq.core.trade.protocol.tasks.buyer.BuyerSetupPayoutTxListener; -import bisq.core.trade.protocol.tasks.buyer.BuyerSignPayoutTx; -import bisq.core.trade.protocol.tasks.buyer.BuyerSignsDelayedPayoutTx; -import bisq.core.trade.protocol.tasks.buyer.BuyerVerifiesFinalDelayedPayoutTx; -import bisq.core.trade.protocol.tasks.buyer.BuyerVerifiesPreparedDelayedPayoutTx; import bisq.core.trade.protocol.tasks.buyer_as_maker.BuyerAsMakerCreatesAndSignsDepositTx; import bisq.core.trade.protocol.tasks.buyer_as_maker.BuyerAsMakerSendsInputsForDepositTxResponse; import bisq.core.trade.protocol.tasks.maker.MakerCreateAndSignContract; @@ -53,7 +42,7 @@ import lombok.extern.slf4j.Slf4j; @Slf4j -public class BuyerAsMakerProtocol extends TradeProtocol implements BuyerProtocol, MakerProtocol { +public class BuyerAsMakerProtocol extends BuyerProtocol implements MakerProtocol { /////////////////////////////////////////////////////////////////////////////////////////// // Constructor @@ -61,24 +50,6 @@ public class BuyerAsMakerProtocol extends TradeProtocol implements BuyerProtocol public BuyerAsMakerProtocol(BuyerAsMakerTrade trade) { super(trade); - - maybeSetupTaskRunners(trade, processModel, this); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Mailbox - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peer) { - super.doApplyMailboxTradeMessage(message, peer); - - if (message instanceof DepositTxAndDelayedPayoutTxMessage) { - handle((DepositTxAndDelayedPayoutTxMessage) message, peer); - } else if (message instanceof PayoutTxPublishedMessage) { - handle((PayoutTxPublishedMessage) message, peer); - } } @@ -97,7 +68,7 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message, MakerProcessesInputsForDepositTxRequest.class, ApplyFilter.class, VerifyPeersAccountAgeWitness.class, - MakerVerifyTakerFeePayment.class, + getVerifyPeersFeePaymentClass(), MakerSetsLockTime.class, MakerCreateAndSignContract.class, BuyerAsMakerCreatesAndSignsDepositTx.class, @@ -118,52 +89,16 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message, // Incoming messages Take offer process /////////////////////////////////////////////////////////////////////////////////////////// - private void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { - given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) - .with(message) - .from(peer)) - .setup(tasks( - BuyerProcessDelayedPayoutTxSignatureRequest.class, - BuyerVerifiesPreparedDelayedPayoutTx.class, - BuyerSignsDelayedPayoutTx.class, - BuyerSendsDelayedPayoutTxSignatureResponse.class) - .withTimeout(30)) - .executeTasks(); + // We keep the handler here in as well to make it more transparent which messages we expect + @Override + protected void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { + super.handle(message, peer); } - // The DepositTxAndDelayedPayoutTxMessage is a mailbox message as earlier we use only the deposit tx which can - // be also with from the network once published. - // Now we send the delayed payout tx as well and with that this message is mandatory for continuing the protocol. - // We do not support mailbox message handling during the take offer process as it is expected that both peers - // are online. - // For backward compatibility and extra resilience we still keep DepositTxAndDelayedPayoutTxMessage as a - // mailbox message but the stored in mailbox case is not expected and the seller would try to send the message again - // in the hope to reach the buyer directly. - private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer) { - given(anyPhase(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) - .with(message) - .from(peer) - .preCondition(trade.getDepositTx() == null || trade.getDelayedPayoutTx() == null, - () -> { - log.warn("We with a DepositTxAndDelayedPayoutTxMessage but we have already processed the deposit and " + - "delayed payout tx so we ignore the message. This can happen if the ACK message to the peer did not " + - "arrive and the peer repeats sending us the message. We send another ACK msg."); - stopTimeout(); - sendAckMessage(message, true, null); - processModel.removeMailboxMessageAfterProcessing(trade); - })) - .setup(tasks( - BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, - BuyerVerifiesFinalDelayedPayoutTx.class, - PublishTradeStatistics.class) - .using(new TradeTaskRunner(trade, - () -> { - stopTimeout(); - handleTaskRunnerSuccess(message); - }, - errorMessage -> handleTaskRunnerFault(message, errorMessage)))) - .run(() -> processModel.witnessDebugLog(trade)) - .executeTasks(); + // We keep the handler here in as well to make it more transparent which messages we expect + @Override + protected void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer) { + super.handle(message, peer); } @@ -171,29 +106,10 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer // User interaction /////////////////////////////////////////////////////////////////////////////////////////// + // We keep the handler here in as well to make it more transparent which messages we expect @Override public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - BuyerEvent event = BuyerEvent.PAYMENT_SENT; - given(phase(Trade.Phase.DEPOSIT_CONFIRMED) - .with(event) - .preCondition(!wasDisputed())) - .setup(tasks( - ApplyFilter.class, - MakerVerifyTakerFeePayment.class, - BuyerSignPayoutTx.class, - BuyerSetupPayoutTxListener.class, - BuyerSendCounterCurrencyTransferStartedMessage.class) - .using(new TradeTaskRunner(trade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess(event); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(event, errorMessage); - }))) - .run(() -> trade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED)) - .executeTasks(); + super.onFiatPaymentStarted(resultHandler, errorMessageHandler); } @@ -201,32 +117,15 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle // Incoming message Payout tx /////////////////////////////////////////////////////////////////////////////////////////// - private void handle(PayoutTxPublishedMessage message, NodeAddress peer) { - given(anyPhase(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) - .with(message) - .from(peer)) - .setup(tasks(BuyerProcessPayoutTxPublishedMessage.class)) - .executeTasks(); + // We keep the handler here in as well to make it more transparent which messages we expect + @Override + protected void handle(PayoutTxPublishedMessage message, NodeAddress peer) { + super.handle(message, peer); } - /////////////////////////////////////////////////////////////////////////////////////////// - // Message dispatcher - /////////////////////////////////////////////////////////////////////////////////////////// - @Override - protected void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer) { - super.doHandleDecryptedMessage(message, peer); - - log.info("Received {} from {} with tradeId {} and uid {}", - message.getClass().getSimpleName(), peer, message.getTradeId(), message.getUid()); - - if (message instanceof DelayedPayoutTxSignatureRequest) { - handle((DelayedPayoutTxSignatureRequest) message, peer); - } else if (message instanceof DepositTxAndDelayedPayoutTxMessage) { - handle((DepositTxAndDelayedPayoutTxMessage) message, peer); - } else if (message instanceof PayoutTxPublishedMessage) { - handle((PayoutTxPublishedMessage) message, peer); - } + protected Class getVerifyPeersFeePaymentClass() { + return MakerVerifyTakerFeePayment.class; } } diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index f4e042a335a..26eefd6ec85 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -26,19 +26,9 @@ import bisq.core.trade.messages.PayoutTxPublishedMessage; import bisq.core.trade.messages.TradeMessage; import bisq.core.trade.protocol.tasks.ApplyFilter; -import bisq.core.trade.protocol.tasks.PublishTradeStatistics; +import bisq.core.trade.protocol.tasks.TradeTask; import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness; -import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest; -import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDepositTxAndDelayedPayoutTxMessage; -import bisq.core.trade.protocol.tasks.buyer.BuyerProcessPayoutTxPublishedMessage; -import bisq.core.trade.protocol.tasks.buyer.BuyerSendCounterCurrencyTransferStartedMessage; -import bisq.core.trade.protocol.tasks.buyer.BuyerSendsDelayedPayoutTxSignatureResponse; import bisq.core.trade.protocol.tasks.buyer.BuyerSetupDepositTxListener; -import bisq.core.trade.protocol.tasks.buyer.BuyerSetupPayoutTxListener; -import bisq.core.trade.protocol.tasks.buyer.BuyerSignPayoutTx; -import bisq.core.trade.protocol.tasks.buyer.BuyerSignsDelayedPayoutTx; -import bisq.core.trade.protocol.tasks.buyer.BuyerVerifiesFinalDelayedPayoutTx; -import bisq.core.trade.protocol.tasks.buyer.BuyerVerifiesPreparedDelayedPayoutTx; import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerCreatesDepositTxInputs; import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerSendsDepositTxMessage; import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerSignsDepositTx; @@ -57,7 +47,7 @@ import lombok.extern.slf4j.Slf4j; @Slf4j -public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol, TakerProtocol { +public class BuyerAsTakerProtocol extends BuyerProtocol implements TakerProtocol { /////////////////////////////////////////////////////////////////////////////////////////// // Constructor @@ -65,24 +55,6 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol public BuyerAsTakerProtocol(BuyerAsTakerTrade trade) { super(trade); - - maybeSetupTaskRunners(trade, processModel, this); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Mailbox - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peer) { - super.doApplyMailboxTradeMessage(message, peer); - - if (message instanceof DepositTxAndDelayedPayoutTxMessage) { - handle((DepositTxAndDelayedPayoutTxMessage) message, peer); - } else if (message instanceof PayoutTxPublishedMessage) { - handle((PayoutTxPublishedMessage) message, peer); - } } @@ -96,7 +68,7 @@ public void takeAvailableOffer() { .with(TakerEvent.TAKE_OFFER)) .setup(tasks( ApplyFilter.class, - TakerVerifyMakerFeePayment.class, + getVerifyPeersFeePaymentClass(), CreateTakerFeeTx.class, BuyerAsTakerCreatesDepositTxInputs.class, TakerSendInputsForDepositTxRequest.class) @@ -126,51 +98,16 @@ private void handle(InputsForDepositTxResponse message, NodeAddress peer) { .executeTasks(); } - private void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { - given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) - .with(message) - .from(peer)) - .setup(tasks( - BuyerProcessDelayedPayoutTxSignatureRequest.class, - BuyerVerifiesPreparedDelayedPayoutTx.class, - BuyerSignsDelayedPayoutTx.class, - BuyerSendsDelayedPayoutTxSignatureResponse.class) - .withTimeout(30)) - .executeTasks(); + // We keep the handler here in as well to make it more transparent which messages we expect + @Override + protected void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { + super.handle(message, peer); } - // The DepositTxAndDelayedPayoutTxMessage is a mailbox message as earlier we use only the deposit tx which can - // be also with from the network once published. - // Now we send the delayed payout tx as well and with that this message is mandatory for continuing the protocol. - // We do not support mailbox message handling during the take offer process as it is expected that both peers - // are online. - // For backward compatibility and extra resilience we still keep DepositTxAndDelayedPayoutTxMessage as a - // mailbox message but the stored in mailbox case is not expected and the seller would try to send the message again - // in the hope to reach the buyer directly. - private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer) { - given(anyPhase(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) - .with(message) - .from(peer) - .preCondition(trade.getDepositTx() == null || trade.getDelayedPayoutTx() == null, - () -> { - log.warn("We with a DepositTxAndDelayedPayoutTxMessage but we have already processed the deposit and " + - "delayed payout tx so we ignore the message. This can happen if the ACK message to the peer did not " + - "arrive and the peer repeats sending us the message. We send another ACK msg."); - stopTimeout(); - sendAckMessage(message, true, null); - processModel.removeMailboxMessageAfterProcessing(trade); - })) - .setup(tasks(BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, - BuyerVerifiesFinalDelayedPayoutTx.class, - PublishTradeStatistics.class) - .using(new TradeTaskRunner(trade, - () -> { - stopTimeout(); - handleTaskRunnerSuccess(message); - }, - errorMessage -> handleTaskRunnerFault(message, errorMessage)))) - .run(() -> processModel.witnessDebugLog(trade)) - .executeTasks(); + // We keep the handler here in as well to make it more transparent which messages we expect + @Override + protected void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer) { + super.handle(message, peer); } @@ -178,29 +115,10 @@ private void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer // User interaction /////////////////////////////////////////////////////////////////////////////////////////// - // User clicked the "bank transfer started" button + // We keep the handler here in as well to make it more transparent which messages we expect @Override public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - BuyerEvent event = BuyerEvent.PAYMENT_SENT; - given(phase(Trade.Phase.DEPOSIT_CONFIRMED) - .with(event) - .preCondition(!wasDisputed())) - .setup(tasks(ApplyFilter.class, - TakerVerifyMakerFeePayment.class, - BuyerSignPayoutTx.class, - BuyerSetupPayoutTxListener.class, - BuyerSendCounterCurrencyTransferStartedMessage.class) - .using(new TradeTaskRunner(trade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess(event); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(event, errorMessage); - }))) - .run(() -> trade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED)) - .executeTasks(); + super.onFiatPaymentStarted(resultHandler, errorMessageHandler); } @@ -208,13 +126,10 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle // Incoming message Payout tx /////////////////////////////////////////////////////////////////////////////////////////// - private void handle(PayoutTxPublishedMessage message, NodeAddress peer) { - given(anyPhase(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) - .with(message) - .from(peer)) - .setup(tasks(BuyerProcessPayoutTxPublishedMessage.class)) - .executeTasks(); - + // We keep the handler here in as well to make it more transparent which messages we expect + @Override + protected void handle(PayoutTxPublishedMessage message, NodeAddress peer) { + super.handle(message, peer); } @@ -226,17 +141,13 @@ private void handle(PayoutTxPublishedMessage message, NodeAddress peer) { protected void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer) { super.doHandleDecryptedMessage(message, peer); - log.info("Received {} from {} with tradeId {} and uid {}", - message.getClass().getSimpleName(), peer, message.getTradeId(), message.getUid()); - if (message instanceof InputsForDepositTxResponse) { handle((InputsForDepositTxResponse) message, peer); - } else if (message instanceof DelayedPayoutTxSignatureRequest) { - handle((DelayedPayoutTxSignatureRequest) message, peer); - } else if (message instanceof DepositTxAndDelayedPayoutTxMessage) { - handle((DepositTxAndDelayedPayoutTxMessage) message, peer); - } else if (message instanceof PayoutTxPublishedMessage) { - handle((PayoutTxPublishedMessage) message, peer); } } + + @Override + protected Class getVerifyPeersFeePaymentClass() { + return TakerVerifyMakerFeePayment.class; + } } 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 da37e2755f2..3222ba9ae80 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java @@ -18,44 +18,191 @@ package bisq.core.trade.protocol; import bisq.core.offer.Offer; +import bisq.core.trade.BuyerTrade; import bisq.core.trade.Trade; +import bisq.core.trade.messages.DelayedPayoutTxSignatureRequest; +import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage; +import bisq.core.trade.messages.PayoutTxPublishedMessage; +import bisq.core.trade.messages.TradeMessage; +import bisq.core.trade.protocol.tasks.ApplyFilter; +import bisq.core.trade.protocol.tasks.PublishTradeStatistics; +import bisq.core.trade.protocol.tasks.TradeTask; +import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest; +import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDepositTxAndDelayedPayoutTxMessage; +import bisq.core.trade.protocol.tasks.buyer.BuyerProcessPayoutTxPublishedMessage; import bisq.core.trade.protocol.tasks.buyer.BuyerSendCounterCurrencyTransferStartedMessage; +import bisq.core.trade.protocol.tasks.buyer.BuyerSendsDelayedPayoutTxSignatureResponse; import bisq.core.trade.protocol.tasks.buyer.BuyerSetupDepositTxListener; import bisq.core.trade.protocol.tasks.buyer.BuyerSetupPayoutTxListener; +import bisq.core.trade.protocol.tasks.buyer.BuyerSignPayoutTx; +import bisq.core.trade.protocol.tasks.buyer.BuyerSignsDelayedPayoutTx; +import bisq.core.trade.protocol.tasks.buyer.BuyerVerifiesFinalDelayedPayoutTx; +import bisq.core.trade.protocol.tasks.buyer.BuyerVerifiesPreparedDelayedPayoutTx; + +import bisq.network.p2p.NodeAddress; import bisq.common.handlers.ErrorMessageHandler; import bisq.common.handlers.ResultHandler; -import static com.google.common.base.Preconditions.checkNotNull; +import lombok.extern.slf4j.Slf4j; -public interface BuyerProtocol { - void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler); +import static com.google.common.base.Preconditions.checkNotNull; +@Slf4j +public abstract class BuyerProtocol extends TradeProtocol { enum BuyerEvent implements TradeProtocol.Event { STARTUP, PAYMENT_SENT } - default void maybeSetupTaskRunners(Trade trade, ProcessModel processModel, TradeProtocol tradeProtocol) { + /////////////////////////////////////////////////////////////////////////////////////////// + // Constructor + /////////////////////////////////////////////////////////////////////////////////////////// + + public BuyerProtocol(BuyerTrade trade) { + super(trade); + Offer offer = checkNotNull(trade.getOffer()); processModel.getTradingPeer().setPubKeyRing(offer.getPubKeyRing()); - tradeProtocol.given(tradeProtocol.phase(Trade.Phase.TAKER_FEE_PUBLISHED) + given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) .with(BuyerEvent.STARTUP)) - .setup(tradeProtocol.tasks(BuyerSetupDepositTxListener.class)) + .setup(tasks(BuyerSetupDepositTxListener.class)) .executeTasks(); - tradeProtocol.given(tradeProtocol.anyPhase(Trade.Phase.FIAT_SENT, Trade.Phase.FIAT_RECEIVED) + given(anyPhase(Trade.Phase.FIAT_SENT, Trade.Phase.FIAT_RECEIVED) .with(BuyerEvent.STARTUP)) - .setup(tradeProtocol.tasks(BuyerSetupPayoutTxListener.class)) + .setup(tasks(BuyerSetupPayoutTxListener.class)) .executeTasks(); - tradeProtocol.given(tradeProtocol.anyPhase(Trade.Phase.FIAT_SENT, Trade.Phase.FIAT_RECEIVED) + given(anyPhase(Trade.Phase.FIAT_SENT, Trade.Phase.FIAT_RECEIVED) .anyState(Trade.State.BUYER_STORED_IN_MAILBOX_FIAT_PAYMENT_INITIATED_MSG, Trade.State.BUYER_SEND_FAILED_FIAT_PAYMENT_INITIATED_MSG) .with(BuyerEvent.STARTUP)) - .setup(tradeProtocol.tasks(BuyerSendCounterCurrencyTransferStartedMessage.class)) + .setup(tasks(BuyerSendCounterCurrencyTransferStartedMessage.class)) + .executeTasks(); + } + + @Override + public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peer) { + super.doApplyMailboxTradeMessage(message, peer); + + if (message instanceof DepositTxAndDelayedPayoutTxMessage) { + handle((DepositTxAndDelayedPayoutTxMessage) message, peer); + } else if (message instanceof PayoutTxPublishedMessage) { + handle((PayoutTxPublishedMessage) message, peer); + } + } + + protected void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { + given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) + .with(message) + .from(peer)) + .setup(tasks( + BuyerProcessDelayedPayoutTxSignatureRequest.class, + BuyerVerifiesPreparedDelayedPayoutTx.class, + BuyerSignsDelayedPayoutTx.class, + BuyerSendsDelayedPayoutTxSignatureResponse.class) + .withTimeout(30)) + .executeTasks(); + } + + // The DepositTxAndDelayedPayoutTxMessage is a mailbox message as earlier we use only the deposit tx which can + // be also with from the network once published. + // Now we send the delayed payout tx as well and with that this message is mandatory for continuing the protocol. + // We do not support mailbox message handling during the take offer process as it is expected that both peers + // are online. + // For backward compatibility and extra resilience we still keep DepositTxAndDelayedPayoutTxMessage as a + // mailbox message but the stored in mailbox case is not expected and the seller would try to send the message again + // in the hope to reach the buyer directly. + protected void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer) { + given(anyPhase(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) + .with(message) + .from(peer) + .preCondition(trade.getDepositTx() == null || trade.getDelayedPayoutTx() == null, + () -> { + log.warn("We with a DepositTxAndDelayedPayoutTxMessage but we have already processed the deposit and " + + "delayed payout tx so we ignore the message. This can happen if the ACK message to the peer did not " + + "arrive and the peer repeats sending us the message. We send another ACK msg."); + stopTimeout(); + sendAckMessage(message, true, null); + processModel.removeMailboxMessageAfterProcessing(trade); + })) + .setup(tasks(BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, + BuyerVerifiesFinalDelayedPayoutTx.class, + PublishTradeStatistics.class) + .using(new TradeTaskRunner(trade, + () -> { + stopTimeout(); + handleTaskRunnerSuccess(message); + }, + errorMessage -> handleTaskRunnerFault(message, errorMessage)))) + .run(() -> processModel.witnessDebugLog(trade)) .executeTasks(); } + + /////////////////////////////////////////////////////////////////////////////////////////// + // User interaction + /////////////////////////////////////////////////////////////////////////////////////////// + + public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + BuyerEvent event = BuyerEvent.PAYMENT_SENT; + given(phase(Trade.Phase.DEPOSIT_CONFIRMED) + .with(event) + .preCondition(!wasDisputed())) + .setup(tasks(ApplyFilter.class, + getVerifyPeersFeePaymentClass(), + BuyerSignPayoutTx.class, + BuyerSetupPayoutTxListener.class, + BuyerSendCounterCurrencyTransferStartedMessage.class) + .using(new TradeTaskRunner(trade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess(event); + }, + (errorMessage) -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(event, errorMessage); + }))) + .run(() -> trade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED)) + .executeTasks(); + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Incoming message Payout tx + /////////////////////////////////////////////////////////////////////////////////////////// + + protected void handle(PayoutTxPublishedMessage message, NodeAddress peer) { + given(anyPhase(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) + .with(message) + .from(peer)) + .setup(tasks(BuyerProcessPayoutTxPublishedMessage.class)) + .executeTasks(); + + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Message dispatcher + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + protected void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer) { + super.doHandleDecryptedMessage(message, peer); + + log.info("Received {} from {} with tradeId {} and uid {}", + message.getClass().getSimpleName(), peer, message.getTradeId(), message.getUid()); + + if (message instanceof DelayedPayoutTxSignatureRequest) { + handle((DelayedPayoutTxSignatureRequest) message, peer); + } else if (message instanceof DepositTxAndDelayedPayoutTxMessage) { + handle((DepositTxAndDelayedPayoutTxMessage) message, peer); + } else if (message instanceof PayoutTxPublishedMessage) { + handle((PayoutTxPublishedMessage) message, peer); + } + } + + abstract protected Class getVerifyPeersFeePaymentClass(); + } From a2e0ec4d2ebe3097bb63894c91e3426080a5739c Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 23 Sep 2020 19:26:49 -0500 Subject: [PATCH 054/143] Change SellerProtocol from interface to abstract class Move all common code of seller protocol classes to SellerProtocol --- .../trade/protocol/SellerAsMakerProtocol.java | 105 +++---------- .../trade/protocol/SellerAsTakerProtocol.java | 115 +++------------ .../core/trade/protocol/SellerProtocol.java | 138 +++++++++++++++++- 3 files changed, 176 insertions(+), 182 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index 752c2420966..14441ab1b6c 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -26,23 +26,14 @@ import bisq.core.trade.messages.InputsForDepositTxRequest; import bisq.core.trade.messages.TradeMessage; import bisq.core.trade.protocol.tasks.ApplyFilter; -import bisq.core.trade.protocol.tasks.PublishTradeStatistics; +import bisq.core.trade.protocol.tasks.TradeTask; import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness; import bisq.core.trade.protocol.tasks.maker.MakerCreateAndSignContract; import bisq.core.trade.protocol.tasks.maker.MakerProcessesInputsForDepositTxRequest; import bisq.core.trade.protocol.tasks.maker.MakerSetsLockTime; import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment; -import bisq.core.trade.protocol.tasks.seller.SellerBroadcastPayoutTx; import bisq.core.trade.protocol.tasks.seller.SellerCreatesDelayedPayoutTx; -import bisq.core.trade.protocol.tasks.seller.SellerFinalizesDelayedPayoutTx; -import bisq.core.trade.protocol.tasks.seller.SellerProcessCounterCurrencyTransferStartedMessage; -import bisq.core.trade.protocol.tasks.seller.SellerProcessDelayedPayoutTxSignatureResponse; -import bisq.core.trade.protocol.tasks.seller.SellerPublishesDepositTx; import bisq.core.trade.protocol.tasks.seller.SellerSendDelayedPayoutTxSignatureRequest; -import bisq.core.trade.protocol.tasks.seller.SellerSendPayoutTxPublishedMessage; -import bisq.core.trade.protocol.tasks.seller.SellerSendsDepositTxAndDelayedPayoutTxMessage; -import bisq.core.trade.protocol.tasks.seller.SellerSignAndFinalizePayoutTx; -import bisq.core.trade.protocol.tasks.seller.SellerSignsDelayedPayoutTx; import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerCreatesUnsignedDepositTx; import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerFinalizesDepositTx; import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerProcessDepositTxMessage; @@ -56,7 +47,7 @@ import lombok.extern.slf4j.Slf4j; @Slf4j -public class SellerAsMakerProtocol extends TradeProtocol implements SellerProtocol, MakerProtocol { +public class SellerAsMakerProtocol extends SellerProtocol implements MakerProtocol { /////////////////////////////////////////////////////////////////////////////////////////// // Constructor @@ -67,20 +58,6 @@ public SellerAsMakerProtocol(SellerAsMakerTrade trade) { } - /////////////////////////////////////////////////////////////////////////////////////////// - // Mailbox - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peerNodeAddress) { - super.doApplyMailboxTradeMessage(message, peerNodeAddress); - - if (message instanceof CounterCurrencyTransferStartedMessage) { - handle((CounterCurrencyTransferStartedMessage) message, peerNodeAddress); - } - } - - /////////////////////////////////////////////////////////////////////////////////////////// // Handle take offer request /////////////////////////////////////////////////////////////////////////////////////////// @@ -96,7 +73,7 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message, MakerProcessesInputsForDepositTxRequest.class, ApplyFilter.class, VerifyPeersAccountAgeWitness.class, - MakerVerifyTakerFeePayment.class, + getVerifyPeersFeePaymentClass(), MakerSetsLockTime.class, MakerCreateAndSignContract.class, SellerAsMakerCreatesUnsignedDepositTx.class, @@ -129,25 +106,10 @@ protected void handle(DepositTxMessage message, NodeAddress peer) { .executeTasks(); } - private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) { - given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) - .with(message) - .from(peer)) - .setup(tasks( - SellerProcessDelayedPayoutTxSignatureResponse.class, - SellerSignsDelayedPayoutTx.class, - SellerFinalizesDelayedPayoutTx.class, - SellerSendsDepositTxAndDelayedPayoutTxMessage.class, - SellerPublishesDepositTx.class, - PublishTradeStatistics.class) - .using(new TradeTaskRunner(trade, - () -> { - stopTimeout(); - handleTaskRunnerSuccess(message); - }, - errorMessage -> handleTaskRunnerFault(message, errorMessage)))) - .run(() -> processModel.witnessDebugLog(trade)) //TODO still needed? If so move to witness domain - .executeTasks(); + // We keep the handler here in as well to make it more transparent which messages we expect + @Override + protected void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) { + super.handle(message, peer); } @@ -155,23 +117,10 @@ private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) // Incoming message when buyer has clicked payment started button /////////////////////////////////////////////////////////////////////////////////////////// - private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress peer) { - given(phase(Trade.Phase.DEPOSIT_CONFIRMED) - .with(message) - .from(peer) - .preCondition(trade.getPayoutTx() == null, - () -> { - log.warn("We with a CounterCurrencyTransferStartedMessage but we have already created the payout tx " + - "so we ignore the message. This can happen if the ACK message to the peer did not " + - "arrive and the peer repeats sending us the message. We send another ACK msg."); - sendAckMessage(message, true, null); - processModel.removeMailboxMessageAfterProcessing(trade); - })) - .setup(tasks( - SellerProcessCounterCurrencyTransferStartedMessage.class, - ApplyFilter.class, - MakerVerifyTakerFeePayment.class)) - .executeTasks(); + // We keep the handler here in as well to make it more transparent which messages we expect + @Override + protected void handle(CounterCurrencyTransferStartedMessage message, NodeAddress peer) { + super.handle(message, peer); } @@ -179,29 +128,10 @@ private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress p // User interaction /////////////////////////////////////////////////////////////////////////////////////////// + // We keep the handler here in as well to make it more transparent which messages we expect @Override public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - SellerEvent event = SellerEvent.PAYMENT_RECEIVED; - given(phase(Trade.Phase.FIAT_SENT) - .with(event) - .preCondition(!wasDisputed())) - .setup(tasks( - ApplyFilter.class, - MakerVerifyTakerFeePayment.class, - SellerSignAndFinalizePayoutTx.class, - SellerBroadcastPayoutTx.class, - SellerSendPayoutTxPublishedMessage.class) - .using(new TradeTaskRunner(trade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess(event); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(event, errorMessage); - }))) - .run(() -> trade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT)) - .executeTasks(); + super.onFiatPaymentReceived(resultHandler, errorMessageHandler); } @@ -218,10 +148,11 @@ protected void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer) if (message instanceof DepositTxMessage) { handle((DepositTxMessage) message, peer); - } else if (message instanceof DelayedPayoutTxSignatureResponse) { - handle((DelayedPayoutTxSignatureResponse) message, peer); - } else if (message instanceof CounterCurrencyTransferStartedMessage) { - handle((CounterCurrencyTransferStartedMessage) message, peer); } } + + @Override + protected Class getVerifyPeersFeePaymentClass() { + return MakerVerifyTakerFeePayment.class; + } } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 3a5090f06a6..3f989a87d65 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -26,19 +26,10 @@ import bisq.core.trade.messages.InputsForDepositTxResponse; import bisq.core.trade.messages.TradeMessage; import bisq.core.trade.protocol.tasks.ApplyFilter; -import bisq.core.trade.protocol.tasks.PublishTradeStatistics; +import bisq.core.trade.protocol.tasks.TradeTask; import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness; -import bisq.core.trade.protocol.tasks.seller.SellerBroadcastPayoutTx; import bisq.core.trade.protocol.tasks.seller.SellerCreatesDelayedPayoutTx; -import bisq.core.trade.protocol.tasks.seller.SellerFinalizesDelayedPayoutTx; -import bisq.core.trade.protocol.tasks.seller.SellerProcessCounterCurrencyTransferStartedMessage; -import bisq.core.trade.protocol.tasks.seller.SellerProcessDelayedPayoutTxSignatureResponse; -import bisq.core.trade.protocol.tasks.seller.SellerPublishesDepositTx; import bisq.core.trade.protocol.tasks.seller.SellerSendDelayedPayoutTxSignatureRequest; -import bisq.core.trade.protocol.tasks.seller.SellerSendPayoutTxPublishedMessage; -import bisq.core.trade.protocol.tasks.seller.SellerSendsDepositTxAndDelayedPayoutTxMessage; -import bisq.core.trade.protocol.tasks.seller.SellerSignAndFinalizePayoutTx; -import bisq.core.trade.protocol.tasks.seller.SellerSignsDelayedPayoutTx; import bisq.core.trade.protocol.tasks.seller_as_taker.SellerAsTakerCreatesDepositTxInputs; import bisq.core.trade.protocol.tasks.seller_as_taker.SellerAsTakerSignsDepositTx; import bisq.core.trade.protocol.tasks.taker.CreateTakerFeeTx; @@ -58,7 +49,7 @@ import static com.google.common.base.Preconditions.checkNotNull; @Slf4j -public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtocol, TakerProtocol { +public class SellerAsTakerProtocol extends SellerProtocol implements TakerProtocol { /////////////////////////////////////////////////////////////////////////////////////////// // Constructor @@ -73,35 +64,21 @@ public SellerAsTakerProtocol(SellerAsTakerTrade trade) { /////////////////////////////////////////////////////////////////////////////////////////// - // Mailbox - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peerNodeAddress) { - super.doApplyMailboxTradeMessage(message, peerNodeAddress); - - if (message instanceof CounterCurrencyTransferStartedMessage) { - handle((CounterCurrencyTransferStartedMessage) message, peerNodeAddress); - } - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Take offer + // User interaction: Take offer /////////////////////////////////////////////////////////////////////////////////////////// @Override public void takeAvailableOffer() { given(phase(Trade.Phase.INIT) - .with(TakerEvent.TAKE_OFFER)) + .with(TakerEvent.TAKE_OFFER) + .from(trade.getTradingPeerNodeAddress())) .setup(tasks( ApplyFilter.class, - TakerVerifyMakerFeePayment.class, - CreateTakerFeeTx.class, // + getVerifyPeersFeePaymentClass(), + CreateTakerFeeTx.class, SellerAsTakerCreatesDepositTxInputs.class, TakerSendInputsForDepositTxRequest.class) .withTimeout(30)) - .run(() -> processModel.setTempTradingPeerNodeAddress(trade.getTradingPeerNodeAddress())) .executeTasks(); } @@ -127,26 +104,10 @@ private void handle(InputsForDepositTxResponse message, NodeAddress peer) { .executeTasks(); } - private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) { - given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) - .with(message) - .from(peer)) - .setup(tasks(SellerProcessDelayedPayoutTxSignatureResponse.class, - SellerSignsDelayedPayoutTx.class, - SellerFinalizesDelayedPayoutTx.class, - SellerSendsDepositTxAndDelayedPayoutTxMessage.class, - SellerPublishesDepositTx.class, - PublishTradeStatistics.class)) - .run(() -> { - // We stop timeout here and don't start a new one as the - // SellerSendsDepositTxAndDelayedPayoutTxMessage repeats the send the message and has it's own - // timeout if it never succeeds. - stopTimeout(); - - //TODO still needed? If so move to witness domain - processModel.witnessDebugLog(trade); - }) - .executeTasks(); + // We keep the handler here in as well to make it more transparent which messages we expect + @Override + protected void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) { + super.handle(message, peer); } @@ -154,23 +115,10 @@ private void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) // Incoming message when buyer has clicked payment started button /////////////////////////////////////////////////////////////////////////////////////////// - private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress peer) { - given(phase(Trade.Phase.DEPOSIT_CONFIRMED) - .with(message) - .from(peer) - .preCondition(trade.getPayoutTx() == null, - () -> { - log.warn("We received a CounterCurrencyTransferStartedMessage but we have already created the payout tx " + - "so we ignore the message. This can happen if the ACK message to the peer did not " + - "arrive and the peer repeats sending us the message. We send another ACK msg."); - sendAckMessage(message, true, null); - processModel.removeMailboxMessageAfterProcessing(trade); - })) - .setup(tasks( - SellerProcessCounterCurrencyTransferStartedMessage.class, - ApplyFilter.class, - TakerVerifyMakerFeePayment.class)) - .executeTasks(); + // We keep the handler here in as well to make it more transparent which messages we expect + @Override + protected void handle(CounterCurrencyTransferStartedMessage message, NodeAddress peer) { + super.handle(message, peer); } @@ -178,30 +126,10 @@ private void handle(CounterCurrencyTransferStartedMessage message, NodeAddress p // User interaction /////////////////////////////////////////////////////////////////////////////////////////// + // We keep the handler here in as well to make it more transparent which messages we expect @Override public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - SellerEvent event = SellerEvent.PAYMENT_RECEIVED; - given(phase(Trade.Phase.FIAT_SENT) - .with(event) - .preCondition(!wasDisputed())) - .setup(tasks( - ApplyFilter.class, - TakerVerifyMakerFeePayment.class, - SellerSignAndFinalizePayoutTx.class, - SellerBroadcastPayoutTx.class, - //TODO add repeated msg send, check UI - SellerSendPayoutTxPublishedMessage.class) - .using(new TradeTaskRunner(trade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess(event); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(event, errorMessage); - }))) - .run(() -> trade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT)) - .executeTasks(); + super.onFiatPaymentReceived(resultHandler, errorMessageHandler); } @@ -218,10 +146,11 @@ protected void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer) if (message instanceof InputsForDepositTxResponse) { handle((InputsForDepositTxResponse) message, peer); - } else if (message instanceof DelayedPayoutTxSignatureResponse) { - handle((DelayedPayoutTxSignatureResponse) message, peer); - } else if (message instanceof CounterCurrencyTransferStartedMessage) { - handle((CounterCurrencyTransferStartedMessage) message, peer); } } + + @Override + protected Class getVerifyPeersFeePaymentClass() { + return TakerVerifyMakerFeePayment.class; + } } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java index 958534936dd..1a4e7c5922c 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java @@ -17,13 +17,147 @@ package bisq.core.trade.protocol; +import bisq.core.trade.SellerTrade; +import bisq.core.trade.Trade; +import bisq.core.trade.messages.CounterCurrencyTransferStartedMessage; +import bisq.core.trade.messages.DelayedPayoutTxSignatureResponse; +import bisq.core.trade.messages.TradeMessage; +import bisq.core.trade.protocol.tasks.ApplyFilter; +import bisq.core.trade.protocol.tasks.PublishTradeStatistics; +import bisq.core.trade.protocol.tasks.TradeTask; +import bisq.core.trade.protocol.tasks.seller.SellerBroadcastPayoutTx; +import bisq.core.trade.protocol.tasks.seller.SellerFinalizesDelayedPayoutTx; +import bisq.core.trade.protocol.tasks.seller.SellerProcessCounterCurrencyTransferStartedMessage; +import bisq.core.trade.protocol.tasks.seller.SellerProcessDelayedPayoutTxSignatureResponse; +import bisq.core.trade.protocol.tasks.seller.SellerPublishesDepositTx; +import bisq.core.trade.protocol.tasks.seller.SellerSendPayoutTxPublishedMessage; +import bisq.core.trade.protocol.tasks.seller.SellerSendsDepositTxAndDelayedPayoutTxMessage; +import bisq.core.trade.protocol.tasks.seller.SellerSignAndFinalizePayoutTx; +import bisq.core.trade.protocol.tasks.seller.SellerSignsDelayedPayoutTx; +import bisq.core.trade.protocol.tasks.taker.TakerVerifyMakerFeePayment; + +import bisq.network.p2p.NodeAddress; + import bisq.common.handlers.ErrorMessageHandler; import bisq.common.handlers.ResultHandler; -public interface SellerProtocol { - void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler); +import lombok.extern.slf4j.Slf4j; +@Slf4j +public abstract class SellerProtocol extends TradeProtocol { enum SellerEvent implements TradeProtocol.Event { PAYMENT_RECEIVED } + + public SellerProtocol(SellerTrade trade) { + super(trade); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Mailbox + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peerNodeAddress) { + super.doApplyMailboxTradeMessage(message, peerNodeAddress); + + if (message instanceof CounterCurrencyTransferStartedMessage) { + handle((CounterCurrencyTransferStartedMessage) message, peerNodeAddress); + } + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Incoming messages + /////////////////////////////////////////////////////////////////////////////////////////// + + protected void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) { + given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) + .with(message) + .from(peer)) + .setup(tasks(SellerProcessDelayedPayoutTxSignatureResponse.class, + SellerSignsDelayedPayoutTx.class, + SellerFinalizesDelayedPayoutTx.class, + SellerSendsDepositTxAndDelayedPayoutTxMessage.class, + SellerPublishesDepositTx.class, + PublishTradeStatistics.class)) + .run(() -> { + // We stop timeout here and don't start a new one as the + // SellerSendsDepositTxAndDelayedPayoutTxMessage repeats the send the message and has it's own + // timeout if it never succeeds. + stopTimeout(); + + //TODO still needed? If so move to witness domain + processModel.witnessDebugLog(trade); + }) + .executeTasks(); + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Incoming message when buyer has clicked payment started button + /////////////////////////////////////////////////////////////////////////////////////////// + + protected void handle(CounterCurrencyTransferStartedMessage message, NodeAddress peer) { + given(phase(Trade.Phase.DEPOSIT_CONFIRMED) + .with(message) + .from(peer) + .preCondition(trade.getPayoutTx() == null, + () -> { + log.warn("We received a CounterCurrencyTransferStartedMessage but we have already created the payout tx " + + "so we ignore the message. This can happen if the ACK message to the peer did not " + + "arrive and the peer repeats sending us the message. We send another ACK msg."); + sendAckMessage(message, true, null); + processModel.removeMailboxMessageAfterProcessing(trade); + })) + .setup(tasks( + SellerProcessCounterCurrencyTransferStartedMessage.class, + ApplyFilter.class, + TakerVerifyMakerFeePayment.class)) //todo get TakerVerifyMakerFeePayment + .executeTasks(); + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // User interaction + /////////////////////////////////////////////////////////////////////////////////////////// + + public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + SellerEvent event = SellerEvent.PAYMENT_RECEIVED; + given(phase(Trade.Phase.FIAT_SENT) + .with(event) + .preCondition(!wasDisputed())) + .setup(tasks( + ApplyFilter.class, + getVerifyPeersFeePaymentClass(), + SellerSignAndFinalizePayoutTx.class, + SellerBroadcastPayoutTx.class, + SellerSendPayoutTxPublishedMessage.class) + .using(new TradeTaskRunner(trade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess(event); + }, + (errorMessage) -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(event, errorMessage); + }))) + .run(() -> trade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT)) + .executeTasks(); + } + + + @Override + protected void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer) { + super.doHandleDecryptedMessage(message, peer); + + log.info("Received {} from {} with tradeId {} and uid {}", + message.getClass().getSimpleName(), peer, message.getTradeId(), message.getUid()); + + if (message instanceof DelayedPayoutTxSignatureResponse) { + handle((DelayedPayoutTxSignatureResponse) message, peer); + } else if (message instanceof CounterCurrencyTransferStartedMessage) { + handle((CounterCurrencyTransferStartedMessage) message, peer); + } + } + + abstract protected Class getVerifyPeersFeePaymentClass(); } From 99afe23de62979c2460df6accc5c61dda234a629 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 23 Sep 2020 19:29:29 -0500 Subject: [PATCH 055/143] Refactor: Rename takeAvailableOffer to onTakeOffer --- core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java | 4 ++-- core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java | 4 ++-- core/src/main/java/bisq/core/trade/TakerTrade.java | 2 +- core/src/main/java/bisq/core/trade/TradeManager.java | 2 +- .../java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java | 2 +- .../java/bisq/core/trade/protocol/SellerAsTakerProtocol.java | 2 +- .../src/main/java/bisq/core/trade/protocol/TakerProtocol.java | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java b/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java index d9b5f86c290..c2192dec04c 100644 --- a/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java +++ b/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java @@ -114,8 +114,8 @@ protected void createTradeProtocol() { } @Override - public void takeAvailableOffer() { + public void onTakeOffer() { checkArgument(tradeProtocol instanceof TakerProtocol, "tradeProtocol NOT instanceof TakerProtocol"); - ((TakerProtocol) tradeProtocol).takeAvailableOffer(); + ((TakerProtocol) tradeProtocol).onTakeOffer(); } } diff --git a/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java b/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java index 79debd8137c..fd75654bdef 100644 --- a/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java +++ b/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java @@ -114,8 +114,8 @@ protected void createTradeProtocol() { } @Override - public void takeAvailableOffer() { + public void onTakeOffer() { checkArgument(tradeProtocol instanceof TakerProtocol, "tradeProtocol NOT instanceof TakerProtocol"); - ((TakerProtocol) tradeProtocol).takeAvailableOffer(); + ((TakerProtocol) tradeProtocol).onTakeOffer(); } } diff --git a/core/src/main/java/bisq/core/trade/TakerTrade.java b/core/src/main/java/bisq/core/trade/TakerTrade.java index c0b7e43de14..767ba31fe58 100644 --- a/core/src/main/java/bisq/core/trade/TakerTrade.java +++ b/core/src/main/java/bisq/core/trade/TakerTrade.java @@ -18,5 +18,5 @@ package bisq.core.trade; public interface TakerTrade { - void takeAvailableOffer(); + void onTakeOffer(); } diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 0da57397674..8f5fc469739 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -555,7 +555,7 @@ private void createTrade(Coin amount, initTrade(trade, useSavingsWallet, fundsNeededForTrade); tradableList.add(trade); - ((TakerTrade) trade).takeAvailableOffer(); + ((TakerTrade) trade).onTakeOffer(); tradeResultHandler.handleResult(trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 26eefd6ec85..aa2aea4090b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -63,7 +63,7 @@ public BuyerAsTakerProtocol(BuyerAsTakerTrade trade) { /////////////////////////////////////////////////////////////////////////////////////////// @Override - public void takeAvailableOffer() { + public void onTakeOffer() { given(phase(Trade.Phase.INIT) .with(TakerEvent.TAKE_OFFER)) .setup(tasks( diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 3f989a87d65..4d41e06f1ef 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -68,7 +68,7 @@ public SellerAsTakerProtocol(SellerAsTakerTrade trade) { /////////////////////////////////////////////////////////////////////////////////////////// @Override - public void takeAvailableOffer() { + public void onTakeOffer() { given(phase(Trade.Phase.INIT) .with(TakerEvent.TAKE_OFFER) .from(trade.getTradingPeerNodeAddress())) diff --git a/core/src/main/java/bisq/core/trade/protocol/TakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TakerProtocol.java index a9576db8a33..a3d15c69b00 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TakerProtocol.java @@ -18,7 +18,7 @@ package bisq.core.trade.protocol; public interface TakerProtocol { - void takeAvailableOffer(); + void onTakeOffer(); enum TakerEvent implements TradeProtocol.Event { TAKE_OFFER From 8847f4b13d735cc31d53f59ea6f7312ed416a345 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 23 Sep 2020 19:35:19 -0500 Subject: [PATCH 056/143] Refactor: Rename createTrade to getNewTrade Move some code to caller method --- .../main/java/bisq/core/trade/MakerTrade.java | 4 +- .../java/bisq/core/trade/TradeManager.java | 44 +++++++++---------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/MakerTrade.java b/core/src/main/java/bisq/core/trade/MakerTrade.java index 5a2fd7dd8d3..dbfb2421276 100644 --- a/core/src/main/java/bisq/core/trade/MakerTrade.java +++ b/core/src/main/java/bisq/core/trade/MakerTrade.java @@ -24,5 +24,7 @@ import bisq.common.handlers.ErrorMessageHandler; public interface MakerTrade { - void handleTakeOfferRequest(InputsForDepositTxRequest message, NodeAddress peerNodeAddress, ErrorMessageHandler errorMessageHandler); + void handleTakeOfferRequest(InputsForDepositTxRequest message, + NodeAddress peerNodeAddress, + ErrorMessageHandler errorMessageHandler); } diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 8f5fc469739..ccbeafbd230 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -495,8 +495,8 @@ public void onTakeOffer(Coin amount, final OfferAvailabilityModel model = getOfferAvailabilityModel(offer); offer.checkOfferAvailability(model, () -> { - if (offer.getState() == Offer.State.AVAILABLE) - createTrade(amount, + if (offer.getState() == Offer.State.AVAILABLE) { + Trade trade = getNewTrade(amount, txFee, takerFee, isCurrencyForTakerFeeBtc, @@ -505,25 +505,27 @@ public void onTakeOffer(Coin amount, offer, paymentAccountId, useSavingsWallet, - model, - tradeResultHandler); + model); + tradableList.add(trade); + ((TakerTrade) trade).onTakeOffer(); + tradeResultHandler.handleResult(trade); + } }, errorMessageHandler); } - private void createTrade(Coin amount, - Coin txFee, - Coin takerFee, - boolean isCurrencyForTakerFeeBtc, - long tradePrice, - Coin fundsNeededForTrade, - Offer offer, - String paymentAccountId, - boolean useSavingsWallet, - OfferAvailabilityModel model, - TradeResultHandler tradeResultHandler) { + private Trade getNewTrade(Coin amount, + Coin txFee, + Coin takerFee, + boolean isCurrencyForTakerFeeBtc, + long tradePrice, + Coin fundsNeededForTrade, + Offer offer, + String paymentAccountId, + boolean useSavingsWallet, + OfferAvailabilityModel model) { Trade trade; - if (offer.isBuyOffer()) + if (offer.isBuyOffer()) { trade = new SellerAsTakerTrade(offer, amount, txFee, @@ -536,7 +538,7 @@ private void createTrade(Coin amount, model.getSelectedRefundAgent(), tradableListStorage, btcWalletService); - else + } else { trade = new BuyerAsTakerTrade(offer, amount, txFee, @@ -549,14 +551,10 @@ private void createTrade(Coin amount, model.getSelectedRefundAgent(), tradableListStorage, btcWalletService); - + } trade.setTakerPaymentAccountId(paymentAccountId); - initTrade(trade, useSavingsWallet, fundsNeededForTrade); - - tradableList.add(trade); - ((TakerTrade) trade).onTakeOffer(); - tradeResultHandler.handleResult(trade); + return trade; } private OfferAvailabilityModel getOfferAvailabilityModel(Offer offer) { From 9644920a52da179ad79380c91cedc34b42d988f6 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 23 Sep 2020 19:52:24 -0500 Subject: [PATCH 057/143] Refactor: Move mediation code to new class --- .../core/trade/protocol/BuyerProtocol.java | 2 +- .../trade/protocol/MediationProtocol.java | 194 +++++++++++++++ .../core/trade/protocol/SellerProtocol.java | 2 +- .../core/trade/protocol/TradeProtocol.java | 227 +++--------------- 4 files changed, 235 insertions(+), 190 deletions(-) create mode 100644 core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java 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 3222ba9ae80..53e97f28869 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java @@ -49,7 +49,7 @@ import static com.google.common.base.Preconditions.checkNotNull; @Slf4j -public abstract class BuyerProtocol extends TradeProtocol { +public abstract class BuyerProtocol extends MediationProtocol { enum BuyerEvent implements TradeProtocol.Event { STARTUP, PAYMENT_SENT diff --git a/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java b/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java new file mode 100644 index 00000000000..3892f4b5f0d --- /dev/null +++ b/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java @@ -0,0 +1,194 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.trade.protocol; + +import bisq.core.trade.Trade; +import bisq.core.trade.messages.MediatedPayoutTxPublishedMessage; +import bisq.core.trade.messages.MediatedPayoutTxSignatureMessage; +import bisq.core.trade.messages.PeerPublishedDelayedPayoutTxMessage; +import bisq.core.trade.messages.TradeMessage; +import bisq.core.trade.protocol.tasks.ApplyFilter; +import bisq.core.trade.protocol.tasks.ProcessPeerPublishedDelayedPayoutTxMessage; +import bisq.core.trade.protocol.tasks.mediation.BroadcastMediatedPayoutTx; +import bisq.core.trade.protocol.tasks.mediation.FinalizeMediatedPayoutTx; +import bisq.core.trade.protocol.tasks.mediation.ProcessMediatedPayoutSignatureMessage; +import bisq.core.trade.protocol.tasks.mediation.ProcessMediatedPayoutTxPublishedMessage; +import bisq.core.trade.protocol.tasks.mediation.SendMediatedPayoutSignatureMessage; +import bisq.core.trade.protocol.tasks.mediation.SendMediatedPayoutTxPublishedMessage; +import bisq.core.trade.protocol.tasks.mediation.SetupMediatedPayoutTxListener; +import bisq.core.trade.protocol.tasks.mediation.SignMediatedPayoutTx; + +import bisq.network.p2p.NodeAddress; + +import bisq.common.handlers.ErrorMessageHandler; +import bisq.common.handlers.ResultHandler; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class MediationProtocol extends TradeProtocol { + + enum DisputeEvent implements TradeProtocol.Event { + MEDIATION_RESULT_ACCEPTED, + MEDIATION_RESULT_REJECTED + } + + public MediationProtocol(Trade trade) { + super(trade); + } + + protected boolean wasDisputed() { + return trade.getDisputeState() != Trade.DisputeState.NO_DISPUTE; + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // User interaction: Trader accepts mediation result + /////////////////////////////////////////////////////////////////////////////////////////// + + // Trader has not yet received the peer's signature but has clicked the accept button. + public void onAcceptMediationResult(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + if (trade.getProcessModel().getTradingPeer().getMediatedPayoutTxSignature() != null) { + errorMessageHandler.handleErrorMessage("We have received already the signature from the peer."); + return; + } + DisputeEvent event = DisputeEvent.MEDIATION_RESULT_ACCEPTED; + TradeTaskRunner taskRunner = new TradeTaskRunner(trade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess(event); + }, + (errorMessage) -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(event, errorMessage); + }); + taskRunner.addTasks( + ApplyFilter.class, + SignMediatedPayoutTx.class, + SendMediatedPayoutSignatureMessage.class, + SetupMediatedPayoutTxListener.class + ); + taskRunner.run(); + } + + + // Trader has already received the peer's signature and has clicked the accept button as well. + public void onFinalizeMediationResultPayout(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + if (trade.getPayoutTx() != null) { + errorMessageHandler.handleErrorMessage("Payout tx is already published."); + return; + } + + DisputeEvent event = DisputeEvent.MEDIATION_RESULT_ACCEPTED; + TradeTaskRunner taskRunner = new TradeTaskRunner(trade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess(event); + }, + (errorMessage) -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(event, errorMessage); + }); + taskRunner.addTasks( + ApplyFilter.class, + SignMediatedPayoutTx.class, + FinalizeMediatedPayoutTx.class, + BroadcastMediatedPayoutTx.class, + SendMediatedPayoutTxPublishedMessage.class + ); + taskRunner.run(); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Mediation: incoming message + /////////////////////////////////////////////////////////////////////////////////////////// + + protected void handle(MediatedPayoutTxSignatureMessage message, NodeAddress peer) { + processModel.setTradeMessage(message); + processModel.setTempTradingPeerNodeAddress(peer); + + TradeTaskRunner taskRunner = new TradeTaskRunner(trade, + () -> handleTaskRunnerSuccess(message), + errorMessage -> handleTaskRunnerFault(message, errorMessage)); + + taskRunner.addTasks( + ProcessMediatedPayoutSignatureMessage.class + ); + taskRunner.run(); + } + + protected void handle(MediatedPayoutTxPublishedMessage message, NodeAddress peer) { + processModel.setTradeMessage(message); + processModel.setTempTradingPeerNodeAddress(peer); + + TradeTaskRunner taskRunner = new TradeTaskRunner(trade, + () -> handleTaskRunnerSuccess(message), + errorMessage -> handleTaskRunnerFault(message, errorMessage)); + + taskRunner.addTasks( + ProcessMediatedPayoutTxPublishedMessage.class + ); + taskRunner.run(); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Peer has published the delayed payout tx + /////////////////////////////////////////////////////////////////////////////////////////// + + private void handle(PeerPublishedDelayedPayoutTxMessage message, NodeAddress peer) { + processModel.setTradeMessage(message); + processModel.setTempTradingPeerNodeAddress(peer); + + TradeTaskRunner taskRunner = new TradeTaskRunner(trade, + () -> handleTaskRunnerSuccess(message), + errorMessage -> handleTaskRunnerFault(message, errorMessage)); + + taskRunner.addTasks( + ProcessPeerPublishedDelayedPayoutTxMessage.class + ); + taskRunner.run(); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Dispatcher + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + protected void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer) { + if (message instanceof MediatedPayoutTxSignatureMessage) { + handle((MediatedPayoutTxSignatureMessage) message, peer); + } else if (message instanceof MediatedPayoutTxPublishedMessage) { + handle((MediatedPayoutTxPublishedMessage) message, peer); + } else if (message instanceof PeerPublishedDelayedPayoutTxMessage) { + handle((PeerPublishedDelayedPayoutTxMessage) message, peer); + } + } + + @Override + protected void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress peerNodeAddress) { + if (tradeMessage instanceof MediatedPayoutTxSignatureMessage) { + handle((MediatedPayoutTxSignatureMessage) tradeMessage, peerNodeAddress); + } else if (tradeMessage instanceof MediatedPayoutTxPublishedMessage) { + handle((MediatedPayoutTxPublishedMessage) tradeMessage, peerNodeAddress); + } else if (tradeMessage instanceof PeerPublishedDelayedPayoutTxMessage) { + handle((PeerPublishedDelayedPayoutTxMessage) tradeMessage, peerNodeAddress); + } + } +} diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java index 1a4e7c5922c..c066be9cb9d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java @@ -44,7 +44,7 @@ import lombok.extern.slf4j.Slf4j; @Slf4j -public abstract class SellerProtocol extends TradeProtocol { +public abstract class SellerProtocol extends MediationProtocol { enum SellerEvent implements TradeProtocol.Event { PAYMENT_RECEIVED } diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index 06f09b58a57..f01fd4760ab 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -22,20 +22,7 @@ import bisq.core.trade.TradeManager; import bisq.core.trade.messages.CounterCurrencyTransferStartedMessage; import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage; -import bisq.core.trade.messages.MediatedPayoutTxPublishedMessage; -import bisq.core.trade.messages.MediatedPayoutTxSignatureMessage; -import bisq.core.trade.messages.PeerPublishedDelayedPayoutTxMessage; import bisq.core.trade.messages.TradeMessage; -import bisq.core.trade.protocol.tasks.ApplyFilter; -import bisq.core.trade.protocol.tasks.ProcessPeerPublishedDelayedPayoutTxMessage; -import bisq.core.trade.protocol.tasks.mediation.BroadcastMediatedPayoutTx; -import bisq.core.trade.protocol.tasks.mediation.FinalizeMediatedPayoutTx; -import bisq.core.trade.protocol.tasks.mediation.ProcessMediatedPayoutSignatureMessage; -import bisq.core.trade.protocol.tasks.mediation.ProcessMediatedPayoutTxPublishedMessage; -import bisq.core.trade.protocol.tasks.mediation.SendMediatedPayoutSignatureMessage; -import bisq.core.trade.protocol.tasks.mediation.SendMediatedPayoutTxPublishedMessage; -import bisq.core.trade.protocol.tasks.mediation.SetupMediatedPayoutTxListener; -import bisq.core.trade.protocol.tasks.mediation.SignMediatedPayoutTx; import bisq.network.p2p.AckMessage; import bisq.network.p2p.AckMessageSourceType; @@ -48,8 +35,6 @@ import bisq.common.Timer; import bisq.common.UserThread; import bisq.common.crypto.PubKeyRing; -import bisq.common.handlers.ErrorMessageHandler; -import bisq.common.handlers.ResultHandler; import bisq.common.proto.network.NetworkEnvelope; import bisq.common.taskrunner.Task; @@ -93,18 +78,18 @@ public TradeProtocol(Trade trade) { this.trade = trade; this.processModel = trade.getProcessModel(); - decryptedDirectMessageListener = (decryptedMessageWithPubKey, peersNodeAddress) -> { + decryptedDirectMessageListener = (decryptedMessageWithPubKey, peer) -> { // We check the sig only as soon we have stored the peers pubKeyRing. PubKeyRing tradingPeerPubKeyRing = processModel.getTradingPeer().getPubKeyRing(); PublicKey signaturePubKey = decryptedMessageWithPubKey.getSignaturePubKey(); if (tradingPeerPubKeyRing != null && signaturePubKey.equals(tradingPeerPubKeyRing.getSignaturePubKey())) { NetworkEnvelope networkEnvelope = decryptedMessageWithPubKey.getNetworkEnvelope(); if (networkEnvelope instanceof TradeMessage) { - TradeMessage tradeMessage = (TradeMessage) networkEnvelope; - nonEmptyStringOf(tradeMessage.getTradeId()); + TradeMessage message = (TradeMessage) networkEnvelope; + nonEmptyStringOf(message.getTradeId()); - if (tradeMessage.getTradeId().equals(processModel.getOfferId())) { - doHandleDecryptedMessage(tradeMessage, peersNodeAddress); + if (message.getTradeId().equals(processModel.getOfferId())) { + doHandleDecryptedMessage(message, peer); } } else if (networkEnvelope instanceof AckMessage) { AckMessage ackMessage = (AckMessage) networkEnvelope; @@ -120,10 +105,10 @@ public TradeProtocol(Trade trade) { if (ackMessage.isSuccess()) { log.info("Received AckMessage for {} from {} with tradeId {} and uid {}", - ackMessage.getSourceMsgClassName(), peersNodeAddress, ackMessage.getSourceId(), ackMessage.getSourceUid()); + ackMessage.getSourceMsgClassName(), peer, ackMessage.getSourceId(), ackMessage.getSourceUid()); } else { log.warn("Received AckMessage with error state for {} from {} with tradeId {} and errorMessage={}", - ackMessage.getSourceMsgClassName(), peersNodeAddress, ackMessage.getSourceId(), ackMessage.getErrorMessage()); + ackMessage.getSourceMsgClassName(), peer, ackMessage.getSourceId(), ackMessage.getErrorMessage()); } } } @@ -131,139 +116,16 @@ public TradeProtocol(Trade trade) { }; processModel.getP2PService().addDecryptedDirectMessageListener(decryptedDirectMessageListener); + //todo move stateChangeListener = (observable, oldValue, newValue) -> { if (newValue.getPhase() == Trade.Phase.TAKER_FEE_PUBLISHED && trade instanceof MakerTrade) processModel.getOpenOfferManager().closeOpenOffer(checkNotNull(trade.getOffer())); }; trade.stateProperty().addListener(stateChangeListener); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Mediation: Called from UI if trader accepts mediation result - /////////////////////////////////////////////////////////////////////////////////////////// - - //TODO - // Trader has not yet received the peer's signature but has clicked the accept button. - public void onAcceptMediationResult(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - if (trade.getProcessModel().getTradingPeer().getMediatedPayoutTxSignature() != null) { - errorMessageHandler.handleErrorMessage("We have received already the signature from the peer."); - return; - } - DisputeEvent event = DisputeEvent.MEDIATION_RESULT_ACCEPTED; - TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess(event); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(event, errorMessage); - }); - taskRunner.addTasks( - ApplyFilter.class, - SignMediatedPayoutTx.class, - SendMediatedPayoutSignatureMessage.class, - SetupMediatedPayoutTxListener.class - ); - taskRunner.run(); } - - // Trader has already received the peer's signature and has clicked the accept button as well. - public void onFinalizeMediationResultPayout(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - if (trade.getPayoutTx() != null) { - errorMessageHandler.handleErrorMessage("Payout tx is already published."); - return; - } - - DisputeEvent event = DisputeEvent.MEDIATION_RESULT_ACCEPTED; - TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess(event); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(event, errorMessage); - }); - taskRunner.addTasks( - ApplyFilter.class, - SignMediatedPayoutTx.class, - FinalizeMediatedPayoutTx.class, - BroadcastMediatedPayoutTx.class, - SendMediatedPayoutTxPublishedMessage.class - ); - taskRunner.run(); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Mediation: incoming message - /////////////////////////////////////////////////////////////////////////////////////////// - - protected void handle(MediatedPayoutTxSignatureMessage tradeMessage, NodeAddress sender) { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - - TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(tradeMessage), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); - - taskRunner.addTasks( - ProcessMediatedPayoutSignatureMessage.class - ); - taskRunner.run(); - } - - protected void handle(MediatedPayoutTxPublishedMessage tradeMessage, NodeAddress sender) { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - - TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(tradeMessage), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); - - taskRunner.addTasks( - ProcessMediatedPayoutTxPublishedMessage.class - ); - taskRunner.run(); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Peer has published the delayed payout tx - /////////////////////////////////////////////////////////////////////////////////////////// - - private void handle(PeerPublishedDelayedPayoutTxMessage tradeMessage, NodeAddress sender) { - processModel.setTradeMessage(tradeMessage); - processModel.setTempTradingPeerNodeAddress(sender); - - TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(tradeMessage), - errorMessage -> handleTaskRunnerFault(tradeMessage, errorMessage)); - - taskRunner.addTasks( - ProcessPeerPublishedDelayedPayoutTxMessage.class - ); - taskRunner.run(); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Dispatcher - /////////////////////////////////////////////////////////////////////////////////////////// - - protected void doHandleDecryptedMessage(TradeMessage tradeMessage, NodeAddress sender) { - if (tradeMessage instanceof MediatedPayoutTxSignatureMessage) { - handle((MediatedPayoutTxSignatureMessage) tradeMessage, sender); - } else if (tradeMessage instanceof MediatedPayoutTxPublishedMessage) { - handle((MediatedPayoutTxPublishedMessage) tradeMessage, sender); - } else if (tradeMessage instanceof PeerPublishedDelayedPayoutTxMessage) { - handle((PeerPublishedDelayedPayoutTxMessage) tradeMessage, sender); - } - } + protected abstract void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer); /////////////////////////////////////////////////////////////////////////////////////////// @@ -290,26 +152,18 @@ public void applyMailboxMessage(DecryptedMessageWithPubKey decryptedMessageWithP if (networkEnvelope instanceof MailboxMessage && networkEnvelope instanceof TradeMessage) { this.trade = trade; - TradeMessage tradeMessage = (TradeMessage) networkEnvelope; + TradeMessage message = (TradeMessage) networkEnvelope; NodeAddress peerNodeAddress = ((MailboxMessage) networkEnvelope).getSenderNodeAddress(); - doApplyMailboxTradeMessage(tradeMessage, peerNodeAddress); + doApplyMailboxTradeMessage(message, peerNodeAddress); } } else { log.error("SignaturePubKey in message does not match the SignaturePubKey we have stored to that trading peer."); } } - protected void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress peerNodeAddress) { + protected void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peerNodeAddress) { log.info("Received {} as MailboxMessage from {} with tradeId {} and uid {}", - tradeMessage.getClass().getSimpleName(), peerNodeAddress, tradeMessage.getTradeId(), tradeMessage.getUid()); - - if (tradeMessage instanceof MediatedPayoutTxSignatureMessage) { - handle((MediatedPayoutTxSignatureMessage) tradeMessage, peerNodeAddress); - } else if (tradeMessage instanceof MediatedPayoutTxPublishedMessage) { - handle((MediatedPayoutTxPublishedMessage) tradeMessage, peerNodeAddress); - } else if (tradeMessage instanceof PeerPublishedDelayedPayoutTxMessage) { - handle((PeerPublishedDelayedPayoutTxMessage) tradeMessage, peerNodeAddress); - } + message.getClass().getSimpleName(), peerNodeAddress, message.getTradeId(), message.getUid()); } protected void startTimeout() { @@ -335,26 +189,26 @@ protected void stopTimeout() { } } - protected void handleTaskRunnerSuccess(TradeMessage tradeMessage) { - handleTaskRunnerSuccess(tradeMessage, null); + protected void handleTaskRunnerSuccess(TradeMessage message) { + handleTaskRunnerSuccess(message, null); } protected void handleTaskRunnerSuccess(Event event) { handleTaskRunnerSuccess(null, event.name()); } - private void handleTaskRunnerSuccess(@Nullable TradeMessage tradeMessage, @Nullable String trigger) { + private void handleTaskRunnerSuccess(@Nullable TradeMessage message, @Nullable String trigger) { String triggerEvent = trigger != null ? trigger : - tradeMessage != null ? tradeMessage.getClass().getSimpleName() : "N/A"; + message != null ? message.getClass().getSimpleName() : "N/A"; log.info("TaskRunner successfully completed. {}", "Triggered from message " + triggerEvent); - sendAckMessage(tradeMessage, true, null); + sendAckMessage(message, true, null); } - protected void handleTaskRunnerFault(@Nullable TradeMessage tradeMessage, String errorMessage) { - log.error("Task runner failed on {} with error {}", tradeMessage, errorMessage); + protected void handleTaskRunnerFault(@Nullable TradeMessage message, String errorMessage) { + log.error("Task runner failed on {} with error {}", message, errorMessage); - sendAckMessage(tradeMessage, false, errorMessage); + sendAckMessage(message, false, errorMessage); cleanupTradeOnFault(); cleanup(); @@ -367,55 +221,52 @@ protected void handleTaskRunnerFault(@Nullable Event event, String errorMessage) cleanup(); } - protected boolean wasDisputed() { - return trade.getDisputeState() != Trade.DisputeState.NO_DISPUTE; - } - protected void sendAckMessage(@Nullable TradeMessage tradeMessage, boolean result, @Nullable String errorMessage) { + protected void sendAckMessage(@Nullable TradeMessage message, boolean result, @Nullable String errorMessage) { // We complete at initial protocol setup with the setup listener tasks. // Other cases are if we start from an UI event the task runner (payment started, confirmed). - // In such cases we have not set any tradeMessage and we ignore the sendAckMessage call. - if (tradeMessage == null) + // In such cases we have not set any message and we ignore the sendAckMessage call. + if (message == null) return; - String tradeId = tradeMessage.getTradeId(); - String sourceUid = tradeMessage.getUid(); + String tradeId = message.getTradeId(); + String sourceUid = message.getUid(); AckMessage ackMessage = new AckMessage(processModel.getMyNodeAddress(), AckMessageSourceType.TRADE_MESSAGE, - tradeMessage.getClass().getSimpleName(), + message.getClass().getSimpleName(), sourceUid, tradeId, result, errorMessage); // If there was an error during offer verification, the tradingPeerNodeAddress of the trade might not be set yet. // We can find the peer's node address in the processModel's tempTradingPeerNodeAddress in that case. - NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress() != null ? + NodeAddress peer = trade.getTradingPeerNodeAddress() != null ? trade.getTradingPeerNodeAddress() : processModel.getTempTradingPeerNodeAddress(); log.info("Send AckMessage for {} to peer {}. tradeId={}, sourceUid={}", - ackMessage.getSourceMsgClassName(), peersNodeAddress, tradeId, sourceUid); + ackMessage.getSourceMsgClassName(), peer, tradeId, sourceUid); processModel.getP2PService().sendEncryptedMailboxMessage( - peersNodeAddress, + peer, processModel.getTradingPeer().getPubKeyRing(), ackMessage, new SendMailboxMessageListener() { @Override public void onArrived() { log.info("AckMessage for {} arrived at peer {}. tradeId={}, sourceUid={}", - ackMessage.getSourceMsgClassName(), peersNodeAddress, tradeId, sourceUid); + ackMessage.getSourceMsgClassName(), peer, tradeId, sourceUid); } @Override public void onStoredInMailbox() { log.info("AckMessage for {} stored in mailbox for peer {}. tradeId={}, sourceUid={}", - ackMessage.getSourceMsgClassName(), peersNodeAddress, tradeId, sourceUid); + ackMessage.getSourceMsgClassName(), peer, tradeId, sourceUid); } @Override public void onFault(String errorMessage) { log.error("AckMessage for {} failed. Peer {}. tradeId={}, sourceUid={}, errorMessage={}", - ackMessage.getSourceMsgClassName(), peersNodeAddress, tradeId, sourceUid, errorMessage); + ackMessage.getSourceMsgClassName(), peer, tradeId, sourceUid, errorMessage); } } ); @@ -493,7 +344,7 @@ public FluentProtocol executeTasks() { startTimeout(setup.getTimeoutSec()); } - NodeAddress peer = condition.getPeersNodeAddress(); + NodeAddress peer = condition.getPeer(); if (peer != null) { processModel.setTempTradingPeerNodeAddress(peer); } @@ -523,7 +374,7 @@ static class Condition { @Getter private Event event; @Getter - private NodeAddress peersNodeAddress; + private NodeAddress peer; private boolean isValid; private boolean isValidated; private Runnable preConditionFailedHandler; @@ -554,15 +405,15 @@ public Condition with(Event event) { return this; } - public Condition with(TradeMessage tradeMessage) { + public Condition with(TradeMessage message) { checkArgument(!isValidated); - this.message = tradeMessage; + this.message = message; return this; } - public Condition from(NodeAddress peersNodeAddress) { + public Condition from(NodeAddress peer) { checkArgument(!isValidated); - this.peersNodeAddress = peersNodeAddress; + this.peer = peer; return this; } From f059f08b273589d252d5e6ab21d108bef81c42bd Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 23 Sep 2020 19:56:41 -0500 Subject: [PATCH 058/143] Refactor: Rearrange methods --- .../core/trade/protocol/TradeProtocol.java | 191 ++++++++++-------- 1 file changed, 103 insertions(+), 88 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index f01fd4760ab..29545bd0bcf 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -61,89 +61,34 @@ interface Event { String name(); } - enum DisputeEvent implements TradeProtocol.Event { - MEDIATION_RESULT_ACCEPTED, - MEDIATION_RESULT_REJECTED - } - private static final long DEFAULT_TIMEOUT_SEC = 180; protected final ProcessModel processModel; - private final DecryptedDirectMessageListener decryptedDirectMessageListener; - private final ChangeListener stateChangeListener; + private DecryptedDirectMessageListener decryptedDirectMessageListener; + private ChangeListener stateChangeListener; protected Trade trade; private Timer timeoutTimer; + + /////////////////////////////////////////////////////////////////////////////////////////// + // Constructor + /////////////////////////////////////////////////////////////////////////////////////////// + public TradeProtocol(Trade trade) { this.trade = trade; this.processModel = trade.getProcessModel(); - decryptedDirectMessageListener = (decryptedMessageWithPubKey, peer) -> { - // We check the sig only as soon we have stored the peers pubKeyRing. - PubKeyRing tradingPeerPubKeyRing = processModel.getTradingPeer().getPubKeyRing(); - PublicKey signaturePubKey = decryptedMessageWithPubKey.getSignaturePubKey(); - if (tradingPeerPubKeyRing != null && signaturePubKey.equals(tradingPeerPubKeyRing.getSignaturePubKey())) { - NetworkEnvelope networkEnvelope = decryptedMessageWithPubKey.getNetworkEnvelope(); - if (networkEnvelope instanceof TradeMessage) { - TradeMessage message = (TradeMessage) networkEnvelope; - nonEmptyStringOf(message.getTradeId()); - - if (message.getTradeId().equals(processModel.getOfferId())) { - doHandleDecryptedMessage(message, peer); - } - } else if (networkEnvelope instanceof AckMessage) { - AckMessage ackMessage = (AckMessage) networkEnvelope; - if (ackMessage.getSourceType() == AckMessageSourceType.TRADE_MESSAGE && - ackMessage.getSourceId().equals(trade.getId())) { - // We handle the ack for CounterCurrencyTransferStartedMessage and DepositTxAndDelayedPayoutTxMessage - // as we support automatic re-send of the msg in case it was not ACKed after a certain time - if (ackMessage.getSourceMsgClassName().equals(CounterCurrencyTransferStartedMessage.class.getSimpleName())) { - processModel.setPaymentStartedAckMessage(ackMessage); - } else if (ackMessage.getSourceMsgClassName().equals(DepositTxAndDelayedPayoutTxMessage.class.getSimpleName())) { - processModel.setDepositTxSentAckMessage(ackMessage); - } - - if (ackMessage.isSuccess()) { - log.info("Received AckMessage for {} from {} with tradeId {} and uid {}", - ackMessage.getSourceMsgClassName(), peer, ackMessage.getSourceId(), ackMessage.getSourceUid()); - } else { - log.warn("Received AckMessage with error state for {} from {} with tradeId {} and errorMessage={}", - ackMessage.getSourceMsgClassName(), peer, ackMessage.getSourceId(), ackMessage.getErrorMessage()); - } - } - } - } - }; - processModel.getP2PService().addDecryptedDirectMessageListener(decryptedDirectMessageListener); - - //todo move - stateChangeListener = (observable, oldValue, newValue) -> { - if (newValue.getPhase() == Trade.Phase.TAKER_FEE_PUBLISHED && trade instanceof MakerTrade) - processModel.getOpenOfferManager().closeOpenOffer(checkNotNull(trade.getOffer())); - }; - trade.stateProperty().addListener(stateChangeListener); - + setupListeners(); } - protected abstract void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer); - /////////////////////////////////////////////////////////////////////////////////////////// // API /////////////////////////////////////////////////////////////////////////////////////////// - public void completed() { cleanup(); } - private void cleanup() { - stopTimeout(); - trade.stateProperty().removeListener(stateChangeListener); - // We removed that from here earlier as it broke the trade process in some non critical error cases. - // But it should be actually removed... - processModel.getP2PService().removeDecryptedDirectMessageListener(decryptedDirectMessageListener); - } - public void applyMailboxMessage(DecryptedMessageWithPubKey decryptedMessageWithPubKey, Trade trade) { NetworkEnvelope networkEnvelope = decryptedMessageWithPubKey.getNetworkEnvelope(); if (processModel.getTradingPeer().getPubKeyRing() != null && @@ -161,6 +106,17 @@ public void applyMailboxMessage(DecryptedMessageWithPubKey decryptedMessageWithP } } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Abstract + /////////////////////////////////////////////////////////////////////////////////////////// + protected abstract void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer); + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Protected + /////////////////////////////////////////////////////////////////////////////////////////// + protected void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peerNodeAddress) { log.info("Received {} as MailboxMessage from {} with tradeId {} and uid {}", message.getClass().getSimpleName(), peerNodeAddress, message.getTradeId(), message.getUid()); @@ -197,31 +153,6 @@ protected void handleTaskRunnerSuccess(Event event) { handleTaskRunnerSuccess(null, event.name()); } - private void handleTaskRunnerSuccess(@Nullable TradeMessage message, @Nullable String trigger) { - String triggerEvent = trigger != null ? trigger : - message != null ? message.getClass().getSimpleName() : "N/A"; - log.info("TaskRunner successfully completed. {}", "Triggered from message " + triggerEvent); - - sendAckMessage(message, true, null); - } - - protected void handleTaskRunnerFault(@Nullable TradeMessage message, String errorMessage) { - log.error("Task runner failed on {} with error {}", message, errorMessage); - - sendAckMessage(message, false, errorMessage); - - cleanupTradeOnFault(); - cleanup(); - } - - protected void handleTaskRunnerFault(@Nullable Event event, String errorMessage) { - log.error("Task runner failed on {} with error {}", event, errorMessage); - - cleanupTradeOnFault(); - cleanup(); - } - - protected void sendAckMessage(@Nullable TradeMessage message, boolean result, @Nullable String errorMessage) { // We complete at initial protocol setup with the setup listener tasks. // Other cases are if we start from an UI event the task runner (payment started, confirmed). @@ -272,6 +203,90 @@ public void onFault(String errorMessage) { ); } + /////////////////////////////////////////////////////////////////////////////////////////// + // Private + /////////////////////////////////////////////////////////////////////////////////////////// + + private void setupListeners() { + decryptedDirectMessageListener = (decryptedMessageWithPubKey, peer) -> { + // We check the sig only as soon we have stored the peers pubKeyRing. + PubKeyRing tradingPeerPubKeyRing = processModel.getTradingPeer().getPubKeyRing(); + PublicKey signaturePubKey = decryptedMessageWithPubKey.getSignaturePubKey(); + if (tradingPeerPubKeyRing != null && signaturePubKey.equals(tradingPeerPubKeyRing.getSignaturePubKey())) { + NetworkEnvelope networkEnvelope = decryptedMessageWithPubKey.getNetworkEnvelope(); + if (networkEnvelope instanceof TradeMessage) { + TradeMessage message = (TradeMessage) networkEnvelope; + nonEmptyStringOf(message.getTradeId()); + + if (message.getTradeId().equals(processModel.getOfferId())) { + doHandleDecryptedMessage(message, peer); + } + } else if (networkEnvelope instanceof AckMessage) { + AckMessage ackMessage = (AckMessage) networkEnvelope; + if (ackMessage.getSourceType() == AckMessageSourceType.TRADE_MESSAGE && + ackMessage.getSourceId().equals(trade.getId())) { + // We handle the ack for CounterCurrencyTransferStartedMessage and DepositTxAndDelayedPayoutTxMessage + // as we support automatic re-send of the msg in case it was not ACKed after a certain time + if (ackMessage.getSourceMsgClassName().equals(CounterCurrencyTransferStartedMessage.class.getSimpleName())) { + processModel.setPaymentStartedAckMessage(ackMessage); + } else if (ackMessage.getSourceMsgClassName().equals(DepositTxAndDelayedPayoutTxMessage.class.getSimpleName())) { + processModel.setDepositTxSentAckMessage(ackMessage); + } + + if (ackMessage.isSuccess()) { + log.info("Received AckMessage for {} from {} with tradeId {} and uid {}", + ackMessage.getSourceMsgClassName(), peer, ackMessage.getSourceId(), ackMessage.getSourceUid()); + } else { + log.warn("Received AckMessage with error state for {} from {} with tradeId {} and errorMessage={}", + ackMessage.getSourceMsgClassName(), peer, ackMessage.getSourceId(), ackMessage.getErrorMessage()); + } + } + } + } + }; + processModel.getP2PService().addDecryptedDirectMessageListener(decryptedDirectMessageListener); + + //todo move + stateChangeListener = (observable, oldValue, newValue) -> { + if (newValue.getPhase() == Trade.Phase.TAKER_FEE_PUBLISHED && trade instanceof MakerTrade) + processModel.getOpenOfferManager().closeOpenOffer(checkNotNull(trade.getOffer())); + }; + trade.stateProperty().addListener(stateChangeListener); + } + + + private void handleTaskRunnerSuccess(@Nullable TradeMessage message, @Nullable String trigger) { + String triggerEvent = trigger != null ? trigger : + message != null ? message.getClass().getSimpleName() : "N/A"; + log.info("TaskRunner successfully completed. {}", "Triggered from message " + triggerEvent); + + sendAckMessage(message, true, null); + } + + protected void handleTaskRunnerFault(@Nullable TradeMessage message, String errorMessage) { + log.error("Task runner failed on {} with error {}", message, errorMessage); + + sendAckMessage(message, false, errorMessage); + + cleanupTradeOnFault(); + cleanup(); + } + + protected void handleTaskRunnerFault(@Nullable Event event, String errorMessage) { + log.error("Task runner failed on {} with error {}", event, errorMessage); + + cleanupTradeOnFault(); + cleanup(); + } + + private void cleanup() { + stopTimeout(); + trade.stateProperty().removeListener(stateChangeListener); + // We removed that from here earlier as it broke the trade process in some non critical error cases. + // But it should be actually removed... + processModel.getP2PService().removeDecryptedDirectMessageListener(decryptedDirectMessageListener); + } + private void cleanupTradeOnFault() { Trade.State state = trade.getState(); log.warn("cleanupTradableOnFault tradeState={}", state); From 03023567a8b1d7f1981d3028d4b7d5740329b429 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 23 Sep 2020 22:24:45 -0500 Subject: [PATCH 059/143] Fix potential bug with peers pub key check. Use new isPubKeyValid method to avoid code duplication. Before we did not apply messages if the peers key was null which can be the case at protocol start for maker side (takers key is not set yet). Makers key is in offer and available from the start. Fix incorrect setPubKeyRing call in BuyerAsTakerProtocol and BuyerProtocol. Only taker can set it from offer. This bug was introduce in past commits of this branch. Move FluentProtocol to own class file Close open offer in task instead at state listener Remove state listener Remove default timeout as not used anymore Add onWithdrawCompleted method to clean up when trade completed Rearrange code in TradeProtocol Rename doHandleDecryptedMessage to onTradeMessage Rename doApplyMailboxTradeMessage to onMailboxMessage --- core/src/main/java/bisq/core/trade/Trade.java | 7 +- .../java/bisq/core/trade/TradeManager.java | 1 + .../trade/protocol/BuyerAsTakerProtocol.java | 10 +- .../core/trade/protocol/BuyerProtocol.java | 17 +- .../core/trade/protocol/FluentProtocol.java | 316 +++++++++++ .../trade/protocol/MediationProtocol.java | 19 +- .../trade/protocol/SellerAsMakerProtocol.java | 4 +- .../trade/protocol/SellerAsTakerProtocol.java | 4 +- .../core/trade/protocol/SellerProtocol.java | 10 +- .../core/trade/protocol/TakerProtocol.java | 2 +- .../core/trade/protocol/TradeProtocol.java | 537 +++++------------- .../MakerSendsInputsForDepositTxResponse.java | 5 + 12 files changed, 499 insertions(+), 433 deletions(-) create mode 100644 core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index 9ca0a4f6a17..8196ac39464 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -703,7 +703,7 @@ public void init(P2PService p2PService, // or async calls there. // Clone to avoid ConcurrentModificationException. We remove items at the applyMailboxMessage call... HashSet set = new HashSet<>(decryptedMessageWithPubKeySet); - set.forEach(msg -> tradeProtocol.applyMailboxMessage(msg, this)); + set.forEach(msg -> tradeProtocol.applyMailboxMessage(msg)); } @@ -773,7 +773,7 @@ void addDecryptedMessageWithPubKey(DecryptedMessageWithPubKey decryptedMessageWi // removeDecryptedMsgWithPubKey will be called synchronous after apply. We don't have threaded context // or async calls there. if (tradeProtocol != null) - tradeProtocol.applyMailboxMessage(decryptedMessageWithPubKey, this); + tradeProtocol.applyMailboxMessage(decryptedMessageWithPubKey); } } @@ -862,9 +862,6 @@ public void setState(State state) { stateProperty.set(state); statePhaseProperty.set(state.getPhase()); - if (state == State.WITHDRAW_COMPLETED && tradeProtocol != null) - tradeProtocol.completed(); - if (changed) persist(); } diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index ccbeafbd230..58137b053ca 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -583,6 +583,7 @@ public void onSuccess(@javax.annotation.Nullable Transaction transaction) { log.debug("onWithdraw onSuccess tx ID:" + transaction.getTxId().toString()); addTradeToClosedTrades(trade); trade.setState(Trade.State.WITHDRAW_COMPLETED); + trade.getTradeProtocol().onWithdrawCompleted(); resultHandler.handleResult(); } } diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index aa2aea4090b..7d5d3e21c15 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -18,6 +18,7 @@ package bisq.core.trade.protocol; +import bisq.core.offer.Offer; import bisq.core.trade.BuyerAsTakerTrade; import bisq.core.trade.Trade; import bisq.core.trade.messages.DelayedPayoutTxSignatureRequest; @@ -46,6 +47,8 @@ import lombok.extern.slf4j.Slf4j; +import static com.google.common.base.Preconditions.checkNotNull; + @Slf4j public class BuyerAsTakerProtocol extends BuyerProtocol implements TakerProtocol { @@ -55,6 +58,9 @@ public class BuyerAsTakerProtocol extends BuyerProtocol implements TakerProtocol public BuyerAsTakerProtocol(BuyerAsTakerTrade trade) { super(trade); + + Offer offer = checkNotNull(trade.getOffer()); + processModel.getTradingPeer().setPubKeyRing(offer.getPubKeyRing()); } @@ -138,8 +144,8 @@ protected void handle(PayoutTxPublishedMessage message, NodeAddress peer) { /////////////////////////////////////////////////////////////////////////////////////////// @Override - protected void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer) { - super.doHandleDecryptedMessage(message, peer); + protected void onTradeMessage(TradeMessage message, NodeAddress peer) { + super.onTradeMessage(message, peer); if (message instanceof InputsForDepositTxResponse) { handle((InputsForDepositTxResponse) message, peer); 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 53e97f28869..c15fb19428a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java @@ -17,7 +17,6 @@ package bisq.core.trade.protocol; -import bisq.core.offer.Offer; import bisq.core.trade.BuyerTrade; import bisq.core.trade.Trade; import bisq.core.trade.messages.DelayedPayoutTxSignatureRequest; @@ -46,11 +45,9 @@ import lombok.extern.slf4j.Slf4j; -import static com.google.common.base.Preconditions.checkNotNull; - @Slf4j public abstract class BuyerProtocol extends MediationProtocol { - enum BuyerEvent implements TradeProtocol.Event { + enum BuyerEvent implements FluentProtocol.Event { STARTUP, PAYMENT_SENT } @@ -62,10 +59,6 @@ enum BuyerEvent implements TradeProtocol.Event { public BuyerProtocol(BuyerTrade trade) { super(trade); - Offer offer = checkNotNull(trade.getOffer()); - processModel.getTradingPeer().setPubKeyRing(offer.getPubKeyRing()); - - given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) .with(BuyerEvent.STARTUP)) .setup(tasks(BuyerSetupDepositTxListener.class)) @@ -85,8 +78,8 @@ public BuyerProtocol(BuyerTrade trade) { } @Override - public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peer) { - super.doApplyMailboxTradeMessage(message, peer); + public void onMailboxMessage(TradeMessage message, NodeAddress peer) { + super.onMailboxMessage(message, peer); if (message instanceof DepositTxAndDelayedPayoutTxMessage) { handle((DepositTxAndDelayedPayoutTxMessage) message, peer); @@ -188,8 +181,8 @@ protected void handle(PayoutTxPublishedMessage message, NodeAddress peer) { /////////////////////////////////////////////////////////////////////////////////////////// @Override - protected void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer) { - super.doHandleDecryptedMessage(message, peer); + protected void onTradeMessage(TradeMessage message, NodeAddress peer) { + super.onTradeMessage(message, peer); log.info("Received {} from {} with tradeId {} and uid {}", message.getClass().getSimpleName(), peer, message.getTradeId(), message.getUid()); diff --git a/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java b/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java new file mode 100644 index 00000000000..6fa0ceb6907 --- /dev/null +++ b/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java @@ -0,0 +1,316 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.trade.protocol; + +import bisq.core.trade.Trade; +import bisq.core.trade.messages.TradeMessage; + +import bisq.network.p2p.NodeAddress; + +import bisq.common.taskrunner.Task; + +import java.util.HashSet; +import java.util.Set; + +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import javax.annotation.Nullable; + +import static bisq.core.util.Validator.isTradeIdValid; +import static com.google.common.base.Preconditions.checkArgument; + +// Main class. Contains the condition and setup, if condition is valid it will execute the +// taskRunner and the optional runnable. +public class FluentProtocol { + interface Event { + String name(); + } + + private final TradeProtocol tradeProtocol; + private Condition condition; + private Setup setup; + + public FluentProtocol(TradeProtocol tradeProtocol) { + this.tradeProtocol = tradeProtocol; + } + + protected FluentProtocol condition(Condition condition) { + this.condition = condition; + return this; + } + + protected FluentProtocol setup(Setup setup) { + this.setup = setup; + return this; + } + + // Can be used before or after executeTasks + public FluentProtocol run(Runnable runnable) { + if (condition.isValid()) { + runnable.run(); + } + return this; + } + + public FluentProtocol executeTasks() { + if (condition.isValid()) { + if (setup.getTimeoutSec() > 0) { + tradeProtocol.startTimeout(setup.getTimeoutSec()); + } + + NodeAddress peer = condition.getPeer(); + if (peer != null) { + tradeProtocol.processModel.setTempTradingPeerNodeAddress(peer); + } + + TradeMessage message = condition.getMessage(); + if (message != null) { + tradeProtocol.processModel.setTradeMessage(message); + } + + TradeTaskRunner taskRunner = setup.getTaskRunner(message, condition.getEvent()); + taskRunner.addTasks(setup.getTasks()); + taskRunner.run(); + } + return this; + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Condition class + /////////////////////////////////////////////////////////////////////////////////////////// + + @Slf4j + public static class Condition { + private final Set expectedPhases = new HashSet<>(); + private final Set expectedStates = new HashSet<>(); + private final Set preConditions = new HashSet<>(); + private final Trade trade; + + @Nullable + @Getter + private TradeMessage message; + @Nullable + @Getter + private Event event; + @Nullable + @Getter + private NodeAddress peer; + @Nullable + private Runnable preConditionFailedHandler; + + private boolean isValid; + private boolean isValidated; // We validate only once + + public Condition(Trade trade) { + this.trade = trade; + } + + public Condition phase(Trade.Phase expectedPhase) { + checkArgument(!isValidated); + this.expectedPhases.add(expectedPhase); + return this; + } + + public Condition anyPhase(Trade.Phase... expectedPhases) { + checkArgument(!isValidated); + this.expectedPhases.addAll(Set.of(expectedPhases)); + return this; + } + + public Condition state(Trade.State state) { + checkArgument(!isValidated); + this.expectedStates.add(state); + return this; + } + + public Condition anyState(Trade.State... states) { + checkArgument(!isValidated); + this.expectedStates.addAll(Set.of(states)); + return this; + } + + public Condition with(TradeMessage message) { + checkArgument(!isValidated); + this.message = message; + return this; + } + + public Condition with(Event event) { + checkArgument(!isValidated); + this.event = event; + return this; + } + + public Condition from(NodeAddress peer) { + checkArgument(!isValidated); + this.peer = peer; + return this; + } + + public Condition preCondition(boolean preCondition) { + checkArgument(!isValidated); + preConditions.add(preCondition); + return this; + } + + public Condition preCondition(boolean preCondition, Runnable conditionFailedHandler) { + checkArgument(!isValidated); + preCondition(preCondition); + + this.preConditionFailedHandler = conditionFailedHandler; + return this; + } + + public boolean isValid() { + if (!isValidated) { + boolean isPhaseValid = isPhaseValid(); + boolean isStateValid = isStateValid(); + + boolean allPreConditionsMet = preConditions.stream().allMatch(e -> e); + boolean isTradeIdValid = message == null || isTradeIdValid(trade.getId(), message); + + if (!allPreConditionsMet) { + log.error("PreConditions not met. preConditions={}, this={}", preConditions, this); + if (preConditionFailedHandler != null) { + preConditionFailedHandler.run(); + } + } + if (!isTradeIdValid) { + log.error("TradeId does not match tradeId in message, TradeId={}, tradeId in message={}", + trade.getId(), message.getTradeId()); + } + + isValid = isPhaseValid && isStateValid && allPreConditionsMet && isTradeIdValid; + isValidated = true; + } + return isValid; + } + + private boolean isPhaseValid() { + if (expectedPhases.isEmpty()) { + return true; + } + + boolean isPhaseValid = expectedPhases.stream().anyMatch(e -> e == trade.getPhase()); + String trigger = message != null ? + message.getClass().getSimpleName() : + event != null ? + event.name() + " event" : + ""; + if (isPhaseValid) { + log.info("We received {} at phase {} and state {}", + trigger, + trade.getPhase(), + trade.getState()); + } else { + log.error("We received {} but we are are not in the correct phase. Expected phases={}, " + + "Trade phase={}, Trade state= {} ", + trigger, + expectedPhases, + trade.getPhase(), + trade.getState()); + } + + return isPhaseValid; + } + + private boolean isStateValid() { + if (expectedStates.isEmpty()) { + return true; + } + + boolean isStateValid = expectedStates.stream().anyMatch(e -> e == trade.getState()); + String trigger = message != null ? + message.getClass().getSimpleName() : + event != null ? + event.name() + " event" : + ""; + if (isStateValid) { + log.info("We received {} at state {}", + trigger, + trade.getState()); + } else { + log.error("We received {} but we are are not in the correct state. Expected states={}, " + + "Trade state= {} ", + trigger, + expectedStates, + trade.getState()); + } + + return isStateValid; + } + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Setup class + /////////////////////////////////////////////////////////////////////////////////////////// + + @Slf4j + public static class Setup { + private final TradeProtocol tradeProtocol; + private final Trade trade; + @Getter + private Class>[] tasks; + @Getter + private int timeoutSec; + @Nullable + private TradeTaskRunner taskRunner; + + public Setup(TradeProtocol tradeProtocol, Trade trade) { + this.tradeProtocol = tradeProtocol; + this.trade = trade; + } + + @SafeVarargs + public final Setup tasks(Class>... tasks) { + this.tasks = tasks; + return this; + } + + public Setup withTimeout(int timeoutSec) { + this.timeoutSec = timeoutSec; + return this; + } + + public Setup using(TradeTaskRunner taskRunner) { + this.taskRunner = taskRunner; + return this; + } + + public TradeTaskRunner getTaskRunner(@Nullable TradeMessage message, @Nullable Event event) { + if (taskRunner == null) { + if (message != null) { + taskRunner = new TradeTaskRunner(trade, + () -> tradeProtocol.handleTaskRunnerSuccess(message), + errorMessage -> tradeProtocol.handleTaskRunnerFault(message, errorMessage)); + } else if (event != null) { + taskRunner = new TradeTaskRunner(trade, + () -> tradeProtocol.handleTaskRunnerSuccess(event), + errorMessage -> tradeProtocol.handleTaskRunnerFault(event, errorMessage)); + } else { + throw new IllegalStateException("addTasks must not be called without message or event " + + "set in case no taskRunner has been created yet"); + } + } + return taskRunner; + } + } +} diff --git a/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java b/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java index 3892f4b5f0d..a90ce705690 100644 --- a/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java @@ -43,7 +43,7 @@ @Slf4j public class MediationProtocol extends TradeProtocol { - enum DisputeEvent implements TradeProtocol.Event { + enum DisputeEvent implements FluentProtocol.Event { MEDIATION_RESULT_ACCEPTED, MEDIATION_RESULT_REJECTED } @@ -171,7 +171,7 @@ private void handle(PeerPublishedDelayedPayoutTxMessage message, NodeAddress pee /////////////////////////////////////////////////////////////////////////////////////////// @Override - protected void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer) { + protected void onTradeMessage(TradeMessage message, NodeAddress peer) { if (message instanceof MediatedPayoutTxSignatureMessage) { handle((MediatedPayoutTxSignatureMessage) message, peer); } else if (message instanceof MediatedPayoutTxPublishedMessage) { @@ -182,13 +182,14 @@ protected void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer) } @Override - protected void doApplyMailboxTradeMessage(TradeMessage tradeMessage, NodeAddress peerNodeAddress) { - if (tradeMessage instanceof MediatedPayoutTxSignatureMessage) { - handle((MediatedPayoutTxSignatureMessage) tradeMessage, peerNodeAddress); - } else if (tradeMessage instanceof MediatedPayoutTxPublishedMessage) { - handle((MediatedPayoutTxPublishedMessage) tradeMessage, peerNodeAddress); - } else if (tradeMessage instanceof PeerPublishedDelayedPayoutTxMessage) { - handle((PeerPublishedDelayedPayoutTxMessage) tradeMessage, peerNodeAddress); + protected void onMailboxMessage(TradeMessage message, NodeAddress peer) { + super.onMailboxMessage(message, peer); + if (message instanceof MediatedPayoutTxSignatureMessage) { + handle((MediatedPayoutTxSignatureMessage) message, peer); + } else if (message instanceof MediatedPayoutTxPublishedMessage) { + handle((MediatedPayoutTxPublishedMessage) message, peer); + } else if (message instanceof PeerPublishedDelayedPayoutTxMessage) { + handle((PeerPublishedDelayedPayoutTxMessage) message, peer); } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index 14441ab1b6c..e4df57ce96d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -140,8 +140,8 @@ public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandl /////////////////////////////////////////////////////////////////////////////////////////// @Override - protected void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer) { - super.doHandleDecryptedMessage(message, peer); + protected void onTradeMessage(TradeMessage message, NodeAddress peer) { + super.onTradeMessage(message, peer); log.info("Received {} from {} with tradeId {} and uid {}", message.getClass().getSimpleName(), peer, message.getTradeId(), message.getUid()); diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 4d41e06f1ef..8d777a3ab8d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -138,8 +138,8 @@ public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandl /////////////////////////////////////////////////////////////////////////////////////////// @Override - protected void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer) { - super.doHandleDecryptedMessage(message, peer); + protected void onTradeMessage(TradeMessage message, NodeAddress peer) { + super.onTradeMessage(message, peer); log.info("Received {} from {} with tradeId {} and uid {}", message.getClass().getSimpleName(), peer, message.getTradeId(), message.getUid()); diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java index c066be9cb9d..0927a453f5b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java @@ -45,7 +45,7 @@ @Slf4j public abstract class SellerProtocol extends MediationProtocol { - enum SellerEvent implements TradeProtocol.Event { + enum SellerEvent implements FluentProtocol.Event { PAYMENT_RECEIVED } @@ -59,8 +59,8 @@ public SellerProtocol(SellerTrade trade) { /////////////////////////////////////////////////////////////////////////////////////////// @Override - public void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peerNodeAddress) { - super.doApplyMailboxTradeMessage(message, peerNodeAddress); + public void onMailboxMessage(TradeMessage message, NodeAddress peerNodeAddress) { + super.onMailboxMessage(message, peerNodeAddress); if (message instanceof CounterCurrencyTransferStartedMessage) { handle((CounterCurrencyTransferStartedMessage) message, peerNodeAddress); @@ -146,8 +146,8 @@ public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandl @Override - protected void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer) { - super.doHandleDecryptedMessage(message, peer); + protected void onTradeMessage(TradeMessage message, NodeAddress peer) { + super.onTradeMessage(message, peer); log.info("Received {} from {} with tradeId {} and uid {}", message.getClass().getSimpleName(), peer, message.getTradeId(), message.getUid()); diff --git a/core/src/main/java/bisq/core/trade/protocol/TakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TakerProtocol.java index a3d15c69b00..249d0ac73bd 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TakerProtocol.java @@ -20,7 +20,7 @@ public interface TakerProtocol { void onTakeOffer(); - enum TakerEvent implements TradeProtocol.Event { + enum TakerEvent implements FluentProtocol.Event { TAKE_OFFER } } diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index 29545bd0bcf..84fbb4af623 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -17,7 +17,6 @@ package bisq.core.trade.protocol; -import bisq.core.trade.MakerTrade; import bisq.core.trade.Trade; import bisq.core.trade.TradeManager; import bisq.core.trade.messages.CounterCurrencyTransferStartedMessage; @@ -38,34 +37,14 @@ import bisq.common.proto.network.NetworkEnvelope; import bisq.common.taskrunner.Task; -import javafx.beans.value.ChangeListener; - -import java.security.PublicKey; - -import java.util.HashSet; -import java.util.Set; - -import lombok.Getter; import lombok.extern.slf4j.Slf4j; import javax.annotation.Nullable; -import static bisq.core.util.Validator.isTradeIdValid; -import static bisq.core.util.Validator.nonEmptyStringOf; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - @Slf4j -public abstract class TradeProtocol { - interface Event { - String name(); - } - - private static final long DEFAULT_TIMEOUT_SEC = 180; +public abstract class TradeProtocol implements DecryptedDirectMessageListener { protected final ProcessModel processModel; - private DecryptedDirectMessageListener decryptedDirectMessageListener; - private ChangeListener stateChangeListener; protected Trade trade; private Timer timeoutTimer; @@ -78,91 +57,113 @@ public TradeProtocol(Trade trade) { this.trade = trade; this.processModel = trade.getProcessModel(); - setupListeners(); + if (!trade.isWithdrawn()) { + processModel.getP2PService().addDecryptedDirectMessageListener(this); + } } /////////////////////////////////////////////////////////////////////////////////////////// // API /////////////////////////////////////////////////////////////////////////////////////////// - public void completed() { + + public void onWithdrawCompleted() { cleanup(); } - public void applyMailboxMessage(DecryptedMessageWithPubKey decryptedMessageWithPubKey, Trade trade) { - NetworkEnvelope networkEnvelope = decryptedMessageWithPubKey.getNetworkEnvelope(); - if (processModel.getTradingPeer().getPubKeyRing() != null && - decryptedMessageWithPubKey.getSignaturePubKey().equals(processModel.getTradingPeer().getPubKeyRing().getSignaturePubKey())) { - processModel.setDecryptedMessageWithPubKey(decryptedMessageWithPubKey); - - if (networkEnvelope instanceof MailboxMessage && networkEnvelope instanceof TradeMessage) { - this.trade = trade; - TradeMessage message = (TradeMessage) networkEnvelope; + public void applyMailboxMessage(DecryptedMessageWithPubKey message) { + if (isPubKeyValid(message)) { + NetworkEnvelope networkEnvelope = message.getNetworkEnvelope(); + if (networkEnvelope instanceof MailboxMessage && + networkEnvelope instanceof TradeMessage) { + processModel.setDecryptedMessageWithPubKey(message); + TradeMessage tradeMessage = (TradeMessage) networkEnvelope; NodeAddress peerNodeAddress = ((MailboxMessage) networkEnvelope).getSenderNodeAddress(); - doApplyMailboxTradeMessage(message, peerNodeAddress); + onMailboxMessage(tradeMessage, peerNodeAddress); } - } else { - log.error("SignaturePubKey in message does not match the SignaturePubKey we have stored to that trading peer."); } } + protected void onMailboxMessage(TradeMessage message, NodeAddress peerNodeAddress) { + log.info("Received {} as MailboxMessage from {} with tradeId {} and uid {}", + message.getClass().getSimpleName(), peerNodeAddress, message.getTradeId(), message.getUid()); + } + /////////////////////////////////////////////////////////////////////////////////////////// - // Abstract + // DecryptedDirectMessageListener /////////////////////////////////////////////////////////////////////////////////////////// - protected abstract void doHandleDecryptedMessage(TradeMessage message, NodeAddress peer); + + @Override + public void onDirectMessage(DecryptedMessageWithPubKey message, NodeAddress peer) { + if (isPubKeyValid(message)) { + NetworkEnvelope networkEnvelope = message.getNetworkEnvelope(); + if (networkEnvelope instanceof TradeMessage) { + onTradeMessage((TradeMessage) networkEnvelope, peer); + } else if (networkEnvelope instanceof AckMessage) { + onAckMessage((AckMessage) networkEnvelope, peer); + } + } + } /////////////////////////////////////////////////////////////////////////////////////////// - // Protected + // Abstract /////////////////////////////////////////////////////////////////////////////////////////// - protected void doApplyMailboxTradeMessage(TradeMessage message, NodeAddress peerNodeAddress) { - log.info("Received {} as MailboxMessage from {} with tradeId {} and uid {}", - message.getClass().getSimpleName(), peerNodeAddress, message.getTradeId(), message.getUid()); - } + protected abstract void onTradeMessage(TradeMessage message, NodeAddress peer); - protected void startTimeout() { - startTimeout(DEFAULT_TIMEOUT_SEC); - } - protected void startTimeout(long timeoutSec) { - stopTimeout(); + /////////////////////////////////////////////////////////////////////////////////////////// + // FluentProtocol + /////////////////////////////////////////////////////////////////////////////////////////// - timeoutTimer = UserThread.runAfter(() -> { - log.error("Timeout reached. TradeID={}, state={}, timeoutSec={}", - trade.getId(), trade.stateProperty().get(), timeoutSec); - trade.setErrorMessage("Timeout reached. Protocol did not complete in " + timeoutSec + " sec."); - cleanupTradeOnFault(); - cleanup(); - }, timeoutSec); + protected FluentProtocol given(FluentProtocol.Condition condition) { + return new FluentProtocol(this).condition(condition); } - protected void stopTimeout() { - if (timeoutTimer != null) { - timeoutTimer.stop(); - timeoutTimer = null; - } + protected FluentProtocol.Condition phase(Trade.Phase expectedPhase) { + return new FluentProtocol.Condition(trade).phase(expectedPhase); } - protected void handleTaskRunnerSuccess(TradeMessage message) { - handleTaskRunnerSuccess(message, null); + protected FluentProtocol.Condition anyPhase(Trade.Phase... expectedPhases) { + return new FluentProtocol.Condition(trade).anyPhase(expectedPhases); } - protected void handleTaskRunnerSuccess(Event event) { - handleTaskRunnerSuccess(null, event.name()); + @SafeVarargs + public final FluentProtocol.Setup tasks(Class>... tasks) { + return new FluentProtocol.Setup(this, trade).tasks(tasks); } - protected void sendAckMessage(@Nullable TradeMessage message, boolean result, @Nullable String errorMessage) { - // We complete at initial protocol setup with the setup listener tasks. - // Other cases are if we start from an UI event the task runner (payment started, confirmed). - // In such cases we have not set any message and we ignore the sendAckMessage call. - if (message == null) - return; + /////////////////////////////////////////////////////////////////////////////////////////// + // ACK msg + /////////////////////////////////////////////////////////////////////////////////////////// + + private void onAckMessage(AckMessage ackMessage, NodeAddress peer) { + if (ackMessage.getSourceType() == AckMessageSourceType.TRADE_MESSAGE && + ackMessage.getSourceId().equals(trade.getId())) { + // We handle the ack for CounterCurrencyTransferStartedMessage and DepositTxAndDelayedPayoutTxMessage + // as we support automatic re-send of the msg in case it was not ACKed after a certain time + if (ackMessage.getSourceMsgClassName().equals(CounterCurrencyTransferStartedMessage.class.getSimpleName())) { + processModel.setPaymentStartedAckMessage(ackMessage); + } else if (ackMessage.getSourceMsgClassName().equals(DepositTxAndDelayedPayoutTxMessage.class.getSimpleName())) { + processModel.setDepositTxSentAckMessage(ackMessage); + } + + if (ackMessage.isSuccess()) { + log.info("Received AckMessage for {} from {} with tradeId {} and uid {}", + ackMessage.getSourceMsgClassName(), peer, trade.getId(), ackMessage.getSourceUid()); + } else { + log.warn("Received AckMessage with error state for {} from {} with tradeId {} and errorMessage={}", + ackMessage.getSourceMsgClassName(), peer, trade.getId(), ackMessage.getErrorMessage()); + } + } + } + + protected void sendAckMessage(TradeMessage message, boolean result, @Nullable String errorMessage) { String tradeId = message.getTradeId(); String sourceUid = message.getUid(); - AckMessage ackMessage = new AckMessage(processModel.getMyNodeAddress(), AckMessageSourceType.TRADE_MESSAGE, message.getClass().getSimpleName(), @@ -203,370 +204,116 @@ public void onFault(String errorMessage) { ); } + /////////////////////////////////////////////////////////////////////////////////////////// - // Private + // Timeout /////////////////////////////////////////////////////////////////////////////////////////// - private void setupListeners() { - decryptedDirectMessageListener = (decryptedMessageWithPubKey, peer) -> { - // We check the sig only as soon we have stored the peers pubKeyRing. - PubKeyRing tradingPeerPubKeyRing = processModel.getTradingPeer().getPubKeyRing(); - PublicKey signaturePubKey = decryptedMessageWithPubKey.getSignaturePubKey(); - if (tradingPeerPubKeyRing != null && signaturePubKey.equals(tradingPeerPubKeyRing.getSignaturePubKey())) { - NetworkEnvelope networkEnvelope = decryptedMessageWithPubKey.getNetworkEnvelope(); - if (networkEnvelope instanceof TradeMessage) { - TradeMessage message = (TradeMessage) networkEnvelope; - nonEmptyStringOf(message.getTradeId()); - - if (message.getTradeId().equals(processModel.getOfferId())) { - doHandleDecryptedMessage(message, peer); - } - } else if (networkEnvelope instanceof AckMessage) { - AckMessage ackMessage = (AckMessage) networkEnvelope; - if (ackMessage.getSourceType() == AckMessageSourceType.TRADE_MESSAGE && - ackMessage.getSourceId().equals(trade.getId())) { - // We handle the ack for CounterCurrencyTransferStartedMessage and DepositTxAndDelayedPayoutTxMessage - // as we support automatic re-send of the msg in case it was not ACKed after a certain time - if (ackMessage.getSourceMsgClassName().equals(CounterCurrencyTransferStartedMessage.class.getSimpleName())) { - processModel.setPaymentStartedAckMessage(ackMessage); - } else if (ackMessage.getSourceMsgClassName().equals(DepositTxAndDelayedPayoutTxMessage.class.getSimpleName())) { - processModel.setDepositTxSentAckMessage(ackMessage); - } - - if (ackMessage.isSuccess()) { - log.info("Received AckMessage for {} from {} with tradeId {} and uid {}", - ackMessage.getSourceMsgClassName(), peer, ackMessage.getSourceId(), ackMessage.getSourceUid()); - } else { - log.warn("Received AckMessage with error state for {} from {} with tradeId {} and errorMessage={}", - ackMessage.getSourceMsgClassName(), peer, ackMessage.getSourceId(), ackMessage.getErrorMessage()); - } - } - } - } - }; - processModel.getP2PService().addDecryptedDirectMessageListener(decryptedDirectMessageListener); - - //todo move - stateChangeListener = (observable, oldValue, newValue) -> { - if (newValue.getPhase() == Trade.Phase.TAKER_FEE_PUBLISHED && trade instanceof MakerTrade) - processModel.getOpenOfferManager().closeOpenOffer(checkNotNull(trade.getOffer())); - }; - trade.stateProperty().addListener(stateChangeListener); - } - - - private void handleTaskRunnerSuccess(@Nullable TradeMessage message, @Nullable String trigger) { - String triggerEvent = trigger != null ? trigger : - message != null ? message.getClass().getSimpleName() : "N/A"; - log.info("TaskRunner successfully completed. {}", "Triggered from message " + triggerEvent); - - sendAckMessage(message, true, null); - } - - protected void handleTaskRunnerFault(@Nullable TradeMessage message, String errorMessage) { - log.error("Task runner failed on {} with error {}", message, errorMessage); - - sendAckMessage(message, false, errorMessage); - - cleanupTradeOnFault(); - cleanup(); - } - - protected void handleTaskRunnerFault(@Nullable Event event, String errorMessage) { - log.error("Task runner failed on {} with error {}", event, errorMessage); - - cleanupTradeOnFault(); - cleanup(); - } - - private void cleanup() { + protected void startTimeout(long timeoutSec) { stopTimeout(); - trade.stateProperty().removeListener(stateChangeListener); - // We removed that from here earlier as it broke the trade process in some non critical error cases. - // But it should be actually removed... - processModel.getP2PService().removeDecryptedDirectMessageListener(decryptedDirectMessageListener); + + timeoutTimer = UserThread.runAfter(() -> { + log.error("Timeout reached. TradeID={}, state={}, timeoutSec={}", + trade.getId(), trade.stateProperty().get(), timeoutSec); + trade.setErrorMessage("Timeout reached. Protocol did not complete in " + timeoutSec + " sec."); + cleanupTradeOnFault(); + }, timeoutSec); } - private void cleanupTradeOnFault() { - Trade.State state = trade.getState(); - log.warn("cleanupTradableOnFault tradeState={}", state); - TradeManager tradeManager = processModel.getTradeManager(); - if (trade.isInPreparation()) { - // no funds left. we just clean up the trade list - tradeManager.removePreparedTrade(trade); - } else if (!trade.isFundsLockedIn()) { - if (processModel.getPreparedDepositTx() == null) { - if (trade.isTakerFeePublished()) { - tradeManager.addTradeToFailedTrades(trade); - } else { - tradeManager.addTradeToClosedTrades(trade); - } - } else { - log.error("We have already sent the prepared deposit tx to the peer but we did not received the reply " + - "about the deposit tx nor saw it in the network. tradeId={}, tradeState={}", trade.getId(), trade.getState()); - } + protected void stopTimeout() { + if (timeoutTimer != null) { + timeoutTimer.stop(); + timeoutTimer = null; } } /////////////////////////////////////////////////////////////////////////////////////////// - // FluentProtocol + // Task runner /////////////////////////////////////////////////////////////////////////////////////////// - protected FluentProtocol given(Condition condition) { - return new FluentProtocol(condition); + protected void handleTaskRunnerSuccess(TradeMessage message) { + handleTaskRunnerSuccess(message, message.getClass().getSimpleName()); } - protected Condition phase(Trade.Phase expectedPhase) { - return new Condition(trade, expectedPhase); + protected void handleTaskRunnerSuccess(FluentProtocol.Event event) { + handleTaskRunnerSuccess(null, event.name()); } - protected Condition anyPhase(Trade.Phase... expectedPhases) { - return new Condition(trade, expectedPhases); + protected void handleTaskRunnerFault(TradeMessage message, String errorMessage) { + handleTaskRunnerFault(message, message.getClass().getSimpleName(), errorMessage); } - @SafeVarargs - public final Setup tasks(Class>... tasks) { - return new Setup(trade, tasks); + protected void handleTaskRunnerFault(FluentProtocol.Event event, String errorMessage) { + handleTaskRunnerFault(null, event.name(), errorMessage); } - // Main class. Contains the condition and setup, if condition is valid it will execute the - // taskRunner and the optional runnable. - class FluentProtocol { - private final Condition condition; - private Setup setup; - - public FluentProtocol(Condition condition) { - this.condition = condition; - } - - protected FluentProtocol setup(Setup setup) { - this.setup = setup; - return this; - } - - // Can be used before or after executeTasks - public FluentProtocol run(Runnable runnable) { - if (condition.isValid()) { - runnable.run(); - } - return this; - } - - public FluentProtocol executeTasks() { - if (condition.isValid()) { - if (setup.getTimeoutSec() > 0) { - startTimeout(setup.getTimeoutSec()); - } - NodeAddress peer = condition.getPeer(); - if (peer != null) { - processModel.setTempTradingPeerNodeAddress(peer); - } + /////////////////////////////////////////////////////////////////////////////////////////// + // Validation + /////////////////////////////////////////////////////////////////////////////////////////// - TradeMessage message = condition.getMessage(); - if (message != null) { - processModel.setTradeMessage(message); - } - TradeTaskRunner taskRunner = setup.getTaskRunner(message, condition.getEvent()); - taskRunner.addTasks(setup.getTasks()); - taskRunner.run(); - } - return this; + private boolean isPubKeyValid(DecryptedMessageWithPubKey message) { + // We can only validate the peers pubKey if we have it already. If we are the taker we get it from the offer + // Otherwise it depends on the state of the trade protocol if we have received the peers pubKeyRing already. + PubKeyRing peersPubKeyRing = processModel.getTradingPeer().getPubKeyRing(); + boolean isValid = true; + if (peersPubKeyRing != null && + !message.getSignaturePubKey().equals(peersPubKeyRing.getSignaturePubKey())) { + isValid = false; + log.error("SignaturePubKey in message does not match the SignaturePubKey we have set for our trading peer."); } + return isValid; } - // - static class Condition { - private final Trade trade; - @Nullable - @Getter - private TradeMessage message; - private final Set expectedPhases = new HashSet<>(); - private final Set expectedStates = new HashSet<>(); - private final Set preConditions = new HashSet<>(); - @Nullable - @Getter - private Event event; - @Getter - private NodeAddress peer; - private boolean isValid; - private boolean isValidated; - private Runnable preConditionFailedHandler; - - public Condition(Trade trade, Trade.Phase expectedPhase) { - this.expectedPhases.add(expectedPhase); - this.trade = trade; - } - - public Condition(Trade trade, Trade.Phase... expectedPhases) { - this.expectedPhases.addAll(Set.of(expectedPhases)); - this.trade = trade; - } - public Condition state(Trade.State state) { - this.expectedStates.add(state); - return this; - } - - public Condition anyState(Trade.State... states) { - this.expectedStates.addAll(Set.of(states)); - return this; - } - - public Condition with(Event event) { - checkArgument(!isValidated); - this.event = event; - return this; - } - - public Condition with(TradeMessage message) { - checkArgument(!isValidated); - this.message = message; - return this; - } - - public Condition from(NodeAddress peer) { - checkArgument(!isValidated); - this.peer = peer; - return this; - } - - public Condition preCondition(boolean preCondition) { - checkArgument(!isValidated); - preConditions.add(preCondition); - return this; - } - - public Condition preCondition(boolean preCondition, Runnable conditionFailedHandler) { - checkArgument(!isValidated); - preConditions.add(preCondition); - this.preConditionFailedHandler = conditionFailedHandler; - return this; - } - - private boolean isValid() { - if (!isValidated) { - boolean isPhaseValid = isPhaseValid(); - boolean isStateValid = isStateValid(); - - boolean allPreConditionsMet = preConditions.stream().allMatch(e -> e); - boolean isTradeIdValid = message == null || isTradeIdValid(trade.getId(), message); - - if (!allPreConditionsMet) { - log.error("PreConditions not met. preConditions={}, this={}", preConditions, this); - if (preConditionFailedHandler != null) { - preConditionFailedHandler.run(); - } - } - if (!isTradeIdValid) { - log.error("TradeId does not match tradeId in message, TradeId={}, tradeId in message={}", - trade.getId(), message.getTradeId()); - } + /////////////////////////////////////////////////////////////////////////////////////////// + // Private + /////////////////////////////////////////////////////////////////////////////////////////// - isValid = isPhaseValid && isStateValid && allPreConditionsMet && isTradeIdValid; - isValidated = true; - } - return isValid; + private void handleTaskRunnerSuccess(@Nullable TradeMessage message, String source) { + log.info("TaskRunner successfully completed. Triggered from {}", source); + if (message != null) { + sendAckMessage(message, true, null); } + } - private boolean isPhaseValid() { - if (expectedPhases.isEmpty()) { - return true; - } - - boolean isPhaseValid = expectedPhases.stream().anyMatch(e -> e == trade.getPhase()); - String trigger = message != null ? - message.getClass().getSimpleName() : - event != null ? - event.name() + " event" : - ""; - if (isPhaseValid) { - log.info("We received {} at phase {} and state {}", - trigger, - trade.getPhase(), - trade.getState()); - } else { - log.error("We received {} but we are are not in the correct phase. Expected phases={}, " + - "Trade phase={}, Trade state= {} ", - trigger, - expectedPhases, - trade.getPhase(), - trade.getState()); - } + private void handleTaskRunnerFault(@Nullable TradeMessage message, String source, String errorMessage) { + log.error("Task runner failed with error {}. Triggered from {}", errorMessage, source); - return isPhaseValid; - } - - private boolean isStateValid() { - if (expectedStates.isEmpty()) { - return true; - } - - boolean isStateValid = expectedStates.stream().anyMatch(e -> e == trade.getState()); - String trigger = message != null ? - message.getClass().getSimpleName() : - event != null ? - event.name() + " event" : - ""; - if (isStateValid) { - log.info("We received {} at state {}", - trigger, - trade.getState()); - } else { - log.error("We received {} but we are are not in the correct state. Expected states={}, " + - "Trade state= {} ", - trigger, - expectedStates, - trade.getState()); - } - - return isStateValid; + if (message != null) { + sendAckMessage(message, false, errorMessage); } + cleanupTradeOnFault(); } - // Setup for task runner - class Setup { - private final Trade trade; - @Getter - private final Class>[] tasks; - @Getter - private int timeoutSec; - @Nullable - private TradeTaskRunner taskRunner; - - @SafeVarargs - public Setup(Trade trade, Class>... tasks) { - this.trade = trade; - this.tasks = tasks; - } - public Setup withTimeout(int timeoutSec) { - this.timeoutSec = timeoutSec; - return this; - } + private void cleanup() { + stopTimeout(); + processModel.getP2PService().removeDecryptedDirectMessageListener(this); + } - public Setup using(TradeTaskRunner taskRunner) { - this.taskRunner = taskRunner; - return this; - } + //todo + private void cleanupTradeOnFault() { + cleanup(); - private TradeTaskRunner getTaskRunner(@Nullable TradeMessage message, @Nullable Event event) { - if (taskRunner == null) { - if (message != null) { - taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(message), - errorMessage -> handleTaskRunnerFault(message, errorMessage)); - } else if (event != null) { - taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(event), - errorMessage -> handleTaskRunnerFault(event, errorMessage)); + log.warn("cleanupTradableOnFault tradeState={}", trade.getState()); + TradeManager tradeManager = processModel.getTradeManager(); + if (trade.isInPreparation()) { + // no funds left. we just clean up the trade list + tradeManager.removePreparedTrade(trade); + } else if (!trade.isFundsLockedIn()) { + // No deposit tx published yet + if (processModel.getPreparedDepositTx() == null) { + if (trade.isTakerFeePublished()) { + tradeManager.addTradeToFailedTrades(trade); } else { - throw new IllegalStateException("addTasks must not be called without message or event " + - "set in case no taskRunner has been created yet"); + tradeManager.addTradeToClosedTrades(trade); } + } else { + log.error("We have already sent the prepared deposit tx to the peer but we did not received the reply " + + "about the deposit tx nor saw it in the network. tradeId={}, tradeState={}", trade.getId(), trade.getState()); } - return taskRunner; } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java index 8831d8eab00..92b63bae0c7 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java @@ -90,6 +90,11 @@ protected void run() { trade.setState(Trade.State.MAKER_SENT_PUBLISH_DEPOSIT_TX_REQUEST); + // We could consider to remove the offer later once the deposit is published to reduce the risk + // of lost maker fee in case of a failed trade. The protocol has not maker specific tasks at that moment on + // so it would require a bit of extra work to add that (without using instance of checks...). + processModel.getOpenOfferManager().closeOpenOffer(checkNotNull(trade.getOffer())); + NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress(); log.info("Send {} to peer {}. tradeId={}, uid={}", message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); From f6eefef1ae13dafed8fb965bd6c2426d4008d27b Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Thu, 24 Sep 2020 19:47:12 -0500 Subject: [PATCH 060/143] Remove handling of failed trades. If a trade is in an invalid state (tx missing) or has an error message set we show in the pending trades view a red trash icon for moving the trade to failed trades. The info icon next to the trade ID is then a warning icon (should be red but css is not my best friend) and if opening trade details window we also color the missing txs red with a warn icon and tooltip. When clicking the trash button a popup is displayed with detail info. At failed trades there is a "undo" icon for reverting the trade back to pending (if user wants to open mediation, etc). All the automatic handling of the failed trades and popups are removed as it never worked well and just confused users... In next commits we will add more instructions what a user should/can do for diff. error cases. TradeManger: - Remove all the failed checks at initPendingTrade. - Remove tradesWithoutDepositTx - Remove tradesForStatistics as it was never read - Remove cleanUpAddressEntries - Rename addTradeToClosedTrades to onTradeCompleted TxIdTextField accepts a null for tx ID and shows then red colored N/A and a warning icon. HyperlinkWithIcon exposed the icon to be accessible for style change. DebugWindow was updated for one variation of the trade protocol (other is missing still). Trade detail window show now always all 4 mandatory txs. Beside that this commit has some cleanups and null pointer fixes (when testing error scenarios i got those NP). --- .../witness/AccountAgeWitnessService.java | 7 +- .../main/java/bisq/core/app/BisqSetup.java | 1 - .../core/btc/wallet/TradeWalletService.java | 1 - .../dispute/mediation/MediationManager.java | 4 +- core/src/main/java/bisq/core/trade/Trade.java | 34 ++-- .../java/bisq/core/trade/TradeManager.java | 120 +++----------- .../trade/failed/FailedTradesManager.java | 7 +- .../core/trade/protocol/TradeProtocol.java | 37 ++--- .../resources/i18n/displayStrings.properties | 27 +++- desktop/src/main/java/bisq/desktop/bisq.css | 16 ++ .../desktop/components/HyperlinkWithIcon.java | 5 + .../desktop/components/TxIdTextField.java | 34 +++- .../java/bisq/desktop/main/MainViewModel.java | 16 -- .../bisq/desktop/main/debug/DebugView.java | 52 +++++- .../main/funds/withdrawal/WithdrawalView.java | 5 +- .../overlays/windows/TradeDetailsWindow.java | 18 +-- .../failedtrades/FailedTradesDataModel.java | 10 +- .../failedtrades/FailedTradesView.fxml | 1 + .../failedtrades/FailedTradesView.java | 61 ++++++- .../pendingtrades/PendingTradesDataModel.java | 9 +- .../pendingtrades/PendingTradesView.fxml | 1 + .../pendingtrades/PendingTradesView.java | 150 +++++++++++++----- .../pendingtrades/steps/TradeStepView.java | 1 - .../steps/buyer/BuyerStep4View.java | 4 +- .../java/bisq/network/p2p/P2PService.java | 5 + 25 files changed, 375 insertions(+), 251 deletions(-) diff --git a/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java index ab8ad18e179..1aeed551502 100644 --- a/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java +++ b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java @@ -267,8 +267,11 @@ private Optional findWitness(Offer offer) { private Optional findTradePeerWitness(Trade trade) { TradingPeer tradingPeer = trade.getProcessModel().getTradingPeer(); - return (tradingPeer.getPaymentAccountPayload() == null || tradingPeer.getPubKeyRing() == null) ? - Optional.empty() : findWitness(tradingPeer.getPaymentAccountPayload(), tradingPeer.getPubKeyRing()); + return (tradingPeer == null || + tradingPeer.getPaymentAccountPayload() == null || + tradingPeer.getPubKeyRing() == null) ? + Optional.empty() : + findWitness(tradingPeer.getPaymentAccountPayload(), tradingPeer.getPubKeyRing()); } private Optional getWitnessByHash(byte[] hash) { diff --git a/core/src/main/java/bisq/core/app/BisqSetup.java b/core/src/main/java/bisq/core/app/BisqSetup.java index 3577f386583..b6889f93daa 100644 --- a/core/src/main/java/bisq/core/app/BisqSetup.java +++ b/core/src/main/java/bisq/core/app/BisqSetup.java @@ -767,7 +767,6 @@ private void initDomainServices() { rejectedTxErrorMessageHandler.accept(Res.get("popup.warning.trade.txRejected", finalDetails, trade.getShortId(), txId)); } - tradeManager.addTradeToFailedTrades(trade); }, 1); } }); diff --git a/core/src/main/java/bisq/core/btc/wallet/TradeWalletService.java b/core/src/main/java/bisq/core/btc/wallet/TradeWalletService.java index 875dbbb2711..7b004d0e84a 100644 --- a/core/src/main/java/bisq/core/btc/wallet/TradeWalletService.java +++ b/core/src/main/java/bisq/core/btc/wallet/TradeWalletService.java @@ -61,7 +61,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Objects; import java.util.stream.Collectors; import org.slf4j.Logger; diff --git a/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java b/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java index ce94b2f3e32..10ded4ead7d 100644 --- a/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java +++ b/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java @@ -37,8 +37,8 @@ import bisq.core.trade.Trade; import bisq.core.trade.TradeManager; import bisq.core.trade.closed.ClosedTradableManager; +import bisq.core.trade.protocol.MediationProtocol; import bisq.core.trade.protocol.ProcessModel; -import bisq.core.trade.protocol.TradeProtocol; import bisq.network.p2p.AckMessageSourceType; import bisq.network.p2p.NodeAddress; @@ -234,7 +234,7 @@ public void acceptMediationResult(Trade trade, ProcessModel processModel = trade.getProcessModel(); processModel.setBuyerPayoutAmountFromMediation(buyerPayoutAmount.value); processModel.setSellerPayoutAmountFromMediation(sellerPayoutAmount.value); - TradeProtocol tradeProtocol = trade.getTradeProtocol(); + MediationProtocol tradeProtocol = (MediationProtocol) trade.getTradeProtocol(); trade.setMediationResultState(MediationResultState.MEDIATION_RESULT_ACCEPTED); diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index 8196ac39464..e8b8acb12b3 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -403,6 +403,8 @@ public static protobuf.Trade.TradePeriodState toProtoMessage(Trade.TradePeriodSt transient protected TradeProtocol tradeProtocol; @Nullable transient private Transaction depositTx; + @Getter + transient private boolean isInitialized; // Added in v1.2.0 @Nullable @@ -704,6 +706,8 @@ public void init(P2PService p2PService, // Clone to avoid ConcurrentModificationException. We remove items at the applyMailboxMessage call... HashSet set = new HashSet<>(decryptedMessageWithPubKeySet); set.forEach(msg -> tradeProtocol.applyMailboxMessage(msg)); + + isInitialized = true; } @@ -744,8 +748,14 @@ public void applyDelayedPayoutTxBytes(byte[] delayedPayoutTxBytes) { @Nullable public Transaction getDelayedPayoutTx() { + return getDelayedPayoutTx(processModel.getBtcWalletService()); + } + + // If called from a not initialized trade (or a closed or failed trade) + // we need to pass the btcWalletService + @Nullable + public Transaction getDelayedPayoutTx(BtcWalletService btcWalletService) { if (delayedPayoutTx == null) { - BtcWalletService btcWalletService = processModel.getBtcWalletService(); if (btcWalletService == null) { log.warn("btcWalletService is null. You might call that method before the tradeManager has " + "initialized all trades"); @@ -944,16 +954,20 @@ public Phase getPhase() { @Nullable public Volume getTradeVolume() { - if (getTradeAmount() != null && getTradePrice() != null) { - Volume volumeByAmount = getTradePrice().getVolumeByAmount(getTradeAmount()); - if (offer != null) { - if (offer.getPaymentMethod().getId().equals(PaymentMethod.HAL_CASH_ID)) - volumeByAmount = OfferUtil.getAdjustedVolumeForHalCash(volumeByAmount); - else if (CurrencyUtil.isFiatCurrency(offer.getCurrencyCode())) - volumeByAmount = OfferUtil.getRoundedFiatVolume(volumeByAmount); + try { + if (getTradeAmount() != null && getTradePrice() != null) { + Volume volumeByAmount = getTradePrice().getVolumeByAmount(getTradeAmount()); + if (offer != null) { + if (offer.getPaymentMethod().getId().equals(PaymentMethod.HAL_CASH_ID)) + volumeByAmount = OfferUtil.getAdjustedVolumeForHalCash(volumeByAmount); + else if (CurrencyUtil.isFiatCurrency(offer.getCurrencyCode())) + volumeByAmount = OfferUtil.getRoundedFiatVolume(volumeByAmount); + } + return volumeByAmount; + } else { + return null; } - return volumeByAmount; - } else { + } catch (Throwable ignore) { return null; } } diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 58137b053ca..fc54866f089 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -82,15 +82,12 @@ import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleLongProperty; -import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import org.bouncycastle.crypto.params.KeyParameter; -import java.util.ArrayList; import java.util.Date; -import java.util.List; import java.util.Optional; import java.util.Set; import java.util.UUID; @@ -137,14 +134,11 @@ public class TradeManager implements PersistedDataHost { private TradableList tradableList; @Getter private final BooleanProperty pendingTradesInitialized = new SimpleBooleanProperty(); - private List tradesForStatistics; @Setter @Nullable private ErrorMessageHandler takeOfferRequestErrorMessageHandler; @Getter private final LongProperty numPendingTrades = new SimpleLongProperty(); - @Getter - private final ObservableList tradesWithoutDepositTx = FXCollections.observableArrayList(); private final DumpDelayedPayoutTx dumpDelayedPayoutTx; @Getter private final boolean allowFaultyDelayedTxs; @@ -283,65 +277,16 @@ public void shutDown() { } private void initPendingTrades() { - List addTradeToFailedTradesList = new ArrayList<>(); - List removePreparedTradeList = new ArrayList<>(); - tradesForStatistics = new ArrayList<>(); - tradableList.forEach(trade -> { - if (trade.isDepositPublished() || - (trade.isTakerFeePublished() && !trade.hasFailed())) { - initPendingTrade(trade); - } else if (trade.isTakerFeePublished() && !trade.isFundsLockedIn()) { - addTradeToFailedTradesList.add(trade); - trade.appendErrorMessage("Invalid state: trade.isTakerFeePublished() && !trade.isFundsLockedIn()"); - } else { - removePreparedTradeList.add(trade); - } - - if (trade.getDepositTx() == null) { - log.warn("Deposit tx for trader with ID {} is null at initPendingTrades. " + - "This can happen for valid transaction in rare cases (e.g. after a SPV resync). " + - "We leave it to the user to move the trade to failed trades if the problem persists.", - trade.getId()); - tradesWithoutDepositTx.add(trade); - } - - try { - TradeDataValidation.validatePayoutTx(trade, - trade.getDelayedPayoutTx(), - daoFacade, - btcWalletService); - } catch (TradeDataValidation.ValidationException e) { - log.warn("Delayed payout tx exception, trade {}, exception {}", trade.getId(), e.getMessage()); - if (!allowFaultyDelayedTxs) { - // We move it to failed trades so it cannot be continued. - log.warn("We move the trade with ID '{}' to failed trades", trade.getId()); - addTradeToFailedTradesList.add(trade); - } - } - } - ); - - // If we have a closed trade where the deposit tx is still not confirmed we move it to failed trades as the - // payout tx cannot be valid as well in this case. As the trade do not progress without confirmation of the - // deposit tx this should normally not happen. If we detect such a trade at start up (done in BisqSetup) we - // show a popup telling the user to do a SPV resync. - closedTradableManager.getClosedTradables().stream() - .filter(tradable -> tradable instanceof Trade) - .map(tradable -> (Trade) tradable) - .filter(Trade::isFundsLockedIn) - .forEach(addTradeToFailedTradesList::add); - - addTradeToFailedTradesList.forEach(closedTradableManager::remove); - - addTradeToFailedTradesList.forEach(this::addTradeToFailedTrades); - - removePreparedTradeList.forEach(this::removePreparedTrade); - - cleanUpAddressEntries(); - + tradableList.forEach(this::initPendingTrade); pendingTradesInitialized.set(true); } + private void initPendingTrade(Trade trade) { + initTrade(trade, trade.getProcessModel().isUseSavingsWallet(), + trade.getProcessModel().getFundsNeededForTrade()); + + trade.updateDepositTxFromWallet(); + } public void onUserConfirmedFiatPaymentReceived(SellerTrade sellerTrade, ResultHandler resultHandler, @@ -349,32 +294,10 @@ public void onUserConfirmedFiatPaymentReceived(SellerTrade sellerTrade, sellerTrade.onFiatPaymentReceived(resultHandler, errorMessageHandler); } - private void initPendingTrade(Trade trade) { - initTrade(trade, trade.getProcessModel().isUseSavingsWallet(), - trade.getProcessModel().getFundsNeededForTrade()); - trade.updateDepositTxFromWallet(); - tradesForStatistics.add(trade); - } - private void onTradesChanged() { this.numPendingTrades.set(tradableList.getList().size()); } - private void cleanUpAddressEntries() { - // We check if we have address entries which are not in our pending trades and clean up those entries. - // They might be either from closed or failed trades or from trades we do not have at all in our data base files. - Set activeTrades = getTradableList().stream() - .map(Tradable::getId) - .collect(Collectors.toSet()); - - btcWalletService.getAddressEntriesForTrade().stream() - .filter(e -> !activeTrades.contains(e.getOfferId())) - .forEach(e -> { - log.warn("We found an outdated addressEntry for trade {}: entry={}", e.getOfferId(), e); - btcWalletService.resetAddressEntriesForPendingTrade(e.getOfferId()); - }); - } - private void handlePayDepositRequest(InputsForDepositTxRequest inputsForDepositTxRequest, NodeAddress peer) { log.info("Received PayDepositRequest from {} with tradeId {} and uid {}", peer, inputsForDepositTxRequest.getTradeId(), inputsForDepositTxRequest.getUid()); @@ -421,8 +344,6 @@ private void handlePayDepositRequest(InputsForDepositTxRequest inputsForDepositT }); } else { // TODO respond - //(RequestDepositTxInputsMessage)message. - // messageService.sendEncryptedMessage(peerAddress,messageWithPubKey.getMessage().); log.debug("We received a take offer request but don't have that offer anymore."); } } @@ -581,7 +502,7 @@ public void onWithdrawRequest(String toAddress, Coin amount, Coin fee, KeyParame public void onSuccess(@javax.annotation.Nullable Transaction transaction) { if (transaction != null) { log.debug("onWithdraw onSuccess tx ID:" + transaction.getTxId().toString()); - addTradeToClosedTrades(trade); + onTradeCompleted(trade); trade.setState(Trade.State.WITHDRAW_COMPLETED); trade.getTradeProtocol().onWithdrawCompleted(); resultHandler.handleResult(); @@ -605,20 +526,26 @@ public void onFailure(@NotNull Throwable t) { } // If trade was completed (closed without fault but might be closed by a dispute) we move it to the closed trades - public void addTradeToClosedTrades(Trade trade) { + public void onTradeCompleted(Trade trade) { removeTrade(trade); closedTradableManager.add(trade); - cleanUpAddressEntries(); + // TODO The address entry should have been removed already. Check and if its the case remove that. + btcWalletService.resetAddressEntriesForPendingTrade(trade.getId()); } // If trade is in already in critical state (if taker role: taker fee; both roles: after deposit published) // we move the trade to failedTradesManager - public void addTradeToFailedTrades(Trade trade) { + public void moveTradeToFailedTrades(Trade trade) { removeTrade(trade); failedTradesManager.add(trade); + } - cleanUpAddressEntries(); + public void addFailedTradeToPending(Trade trade) { + if (!trade.isInitialized()) { + initPendingTrade(trade); + } + tradableList.add(trade); } // If trade still has funds locked up it might come back from failed trades @@ -652,15 +579,6 @@ private boolean recoverAddresses(Trade trade) { return true; } - - // If trade is in preparation (if taker role: before taker fee is paid; both roles: before deposit published) - // we just remove the trade from our list. We don't store those trades. - public void removePreparedTrade(Trade trade) { - removeTrade(trade); - - cleanUpAddressEntries(); - } - private void removeTrade(Trade trade) { tradableList.remove(trade); } @@ -675,7 +593,7 @@ public void closeDisputedTrade(String tradeId, Trade.DisputeState disputeState) if (tradeOptional.isPresent()) { Trade trade = tradeOptional.get(); trade.setDisputeState(disputeState); - addTradeToClosedTrades(trade); + onTradeCompleted(trade); btcWalletService.swapTradeEntryToAvailableEntry(trade.getId(), AddressEntry.Context.TRADE_PAYOUT); } } diff --git a/core/src/main/java/bisq/core/trade/failed/FailedTradesManager.java b/core/src/main/java/bisq/core/trade/failed/FailedTradesManager.java index ed7b633847e..1d68dfa4531 100644 --- a/core/src/main/java/bisq/core/trade/failed/FailedTradesManager.java +++ b/core/src/main/java/bisq/core/trade/failed/FailedTradesManager.java @@ -26,15 +26,12 @@ import bisq.core.trade.Trade; import bisq.core.trade.TradeUtils; -import bisq.common.config.Config; import bisq.common.crypto.KeyRing; import bisq.common.proto.persistable.PersistedDataHost; import bisq.common.storage.Storage; import com.google.inject.Inject; -import javax.inject.Named; - import javafx.collections.ObservableList; import java.util.Optional; @@ -90,6 +87,10 @@ public void add(Trade trade) { } } + public void removeTrade(Trade trade) { + failedTrades.remove(trade); + } + public boolean wasMyOffer(Offer offer) { return offer.isMyOffer(keyRing); } diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index 84fbb4af623..5b88845737c 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -18,7 +18,6 @@ package bisq.core.trade.protocol; import bisq.core.trade.Trade; -import bisq.core.trade.TradeManager; import bisq.core.trade.messages.CounterCurrencyTransferStartedMessage; import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage; import bisq.core.trade.messages.TradeMessage; @@ -162,6 +161,12 @@ private void onAckMessage(AckMessage ackMessage, NodeAddress peer) { } protected void sendAckMessage(TradeMessage message, boolean result, @Nullable String errorMessage) { + PubKeyRing peersPubKeyRing = processModel.getTradingPeer().getPubKeyRing(); + if (peersPubKeyRing == null) { + log.error("We cannot send the ACK message as peersPubKeyRing is null"); + return; + } + String tradeId = message.getTradeId(); String sourceUid = message.getUid(); AckMessage ackMessage = new AckMessage(processModel.getMyNodeAddress(), @@ -180,7 +185,7 @@ protected void sendAckMessage(TradeMessage message, boolean result, @Nullable St ackMessage.getSourceMsgClassName(), peer, tradeId, sourceUid); processModel.getP2PService().sendEncryptedMailboxMessage( peer, - processModel.getTradingPeer().getPubKeyRing(), + peersPubKeyRing, ackMessage, new SendMailboxMessageListener() { @Override @@ -216,7 +221,7 @@ protected void startTimeout(long timeoutSec) { log.error("Timeout reached. TradeID={}, state={}, timeoutSec={}", trade.getId(), trade.stateProperty().get(), timeoutSec); trade.setErrorMessage("Timeout reached. Protocol did not complete in " + timeoutSec + " sec."); - cleanupTradeOnFault(); + cleanup(); }, timeoutSec); } @@ -284,7 +289,7 @@ private void handleTaskRunnerFault(@Nullable TradeMessage message, String source if (message != null) { sendAckMessage(message, false, errorMessage); } - cleanupTradeOnFault(); + cleanup(); } @@ -292,28 +297,4 @@ private void cleanup() { stopTimeout(); processModel.getP2PService().removeDecryptedDirectMessageListener(this); } - - //todo - private void cleanupTradeOnFault() { - cleanup(); - - log.warn("cleanupTradableOnFault tradeState={}", trade.getState()); - TradeManager tradeManager = processModel.getTradeManager(); - if (trade.isInPreparation()) { - // no funds left. we just clean up the trade list - tradeManager.removePreparedTrade(trade); - } else if (!trade.isFundsLockedIn()) { - // No deposit tx published yet - if (processModel.getPreparedDepositTx() == null) { - if (trade.isTakerFeePublished()) { - tradeManager.addTradeToFailedTrades(trade); - } else { - tradeManager.addTradeToClosedTrades(trade); - } - } else { - log.error("We have already sent the prepared deposit tx to the peer but we did not received the reply " + - "about the deposit tx nor saw it in the network. tradeId={}, tradeState={}", trade.getId(), trade.getState()); - } - } - } } diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index d6084147c9c..a7808dda888 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -831,10 +831,10 @@ portfolio.pending.timeLockNotOver=You have to wait until ≈{0} ({1} more blocks portfolio.pending.error.depositTxNull=The deposit transaction is null. You cannot open a dispute \ without a valid deposit transaction. Please go to \"Settings/Network info\" and do a SPV resync.\n\n\ For further help please contact the Bisq support channel at the Bisq Keybase team. -portfolio.pending.mediationResult.error.depositTxNull=The deposit transaction is null. The trade gets moved to the \ - failed trades section. -portfolio.pending.mediationResult.error.delayedPayoutTxNull=The delayed payout transaction is null. The trade gets \ - moved to the failed trades section. +portfolio.pending.mediationResult.error.depositTxNull=The deposit transaction is null. You can move the \ + trade to the failed trades screen by clicking the trash can icon. +portfolio.pending.mediationResult.error.delayedPayoutTxNull=The delayed payout transaction is null. You can move the \ + trade to the failed trades screen by clicking the trash can icon. portfolio.pending.error.depositTxNotConfirmed=The deposit transaction is not confirmed. You can not open an arbitration dispute \ with an unconfirmed deposit transaction. Please wait until it is confirmed or go to \"Settings/Network info\" and do a SPV resync.\n\n\ For further help please contact the Bisq support channel at the Bisq Keybase team. @@ -904,6 +904,17 @@ portfolio.pending.mediationResult.popup.selfAccepted.lockTimeOver=You have accep portfolio.pending.mediationResult.popup.openArbitration=Reject and request arbitration portfolio.pending.mediationResult.popup.alreadyAccepted=You've already accepted +portfolio.pending.moveToFailed.popup=This trade has an invalid state.\n\n\ + Do you want to move the trade to failed trades?\n\n\ + You cannot open mediation or arbitration from the failed trades view, but you can move it back to the open \ + trades screen any time.\n\n\ + Reason for the invalid trade state:\n{0} +portfolio.pending.moveTradeToFailed=Move trade to failed trades +portfolio.failed.revertToPending.popup=Do you want to move the trade to open trades? +portfolio.failed.revertToPending=Move trade to open trades +trade.error.delayedPayoutTxIsNull=Delayed payout transaction is null +trade.error.depositTxIsNull=Deposit transaction is null + portfolio.closed.completed=Completed portfolio.closed.ticketClosed=Arbitrated portfolio.closed.mediationTicketClosed=Mediated @@ -914,8 +925,8 @@ portfolio.failed.unfail=Before proceeding, make sure you have a backup of your d This is a way to unlock funds stuck in a failed trade. portfolio.failed.cantUnfail=This trade cannot be moved back to pending trades at the moment. \n\ Try again after completion of trade(s) {0} -portfolio.failed.depositTxNull=The trade cannot be reverted to a pending trade. Deposit transaction is null. -portfolio.failed.delayedPayoutTxNull=The trade cannot be reverted to a pending trade. Delayed payout transaction is null. +portfolio.failed.depositTxNull=The trade cannot be reverted to a open trade. Deposit transaction is null. +portfolio.failed.delayedPayoutTxNull=The trade cannot be reverted to a open trade. Delayed payout transaction is null. #################################################################### @@ -2948,6 +2959,7 @@ peerInfoIcon.tooltip.age=Payment account created {0} ago. peerInfoIcon.tooltip.unknownAge=Payment account age not known. tooltip.openPopupForDetails=Open popup for details +tooltip.invalidTradeState.warning=This trade is in an invalid state. Open the details window for more information tooltip.openBlockchainForAddress=Open external blockchain explorer for address: {0} tooltip.openBlockchainForTx=Open external blockchain explorer for transaction: {0} @@ -2972,7 +2984,8 @@ addressTextField.openWallet.failed=Opening a default Bitcoin wallet application peerInfoIcon.tooltip={0}\nTag: {1} txIdTextField.copyIcon.tooltip=Copy transaction ID to clipboard -txIdTextField.blockExplorerIcon.tooltip=Open a blockchain explorer with that transactions ID +txIdTextField.blockExplorerIcon.tooltip=Open a blockchain explorer with that transaction ID +txIdTextField.missingTx.warning.tooltip=Missing required transaction #################################################################### diff --git a/desktop/src/main/java/bisq/desktop/bisq.css b/desktop/src/main/java/bisq/desktop/bisq.css index 114f272eda1..24245a4d4ef 100644 --- a/desktop/src/main/java/bisq/desktop/bisq.css +++ b/desktop/src/main/java/bisq/desktop/bisq.css @@ -85,6 +85,11 @@ -fx-fill: -bs-color-gray-6; } +.error-icon { + -fx-text-fill: -bs-rd-error-red; + -fx-fill: -bs-rd-error-red; +} + .zero-decimals { -fx-text-fill: -bs-color-gray-3; } @@ -903,6 +908,11 @@ textfield */ -fx-fill: -fx-accent; } +.hyperlink.error { + -fx-text-fill: -bs-rd-error-red; + -fx-fill: -bs-rd-error-red; +} + /******************************************************************************* * * * Table * @@ -1393,6 +1403,12 @@ textfield */ -fx-text-fill: -bs-text-color; } +#address-text-field-error { + -fx-cursor: hand; + -fx-text-fill: -bs-rd-error-red; + -fx-prompt-text-fill: -bs-text-color; +} + /* Account setup */ #wizard-item-background-deactivated { -fx-body-color: linear-gradient(to bottom, -bs-content-background-gray, -bs-color-gray-aaa); diff --git a/desktop/src/main/java/bisq/desktop/components/HyperlinkWithIcon.java b/desktop/src/main/java/bisq/desktop/components/HyperlinkWithIcon.java index 8834e001a9f..903d0e6b196 100644 --- a/desktop/src/main/java/bisq/desktop/components/HyperlinkWithIcon.java +++ b/desktop/src/main/java/bisq/desktop/components/HyperlinkWithIcon.java @@ -31,7 +31,11 @@ import javafx.geometry.Insets; +import lombok.Getter; + public class HyperlinkWithIcon extends Hyperlink { + @Getter + private Node icon; public HyperlinkWithIcon(String text) { this(text, AwesomeIcon.INFO_SIGN); @@ -77,6 +81,7 @@ public void hideIcon() { } private void setIcon(Node icon) { + this.icon = icon; setGraphic(icon); setContentDisplay(ContentDisplay.RIGHT); diff --git a/desktop/src/main/java/bisq/desktop/components/TxIdTextField.java b/desktop/src/main/java/bisq/desktop/components/TxIdTextField.java index 40a4df535ad..84cea87e541 100644 --- a/desktop/src/main/java/bisq/desktop/components/TxIdTextField.java +++ b/desktop/src/main/java/bisq/desktop/components/TxIdTextField.java @@ -40,8 +40,11 @@ import javafx.scene.control.Tooltip; import javafx.scene.layout.AnchorPane; +import lombok.Getter; import lombok.Setter; +import javax.annotation.Nullable; + public class TxIdTextField extends AnchorPane { private static Preferences preferences; @@ -55,11 +58,11 @@ public static void setWalletService(BtcWalletService walletService) { TxIdTextField.walletService = walletService; } + @Getter private final TextField textField; private final Tooltip progressIndicatorTooltip; private final TxConfidenceIndicator txConfidenceIndicator; - private final Label copyIcon; - private final Label blockExplorerIcon; + private final Label copyIcon, blockExplorerIcon, missingTxWarningIcon; private TxConfidenceListener txConfidenceListener; @Setter private boolean isBsq; @@ -99,6 +102,16 @@ public TxIdTextField() { AnchorPane.setRightAnchor(blockExplorerIcon, 52.0); AnchorPane.setTopAnchor(blockExplorerIcon, 4.0); + missingTxWarningIcon = new Label(); + missingTxWarningIcon.getStyleClass().addAll("icon", "error-icon"); + AwesomeDude.setIcon(missingTxWarningIcon, AwesomeIcon.WARNING_SIGN); + missingTxWarningIcon.setTooltip(new Tooltip(Res.get("txIdTextField.missingTx.warning.tooltip"))); + missingTxWarningIcon.setMinWidth(20); + AnchorPane.setRightAnchor(missingTxWarningIcon, 52.0); + AnchorPane.setTopAnchor(missingTxWarningIcon, 4.0); + missingTxWarningIcon.setVisible(false); + missingTxWarningIcon.setManaged(false); + textField = new JFXTextField(); textField.setId("address-text-field"); textField.setEditable(false); @@ -106,13 +119,26 @@ public TxIdTextField() { AnchorPane.setRightAnchor(textField, 80.0); AnchorPane.setLeftAnchor(textField, 0.0); textField.focusTraversableProperty().set(focusTraversableProperty().get()); - getChildren().addAll(textField, copyIcon, blockExplorerIcon, txConfidenceIndicator); + getChildren().addAll(textField, missingTxWarningIcon, blockExplorerIcon, copyIcon, txConfidenceIndicator); } - public void setup(String txId) { + public void setup(@Nullable String txId) { if (txConfidenceListener != null) walletService.removeTxConfidenceListener(txConfidenceListener); + if (txId == null) { + textField.setText(Res.get("shared.na")); + textField.setId("address-text-field-error"); + blockExplorerIcon.setVisible(false); + blockExplorerIcon.setManaged(false); + copyIcon.setVisible(false); + copyIcon.setManaged(false); + txConfidenceIndicator.setVisible(false); + missingTxWarningIcon.setVisible(true); + missingTxWarningIcon.setManaged(true); + return; + } + txConfidenceListener = new TxConfidenceListener(txId) { @Override public void onTransactionConfidenceChanged(TransactionConfidence confidence) { diff --git a/desktop/src/main/java/bisq/desktop/main/MainViewModel.java b/desktop/src/main/java/bisq/desktop/main/MainViewModel.java index 1fd34cb7bd8..5b11d08ce74 100644 --- a/desktop/src/main/java/bisq/desktop/main/MainViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/MainViewModel.java @@ -56,7 +56,6 @@ import bisq.core.presentation.TradePresentation; import bisq.core.provider.fee.FeeService; import bisq.core.provider.price.PriceFeedService; -import bisq.core.trade.Trade; import bisq.core.trade.TradeManager; import bisq.core.user.DontShowAgainLookup; import bisq.core.user.Preferences; @@ -86,7 +85,6 @@ import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; -import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import java.util.ArrayList; @@ -407,20 +405,6 @@ private void setupHandlers() { .warning(Res.get("popup.error.takeOfferRequestFailed", errorMessage)) .show()); - tradeManager.getTradesWithoutDepositTx().addListener((ListChangeListener) c -> { - c.next(); - if (c.wasAdded()) { - c.getAddedSubList().forEach(trade -> - new Popup().warning(Res.get("popup.warning.trade.depositTxNull", trade.getShortId())) - .actionButtonText(Res.get("popup.warning.trade.depositTxNull.shutDown")) - .onAction(() -> BisqApp.getShutDownHandler().run()) - .secondaryActionButtonText(Res.get("popup.warning.trade.depositTxNull.moveToFailedTrades")) - .onSecondaryAction(() -> tradeManager.addTradeToFailedTrades(trade)) - .show() - ); - } - }); - bisqSetup.getBtcSyncProgress().addListener((observable, oldValue, newValue) -> updateBtcSyncProgress()); daoPresentation.getBsqSyncProgress().addListener((observable, oldValue, newValue) -> updateBtcSyncProgress()); diff --git a/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java b/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java index 1b75096665f..c061ef0b954 100644 --- a/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java +++ b/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java @@ -28,26 +28,43 @@ import bisq.core.offer.placeoffer.tasks.ValidateOffer; import bisq.core.trade.protocol.tasks.ApplyFilter; import bisq.core.trade.protocol.tasks.PublishTradeStatistics; +import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness; +import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest; +import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDepositTxAndDelayedPayoutTxMessage; +import bisq.core.trade.protocol.tasks.buyer.BuyerProcessPayoutTxPublishedMessage; import bisq.core.trade.protocol.tasks.buyer.BuyerSendCounterCurrencyTransferStartedMessage; +import bisq.core.trade.protocol.tasks.buyer.BuyerSendsDelayedPayoutTxSignatureResponse; import bisq.core.trade.protocol.tasks.buyer.BuyerSetupDepositTxListener; import bisq.core.trade.protocol.tasks.buyer.BuyerSetupPayoutTxListener; import bisq.core.trade.protocol.tasks.buyer.BuyerSignPayoutTx; +import bisq.core.trade.protocol.tasks.buyer.BuyerSignsDelayedPayoutTx; +import bisq.core.trade.protocol.tasks.buyer.BuyerVerifiesFinalDelayedPayoutTx; +import bisq.core.trade.protocol.tasks.buyer.BuyerVerifiesPreparedDelayedPayoutTx; import bisq.core.trade.protocol.tasks.buyer_as_maker.BuyerAsMakerCreatesAndSignsDepositTx; +import bisq.core.trade.protocol.tasks.buyer_as_maker.BuyerAsMakerSendsInputsForDepositTxResponse; import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerCreatesDepositTxInputs; import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerSignsDepositTx; import bisq.core.trade.protocol.tasks.maker.MakerCreateAndSignContract; import bisq.core.trade.protocol.tasks.maker.MakerProcessesInputsForDepositTxRequest; +import bisq.core.trade.protocol.tasks.maker.MakerSetsLockTime; import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment; import bisq.core.trade.protocol.tasks.seller.SellerBroadcastPayoutTx; +import bisq.core.trade.protocol.tasks.seller.SellerCreatesDelayedPayoutTx; +import bisq.core.trade.protocol.tasks.seller.SellerFinalizesDelayedPayoutTx; import bisq.core.trade.protocol.tasks.seller.SellerProcessCounterCurrencyTransferStartedMessage; +import bisq.core.trade.protocol.tasks.seller.SellerProcessDelayedPayoutTxSignatureResponse; +import bisq.core.trade.protocol.tasks.seller.SellerPublishesDepositTx; +import bisq.core.trade.protocol.tasks.seller.SellerSendDelayedPayoutTxSignatureRequest; import bisq.core.trade.protocol.tasks.seller.SellerSendPayoutTxPublishedMessage; import bisq.core.trade.protocol.tasks.seller.SellerSendsDepositTxAndDelayedPayoutTxMessage; import bisq.core.trade.protocol.tasks.seller.SellerSignAndFinalizePayoutTx; +import bisq.core.trade.protocol.tasks.seller.SellerSignsDelayedPayoutTx; import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerCreatesUnsignedDepositTx; import bisq.core.trade.protocol.tasks.seller_as_taker.SellerAsTakerCreatesDepositTxInputs; import bisq.core.trade.protocol.tasks.seller_as_taker.SellerAsTakerSignsDepositTx; import bisq.core.trade.protocol.tasks.taker.CreateTakerFeeTx; import bisq.core.trade.protocol.tasks.taker.TakerProcessesInputsForDepositTxResponse; +import bisq.core.trade.protocol.tasks.taker.TakerPublishFeeTx; import bisq.core.trade.protocol.tasks.taker.TakerSendInputsForDepositTxRequest; import bisq.core.trade.protocol.tasks.taker.TakerVerifyAndSignContract; import bisq.core.trade.protocol.tasks.taker.TakerVerifyMakerFeePayment; @@ -104,22 +121,35 @@ public void initialize() { FXCollections.observableArrayList(Arrays.asList( MakerProcessesInputsForDepositTxRequest.class, ApplyFilter.class, + VerifyPeersAccountAgeWitness.class, MakerVerifyTakerFeePayment.class, + MakerSetsLockTime.class, MakerCreateAndSignContract.class, BuyerAsMakerCreatesAndSignsDepositTx.class, BuyerSetupDepositTxListener.class, + BuyerAsMakerSendsInputsForDepositTxResponse.class, - MakerVerifyTakerFeePayment.class, + BuyerProcessDelayedPayoutTxSignatureRequest.class, + BuyerVerifiesPreparedDelayedPayoutTx.class, + BuyerSignsDelayedPayoutTx.class, + BuyerSendsDelayedPayoutTxSignatureResponse.class, + + BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, + BuyerVerifiesFinalDelayedPayoutTx.class, PublishTradeStatistics.class, ApplyFilter.class, MakerVerifyTakerFeePayment.class, BuyerSignPayoutTx.class, + BuyerSetupPayoutTxListener.class, BuyerSendCounterCurrencyTransferStartedMessage.class, - BuyerSetupPayoutTxListener.class) + + BuyerProcessPayoutTxPublishedMessage.class + ) )); addGroup("SellerAsTakerProtocol", FXCollections.observableArrayList(Arrays.asList( + ApplyFilter.class, TakerVerifyMakerFeePayment.class, CreateTakerFeeTx.class, SellerAsTakerCreatesDepositTxInputs.class, @@ -127,20 +157,34 @@ public void initialize() { TakerProcessesInputsForDepositTxResponse.class, ApplyFilter.class, - TakerVerifyMakerFeePayment.class, + VerifyPeersAccountAgeWitness.class, TakerVerifyAndSignContract.class, + TakerPublishFeeTx.class, SellerAsTakerSignsDepositTx.class, + SellerCreatesDelayedPayoutTx.class, + SellerSendDelayedPayoutTxSignatureRequest.class, + + SellerProcessDelayedPayoutTxSignatureResponse.class, + SellerSignsDelayedPayoutTx.class, + SellerFinalizesDelayedPayoutTx.class, SellerSendsDepositTxAndDelayedPayoutTxMessage.class, + SellerPublishesDepositTx.class, + PublishTradeStatistics.class, SellerProcessCounterCurrencyTransferStartedMessage.class, + ApplyFilter.class, TakerVerifyMakerFeePayment.class, ApplyFilter.class, TakerVerifyMakerFeePayment.class, SellerSignAndFinalizePayoutTx.class, SellerBroadcastPayoutTx.class, - SellerSendPayoutTxPublishedMessage.class) + SellerSendPayoutTxPublishedMessage.class + + ) )); + + //todo addGroup("BuyerAsTakerProtocol", FXCollections.observableArrayList(Arrays.asList( TakerVerifyMakerFeePayment.class, diff --git a/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java b/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java index 66c20405b7c..9c5af4c2997 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java @@ -41,9 +41,9 @@ import bisq.core.trade.TradeManager; import bisq.core.user.Preferences; import bisq.core.util.FormattingUtils; +import bisq.core.util.ParsingUtils; import bisq.core.util.coin.CoinFormatter; import bisq.core.util.coin.CoinUtil; -import bisq.core.util.ParsingUtils; import bisq.core.util.validation.BtcAddressValidator; import bisq.network.p2p.P2PService; @@ -100,7 +100,6 @@ import java.util.ArrayList; import java.util.Comparator; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -399,7 +398,7 @@ public void onSuccess(@javax.annotation.Nullable Transaction transaction) { .forEach(trade -> walletService.getAddressEntry(trade.getId(), AddressEntry.Context.TRADE_PAYOUT) .ifPresent(addressEntry -> { if (walletService.getBalanceForAddress(addressEntry.getAddress()).isZero()) - tradeManager.addTradeToClosedTrades(trade); + tradeManager.onTradeCompleted(trade); })); } diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java index dae9eb3ad47..154482e7c8a 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java @@ -26,6 +26,7 @@ import bisq.desktop.util.Layout; import bisq.core.account.witness.AccountAgeWitnessService; +import bisq.core.btc.wallet.BtcWalletService; import bisq.core.locale.CurrencyUtil; import bisq.core.locale.Res; import bisq.core.offer.Offer; @@ -78,6 +79,7 @@ public class TradeDetailsWindow extends Overlay { private final CoinFormatter formatter; private final ArbitrationManager arbitrationManager; private final TradeManager tradeManager; + private final BtcWalletService btcWalletService; private final AccountAgeWitnessService accountAgeWitnessService; private Trade trade; private ChangeListener changeListener; @@ -94,10 +96,12 @@ public class TradeDetailsWindow extends Overlay { public TradeDetailsWindow(@Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, ArbitrationManager arbitrationManager, TradeManager tradeManager, + BtcWalletService btcWalletService, AccountAgeWitnessService accountAgeWitnessService) { this.formatter = formatter; this.arbitrationManager = arbitrationManager; this.tradeManager = tradeManager; + this.btcWalletService = btcWalletService; this.accountAgeWitnessService = accountAgeWitnessService; type = Type.Confirmation; } @@ -166,7 +170,7 @@ private void addContent() { addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.paymentMethod"), paymentMethodText); // second group - rows = 8; + rows = 9; PaymentAccountPayload buyerPaymentAccountPayload = null; PaymentAccountPayload sellerPaymentAccountPayload = null; @@ -185,9 +189,6 @@ private void addContent() { rows++; } - if (trade.getTakerFeeTxId() != null) - rows++; - if (trade.getPayoutTx() != null) rows++; boolean showDisputedTx = arbitrationManager.findOwnDispute(trade.getId()).isPresent() && @@ -280,15 +281,14 @@ private void addContent() { } addLabelTxIdTextField(gridPane, ++rowIndex, Res.get("shared.makerFeeTxId"), offer.getOfferFeePaymentTxId()); - if (trade.getTakerFeeTxId() != null) - addLabelTxIdTextField(gridPane, ++rowIndex, Res.get("shared.takerFeeTxId"), trade.getTakerFeeTxId()); + addLabelTxIdTextField(gridPane, ++rowIndex, Res.get("shared.takerFeeTxId"), trade.getTakerFeeTxId()); Transaction depositTx = trade.getDepositTx(); - String depositTxString = depositTx != null ? depositTx.getTxId().toString() : Res.get("shared.na"); + String depositTxString = depositTx != null ? depositTx.getTxId().toString() : null; addLabelTxIdTextField(gridPane, ++rowIndex, Res.get("shared.depositTransactionId"), depositTxString); - Transaction delayedPayoutTx = trade.getDelayedPayoutTx(); - String delayedPayoutTxString = delayedPayoutTx != null ? delayedPayoutTx.getTxId().toString() : Res.get("shared.na"); + Transaction delayedPayoutTx = trade.getDelayedPayoutTx(btcWalletService); + String delayedPayoutTxString = delayedPayoutTx != null ? delayedPayoutTx.getTxId().toString() : null; addLabelTxIdTextField(gridPane, ++rowIndex, Res.get("shared.delayedPayoutTxId"), delayedPayoutTxString); if (trade.getPayoutTx() != null) diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesDataModel.java index 2b7dd31f7e5..c4e1a227908 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesDataModel.java @@ -22,6 +22,7 @@ import bisq.core.offer.Offer; import bisq.core.offer.OfferPayload; import bisq.core.trade.Trade; +import bisq.core.trade.TradeManager; import bisq.core.trade.failed.FailedTradesManager; import com.google.inject.Inject; @@ -35,13 +36,15 @@ class FailedTradesDataModel extends ActivatableDataModel { private final FailedTradesManager failedTradesManager; + private final TradeManager tradeManager; private final ObservableList list = FXCollections.observableArrayList(); private final ListChangeListener tradesListChangeListener; @Inject - public FailedTradesDataModel(FailedTradesManager failedTradesManager) { + public FailedTradesDataModel(FailedTradesManager failedTradesManager, TradeManager tradeManager) { this.failedTradesManager = failedTradesManager; + this.tradeManager = tradeManager; tradesListChangeListener = change -> applyList(); } @@ -74,6 +77,11 @@ private void applyList() { list.sort((o1, o2) -> o2.getTrade().getDate().compareTo(o1.getTrade().getDate())); } + public void moveTradeToPendingTrades(Trade trade) { + failedTradesManager.removeTrade(trade); + tradeManager.addFailedTradeToPending(trade); + } + public void unfailTrade(Trade trade) { failedTradesManager.unfailTrade(trade); } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.fxml b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.fxml index 12471a701a1..840a022f27a 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.fxml +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.fxml @@ -37,6 +37,7 @@ + diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.java index 2f22f370633..b5a02c77d8a 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.java @@ -23,6 +23,7 @@ import bisq.desktop.components.HyperlinkWithIcon; import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.main.overlays.windows.TradeDetailsWindow; +import bisq.desktop.util.FormBuilder; import bisq.core.locale.Res; import bisq.core.trade.Trade; @@ -33,9 +34,14 @@ import javax.inject.Inject; import javax.inject.Named; +import de.jensd.fx.fontawesome.AwesomeIcon; + +import com.jfoenix.controls.JFXButton; + import javafx.fxml.FXML; import javafx.scene.Scene; +import javafx.scene.control.Label; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; @@ -61,7 +67,7 @@ public class FailedTradesView extends ActivatableViewAndModel tableView; @FXML TableColumn priceColumn, amountColumn, volumeColumn, - marketColumn, directionColumn, dateColumn, tradeIdColumn, stateColumn; + marketColumn, directionColumn, dateColumn, tradeIdColumn, stateColumn, removeTradeColumn; private final TradeDetailsWindow tradeDetailsWindow; private SortedList sortedList; private EventHandler keyEventEventHandler; @@ -99,6 +105,7 @@ public void initialize() { setDateColumnCellFactory(); setMarketColumnCellFactory(); setStateColumnCellFactory(); + setRemoveTradeColumnCellFactory(); tradeIdColumn.setComparator(Comparator.comparing(o -> o.getTrade().getId())); dateColumn.setComparator(Comparator.comparing(o -> o.getTrade().getDate())); @@ -178,6 +185,13 @@ protected void deactivate() { sortedList.comparatorProperty().unbind(); } + private void onRevertTrade(Trade trade) { + new Popup().attention(Res.get("portfolio.failed.revertToPending.popup")) + .onAction(() -> model.dataModel.moveTradeToPendingTrades(trade)) + .actionButtonText(Res.get("shared.yes")) + .closeButtonText(Res.get("shared.no")) + .show(); + } private void setTradeIdColumnCellFactory() { tradeIdColumn.getStyleClass().add("first-column"); @@ -211,7 +225,7 @@ public void updateItem(final FailedTradesListItem item, boolean empty) { } private void setDateColumnCellFactory() { - dateColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); + dateColumn.setCellValueFactory((trade) -> new ReadOnlyObjectWrapper<>(trade.getValue())); dateColumn.setCellFactory( new Callback<>() { @Override @@ -232,7 +246,7 @@ public void updateItem(final FailedTradesListItem item, boolean empty) { } private void setMarketColumnCellFactory() { - marketColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); + marketColumn.setCellValueFactory((trade) -> new ReadOnlyObjectWrapper<>(trade.getValue())); marketColumn.setCellFactory( new Callback<>() { @Override @@ -251,7 +265,7 @@ public void updateItem(final FailedTradesListItem item, boolean empty) { private void setStateColumnCellFactory() { stateColumn.getStyleClass().add("last-column"); - stateColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); + stateColumn.setCellValueFactory((trade) -> new ReadOnlyObjectWrapper<>(trade.getValue())); stateColumn.setCellFactory( new Callback<>() { @Override @@ -273,7 +287,7 @@ public void updateItem(final FailedTradesListItem item, boolean empty) { private void setAmountColumnCellFactory() { - amountColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); + amountColumn.setCellValueFactory((trade) -> new ReadOnlyObjectWrapper<>(trade.getValue())); amountColumn.setCellFactory( new Callback<>() { @Override @@ -291,7 +305,7 @@ public void updateItem(final FailedTradesListItem item, boolean empty) { } private void setPriceColumnCellFactory() { - priceColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); + priceColumn.setCellValueFactory((trade) -> new ReadOnlyObjectWrapper<>(trade.getValue())); priceColumn.setCellFactory( new Callback<>() { @Override @@ -309,7 +323,7 @@ public void updateItem(final FailedTradesListItem item, boolean empty) { } private void setVolumeColumnCellFactory() { - volumeColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); + volumeColumn.setCellValueFactory((trade) -> new ReadOnlyObjectWrapper<>(trade.getValue())); volumeColumn.setCellFactory( new Callback<>() { @Override @@ -330,7 +344,7 @@ public void updateItem(final FailedTradesListItem item, boolean empty) { } private void setDirectionColumnCellFactory() { - directionColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); + directionColumn.setCellValueFactory((trade) -> new ReadOnlyObjectWrapper<>(trade.getValue())); directionColumn.setCellFactory( new Callback<>() { @Override @@ -346,5 +360,36 @@ public void updateItem(final FailedTradesListItem item, boolean empty) { } }); } + + private TableColumn setRemoveTradeColumnCellFactory() { + removeTradeColumn.setCellValueFactory((trade) -> new ReadOnlyObjectWrapper<>(trade.getValue())); + removeTradeColumn.setCellFactory( + new Callback<>() { + @Override + public TableCell call(TableColumn column) { + return new TableCell<>() { + + @Override + public void updateItem(FailedTradesListItem newItem, boolean empty) { + super.updateItem(newItem, empty); + if (!empty && newItem != null) { + Label icon = FormBuilder.getIcon(AwesomeIcon.UNDO); + icon.getStyleClass().addAll("icon", "dao-remove-proposal-icon"); + JFXButton iconButton = new JFXButton("", icon); + iconButton.setStyle("-fx-cursor: hand;"); + iconButton.getStyleClass().add("hidden-icon-button"); + iconButton.setTooltip(new Tooltip(Res.get("portfolio.failed.revertToPending"))); + iconButton.setOnAction(e -> onRevertTrade(newItem.getTrade())); + setGraphic(iconButton); + } else { + setGraphic(null); + } + } + }; + } + }); + return removeTradeColumn; + } } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java index 053fbb0b8d0..ee6343ef0b0 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -79,7 +79,6 @@ import org.bouncycastle.crypto.params.KeyParameter; -import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; @@ -232,10 +231,6 @@ public void onOpenSupportTicket() { tryOpenDispute(true); } - public void onMoveToFailedTrades() { - tradeManager.addTradeToFailedTrades(getTrade()); - } - /////////////////////////////////////////////////////////////////////////////////////////// // Getters @@ -687,8 +682,8 @@ public boolean isBootstrappedOrShowPopup() { return GUIUtil.isBootstrappedOrShowPopup(p2PService); } - public void addTradeToFailedTrades() { - tradeManager.addTradeToFailedTrades(selectedTrade); + public void moveTradeToFailedTrades(Trade trade) { + tradeManager.moveTradeToFailedTrades(trade); } public boolean isSignWitnessTrade() { diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.fxml b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.fxml index 16a304db66d..75dd225d318 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.fxml +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.fxml @@ -39,6 +39,7 @@ + diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java index d211997f8a5..ce4389b8368 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java @@ -50,9 +50,11 @@ import javax.inject.Inject; import javax.inject.Named; +import de.jensd.fx.fontawesome.AwesomeIcon; import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon; import com.jfoenix.controls.JFXBadge; +import com.jfoenix.controls.JFXButton; import javafx.fxml.FXML; @@ -64,6 +66,7 @@ import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.Button; +import javafx.scene.control.Label; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; @@ -87,6 +90,7 @@ import javafx.event.EventHandler; import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; import javafx.collections.transformation.SortedList; import javafx.util.Callback; @@ -97,6 +101,9 @@ @FxmlView public class PendingTradesView extends ActivatableViewAndModel { + public interface ChatCallback { + void onOpenChat(Trade trade); + } private final TradeDetailsWindow tradeDetailsWindow; private final CoinFormatter formatter; @@ -108,7 +115,7 @@ public class PendingTradesView extends ActivatableViewAndModel tableView; @FXML TableColumn priceColumn, volumeColumn, amountColumn, avatarColumn, - marketColumn, roleColumn, paymentMethodColumn, tradeIdColumn, dateColumn, chatColumn; + marketColumn, roleColumn, paymentMethodColumn, tradeIdColumn, dateColumn, chatColumn, moveTradeToFailedColumn; private SortedList sortedList; private TradeSubView selectedSubView; private EventHandler keyEventEventHandler; @@ -165,6 +172,7 @@ public void initialize() { paymentMethodColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.paymentMethod"))); avatarColumn.setText(""); chatColumn.setText(""); + moveTradeToFailedColumn.setText(""); setTradeIdColumnCellFactory(); setDateColumnCellFactory(); @@ -176,6 +184,7 @@ public void initialize() { setRoleColumnCellFactory(); setAvatarColumnCellFactory(); setChatColumnCellFactory(); + setRemoveTradeColumnCellFactory(); tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); tableView.setPlaceholder(new AutoTooltipLabel(Res.get("table.placeholder.noItems", Res.get("shared.openTrades")))); @@ -212,10 +221,6 @@ public void initialize() { .closeButtonText(Res.get("shared.cancel")) .onClose(popup::hide) .show(); - } else if (Utilities.isAltOrCtrlPressed(KeyCode.Y, keyEvent)) { - new Popup().warning(Res.get("portfolio.pending.removeFailedTrade")) - .onAction(model.dataModel::onMoveToFailedTrades) - .show(); } }; @@ -224,26 +229,16 @@ public void initialize() { @Override protected void activate() { - sortedList = new SortedList<>(model.dataModel.list); + ObservableList list = model.dataModel.list; + sortedList = new SortedList<>(list); sortedList.comparatorProperty().bind(tableView.comparatorProperty()); tableView.setItems(sortedList); + updateMoveTradeToFailedColumnState(); + scene = root.getScene(); if (scene != null) { scene.addEventHandler(KeyEvent.KEY_RELEASED, keyEventEventHandler); - - //TODO: in what cases is it necessary to request focus? - /*appFocusSubscription = EasyBind.subscribe(scene.getWindow().focusedProperty(), isFocused -> { - if (isFocused && model.dataModel.selectedItemProperty.get() != null) { - // Focus selectedItem from model - int index = table.getItems().indexOf(model.dataModel.selectedItemProperty.get()); - UserThread.execute(() -> { - //TODO app wide focus - //table.requestFocus(); - //UserThread.execute(() -> table.getFocusModel().focus(index)); - }); - } - });*/ } selectedItemSubscription = EasyBind.subscribe(model.dataModel.selectedItemProperty, selectedItem -> { @@ -287,7 +282,7 @@ else if (root.getChildren().size() == 2) updateTableSelection(); - model.dataModel.list.addListener(tradesListChangeListener); + list.addListener(tradesListChangeListener); updateNewChatMessagesByTradeMap(); } @@ -313,6 +308,41 @@ private void removeSelectedSubView() { } } + private void updateMoveTradeToFailedColumnState() { + moveTradeToFailedColumn.setVisible(model.dataModel.list.stream().anyMatch(item -> isInvalidState(item.getTrade()))); + } + + private boolean isInvalidState(Trade trade) { + String errorMessage = trade.getErrorMessage(); + boolean hasErrorMsg = errorMessage != null && !errorMessage.isEmpty(); + return hasErrorMsg || + trade.getDepositTxId() == null || + trade.getDelayedPayoutTxBytes() == null; + } + + private void onMoveTradeToFailedTrades(Trade trade) { + String reason; + String errorMessage = trade.getErrorMessage(); + if (errorMessage != null && !errorMessage.isEmpty()) { + reason = errorMessage; + } else if (trade.getDepositTxId() == null) { + reason = Res.get("trade.error.depositTxIsNull"); + } else if (trade.getDelayedPayoutTxBytes() == null) { + reason = Res.get("trade.error.delayedPayoutTxIsNull"); + } else { + reason = Res.get("shared.na"); + } + new Popup().attention(Res.get("portfolio.pending.moveToFailed.popup", reason)) + .onAction(() -> { + model.dataModel.moveTradeToFailedTrades(trade); + updateMoveTradeToFailedColumnState(); + }) + .actionButtonText(Res.get("shared.yes")) + .closeButtonText(Res.get("shared.no")) + .show(); + } + + /////////////////////////////////////////////////////////////////////////////////////////// // Chat /////////////////////////////////////////////////////////////////////////////////////////// @@ -503,9 +533,18 @@ public void updateItem(final PendingTradesListItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { - field = new HyperlinkWithIcon(item.getTrade().getShortId()); - field.setOnAction(event -> tradeDetailsWindow.show(item.getTrade())); - field.setTooltip(new Tooltip(Res.get("tooltip.openPopupForDetails"))); + if (isInvalidState(item.getTrade())) { + field = new HyperlinkWithIcon(item.getTrade().getShortId(), AwesomeIcon.WARNING_SIGN); + field.setOnAction(event -> tradeDetailsWindow.show(item.getTrade())); + field.setTooltip(new Tooltip(Res.get("tooltip.invalidTradeState.warning"))); + //FIXME icon does not take red color ;-( + field.getIcon().getStyleClass().clear(); + field.getIcon().getStyleClass().addAll("hyperlink", "error"); + } else { + field = new HyperlinkWithIcon(item.getTrade().getShortId()); + field.setOnAction(event -> tradeDetailsWindow.show(item.getTrade())); + field.setTooltip(new Tooltip(Res.get("tooltip.openPopupForDetails"))); + } setGraphic(field); } else { setGraphic(null); @@ -519,7 +558,7 @@ public void updateItem(final PendingTradesListItem item, boolean empty) { } private void setDateColumnCellFactory() { - dateColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); + dateColumn.setCellValueFactory((trade) -> new ReadOnlyObjectWrapper<>(trade.getValue())); dateColumn.setCellFactory( new Callback<>() { @Override @@ -541,7 +580,7 @@ public void updateItem(final PendingTradesListItem item, boolean empty) { } private void setAmountColumnCellFactory() { - amountColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); + amountColumn.setCellValueFactory((trade) -> new ReadOnlyObjectWrapper<>(trade.getValue())); amountColumn.setCellFactory( new Callback<>() { @Override @@ -562,7 +601,7 @@ public void updateItem(final PendingTradesListItem item, boolean empty) { } private void setPriceColumnCellFactory() { - priceColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); + priceColumn.setCellValueFactory((trade) -> new ReadOnlyObjectWrapper<>(trade.getValue())); priceColumn.setCellFactory( new Callback<>() { @Override @@ -583,7 +622,7 @@ public void updateItem(final PendingTradesListItem item, boolean empty) { } private void setVolumeColumnCellFactory() { - volumeColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); + volumeColumn.setCellValueFactory((trade) -> new ReadOnlyObjectWrapper<>(trade.getValue())); volumeColumn.setCellFactory( new Callback<>() { @Override @@ -593,9 +632,13 @@ public TableCell call( @Override public void updateItem(final PendingTradesListItem item, boolean empty) { super.updateItem(item, empty); - if (item != null && !empty) - setGraphic(new AutoTooltipLabel(DisplayUtils.formatVolumeWithCode(item.getTrade().getTradeVolume()))); - else + if (item != null && !empty) { + try { + String volume = DisplayUtils.formatVolumeWithCode(item.getTrade().getTradeVolume()); + setGraphic(new AutoTooltipLabel(volume)); + } catch (Throwable ignore) { + } + } else setGraphic(null); } }; @@ -604,7 +647,7 @@ public void updateItem(final PendingTradesListItem item, boolean empty) { } private void setPaymentMethodColumnCellFactory() { - paymentMethodColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); + paymentMethodColumn.setCellValueFactory((trade) -> new ReadOnlyObjectWrapper<>(trade.getValue())); paymentMethodColumn.setCellFactory( new Callback<>() { @Override @@ -625,7 +668,7 @@ public void updateItem(final PendingTradesListItem item, boolean empty) { } private void setMarketColumnCellFactory() { - marketColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); + marketColumn.setCellValueFactory((trade) -> new ReadOnlyObjectWrapper<>(trade.getValue())); marketColumn.setCellFactory( new Callback<>() { @Override @@ -643,7 +686,7 @@ public void updateItem(final PendingTradesListItem item, boolean empty) { } private void setRoleColumnCellFactory() { - roleColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); + roleColumn.setCellValueFactory((trade) -> new ReadOnlyObjectWrapper<>(trade.getValue())); roleColumn.setCellFactory( new Callback<>() { @Override @@ -665,7 +708,7 @@ public void updateItem(final PendingTradesListItem item, boolean empty) { @SuppressWarnings("UnusedReturnValue") private TableColumn setAvatarColumnCellFactory() { - avatarColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); + avatarColumn.setCellValueFactory((trade) -> new ReadOnlyObjectWrapper<>(trade.getValue())); avatarColumn.getStyleClass().addAll("last-column", "avatar-column"); avatarColumn.setCellFactory( new Callback<>() { @@ -675,7 +718,7 @@ public TableCell call(TableColumn< return new TableCell<>() { @Override - public void updateItem(final PendingTradesListItem newItem, boolean empty) { + public void updateItem(PendingTradesListItem newItem, boolean empty) { super.updateItem(newItem, empty); if (!empty && newItem != null) { final Trade trade = newItem.getTrade(); @@ -704,8 +747,7 @@ public void updateItem(final PendingTradesListItem newItem, boolean empty) { @SuppressWarnings("UnusedReturnValue") private TableColumn setChatColumnCellFactory() { - chatColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); - //TODO + chatColumn.setCellValueFactory((trade) -> new ReadOnlyObjectWrapper<>(trade.getValue())); chatColumn.getStyleClass().addAll("last-column", "avatar-column"); chatColumn.setSortable(false); chatColumn.setCellFactory( @@ -715,7 +757,7 @@ public TableCell call(TableColumn< return new TableCell<>() { @Override - public void updateItem(final PendingTradesListItem newItem, boolean empty) { + public void updateItem(PendingTradesListItem newItem, boolean empty) { super.updateItem(newItem, empty); if (!empty && newItem != null) { @@ -772,8 +814,34 @@ public void updateItem(final PendingTradesListItem newItem, boolean empty) { return chatColumn; } - public interface ChatCallback { - void onOpenChat(Trade trade); - } + private TableColumn setRemoveTradeColumnCellFactory() { + moveTradeToFailedColumn.setCellValueFactory((trade) -> new ReadOnlyObjectWrapper<>(trade.getValue())); + moveTradeToFailedColumn.setCellFactory( + new Callback<>() { + @Override + public TableCell call(TableColumn column) { + return new TableCell<>() { + @Override + public void updateItem(PendingTradesListItem newItem, boolean empty) { + super.updateItem(newItem, empty); + if (!empty && newItem != null && isInvalidState(newItem.getTrade())) { + Label icon = FormBuilder.getIcon(AwesomeIcon.TRASH); + icon.getStyleClass().addAll("icon", "error-icon"); + JFXButton iconButton = new JFXButton("", icon); + iconButton.setStyle("-fx-cursor: hand;"); + iconButton.getStyleClass().add("hidden-icon-button"); + iconButton.setTooltip(new Tooltip(Res.get("portfolio.pending.moveTradeToFailed"))); + iconButton.setOnAction(e -> onMoveTradeToFailedTrades(newItem.getTrade())); + setGraphic(iconButton); + } else { + setGraphic(null); + } + } + }; + } + }); + return moveTradeToFailedColumn; + } } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java index 4c91de86146..4e8a6c25338 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java @@ -588,7 +588,6 @@ private void openMediationResultPopup(String headLine) { if (trade.getDepositTx() == null) { log.error("trade.getDepositTx() was null at openMediationResultPopup. " + "We add the trade to failed trades. TradeId={}", trade.getId()); - model.dataModel.addTradeToFailedTrades(); new Popup().warning(Res.get("portfolio.pending.mediationResult.error.depositTxNull")).show(); return; } else if (trade.getDelayedPayoutTx() == null) { diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep4View.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep4View.java index 349781cb9ae..55378fd5675 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep4View.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep4View.java @@ -151,7 +151,7 @@ protected void addContent() { useSavingsWalletButton.setOnAction(e -> { handleTradeCompleted(); - model.dataModel.tradeManager.addTradeToClosedTrades(trade); + model.dataModel.tradeManager.onTradeCompleted(trade); }); withdrawToExternalWalletButton.setOnAction(e -> { onWithdrawal(); @@ -199,7 +199,7 @@ private void reviewWithdrawal() { Coin receiverAmount = amount.subtract(fee); if (balance.isZero()) { new Popup().warning(Res.get("portfolio.pending.step5_buyer.alreadyWithdrawn")).show(); - model.dataModel.tradeManager.addTradeToClosedTrades(trade); + model.dataModel.tradeManager.onTradeCompleted(trade); } else { if (toAddresses.isEmpty()) { validateWithdrawAddress(); diff --git a/p2p/src/main/java/bisq/network/p2p/P2PService.java b/p2p/src/main/java/bisq/network/p2p/P2PService.java index f2412471315..8eb0df0903c 100644 --- a/p2p/src/main/java/bisq/network/p2p/P2PService.java +++ b/p2p/src/main/java/bisq/network/p2p/P2PService.java @@ -555,6 +555,11 @@ private void processMailboxEntry(ProtectedMailboxStorageEntry protectedMailboxSt public void sendEncryptedMailboxMessage(NodeAddress peersNodeAddress, PubKeyRing peersPubKeyRing, NetworkEnvelope message, SendMailboxMessageListener sendMailboxMessageListener) { + if (peersPubKeyRing == null) { + log.error("sendEncryptedMailboxMessage: peersPubKeyRing is null. We ignore the call."); + return; + } + checkNotNull(peersNodeAddress, "PeerAddress must not be null (sendEncryptedMailboxMessage)"); checkNotNull(networkNode.getNodeAddress(), From b4944346230fa3abbf9700732f6e68a3f4955db8 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Thu, 24 Sep 2020 21:07:40 -0500 Subject: [PATCH 061/143] Add warn icon next to trash icon. Show popup with info about the problem and instructions. Set trash button disabled if the tx chain is valid to avoid that users move to failed while trade is valid to be completed. Contract: Add isMyRoleMaker method Trade: Add hasErrorMessage and isTxChainInvalid methods --- .../main/java/bisq/core/trade/Contract.java | 4 + core/src/main/java/bisq/core/trade/Trade.java | 11 ++ .../resources/i18n/displayStrings.properties | 44 +++++++- .../overlays/windows/TradeDetailsWindow.java | 1 + .../pendingtrades/PendingTradesView.fxml | 4 +- .../pendingtrades/PendingTradesView.java | 106 +++++++++++++----- 6 files changed, 132 insertions(+), 38 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/Contract.java b/core/src/main/java/bisq/core/trade/Contract.java index 9374eafb1f9..174719b0651 100644 --- a/core/src/main/java/bisq/core/trade/Contract.java +++ b/core/src/main/java/bisq/core/trade/Contract.java @@ -267,6 +267,10 @@ public boolean isMyRoleBuyer(PubKeyRing myPubKeyRing) { return getBuyerPubKeyRing().equals(myPubKeyRing); } + public boolean isMyRoleMaker(PubKeyRing myPubKeyRing) { + return isBuyerMakerAndSellerTaker() == isMyRoleBuyer(myPubKeyRing); + } + public void printDiff(@Nullable String peersContractAsJson) { String json = Utilities.objectToJson(this); String diff = StringUtils.difference(json, peersContractAsJson); diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index e8b8acb12b3..12919eaaa74 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -1154,11 +1154,22 @@ public Transaction getPayoutTx() { return payoutTx; } + public boolean hasErrorMessage() { + return getErrorMessage() != null && !getErrorMessage().isEmpty(); + } + @Nullable public String getErrorMessage() { return errorMessageProperty.get(); } + public boolean isTxChainInvalid() { + return offer.getOfferFeePaymentTxId() == null || + getTakerFeeTxId() == null || + getDepositTxId() == null || + getDelayedPayoutTxBytes() == null; + } + public byte[] getArbitratorBtcPubKey() { // In case we are already in a trade the arbitrator can have been revoked and we still can complete the trade // Only new trades cannot start without any arbitrator diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index a7808dda888..57fb5bc6ea2 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -904,16 +904,48 @@ portfolio.pending.mediationResult.popup.selfAccepted.lockTimeOver=You have accep portfolio.pending.mediationResult.popup.openArbitration=Reject and request arbitration portfolio.pending.mediationResult.popup.alreadyAccepted=You've already accepted -portfolio.pending.moveToFailed.popup=This trade has an invalid state.\n\n\ +portfolio.pending.failedTrade.taker.missingTakerFeeTx=The taker fee transaction is missing.\n\n\ + Without that the trade cannot be completed. No funds have been locked up and no trade fee has been paid. \ + You can move the trade to failed trades. +portfolio.pending.failedTrade.maker.missingTakerFeeTx=The peer's taker fee transaction is missing.\n\n\ + Without that the trade cannot be completed. No funds have been locked up. \ + Your offer is still available for other traders so you have not lost the maker fee. \ + You can move the trade to failed trades. +portfolio.pending.failedTrade.missingDepositTx=The deposit transaction (the 2of2 Multisig transaction) is missing.\n\n\ + Without that the trade cannot be completed. No funds have been locked up but your trade fee has been paid. \ + You can request at https://github.com/bisq-network/support/issues for getting reimbursed the lost trade fee. \ + You can move the trade to failed trades. +portfolio.pending.failedTrade.buyer.existingDepositTxButMissingDelayedPayoutTx=The delayed payout transaction is missing.\n\n\ + Without that arbitration cannot be opened. The funds have been locked up in the deposit transaction and you must not \ + send the fiat or altcoin payment to the BTC seller. Open a mediation ticket by clicking cmd+o (or ctrl+o). \ + The mediator should make a suggested payout so that the seller receives their trade amount back and both traders get \ + back their security deposit. That way there is no security risk and only the trade fee is lost. \ + You can request at https://github.com/bisq-network/support/issues for getting reimbursed the lost trade fee. +portfolio.pending.failedTrade.seller.existingDepositTxButMissingDelayedPayoutTx=The delayed payout transaction is missing.\n\n\ + Without that arbitration cannot be opened. The funds have been locked up in the deposit transaction. If the buyer is \ + also missing the delayed payout transaction he is instructed to not send the payment but open a mediation ticket. \ + You should open a mediation ticket as well by clicking cmd+o (or ctrl+o). \ + In case that the buyer has not sent the payment the mediator should make a suggested payout so that you receive \ + your trade amount back and both traders get back their security deposit. Otherwise the trade amount should go to the buyer. \ + You can request at https://github.com/bisq-network/support/issues for getting reimbursed the lost trade fee. +portfolio.pending.failedTrade.errorMsgSet=There have been an error during the trade protocol execution.\n\n\ + This error might not be critical and trade can be completed normally. If you are unsure you can open a mediation \ + ticket to get advice from the Bisq mediators. If the error was critical and the trade cannot be completed you might \ + have lost your trade fee. If so, you can request at https://github.com/bisq-network/support/issues for \ + getting reimbursed the lost trade fee. +portfolio.pending.failedTrade.missingContract=The trade contract is not set.\n\n\ + The trade cannot be completed and you might \ + have lost your trade fee. If so, you can request at https://github.com/bisq-network/support/issues for \ + getting reimbursed the lost trade fee. +portfolio.pending.failedTrade.info.popup=This trade has an invalid state.\n\n{0} +portfolio.pending.failedTrade.moveToFailed=This trade has an invalid state.\n\n{0}\n\n\ Do you want to move the trade to failed trades?\n\n\ You cannot open mediation or arbitration from the failed trades view, but you can move it back to the open \ - trades screen any time.\n\n\ - Reason for the invalid trade state:\n{0} -portfolio.pending.moveTradeToFailed=Move trade to failed trades + trades screen any time. +portfolio.pending.failedTrade.moveTradeToFailedIcon.tooltip=Move trade to failed trades +portfolio.pending.failedTrade.warningIcon.tooltip=Click to open details about the issues of that trade portfolio.failed.revertToPending.popup=Do you want to move the trade to open trades? portfolio.failed.revertToPending=Move trade to open trades -trade.error.delayedPayoutTxIsNull=Delayed payout transaction is null -trade.error.depositTxIsNull=Deposit transaction is null portfolio.closed.completed=Completed portfolio.closed.ticketClosed=Arbitrated diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java index 154482e7c8a..644cfa3aad3 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java @@ -353,6 +353,7 @@ private void addContent() { textArea = addConfirmationLabelTextArea(gridPane, ++rowIndex, Res.get("shared.errorMessage"), "", 0).second; textArea.setText(trade.getErrorMessage()); textArea.setEditable(false); + //TODO paint red IntegerProperty count = new SimpleIntegerProperty(20); int rowHeight = 10; diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.fxml b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.fxml index 75dd225d318..be897e53c32 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.fxml +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.fxml @@ -36,10 +36,10 @@ - + - + diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java index ce4389b8368..f0ef8bb1bc5 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java @@ -36,6 +36,7 @@ import bisq.core.support.messages.ChatMessage; import bisq.core.support.traderchat.TradeChatSession; import bisq.core.support.traderchat.TraderChatManager; +import bisq.core.trade.Contract; import bisq.core.trade.Trade; import bisq.core.user.Preferences; import bisq.core.util.FormattingUtils; @@ -45,6 +46,7 @@ import bisq.common.UserThread; import bisq.common.config.Config; +import bisq.common.crypto.PubKeyRing; import bisq.common.util.Utilities; import javax.inject.Inject; @@ -74,6 +76,7 @@ import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; @@ -309,30 +312,16 @@ private void removeSelectedSubView() { } private void updateMoveTradeToFailedColumnState() { - moveTradeToFailedColumn.setVisible(model.dataModel.list.stream().anyMatch(item -> isInvalidState(item.getTrade()))); + moveTradeToFailedColumn.setVisible(model.dataModel.list.stream().anyMatch(item -> isMaybeInvalidTrade(item.getTrade()))); } - private boolean isInvalidState(Trade trade) { - String errorMessage = trade.getErrorMessage(); - boolean hasErrorMsg = errorMessage != null && !errorMessage.isEmpty(); - return hasErrorMsg || - trade.getDepositTxId() == null || - trade.getDelayedPayoutTxBytes() == null; + private boolean isMaybeInvalidTrade(Trade trade) { + return trade.isTxChainInvalid() || trade.hasErrorMessage(); } - private void onMoveTradeToFailedTrades(Trade trade) { - String reason; - String errorMessage = trade.getErrorMessage(); - if (errorMessage != null && !errorMessage.isEmpty()) { - reason = errorMessage; - } else if (trade.getDepositTxId() == null) { - reason = Res.get("trade.error.depositTxIsNull"); - } else if (trade.getDelayedPayoutTxBytes() == null) { - reason = Res.get("trade.error.delayedPayoutTxIsNull"); - } else { - reason = Res.get("shared.na"); - } - new Popup().attention(Res.get("portfolio.pending.moveToFailed.popup", reason)) + private void onMoveInvalidTradeToFailedTrades(Trade trade) { + new Popup().width(900).attention(Res.get("portfolio.pending.failedTrade.moveToFailed", + getInvalidTradeDetails(trade))) .onAction(() -> { model.dataModel.moveTradeToFailedTrades(trade); updateMoveTradeToFailedColumnState(); @@ -342,6 +331,45 @@ private void onMoveTradeToFailedTrades(Trade trade) { .show(); } + private void onShowInfoForInvalidTrade(Trade trade) { + new Popup().width(900).attention(Res.get("portfolio.pending.failedTrade.info.popup", + getInvalidTradeDetails(trade))) + .show(); + } + + private String getInvalidTradeDetails(Trade trade) { + Contract contract = trade.getContract(); + if (contract == null) { + return Res.get("portfolio.pending.failedTrade.missingContract"); + } + + PubKeyRing myPubKeyRing = model.dataModel.getPubKeyRing(); + boolean isMyRoleBuyer = contract.isMyRoleBuyer(myPubKeyRing); + boolean isMyRoleMaker = contract.isMyRoleMaker(myPubKeyRing); + + if (trade.getTakerFeeTxId() == null) { + return isMyRoleMaker ? + Res.get("portfolio.pending.failedTrade.maker.missingTakerFeeTx") : + Res.get("portfolio.pending.failedTrade.taker.missingTakerFeeTx"); + } + + if (trade.getDepositTx() == null) { + return Res.get("portfolio.pending.failedTrade.missingDepositTx"); + } + + if (trade.getDelayedPayoutTx() == null) { + return isMyRoleBuyer ? + Res.get("portfolio.pending.failedTrade.buyer.existingDepositTxButMissingDelayedPayoutTx") : + Res.get("portfolio.pending.failedTrade.seller.existingDepositTxButMissingDelayedPayoutTx"); + } + + if (trade.hasErrorMessage()) { + return Res.get("portfolio.pending.failedTrade.errorMsgSet"); + } + + return Res.get("shared.na"); + } + /////////////////////////////////////////////////////////////////////////////////////////// // Chat @@ -533,7 +561,7 @@ public void updateItem(final PendingTradesListItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { - if (isInvalidState(item.getTrade())) { + if (isMaybeInvalidTrade(item.getTrade())) { field = new HyperlinkWithIcon(item.getTrade().getShortId(), AwesomeIcon.WARNING_SIGN); field.setOnAction(event -> tradeDetailsWindow.show(item.getTrade())); field.setTooltip(new Tooltip(Res.get("tooltip.invalidTradeState.warning"))); @@ -826,15 +854,33 @@ public TableCell call(TableColumn< @Override public void updateItem(PendingTradesListItem newItem, boolean empty) { super.updateItem(newItem, empty); - if (!empty && newItem != null && isInvalidState(newItem.getTrade())) { - Label icon = FormBuilder.getIcon(AwesomeIcon.TRASH); - icon.getStyleClass().addAll("icon", "error-icon"); - JFXButton iconButton = new JFXButton("", icon); - iconButton.setStyle("-fx-cursor: hand;"); - iconButton.getStyleClass().add("hidden-icon-button"); - iconButton.setTooltip(new Tooltip(Res.get("portfolio.pending.moveTradeToFailed"))); - iconButton.setOnAction(e -> onMoveTradeToFailedTrades(newItem.getTrade())); - setGraphic(iconButton); + if (!empty && newItem != null && isMaybeInvalidTrade(newItem.getTrade())) { + Trade trade = newItem.getTrade(); + + Label warnIcon = FormBuilder.getIcon(AwesomeIcon.WARNING_SIGN); + warnIcon.getStyleClass().addAll("icon", "error-icon"); + JFXButton warnIconButton = new JFXButton("", warnIcon); + warnIconButton.setStyle("-fx-cursor: hand;"); + warnIconButton.getStyleClass().add("hidden-icon-button"); + warnIconButton.setTooltip(new Tooltip(Res.get("portfolio.pending.failedTrade.warningIcon.tooltip"))); + warnIconButton.setOnAction(e -> onShowInfoForInvalidTrade(trade)); + + Label trashIcon = FormBuilder.getIcon(AwesomeIcon.TRASH); + trashIcon.getStyleClass().addAll("icon", "error-icon"); + JFXButton trashIconButton = new JFXButton("", trashIcon); + trashIconButton.setStyle("-fx-cursor: hand;"); + trashIconButton.getStyleClass().add("hidden-icon-button"); + trashIconButton.setTooltip(new Tooltip(Res.get("portfolio.pending.failedTrade.moveTradeToFailedIcon.tooltip"))); + trashIconButton.setOnAction(e -> onMoveInvalidTradeToFailedTrades(trade)); + + // We only allow to move to failed trade if the txs are invalid. + // Otherwise the trade has to be completed. + trashIconButton.setDisable(!trade.isTxChainInvalid()); + + HBox hBox = new HBox(); + hBox.setSpacing(0); + hBox.getChildren().addAll(warnIconButton, trashIconButton); + setGraphic(hBox); } else { setGraphic(null); } From 7167e2a8bdc69d33701a24373d98fdcaae026ef3 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Thu, 24 Sep 2020 21:10:02 -0500 Subject: [PATCH 062/143] Add check if trade has been paid out for button disable state --- .../main/portfolio/pendingtrades/PendingTradesView.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java index f0ef8bb1bc5..70db4ad365e 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java @@ -875,7 +875,9 @@ public void updateItem(PendingTradesListItem newItem, boolean empty) { // We only allow to move to failed trade if the txs are invalid. // Otherwise the trade has to be completed. - trashIconButton.setDisable(!trade.isTxChainInvalid()); + boolean isTxChainValid = !trade.isTxChainInvalid(); + boolean paidOut = trade.getPayoutTxId() != null; + trashIconButton.setDisable(isTxChainValid || paidOut); HBox hBox = new HBox(); hBox.setSpacing(0); From 6f614f4f4c54b1336a03186cafeef33a7357551f Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 00:19:43 -0500 Subject: [PATCH 063/143] Set takerFeeTxId and depositTx in trade only once they are published. Before that we keep it temporary in the processModel. The buyer receives the takerFeeTxId with the frist message, but at the moment it is not published. To reflect that he also keeps it in the process model and at the next message when the fee tx is published he sets it in the Trade. Remove `checkArgument(!walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG).isPresent(), "addressEntry must not be set here."); ` as it causes failure if a taker takes same offer after certain error conditions again. --- core/src/main/java/bisq/core/trade/Trade.java | 2 +- .../main/java/bisq/core/trade/protocol/ProcessModel.java | 5 +++++ .../BuyerProcessDelayedPayoutTxSignatureRequest.java | 5 +++++ .../protocol/tasks/maker/MakerCreateAndSignContract.java | 9 ++------- .../maker/MakerProcessesInputsForDepositTxRequest.java | 7 ++++++- .../tasks/seller/SellerCreatesDelayedPayoutTx.java | 2 +- .../protocol/tasks/seller/SellerPublishesDepositTx.java | 6 +++++- .../SellerSendsDepositTxAndDelayedPayoutTxMessage.java | 2 +- .../seller_as_taker/SellerAsTakerSignsDepositTx.java | 3 ++- .../trade/protocol/tasks/taker/CreateTakerFeeTx.java | 4 +++- .../trade/protocol/tasks/taker/TakerPublishFeeTx.java | 3 +-- .../tasks/taker/TakerSendInputsForDepositTxRequest.java | 2 +- .../protocol/tasks/taker/TakerVerifyAndSignContract.java | 2 +- 13 files changed, 34 insertions(+), 18 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index 12919eaaa74..628d0ec1841 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -1164,7 +1164,7 @@ public String getErrorMessage() { } public boolean isTxChainInvalid() { - return offer.getOfferFeePaymentTxId() == null || + return checkNotNull(offer).getOfferFeePaymentTxId() == null || getTakerFeeTxId() == null || getDepositTxId() == null || getDelayedPayoutTxBytes() == null; diff --git a/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java b/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java index e60237def8a..3a76e460881 100644 --- a/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java +++ b/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java @@ -169,6 +169,11 @@ public class ProcessModel implements Model, PersistablePayload { @Setter private long sellerPayoutAmountFromMediation; + // Added in v 1.4.0 + @Setter + @Getter + transient private Transaction depositTx; + // We want to indicate the user the state of the message delivery of the // CounterCurrencyTransferStartedMessage. As well we do an automatic re-send in case it was not ACKed yet. // To enable that even after restart we persist the state. diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDelayedPayoutTxSignatureRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDelayedPayoutTxSignatureRequest.java index 4ef0e01117e..806b90b05ef 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDelayedPayoutTxSignatureRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDelayedPayoutTxSignatureRequest.java @@ -47,6 +47,11 @@ protected void run() { Transaction preparedDelayedPayoutTx = processModel.getBtcWalletService().getTxFromSerializedTx(delayedPayoutTxAsBytes); processModel.setPreparedDelayedPayoutTx(preparedDelayedPayoutTx); + // When we receive that message the taker has published the taker fee, so we apply it to the trade. + // The takerFeeTx was sent in the first message. It should be part of DelayedPayoutTxSignatureRequest + // but that cannot be changed due backward compatibility issues. It is a left over from the old trade protocol. + trade.setTakerFeeTxId(processModel.getTakeOfferFeeTxId()); + trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress()); complete(); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java index 77b154e99d7..ebc2ee2d9a0 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerCreateAndSignContract.java @@ -32,11 +32,8 @@ import bisq.common.taskrunner.TaskRunner; import bisq.common.util.Utilities; -import com.google.common.base.Preconditions; - import lombok.extern.slf4j.Slf4j; -import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @Slf4j @@ -49,7 +46,7 @@ public MakerCreateAndSignContract(TaskRunner taskHandler, Trade trade) { protected void run() { try { runInterceptHook(); - Preconditions.checkNotNull(trade.getTakerFeeTxId(), "trade.getTakeOfferFeeTxId() must not be null"); + String takerFeeTxId = checkNotNull(processModel.getTakeOfferFeeTxId()); TradingPeer taker = processModel.getTradingPeer(); boolean isBuyerMakerAndSellerTaker = trade instanceof BuyerAsMakerTrade; @@ -60,8 +57,6 @@ protected void run() { BtcWalletService walletService = processModel.getBtcWalletService(); String id = processModel.getOffer().getId(); - checkArgument(!walletService.getAddressEntry(id, AddressEntry.Context.MULTI_SIG).isPresent(), - "addressEntry must not be set here."); AddressEntry makerAddressEntry = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.MULTI_SIG); byte[] makerMultiSigPubKey = makerAddressEntry.getPubKey(); @@ -70,7 +65,7 @@ protected void run() { processModel.getOffer().getOfferPayload(), checkNotNull(trade.getTradeAmount()).value, trade.getTradePrice().getValue(), - trade.getTakerFeeTxId(), + takerFeeTxId, buyerNodeAddress, sellerNodeAddress, trade.getMediatorNodeAddress(), diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java index a6cd000dbec..404c893c379 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java @@ -68,7 +68,12 @@ protected void run() { tradingPeer.setPubKeyRing(checkNotNull(request.getTakerPubKeyRing())); tradingPeer.setAccountId(nonEmptyStringOf(request.getTakerAccountId())); - trade.setTakerFeeTxId(nonEmptyStringOf(request.getTakerFeeTxId())); + + // We set the taker fee only in the processModel yet not in the trade as the tx was only created but not + // published yet. Once it was published we move it to trade. The takerFeeTx should be sent in a later + // message bu that cannot be changed due backward compatibility issues. It is a left over from the + // old trade protocol. + processModel.setTakeOfferFeeTxId(nonEmptyStringOf(request.getTakerFeeTxId())); // Taker has to sign offerId (he cannot manipulate that - so we avoid to have a challenge protocol for // passing the nonce we want to get signed) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerCreatesDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerCreatesDelayedPayoutTx.java index 5cd1ca6230c..aaf667c41d2 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerCreatesDelayedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerCreatesDelayedPayoutTx.java @@ -46,7 +46,7 @@ protected void run() { String donationAddressString = processModel.getDaoFacade().getParamValue(Param.RECIPIENT_BTC_ADDRESS); Coin minerFee = trade.getTxFee(); TradeWalletService tradeWalletService = processModel.getTradeWalletService(); - Transaction depositTx = checkNotNull(trade.getDepositTx()); + Transaction depositTx = checkNotNull(processModel.getDepositTx()); long lockTime = trade.getLockTime(); Transaction preparedDelayedPayoutTx = tradeWalletService.createDelayedUnsignedPayoutTx(depositTx, diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerPublishesDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerPublishesDepositTx.java index 7f4aef9386b..1cdc2e43583 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerPublishesDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerPublishesDepositTx.java @@ -40,11 +40,15 @@ protected void run() { try { runInterceptHook(); - processModel.getTradeWalletService().broadcastTx(trade.getDepositTx(), + final Transaction depositTx = processModel.getDepositTx(); + processModel.getTradeWalletService().broadcastTx(depositTx, new TxBroadcaster.Callback() { @Override public void onSuccess(Transaction transaction) { if (!completed) { + // Now as we have published the deposit tx we set it in trade + trade.applyDepositTx(depositTx); + trade.setState(Trade.State.SELLER_PUBLISHED_DEPOSIT_TX); processModel.getBtcWalletService().swapTradeEntryToAvailableEntry(processModel.getOffer().getId(), diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java index 20871176486..fc3bf6b6d0c 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java @@ -67,7 +67,7 @@ protected TradeMessage getMessage(String tradeId) { deterministicId, processModel.getOfferId(), processModel.getMyNodeAddress(), - checkNotNull(trade.getDepositTx()).bitcoinSerialize(), + checkNotNull(processModel.getDepositTx()).bitcoinSerialize(), checkNotNull(trade.getDelayedPayoutTx()).bitcoinSerialize()); } return message; diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java index 389c4ce040a..16b4084eb9a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_taker/SellerAsTakerSignsDepositTx.java @@ -80,7 +80,8 @@ protected void run() { tradingPeer.getMultiSigPubKey(), sellerMultiSigPubKey); - trade.applyDepositTx(depositTx); + // We set the deposit tx to trade once we have it published + processModel.setDepositTx(depositTx); complete(); } catch (Throwable t) { diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java index 43ae278014d..1363f3e0236 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java @@ -95,7 +95,9 @@ protected void run() { // We did not broadcast and commit the tx yet to avoid issues with lost trade fee in case the // take offer attempt failed. - trade.setTakerFeeTxId(transaction.getTxId().toString()); + // We do not set the takerFeeTxId yet to trade as it is not published. + processModel.setTakeOfferFeeTxId(transaction.getTxId().toString()); + processModel.setTakeOfferFeeTx(transaction); walletService.swapTradeEntryToAvailableEntry(id, AddressEntry.Context.OFFER_FUNDING); complete(); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerPublishFeeTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerPublishFeeTx.java index 9ca6bfc5135..a5da55a2d35 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerPublishFeeTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerPublishFeeTx.java @@ -57,6 +57,7 @@ protected void run() { new TxBroadcaster.Callback() { @Override public void onSuccess(Transaction transaction) { + trade.setTakerFeeTxId(transaction.getTxId().toString()); trade.setState(Trade.State.TAKER_PUBLISHED_TAKER_FEE_TX); complete(); } @@ -81,9 +82,7 @@ public void onSuccess(@Nullable Transaction transaction) { if (!completed) { if (transaction != null) { trade.setTakerFeeTxId(transaction.getTxId().toString()); - processModel.setTakeOfferFeeTx(transaction); trade.setState(Trade.State.TAKER_PUBLISHED_TAKER_FEE_TX); - complete(); } } else { diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java index f7ec1e82ca9..1170e18074d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java @@ -58,7 +58,7 @@ protected void run() { try { runInterceptHook(); Coin tradeAmount = checkNotNull(trade.getTradeAmount(), "TradeAmount must not be null"); - String takerFeeTxId = checkNotNull(trade.getTakerFeeTxId(), "TakeOfferFeeTxId must not be null"); + String takerFeeTxId = checkNotNull(processModel.getTakeOfferFeeTxId(), "TakeOfferFeeTxId must not be null"); User user = checkNotNull(processModel.getUser(), "User must not be null"); List acceptedArbitratorAddresses = user.getAcceptedArbitratorAddresses() == null ? new ArrayList<>() : diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java index ba3e42ede46..15fef9aa327 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerVerifyAndSignContract.java @@ -53,7 +53,7 @@ protected void run() { try { runInterceptHook(); - String takerFeeTxId = checkNotNull(trade.getTakerFeeTxId()); + String takerFeeTxId = checkNotNull(processModel.getTakeOfferFeeTxId()); TradingPeer maker = processModel.getTradingPeer(); PaymentAccountPayload makerPaymentAccountPayload = checkNotNull(maker.getPaymentAccountPayload()); PaymentAccountPayload takerPaymentAccountPayload = checkNotNull(processModel.getPaymentAccountPayload(trade)); From f1df52790b28e892139f579be951b1e3c7b16825 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 00:20:17 -0500 Subject: [PATCH 064/143] improve trade details window --- .../resources/i18n/displayStrings.properties | 7 +- .../offer/takeoffer/TakeOfferViewModel.java | 3 - .../overlays/windows/TradeDetailsWindow.java | 79 ++++++++++--------- .../pendingtrades/PendingTradesView.java | 2 +- 4 files changed, 48 insertions(+), 43 deletions(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 57fb5bc6ea2..0eb1e2b4179 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -929,7 +929,8 @@ portfolio.pending.failedTrade.seller.existingDepositTxButMissingDelayedPayoutTx= your trade amount back and both traders get back their security deposit. Otherwise the trade amount should go to the buyer. \ You can request at https://github.com/bisq-network/support/issues for getting reimbursed the lost trade fee. portfolio.pending.failedTrade.errorMsgSet=There have been an error during the trade protocol execution.\n\n\ - This error might not be critical and trade can be completed normally. If you are unsure you can open a mediation \ + Error: {0}\n\n\ + This error might not be critical and the trade could be completed normally. If you are unsure you can open a mediation \ ticket to get advice from the Bisq mediators. If the error was critical and the trade cannot be completed you might \ have lost your trade fee. If so, you can request at https://github.com/bisq-network/support/issues for \ getting reimbursed the lost trade fee. @@ -937,8 +938,8 @@ portfolio.pending.failedTrade.missingContract=The trade contract is not set.\n\n The trade cannot be completed and you might \ have lost your trade fee. If so, you can request at https://github.com/bisq-network/support/issues for \ getting reimbursed the lost trade fee. -portfolio.pending.failedTrade.info.popup=This trade has an invalid state.\n\n{0} -portfolio.pending.failedTrade.moveToFailed=This trade has an invalid state.\n\n{0}\n\n\ +portfolio.pending.failedTrade.info.popup=The trade protocol encountered some problems.\n\n{0} +portfolio.pending.failedTrade.moveToFailed=The trade protocol encountered some problems.\n\n{0}\n\n\ Do you want to move the trade to failed trades?\n\n\ You cannot open mediation or arbitration from the failed trades view, but you can move it back to the open \ trades screen any time. diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java index 685fb6dbe1b..c868ab2d995 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java @@ -491,9 +491,6 @@ private void applyTradeState() { showTransactionPublishedScreen.set(true); updateSpinnerInfo(); - } else { - final String msg = "trade.getDepositTx() must not be null."; - DevEnv.logErrorAndThrowIfDevMode(msg); } } } diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java index 644cfa3aad3..494dad9d02c 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java @@ -42,6 +42,7 @@ import bisq.network.p2p.NodeAddress; import bisq.common.UserThread; +import bisq.common.util.Tuple3; import org.bitcoinj.core.Transaction; import org.bitcoinj.core.Utils; @@ -60,6 +61,9 @@ import javafx.scene.control.Tooltip; import javafx.scene.input.KeyCode; import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.Region; import javafx.geometry.Insets; @@ -170,7 +174,7 @@ private void addContent() { addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.paymentMethod"), paymentMethodText); // second group - rows = 9; + rows = 7; PaymentAccountPayload buyerPaymentAccountPayload = null; PaymentAccountPayload sellerPaymentAccountPayload = null; @@ -189,6 +193,10 @@ private void addContent() { rows++; } + boolean showXmrProofResult = checkNotNull(trade.getOffer()).getCurrencyCode().equals("XMR") && + trade.getAssetTxProofResult() != null && + trade.getAssetTxProofResult() != AssetTxProofResult.UNDEFINED; + if (trade.getPayoutTx() != null) rows++; boolean showDisputedTx = arbitrationManager.findOwnDispute(trade.getId()).isPresent() && @@ -199,6 +207,8 @@ private void addContent() { rows += 2; if (trade.getTradingPeerNodeAddress() != null) rows++; + if (showXmrProofResult) + rows++; addTitledGroupBg(gridPane, ++rowIndex, rows, Res.get("shared.details"), Layout.GROUP_DISTANCE); addConfirmationLabelTextFieldWithCopyIcon(gridPane, rowIndex, Res.get("shared.tradeId"), @@ -231,20 +241,12 @@ private void addContent() { addConfirmationLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, Res.get("tradeDetailsWindow.tradingPeersOnion"), trade.getTradingPeerNodeAddress().getFullAddress()); - if (checkNotNull(trade.getOffer()).getCurrencyCode().equals("XMR") && - trade.getAssetTxProofResult() != null && - trade.getAssetTxProofResult() != AssetTxProofResult.UNDEFINED) { + if (showXmrProofResult) { // As the window is already overloaded we replace the tradingPeersPubKeyHash field with the auto-conf state // if XMR is the currency addConfirmationLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, Res.get("portfolio.pending.step3_seller.autoConf.status.label"), GUIUtil.getProofResultAsString(trade.getAssetTxProofResult())); - } else { - addConfirmationLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, - Res.get("tradeDetailsWindow.tradingPeersPubKeyHash"), - trade.getContract() != null ? Utils.HEX.encode(trade.getContract().getPeersPubKeyRing( - tradeManager.getKeyRing().getPubKeyRing()).getSignaturePubKeyBytes()) : - Res.get("shared.na")); } if (contract != null) { @@ -298,10 +300,38 @@ private void addContent() { addLabelTxIdTextField(gridPane, ++rowIndex, Res.get("tradeDetailsWindow.disputedPayoutTxId"), arbitrationManager.findOwnDispute(trade.getId()).get().getDisputePayoutTxId()); + if (trade.hasFailed()) { + textArea = addConfirmationLabelTextArea(gridPane, ++rowIndex, Res.get("shared.errorMessage"), "", 0).second; + textArea.setText(trade.getErrorMessage()); + textArea.setEditable(false); + //TODO paint red + + IntegerProperty count = new SimpleIntegerProperty(20); + int rowHeight = 10; + textArea.prefHeightProperty().bindBidirectional(count); + changeListener = (ov, old, newVal) -> { + if (newVal.intValue() > rowHeight) + count.setValue(count.get() + newVal.intValue() + 10); + }; + textArea.scrollTopProperty().addListener(changeListener); + textArea.setScrollTop(30); + + addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("tradeDetailsWindow.tradeState"), trade.getState().getPhase().name()); + } + + Tuple3 tuple = add2ButtonsWithBox(gridPane, ++rowIndex, + Res.get("shared.viewContractAsJson"), Res.get("shared.close"), 15, false); + Button viewContractButton = tuple.first; + viewContractButton.setMaxWidth(Region.USE_COMPUTED_SIZE); + Button closeButton = tuple.second; + closeButton.setMaxWidth(Region.USE_COMPUTED_SIZE); + HBox hBox = tuple.third; + GridPane.setColumnSpan(hBox, 2); + Region spacer = new Region(); + HBox.setHgrow(spacer, Priority.ALWAYS); + hBox.getChildren().add(0, spacer); + if (contract != null) { - Button viewContractButton = addConfirmationLabelButton(gridPane, ++rowIndex, Res.get("shared.contractAsJson"), - Res.get("shared.viewContractAsJson"), 0).second; - viewContractButton.setDefaultButton(false); viewContractButton.setOnAction(e -> { TextArea textArea = new BisqTextArea(); textArea.setText(trade.getContractAsJson()); @@ -349,29 +379,6 @@ private void addContent() { }); } - if (trade.hasFailed()) { - textArea = addConfirmationLabelTextArea(gridPane, ++rowIndex, Res.get("shared.errorMessage"), "", 0).second; - textArea.setText(trade.getErrorMessage()); - textArea.setEditable(false); - //TODO paint red - - IntegerProperty count = new SimpleIntegerProperty(20); - int rowHeight = 10; - textArea.prefHeightProperty().bindBidirectional(count); - changeListener = (ov, old, newVal) -> { - if (newVal.intValue() > rowHeight) - count.setValue(count.get() + newVal.intValue() + 10); - }; - textArea.scrollTopProperty().addListener(changeListener); - textArea.setScrollTop(30); - - addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("tradeDetailsWindow.tradeState"), trade.getState().getPhase().name()); - } - - Button closeButton = addButtonAfterGroup(gridPane, ++rowIndex, Res.get("shared.close")); - GridPane.setColumnSpan(closeButton, 2); - //TODO app wide focus - //closeButton.requestFocus(); closeButton.setOnAction(e -> { closeHandlerOptional.ifPresent(Runnable::run); hide(); diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java index 70db4ad365e..0678c3c089e 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java @@ -364,7 +364,7 @@ private String getInvalidTradeDetails(Trade trade) { } if (trade.hasErrorMessage()) { - return Res.get("portfolio.pending.failedTrade.errorMsgSet"); + return Res.get("portfolio.pending.failedTrade.errorMsgSet", trade.getErrorMessage()); } return Res.get("shared.na"); From b958c7519b6982eb06c525cc03883c8ad46b9765 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 14:17:04 -0500 Subject: [PATCH 065/143] Add MakerRemovesOpenOffer task. Removes offer once the taker fee was published. So we ensure that maker fee is not lost if an error happens before that. --- .../trade/protocol/BuyerAsMakerProtocol.java | 19 +++++-- .../trade/protocol/BuyerAsTakerProtocol.java | 17 +++++-- .../core/trade/protocol/BuyerProtocol.java | 17 +------ .../trade/protocol/SellerAsMakerProtocol.java | 2 + .../tasks/maker/MakerRemovesOpenOffer.java | 49 +++++++++++++++++++ .../MakerSendsInputsForDepositTxResponse.java | 5 -- .../SellerAsMakerProcessDepositTxMessage.java | 8 ++- ...erProcessesInputsForDepositTxResponse.java | 5 +- 8 files changed, 91 insertions(+), 31 deletions(-) create mode 100644 core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerRemovesOpenOffer.java diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index dee6ffe8acf..71257f487c2 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -26,11 +26,16 @@ import bisq.core.trade.protocol.tasks.ApplyFilter; import bisq.core.trade.protocol.tasks.TradeTask; import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness; +import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest; +import bisq.core.trade.protocol.tasks.buyer.BuyerSendsDelayedPayoutTxSignatureResponse; import bisq.core.trade.protocol.tasks.buyer.BuyerSetupDepositTxListener; +import bisq.core.trade.protocol.tasks.buyer.BuyerSignsDelayedPayoutTx; +import bisq.core.trade.protocol.tasks.buyer.BuyerVerifiesPreparedDelayedPayoutTx; import bisq.core.trade.protocol.tasks.buyer_as_maker.BuyerAsMakerCreatesAndSignsDepositTx; import bisq.core.trade.protocol.tasks.buyer_as_maker.BuyerAsMakerSendsInputsForDepositTxResponse; import bisq.core.trade.protocol.tasks.maker.MakerCreateAndSignContract; import bisq.core.trade.protocol.tasks.maker.MakerProcessesInputsForDepositTxRequest; +import bisq.core.trade.protocol.tasks.maker.MakerRemovesOpenOffer; import bisq.core.trade.protocol.tasks.maker.MakerSetsLockTime; import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment; @@ -89,10 +94,18 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message, // Incoming messages Take offer process /////////////////////////////////////////////////////////////////////////////////////////// - // We keep the handler here in as well to make it more transparent which messages we expect - @Override protected void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { - super.handle(message, peer); + given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) + .with(message) + .from(peer)) + .setup(tasks( + BuyerProcessDelayedPayoutTxSignatureRequest.class, + MakerRemovesOpenOffer.class, + BuyerVerifiesPreparedDelayedPayoutTx.class, + BuyerSignsDelayedPayoutTx.class, + BuyerSendsDelayedPayoutTxSignatureResponse.class) + .withTimeout(30)) + .executeTasks(); } // We keep the handler here in as well to make it more transparent which messages we expect diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 7d5d3e21c15..78d89633891 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -29,7 +29,11 @@ import bisq.core.trade.protocol.tasks.ApplyFilter; import bisq.core.trade.protocol.tasks.TradeTask; import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness; +import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest; +import bisq.core.trade.protocol.tasks.buyer.BuyerSendsDelayedPayoutTxSignatureResponse; import bisq.core.trade.protocol.tasks.buyer.BuyerSetupDepositTxListener; +import bisq.core.trade.protocol.tasks.buyer.BuyerSignsDelayedPayoutTx; +import bisq.core.trade.protocol.tasks.buyer.BuyerVerifiesPreparedDelayedPayoutTx; import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerCreatesDepositTxInputs; import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerSendsDepositTxMessage; import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerSignsDepositTx; @@ -104,10 +108,17 @@ private void handle(InputsForDepositTxResponse message, NodeAddress peer) { .executeTasks(); } - // We keep the handler here in as well to make it more transparent which messages we expect - @Override protected void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { - super.handle(message, peer); + given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) + .with(message) + .from(peer)) + .setup(tasks( + BuyerProcessDelayedPayoutTxSignatureRequest.class, + BuyerVerifiesPreparedDelayedPayoutTx.class, + BuyerSignsDelayedPayoutTx.class, + BuyerSendsDelayedPayoutTxSignatureResponse.class) + .withTimeout(30)) + .executeTasks(); } // We keep the handler here in as well to make it more transparent which messages we expect 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 c15fb19428a..4136395e80d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java @@ -26,17 +26,13 @@ import bisq.core.trade.protocol.tasks.ApplyFilter; import bisq.core.trade.protocol.tasks.PublishTradeStatistics; import bisq.core.trade.protocol.tasks.TradeTask; -import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDelayedPayoutTxSignatureRequest; import bisq.core.trade.protocol.tasks.buyer.BuyerProcessDepositTxAndDelayedPayoutTxMessage; import bisq.core.trade.protocol.tasks.buyer.BuyerProcessPayoutTxPublishedMessage; import bisq.core.trade.protocol.tasks.buyer.BuyerSendCounterCurrencyTransferStartedMessage; -import bisq.core.trade.protocol.tasks.buyer.BuyerSendsDelayedPayoutTxSignatureResponse; import bisq.core.trade.protocol.tasks.buyer.BuyerSetupDepositTxListener; import bisq.core.trade.protocol.tasks.buyer.BuyerSetupPayoutTxListener; import bisq.core.trade.protocol.tasks.buyer.BuyerSignPayoutTx; -import bisq.core.trade.protocol.tasks.buyer.BuyerSignsDelayedPayoutTx; import bisq.core.trade.protocol.tasks.buyer.BuyerVerifiesFinalDelayedPayoutTx; -import bisq.core.trade.protocol.tasks.buyer.BuyerVerifiesPreparedDelayedPayoutTx; import bisq.network.p2p.NodeAddress; @@ -88,18 +84,7 @@ public void onMailboxMessage(TradeMessage message, NodeAddress peer) { } } - protected void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { - given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) - .with(message) - .from(peer)) - .setup(tasks( - BuyerProcessDelayedPayoutTxSignatureRequest.class, - BuyerVerifiesPreparedDelayedPayoutTx.class, - BuyerSignsDelayedPayoutTx.class, - BuyerSendsDelayedPayoutTxSignatureResponse.class) - .withTimeout(30)) - .executeTasks(); - } + protected abstract void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer); // The DepositTxAndDelayedPayoutTxMessage is a mailbox message as earlier we use only the deposit tx which can // be also with from the network once published. diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index e4df57ce96d..e57cb09b78a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -30,6 +30,7 @@ import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness; import bisq.core.trade.protocol.tasks.maker.MakerCreateAndSignContract; import bisq.core.trade.protocol.tasks.maker.MakerProcessesInputsForDepositTxRequest; +import bisq.core.trade.protocol.tasks.maker.MakerRemovesOpenOffer; import bisq.core.trade.protocol.tasks.maker.MakerSetsLockTime; import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment; import bisq.core.trade.protocol.tasks.seller.SellerCreatesDelayedPayoutTx; @@ -99,6 +100,7 @@ protected void handle(DepositTxMessage message, NodeAddress peer) { .from(peer)) .setup(tasks( SellerAsMakerProcessDepositTxMessage.class, + MakerRemovesOpenOffer.class, SellerAsMakerFinalizesDepositTx.class, SellerCreatesDelayedPayoutTx.class, SellerSendDelayedPayoutTxSignatureRequest.class) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerRemovesOpenOffer.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerRemovesOpenOffer.java new file mode 100644 index 00000000000..9c0ae01ad78 --- /dev/null +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerRemovesOpenOffer.java @@ -0,0 +1,49 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.trade.protocol.tasks.maker; + +import bisq.core.trade.Trade; +import bisq.core.trade.protocol.tasks.TradeTask; + +import bisq.common.taskrunner.TaskRunner; + +import lombok.extern.slf4j.Slf4j; + +import static com.google.common.base.Preconditions.checkNotNull; + +@Slf4j +public class MakerRemovesOpenOffer extends TradeTask { + public MakerRemovesOpenOffer(TaskRunner taskHandler, Trade trade) { + super(taskHandler, trade); + } + + @Override + protected void run() { + try { + runInterceptHook(); + + // Once the taker fee is published we remove our open offer + checkNotNull(trade.getTakerFeeTxId()); + processModel.getOpenOfferManager().closeOpenOffer(checkNotNull(trade.getOffer())); + + complete(); + } catch (Throwable t) { + failed(t); + } + } +} diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java index 92b63bae0c7..8831d8eab00 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerSendsInputsForDepositTxResponse.java @@ -90,11 +90,6 @@ protected void run() { trade.setState(Trade.State.MAKER_SENT_PUBLISH_DEPOSIT_TX_REQUEST); - // We could consider to remove the offer later once the deposit is published to reduce the risk - // of lost maker fee in case of a failed trade. The protocol has not maker specific tasks at that moment on - // so it would require a bit of extra work to add that (without using instance of checks...). - processModel.getOpenOfferManager().closeOpenOffer(checkNotNull(trade.getOffer())); - NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress(); log.info("Send {} to peer {}. tradeId={}, uid={}", message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerProcessDepositTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerProcessDepositTxMessage.java index 26dfd96b240..ea61b2fa506 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerProcessDepositTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerProcessDepositTxMessage.java @@ -42,11 +42,15 @@ protected void run() { DepositTxMessage message = (DepositTxMessage) processModel.getTradeMessage(); Validator.checkTradeId(processModel.getOfferId(), message); checkNotNull(message); - checkNotNull(message.getDepositTx()); - processModel.getTradingPeer().setPreparedDepositTx(message.getDepositTx()); + processModel.getTradingPeer().setPreparedDepositTx(checkNotNull(message.getDepositTx())); trade.setTradingPeerNodeAddress(processModel.getTempTradingPeerNodeAddress()); + // When we receive that message the taker has published the taker fee, so we apply it to the trade. + // The takerFeeTx was sent in the first message. It should be part of DelayedPayoutTxSignatureRequest + // but that cannot be changed due backward compatibility issues. It is a left over from the old trade protocol. + trade.setTakerFeeTxId(processModel.getTakeOfferFeeTxId()); + complete(); } catch (Throwable t) { failed(t); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java index 1aa4c5d213d..1a84e311c4f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerProcessesInputsForDepositTxResponse.java @@ -55,7 +55,8 @@ protected void run() { tradingPeer.setContractSignature(nonEmptyStringOf(response.getMakerContractSignature())); tradingPeer.setPayoutAddressString(nonEmptyStringOf(response.getMakerPayoutAddressString())); tradingPeer.setRawTransactionInputs(checkNotNull(response.getMakerInputs())); - processModel.setPreparedDepositTx(checkNotNull(response.getPreparedDepositTx())); + byte[] preparedDepositTx = checkNotNull(response.getPreparedDepositTx()); + processModel.setPreparedDepositTx(preparedDepositTx); long lockTime = response.getLockTime(); if (Config.baseCurrencyNetwork().isMainnet()) { int myLockTime = processModel.getBtcWalletService().getBestChainHeight() + @@ -72,7 +73,7 @@ protected void run() { // Maker has to sign preparedDepositTx. He cannot manipulate the preparedDepositTx - so we avoid to have a // challenge protocol for passing the nonce we want to get signed. - tradingPeer.setAccountAgeWitnessNonce(checkNotNull(response.getPreparedDepositTx())); + tradingPeer.setAccountAgeWitnessNonce(preparedDepositTx); tradingPeer.setAccountAgeWitnessSignature(checkNotNull(response.getAccountAgeWitnessSignatureOfPreparedDepositTx())); tradingPeer.setCurrentDate(response.getCurrentDate()); From 568dcdaad4c71ccaeb522fe81ce8d79d670f7fc6 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 15:32:49 -0500 Subject: [PATCH 066/143] Update tasks in debugview --- .../core/trade/protocol/SellerProtocol.java | 3 +- .../bisq/desktop/main/debug/DebugView.java | 46 ++++++++++++++++--- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java index 0927a453f5b..4d0ed2e06f1 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java @@ -34,7 +34,6 @@ import bisq.core.trade.protocol.tasks.seller.SellerSendsDepositTxAndDelayedPayoutTxMessage; import bisq.core.trade.protocol.tasks.seller.SellerSignAndFinalizePayoutTx; import bisq.core.trade.protocol.tasks.seller.SellerSignsDelayedPayoutTx; -import bisq.core.trade.protocol.tasks.taker.TakerVerifyMakerFeePayment; import bisq.network.p2p.NodeAddress; @@ -112,7 +111,7 @@ protected void handle(CounterCurrencyTransferStartedMessage message, NodeAddress .setup(tasks( SellerProcessCounterCurrencyTransferStartedMessage.class, ApplyFilter.class, - TakerVerifyMakerFeePayment.class)) //todo get TakerVerifyMakerFeePayment + getVerifyPeersFeePaymentClass())) .executeTasks(); } diff --git a/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java b/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java index c061ef0b954..4a3cbdfb7c3 100644 --- a/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java +++ b/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java @@ -43,9 +43,11 @@ import bisq.core.trade.protocol.tasks.buyer_as_maker.BuyerAsMakerCreatesAndSignsDepositTx; import bisq.core.trade.protocol.tasks.buyer_as_maker.BuyerAsMakerSendsInputsForDepositTxResponse; import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerCreatesDepositTxInputs; +import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerSendsDepositTxMessage; import bisq.core.trade.protocol.tasks.buyer_as_taker.BuyerAsTakerSignsDepositTx; import bisq.core.trade.protocol.tasks.maker.MakerCreateAndSignContract; import bisq.core.trade.protocol.tasks.maker.MakerProcessesInputsForDepositTxRequest; +import bisq.core.trade.protocol.tasks.maker.MakerRemovesOpenOffer; import bisq.core.trade.protocol.tasks.maker.MakerSetsLockTime; import bisq.core.trade.protocol.tasks.maker.MakerVerifyTakerFeePayment; import bisq.core.trade.protocol.tasks.seller.SellerBroadcastPayoutTx; @@ -60,6 +62,9 @@ import bisq.core.trade.protocol.tasks.seller.SellerSignAndFinalizePayoutTx; import bisq.core.trade.protocol.tasks.seller.SellerSignsDelayedPayoutTx; import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerCreatesUnsignedDepositTx; +import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerFinalizesDepositTx; +import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerProcessDepositTxMessage; +import bisq.core.trade.protocol.tasks.seller_as_maker.SellerAsMakerSendsInputsForDepositTxResponse; import bisq.core.trade.protocol.tasks.seller_as_taker.SellerAsTakerCreatesDepositTxInputs; import bisq.core.trade.protocol.tasks.seller_as_taker.SellerAsTakerSignsDepositTx; import bisq.core.trade.protocol.tasks.taker.CreateTakerFeeTx; @@ -130,6 +135,7 @@ public void initialize() { BuyerAsMakerSendsInputsForDepositTxResponse.class, BuyerProcessDelayedPayoutTxSignatureRequest.class, + MakerRemovesOpenOffer.class, BuyerVerifiesPreparedDelayedPayoutTx.class, BuyerSignsDelayedPayoutTx.class, BuyerSendsDelayedPayoutTxSignatureResponse.class, @@ -187,6 +193,7 @@ public void initialize() { //todo addGroup("BuyerAsTakerProtocol", FXCollections.observableArrayList(Arrays.asList( + ApplyFilter.class, TakerVerifyMakerFeePayment.class, CreateTakerFeeTx.class, BuyerAsTakerCreatesDepositTxInputs.class, @@ -194,37 +201,64 @@ public void initialize() { TakerProcessesInputsForDepositTxResponse.class, ApplyFilter.class, - TakerVerifyMakerFeePayment.class, + VerifyPeersAccountAgeWitness.class, TakerVerifyAndSignContract.class, + TakerPublishFeeTx.class, BuyerAsTakerSignsDepositTx.class, - SellerSendsDepositTxAndDelayedPayoutTxMessage.class, + BuyerSetupDepositTxListener.class, + BuyerAsTakerSendsDepositTxMessage.class, + + BuyerProcessDelayedPayoutTxSignatureRequest.class, + BuyerVerifiesPreparedDelayedPayoutTx.class, + BuyerSignsDelayedPayoutTx.class, + BuyerSendsDelayedPayoutTxSignatureResponse.class, + + BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, + BuyerVerifiesFinalDelayedPayoutTx.class, + PublishTradeStatistics.class, ApplyFilter.class, TakerVerifyMakerFeePayment.class, BuyerSignPayoutTx.class, + BuyerSetupPayoutTxListener.class, BuyerSendCounterCurrencyTransferStartedMessage.class, - BuyerSetupPayoutTxListener.class) + + BuyerProcessPayoutTxPublishedMessage.class) )); addGroup("SellerAsMakerProtocol", FXCollections.observableArrayList(Arrays.asList( MakerProcessesInputsForDepositTxRequest.class, ApplyFilter.class, + VerifyPeersAccountAgeWitness.class, MakerVerifyTakerFeePayment.class, + MakerSetsLockTime.class, MakerCreateAndSignContract.class, SellerAsMakerCreatesUnsignedDepositTx.class, - BuyerSetupDepositTxListener.class, + SellerAsMakerSendsInputsForDepositTxResponse.class, + SellerAsMakerProcessDepositTxMessage.class, + MakerRemovesOpenOffer.class, + SellerAsMakerFinalizesDepositTx.class, + SellerCreatesDelayedPayoutTx.class, + SellerSendDelayedPayoutTxSignatureRequest.class, + + SellerProcessDelayedPayoutTxSignatureResponse.class, + SellerSignsDelayedPayoutTx.class, + SellerFinalizesDelayedPayoutTx.class, + SellerSendsDepositTxAndDelayedPayoutTxMessage.class, + SellerPublishesDepositTx.class, PublishTradeStatistics.class, - MakerVerifyTakerFeePayment.class, SellerProcessCounterCurrencyTransferStartedMessage.class, + ApplyFilter.class, MakerVerifyTakerFeePayment.class, ApplyFilter.class, MakerVerifyTakerFeePayment.class, SellerSignAndFinalizePayoutTx.class, SellerBroadcastPayoutTx.class, - SellerSendPayoutTxPublishedMessage.class) + SellerSendPayoutTxPublishedMessage.class + ) )); } From 95cb3b271008f68ff6558450fb4c6e7ceb11668d Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 17:06:13 -0500 Subject: [PATCH 067/143] Fix deposit tx setters --- core/src/main/java/bisq/core/trade/Trade.java | 5 +- .../BuyerAsTakerSignsDepositTx.java | 2 +- .../SellerAsMakerFinalizesDepositTx.java | 2 +- .../tasks/taker/TakerPublishFeeTx.java | 52 +++++++++++-------- .../steps/buyer/BuyerStep2View.java | 5 +- 5 files changed, 38 insertions(+), 28 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index 9e163f53ba2..55be47724d7 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -123,7 +123,7 @@ public enum State { // maker perspective MAKER_SENT_PUBLISH_DEPOSIT_TX_REQUEST(Phase.TAKER_FEE_PUBLISHED), MAKER_SAW_ARRIVED_PUBLISH_DEPOSIT_TX_REQUEST(Phase.TAKER_FEE_PUBLISHED), - MAKER_STORED_IN_MAILBOX_PUBLISH_DEPOSIT_TX_REQUEST(Phase.TAKER_FEE_PUBLISHED), //todo remove + MAKER_STORED_IN_MAILBOX_PUBLISH_DEPOSIT_TX_REQUEST(Phase.TAKER_FEE_PUBLISHED), //not a mailbox msg, not used... MAKER_SEND_FAILED_PUBLISH_DEPOSIT_TX_REQUEST(Phase.TAKER_FEE_PUBLISHED), // taker perspective @@ -1232,8 +1232,9 @@ public void onFailure(@NotNull Throwable t) { private void setConfirmedState() { // we only apply the state if we are not already further in the process - if (!isDepositConfirmed()) + if (!isDepositConfirmed()) { setState(State.DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN); + } } @Override diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSignsDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSignsDepositTx.java index 95bdbb2b91b..50e302db54c 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSignsDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSignsDepositTx.java @@ -86,7 +86,7 @@ protected void run() { sellerInputs, buyerMultiSigPubKey, sellerMultiSigPubKey); - trade.applyDepositTx(depositTx); + processModel.setDepositTx(depositTx); complete(); } catch (Throwable t) { diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerFinalizesDepositTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerFinalizesDepositTx.java index 0a130b17dcd..1a580b2fc7f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerFinalizesDepositTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller_as_maker/SellerAsMakerFinalizesDepositTx.java @@ -46,7 +46,7 @@ protected void run() { int numTakersInputs = checkNotNull(processModel.getTradingPeer().getRawTransactionInputs()).size(); processModel.getTradeWalletService().sellerAsMakerFinalizesDepositTx(myDepositTx, takersDepositTx, numTakersInputs); - trade.applyDepositTx(myDepositTx); + processModel.setDepositTx(myDepositTx); complete(); } catch (Throwable t) { diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerPublishFeeTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerPublishFeeTx.java index a5da55a2d35..a1c4914a49e 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerPublishFeeTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerPublishFeeTx.java @@ -57,14 +57,12 @@ protected void run() { new TxBroadcaster.Callback() { @Override public void onSuccess(Transaction transaction) { - trade.setTakerFeeTxId(transaction.getTxId().toString()); - trade.setState(Trade.State.TAKER_PUBLISHED_TAKER_FEE_TX); - complete(); + TakerPublishFeeTx.this.onSuccess(transaction); } @Override public void onFailure(TxBroadcastException exception) { - failed(exception); + TakerPublishFeeTx.this.onFailure(exception); } }); } else { @@ -79,29 +77,12 @@ public void onFailure(TxBroadcastException exception) { new TxBroadcaster.Callback() { @Override public void onSuccess(@Nullable Transaction transaction) { - if (!completed) { - if (transaction != null) { - trade.setTakerFeeTxId(transaction.getTxId().toString()); - trade.setState(Trade.State.TAKER_PUBLISHED_TAKER_FEE_TX); - complete(); - } - } else { - log.warn("We got the onSuccess callback called after the timeout has been triggered a complete()."); - } + TakerPublishFeeTx.this.onSuccess(transaction); } @Override public void onFailure(TxBroadcastException exception) { - if (!completed) { - log.error(exception.toString()); - exception.printStackTrace(); - trade.setErrorMessage("An error occurred.\n" + - "Error message:\n" - + exception.getMessage()); - failed(exception); - } else { - log.warn("We got the onFailure callback called after the timeout has been triggered a complete()."); - } + TakerPublishFeeTx.this.onFailure(exception); } }, 1); @@ -110,4 +91,29 @@ public void onFailure(TxBroadcastException exception) { failed(t); } } + + protected void onFailure(TxBroadcastException exception) { + if (!completed) { + log.error(exception.toString()); + exception.printStackTrace(); + trade.setErrorMessage("An error occurred.\n" + + "Error message:\n" + + exception.getMessage()); + failed(exception); + } else { + log.warn("We got the onFailure callback called after the timeout has been triggered a complete()."); + } + } + + protected void onSuccess(@org.jetbrains.annotations.Nullable Transaction transaction) { + if (!completed) { + if (transaction != null) { + trade.setTakerFeeTxId(transaction.getTxId().toString()); + trade.setState(Trade.State.TAKER_PUBLISHED_TAKER_FEE_TX); + complete(); + } + } else { + log.warn("We got the onSuccess callback called after the timeout has been triggered a complete()."); + } + } } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java index 150c38bca25..a60d1dcd723 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java @@ -507,8 +507,11 @@ private void showConfirmPaymentStartedPopup() { private void confirmPaymentStarted() { busyAnimation.play(); statusLabel.setText(Res.get("shared.sendingConfirmation")); - if (trade.isFiatSent()) + + //TODO seems this was a hack to enable repeated confirm??? + if (trade.isFiatSent()) { trade.setState(Trade.State.DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN); + } model.dataModel.onPaymentStarted(() -> { }, errorMessage -> { From 3987f9cd5ad26148b64ad60b8d8bf451ce8f9e44 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 18:16:50 -0500 Subject: [PATCH 068/143] Fix incorrect getDepositTx calls --- core/src/main/java/bisq/core/trade/Trade.java | 2 +- .../core/trade/protocol/FluentProtocol.java | 26 ++++---- .../core/trade/protocol/TradeProtocol.java | 5 +- .../BuyerAsTakerSendsDepositTxMessage.java | 10 +-- .../bisq/desktop/main/debug/DebugView.java | 63 ++++++++++--------- .../pendingtrades/PendingTradesView.java | 7 ++- 6 files changed, 61 insertions(+), 52 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index 55be47724d7..eac9b39b75f 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -1010,7 +1010,7 @@ else if (blockTime < tradeTime) startTime = now; } } else { - log.warn("depositTx is null"); + log.warn("Cannot set TradeStartTime because depositTx is null. TradeId={}", getId()); startTime = now; } return startTime; diff --git a/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java b/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java index 6fa0ceb6907..91b4f29cd3f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java @@ -187,7 +187,7 @@ public boolean isValid() { boolean isTradeIdValid = message == null || isTradeIdValid(trade.getId(), message); if (!allPreConditionsMet) { - log.error("PreConditions not met. preConditions={}, this={}", preConditions, this); + log.error("PreConditions not met. preConditions={}, this={}, tradeId={}", preConditions, this, trade.getId()); if (preConditionFailedHandler != null) { preConditionFailedHandler.run(); } @@ -215,17 +215,19 @@ private boolean isPhaseValid() { event.name() + " event" : ""; if (isPhaseValid) { - log.info("We received {} at phase {} and state {}", + log.info("We received {} at phase {} and state {}, tradeId={}", trigger, trade.getPhase(), - trade.getState()); + trade.getState(), + trade.getId()); } else { - log.error("We received {} but we are are not in the correct phase. Expected phases={}, " + - "Trade phase={}, Trade state= {} ", + log.error("We received {} but we are are not in the expected phase. Expected phases={}, " + + "Trade phase={}, Trade state= {}, tradeId={}", trigger, expectedPhases, trade.getPhase(), - trade.getState()); + trade.getState(), + trade.getId()); } return isPhaseValid; @@ -243,15 +245,17 @@ private boolean isStateValid() { event.name() + " event" : ""; if (isStateValid) { - log.info("We received {} at state {}", + log.info("We received {} at state {}, tradeId={}", trigger, - trade.getState()); + trade.getState(), + trade.getId()); } else { - log.error("We received {} but we are are not in the correct state. Expected states={}, " + - "Trade state= {} ", + log.error("We received {} but we are are not in the expected state. Expected states={}, " + + "Trade state= {}, tradeId={}", trigger, expectedStates, - trade.getState()); + trade.getState(), + trade.getId()); } return isStateValid; diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index 5b88845737c..885b2d4d0c0 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -97,7 +97,7 @@ protected void onMailboxMessage(TradeMessage message, NodeAddress peerNodeAddres public void onDirectMessage(DecryptedMessageWithPubKey message, NodeAddress peer) { if (isPubKeyValid(message)) { NetworkEnvelope networkEnvelope = message.getNetworkEnvelope(); - if (networkEnvelope instanceof TradeMessage) { + if (networkEnvelope instanceof TradeMessage && isMyTradeMessage((TradeMessage) networkEnvelope)) { onTradeMessage((TradeMessage) networkEnvelope, peer); } else if (networkEnvelope instanceof AckMessage) { onAckMessage((AckMessage) networkEnvelope, peer); @@ -292,6 +292,9 @@ private void handleTaskRunnerFault(@Nullable TradeMessage message, String source cleanup(); } + private boolean isMyTradeMessage(TradeMessage message) { + return message.getTradeId().equals(trade.getId()); + } private void cleanup() { stopTimeout(); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSendsDepositTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSendsDepositTxMessage.java index 81e82464eef..08682bce8b4 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSendsDepositTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer_as_taker/BuyerAsTakerSendsDepositTxMessage.java @@ -40,13 +40,11 @@ public BuyerAsTakerSendsDepositTxMessage(TaskRunner taskHandler, Trade tr protected void run() { try { runInterceptHook(); - if (trade.getDepositTx() != null) { + if (processModel.getDepositTx() != null) { DepositTxMessage message = new DepositTxMessage(UUID.randomUUID().toString(), processModel.getOfferId(), processModel.getMyNodeAddress(), - trade.getDepositTx().bitcoinSerialize()); - - // todo trade.setState + processModel.getDepositTx().bitcoinSerialize()); NodeAddress peersNodeAddress = trade.getTradingPeerNodeAddress(); log.info("Send {} to peer {}. tradeId={}, uid={}", @@ -60,7 +58,6 @@ protected void run() { public void onArrived() { log.info("{} arrived at peer {}. tradeId={}, uid={}", message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid()); - // todo trade.setState complete(); } @@ -69,14 +66,13 @@ public void onFault(String errorMessage) { log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}", message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage); - // todo trade.setState appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage); failed(); } } ); } else { - log.error("trade.getDepositTx() = " + trade.getDepositTx()); + log.error("processModel.getDepositTx() = " + processModel.getDepositTx()); failed("DepositTx is null"); } } catch (Throwable t) { diff --git a/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java b/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java index 4a3cbdfb7c3..86b0c4d0d05 100644 --- a/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java +++ b/desktop/src/main/java/bisq/desktop/main/debug/DebugView.java @@ -122,37 +122,7 @@ public void initialize() { AddToOfferBook.class) )); - addGroup("BuyerAsMakerProtocol", - FXCollections.observableArrayList(Arrays.asList( - MakerProcessesInputsForDepositTxRequest.class, - ApplyFilter.class, - VerifyPeersAccountAgeWitness.class, - MakerVerifyTakerFeePayment.class, - MakerSetsLockTime.class, - MakerCreateAndSignContract.class, - BuyerAsMakerCreatesAndSignsDepositTx.class, - BuyerSetupDepositTxListener.class, - BuyerAsMakerSendsInputsForDepositTxResponse.class, - BuyerProcessDelayedPayoutTxSignatureRequest.class, - MakerRemovesOpenOffer.class, - BuyerVerifiesPreparedDelayedPayoutTx.class, - BuyerSignsDelayedPayoutTx.class, - BuyerSendsDelayedPayoutTxSignatureResponse.class, - - BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, - BuyerVerifiesFinalDelayedPayoutTx.class, - PublishTradeStatistics.class, - - ApplyFilter.class, - MakerVerifyTakerFeePayment.class, - BuyerSignPayoutTx.class, - BuyerSetupPayoutTxListener.class, - BuyerSendCounterCurrencyTransferStartedMessage.class, - - BuyerProcessPayoutTxPublishedMessage.class - ) - )); addGroup("SellerAsTakerProtocol", FXCollections.observableArrayList(Arrays.asList( ApplyFilter.class, @@ -189,8 +159,39 @@ public void initialize() { ) )); + addGroup("BuyerAsMakerProtocol", + FXCollections.observableArrayList(Arrays.asList( + MakerProcessesInputsForDepositTxRequest.class, + ApplyFilter.class, + VerifyPeersAccountAgeWitness.class, + MakerVerifyTakerFeePayment.class, + MakerSetsLockTime.class, + MakerCreateAndSignContract.class, + BuyerAsMakerCreatesAndSignsDepositTx.class, + BuyerSetupDepositTxListener.class, + BuyerAsMakerSendsInputsForDepositTxResponse.class, + + BuyerProcessDelayedPayoutTxSignatureRequest.class, + MakerRemovesOpenOffer.class, + BuyerVerifiesPreparedDelayedPayoutTx.class, + BuyerSignsDelayedPayoutTx.class, + BuyerSendsDelayedPayoutTxSignatureResponse.class, + + BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, + BuyerVerifiesFinalDelayedPayoutTx.class, + PublishTradeStatistics.class, + + ApplyFilter.class, + MakerVerifyTakerFeePayment.class, + BuyerSignPayoutTx.class, + BuyerSetupPayoutTxListener.class, + BuyerSendCounterCurrencyTransferStartedMessage.class, + + BuyerProcessPayoutTxPublishedMessage.class + ) + )); + - //todo addGroup("BuyerAsTakerProtocol", FXCollections.observableArrayList(Arrays.asList( ApplyFilter.class, diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java index 0678c3c089e..e96c704afda 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java @@ -227,7 +227,7 @@ public void initialize() { } }; - tradesListChangeListener = c -> updateNewChatMessagesByTradeMap(); + tradesListChangeListener = c -> onListChanged(); } @Override @@ -540,6 +540,11 @@ private void updateTableSelection() { } } + private void onListChanged() { + updateNewChatMessagesByTradeMap(); + updateMoveTradeToFailedColumnState(); + } + /////////////////////////////////////////////////////////////////////////////////////////// // CellFactories /////////////////////////////////////////////////////////////////////////////////////////// From dceba6d35030286eeb977be834dd670abb9f07c3 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 20:09:31 -0500 Subject: [PATCH 069/143] Bug fix: we created a new address entry which causes bugs in case a user takes an offer again which failed in an early preparation state before. --- .../core/trade/protocol/tasks/taker/CreateTakerFeeTx.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java index 1363f3e0236..e2dd1ed13b2 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/CreateTakerFeeTx.java @@ -53,8 +53,8 @@ protected void run() { // appear as unused and therefore selected for the outputs for the MS tx. // That would cause incorrect display of the balance as // the change output would be considered as not available balance (part of the locked trade amount). - walletService.getNewAddressEntry(id, AddressEntry.Context.MULTI_SIG); - walletService.getNewAddressEntry(id, AddressEntry.Context.TRADE_PAYOUT); + walletService.getOrCreateAddressEntry(id, AddressEntry.Context.MULTI_SIG); + walletService.getOrCreateAddressEntry(id, AddressEntry.Context.TRADE_PAYOUT); AddressEntry fundingAddressEntry = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.OFFER_FUNDING); AddressEntry reservedForTradeAddressEntry = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.RESERVED_FOR_TRADE); From 98dec09c18801a2bbbbaad94c7bcbddc076b4c50 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 21:10:20 -0500 Subject: [PATCH 070/143] Rename given method to expect to make it more clear that it is mandatory that the condition is met. Also added a protocol error handler if the condition is not met. For more tolerant usage we added the given method, which does not log errors and does not call a error handler. --- core/src/main/java/bisq/core/trade/Trade.java | 7 +- .../trade/protocol/BuyerAsMakerProtocol.java | 4 +- .../trade/protocol/BuyerAsTakerProtocol.java | 6 +- .../core/trade/protocol/BuyerProtocol.java | 8 +- .../core/trade/protocol/FluentProtocol.java | 142 +++++++++++++----- .../trade/protocol/SellerAsMakerProtocol.java | 4 +- .../trade/protocol/SellerAsTakerProtocol.java | 4 +- .../core/trade/protocol/SellerProtocol.java | 6 +- .../core/trade/protocol/TradeProtocol.java | 22 ++- 9 files changed, 141 insertions(+), 62 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index eac9b39b75f..b4ae19aac9c 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -730,8 +730,9 @@ public void applyDepositTx(Transaction tx) { @Nullable public Transaction getDepositTx() { - if (depositTx == null) + if (depositTx == null) { depositTx = depositTxId != null ? btcWalletService.getTransaction(depositTxId) : null; + } return depositTx; } @@ -985,9 +986,9 @@ private long getMaxTradePeriod() { } private long getTradeStartTime() { - final long now = System.currentTimeMillis(); + long now = System.currentTimeMillis(); long startTime; - final Transaction depositTx = getDepositTx(); + Transaction depositTx = getDepositTx(); if (depositTx != null && getTakeOfferDate() != null) { if (depositTx.getConfidence().getDepthInBlocks() > 0) { final long tradeTime = getTakeOfferDate().getTime(); diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 71257f487c2..a6d32ecf679 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -66,7 +66,7 @@ public BuyerAsMakerProtocol(BuyerAsMakerTrade trade) { public void handleTakeOfferRequest(InputsForDepositTxRequest message, NodeAddress peer, ErrorMessageHandler errorMessageHandler) { - given(phase(Trade.Phase.INIT) + expect(phase(Trade.Phase.INIT) .with(message) .from(peer)) .setup(tasks( @@ -95,7 +95,7 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message, /////////////////////////////////////////////////////////////////////////////////////////// protected void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { - given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) + expect(phase(Trade.Phase.TAKER_FEE_PUBLISHED) .with(message) .from(peer)) .setup(tasks( diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 78d89633891..1e08c09ee4f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -74,7 +74,7 @@ public BuyerAsTakerProtocol(BuyerAsTakerTrade trade) { @Override public void onTakeOffer() { - given(phase(Trade.Phase.INIT) + expect(phase(Trade.Phase.INIT) .with(TakerEvent.TAKE_OFFER)) .setup(tasks( ApplyFilter.class, @@ -93,7 +93,7 @@ public void onTakeOffer() { /////////////////////////////////////////////////////////////////////////////////////////// private void handle(InputsForDepositTxResponse message, NodeAddress peer) { - given(phase(Trade.Phase.INIT) + expect(phase(Trade.Phase.INIT) .with(message) .from(peer)) .setup(tasks(TakerProcessesInputsForDepositTxResponse.class, @@ -109,7 +109,7 @@ private void handle(InputsForDepositTxResponse message, NodeAddress peer) { } protected void handle(DelayedPayoutTxSignatureRequest message, NodeAddress peer) { - given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) + expect(phase(Trade.Phase.TAKER_FEE_PUBLISHED) .with(message) .from(peer)) .setup(tasks( 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 4136395e80d..a382e9015e4 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java @@ -55,6 +55,8 @@ enum BuyerEvent implements FluentProtocol.Event { public BuyerProtocol(BuyerTrade trade) { super(trade); + // We get called the constructor with any possible state and phase. As we don't want to log an error for such + // cases we use the alternative 'given' method instead of 'expect'. given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) .with(BuyerEvent.STARTUP)) .setup(tasks(BuyerSetupDepositTxListener.class)) @@ -95,7 +97,7 @@ public void onMailboxMessage(TradeMessage message, NodeAddress peer) { // mailbox message but the stored in mailbox case is not expected and the seller would try to send the message again // in the hope to reach the buyer directly. protected void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress peer) { - given(anyPhase(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) + expect(anyPhase(Trade.Phase.TAKER_FEE_PUBLISHED, Trade.Phase.DEPOSIT_PUBLISHED) .with(message) .from(peer) .preCondition(trade.getDepositTx() == null || trade.getDelayedPayoutTx() == null, @@ -126,7 +128,7 @@ protected void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress pe public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { BuyerEvent event = BuyerEvent.PAYMENT_SENT; - given(phase(Trade.Phase.DEPOSIT_CONFIRMED) + expect(phase(Trade.Phase.DEPOSIT_CONFIRMED) .with(event) .preCondition(!wasDisputed())) .setup(tasks(ApplyFilter.class, @@ -152,7 +154,7 @@ public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandle /////////////////////////////////////////////////////////////////////////////////////////// protected void handle(PayoutTxPublishedMessage message, NodeAddress peer) { - given(anyPhase(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) + expect(anyPhase(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) .with(message) .from(peer)) .setup(tasks(BuyerProcessPayoutTxPublishedMessage.class)) diff --git a/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java b/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java index 91b4f29cd3f..0edefd3a8a6 100644 --- a/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java @@ -24,8 +24,11 @@ import bisq.common.taskrunner.Task; +import java.text.MessageFormat; + import java.util.HashSet; import java.util.Set; +import java.util.function.Consumer; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -38,6 +41,8 @@ // Main class. Contains the condition and setup, if condition is valid it will execute the // taskRunner and the optional runnable. public class FluentProtocol { + + interface Event { String name(); } @@ -45,6 +50,7 @@ interface Event { private final TradeProtocol tradeProtocol; private Condition condition; private Setup setup; + private Consumer resultHandler; public FluentProtocol(TradeProtocol tradeProtocol) { this.tradeProtocol = tradeProtocol; @@ -60,16 +66,26 @@ protected FluentProtocol setup(Setup setup) { return this; } + + public FluentProtocol resultHandler(Consumer resultHandler) { + this.resultHandler = resultHandler; + return this; + } + // Can be used before or after executeTasks public FluentProtocol run(Runnable runnable) { - if (condition.isValid()) { + Condition.Result result = condition.getResult(); + if (result.isValid) { runnable.run(); + } else if (resultHandler != null) { + resultHandler.accept(result); } return this; } public FluentProtocol executeTasks() { - if (condition.isValid()) { + Condition.Result result = condition.getResult(); + if (result.isValid) { if (setup.getTimeoutSec() > 0) { tradeProtocol.startTimeout(setup.getTimeoutSec()); } @@ -87,6 +103,8 @@ public FluentProtocol executeTasks() { TradeTaskRunner taskRunner = setup.getTaskRunner(message, condition.getEvent()); taskRunner.addTasks(setup.getTasks()); taskRunner.run(); + } else if (resultHandler != null) { + resultHandler.accept(result); } return this; } @@ -98,10 +116,37 @@ public FluentProtocol executeTasks() { @Slf4j public static class Condition { + enum Result { + VALID(true), + INVALID_PHASE, + INVALID_STATE, + INVALID_PRE_CONDITION, + INVALID_TRADE_ID; + + @Getter + private boolean isValid; + @Getter + private String info; + + Result() { + } + + Result(boolean isValid) { + this.isValid = isValid; + } + + public Result info(String info) { + this.info = info; + return this; + } + } + private final Set expectedPhases = new HashSet<>(); private final Set expectedStates = new HashSet<>(); private final Set preConditions = new HashSet<>(); private final Trade trade; + @Nullable + private Result result; @Nullable @Getter @@ -115,97 +160,110 @@ public static class Condition { @Nullable private Runnable preConditionFailedHandler; - private boolean isValid; - private boolean isValidated; // We validate only once public Condition(Trade trade) { this.trade = trade; } public Condition phase(Trade.Phase expectedPhase) { - checkArgument(!isValidated); + checkArgument(result == null); this.expectedPhases.add(expectedPhase); return this; } public Condition anyPhase(Trade.Phase... expectedPhases) { - checkArgument(!isValidated); + checkArgument(result == null); this.expectedPhases.addAll(Set.of(expectedPhases)); return this; } public Condition state(Trade.State state) { - checkArgument(!isValidated); + checkArgument(result == null); this.expectedStates.add(state); return this; } public Condition anyState(Trade.State... states) { - checkArgument(!isValidated); + checkArgument(result == null); this.expectedStates.addAll(Set.of(states)); return this; } public Condition with(TradeMessage message) { - checkArgument(!isValidated); + checkArgument(result == null); this.message = message; return this; } public Condition with(Event event) { - checkArgument(!isValidated); + checkArgument(result == null); this.event = event; return this; } public Condition from(NodeAddress peer) { - checkArgument(!isValidated); + checkArgument(result == null); this.peer = peer; return this; } public Condition preCondition(boolean preCondition) { - checkArgument(!isValidated); + checkArgument(result == null); preConditions.add(preCondition); return this; } public Condition preCondition(boolean preCondition, Runnable conditionFailedHandler) { - checkArgument(!isValidated); + checkArgument(result == null); preCondition(preCondition); this.preConditionFailedHandler = conditionFailedHandler; return this; } - public boolean isValid() { - if (!isValidated) { - boolean isPhaseValid = isPhaseValid(); - boolean isStateValid = isStateValid(); - - boolean allPreConditionsMet = preConditions.stream().allMatch(e -> e); + public Result getResult() { + if (result == null) { boolean isTradeIdValid = message == null || isTradeIdValid(trade.getId(), message); + if (!isTradeIdValid) { + String info = MessageFormat.format("TradeId does not match tradeId in message, TradeId={0}, tradeId in message={1}", + trade.getId(), message.getTradeId()); + result = Result.INVALID_TRADE_ID.info(info); + return result; + } + + + Result phaseValidationResult = getPhaseResult(); + if (!phaseValidationResult.isValid) { + result = phaseValidationResult; + return result; + } + + Result stateResult = getStateResult(); + if (!stateResult.isValid) { + result = stateResult; + return result; + } + boolean allPreConditionsMet = preConditions.stream().allMatch(e -> e); if (!allPreConditionsMet) { - log.error("PreConditions not met. preConditions={}, this={}, tradeId={}", preConditions, this, trade.getId()); + String info = MessageFormat.format("PreConditions not met. preConditions={0}, this={1}, tradeId={2}", + preConditions, this, trade.getId()); + result = Result.INVALID_PRE_CONDITION.info(info); + if (preConditionFailedHandler != null) { preConditionFailedHandler.run(); } - } - if (!isTradeIdValid) { - log.error("TradeId does not match tradeId in message, TradeId={}, tradeId in message={}", - trade.getId(), message.getTradeId()); + return result; } - isValid = isPhaseValid && isStateValid && allPreConditionsMet && isTradeIdValid; - isValidated = true; + result = Result.VALID; } - return isValid; + return result; } - private boolean isPhaseValid() { + private Result getPhaseResult() { if (expectedPhases.isEmpty()) { - return true; + return Result.VALID; } boolean isPhaseValid = expectedPhases.stream().anyMatch(e -> e == trade.getPhase()); @@ -215,27 +273,28 @@ private boolean isPhaseValid() { event.name() + " event" : ""; if (isPhaseValid) { - log.info("We received {} at phase {} and state {}, tradeId={}", + String info = MessageFormat.format("We received {0} at phase {1} and state {2}, tradeId={3}", trigger, trade.getPhase(), trade.getState(), trade.getId()); + log.info(info); + return Result.VALID.info(info); } else { - log.error("We received {} but we are are not in the expected phase. Expected phases={}, " + - "Trade phase={}, Trade state= {}, tradeId={}", + String info = MessageFormat.format("We received {0} but we are are not in the expected phase. " + + "Expected phases={1}, Trade phase={2}, Trade state= {3}, tradeId={4}", trigger, expectedPhases, trade.getPhase(), trade.getState(), trade.getId()); + return Result.INVALID_PHASE.info(info); } - - return isPhaseValid; } - private boolean isStateValid() { + private Result getStateResult() { if (expectedStates.isEmpty()) { - return true; + return Result.VALID; } boolean isStateValid = expectedStates.stream().anyMatch(e -> e == trade.getState()); @@ -245,20 +304,21 @@ private boolean isStateValid() { event.name() + " event" : ""; if (isStateValid) { - log.info("We received {} at state {}, tradeId={}", + String info = MessageFormat.format("We received {0} at state {1}, tradeId={2}", trigger, trade.getState(), trade.getId()); + log.info(info); + return Result.VALID.info(info); } else { - log.error("We received {} but we are are not in the expected state. Expected states={}, " + - "Trade state= {}, tradeId={}", + String info = MessageFormat.format("We received {0} but we are are not in the expected state. " + + "Expected states={1}, Trade state= {2}, tradeId={3}", trigger, expectedStates, trade.getState(), trade.getId()); + return Result.INVALID_STATE.info(info); } - - return isStateValid; } } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index e57cb09b78a..7e38c4db294 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -67,7 +67,7 @@ public SellerAsMakerProtocol(SellerAsMakerTrade trade) { public void handleTakeOfferRequest(InputsForDepositTxRequest message, NodeAddress peer, ErrorMessageHandler errorMessageHandler) { - given(phase(Trade.Phase.INIT) + expect(phase(Trade.Phase.INIT) .with(message) .from(peer)) .setup(tasks( @@ -95,7 +95,7 @@ public void handleTakeOfferRequest(InputsForDepositTxRequest message, /////////////////////////////////////////////////////////////////////////////////////////// protected void handle(DepositTxMessage message, NodeAddress peer) { - given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) + expect(phase(Trade.Phase.TAKER_FEE_PUBLISHED) .with(message) .from(peer)) .setup(tasks( diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 8d777a3ab8d..f3a360d9ef6 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -69,7 +69,7 @@ public SellerAsTakerProtocol(SellerAsTakerTrade trade) { @Override public void onTakeOffer() { - given(phase(Trade.Phase.INIT) + expect(phase(Trade.Phase.INIT) .with(TakerEvent.TAKE_OFFER) .from(trade.getTradingPeerNodeAddress())) .setup(tasks( @@ -88,7 +88,7 @@ public void onTakeOffer() { /////////////////////////////////////////////////////////////////////////////////////////// private void handle(InputsForDepositTxResponse message, NodeAddress peer) { - given(phase(Trade.Phase.INIT) + expect(phase(Trade.Phase.INIT) .with(message) .from(peer)) .setup(tasks( diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java index 4d0ed2e06f1..e2014b548bc 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java @@ -71,7 +71,7 @@ public void onMailboxMessage(TradeMessage message, NodeAddress peerNodeAddress) /////////////////////////////////////////////////////////////////////////////////////////// protected void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer) { - given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) + expect(phase(Trade.Phase.TAKER_FEE_PUBLISHED) .with(message) .from(peer)) .setup(tasks(SellerProcessDelayedPayoutTxSignatureResponse.class, @@ -97,7 +97,7 @@ protected void handle(DelayedPayoutTxSignatureResponse message, NodeAddress peer /////////////////////////////////////////////////////////////////////////////////////////// protected void handle(CounterCurrencyTransferStartedMessage message, NodeAddress peer) { - given(phase(Trade.Phase.DEPOSIT_CONFIRMED) + expect(phase(Trade.Phase.DEPOSIT_CONFIRMED) .with(message) .from(peer) .preCondition(trade.getPayoutTx() == null, @@ -121,7 +121,7 @@ protected void handle(CounterCurrencyTransferStartedMessage message, NodeAddress public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { SellerEvent event = SellerEvent.PAYMENT_RECEIVED; - given(phase(Trade.Phase.FIAT_SENT) + expect(phase(Trade.Phase.FIAT_SENT) .with(event) .preCondition(!wasDisputed())) .setup(tasks( diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index 885b2d4d0c0..252aab97032 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -117,8 +117,24 @@ public void onDirectMessage(DecryptedMessageWithPubKey message, NodeAddress peer // FluentProtocol /////////////////////////////////////////////////////////////////////////////////////////// + // We log an error if condition is not met and call the protocol error handler + protected FluentProtocol expect(FluentProtocol.Condition condition) { + return new FluentProtocol(this) + .condition(condition) + .resultHandler(result -> { + if (!result.isValid()) { + log.error(result.getInfo()); + handleTaskRunnerFault(null, + result.name(), + result.getInfo()); + } + }); + } + + // We execute only if condition is met but do not log an error. protected FluentProtocol given(FluentProtocol.Condition condition) { - return new FluentProtocol(this).condition(condition); + return new FluentProtocol(this) + .condition(condition); } protected FluentProtocol.Condition phase(Trade.Phase expectedPhase) { @@ -277,13 +293,13 @@ private boolean isPubKeyValid(DecryptedMessageWithPubKey message) { /////////////////////////////////////////////////////////////////////////////////////////// private void handleTaskRunnerSuccess(@Nullable TradeMessage message, String source) { - log.info("TaskRunner successfully completed. Triggered from {}", source); + log.info("TaskRunner successfully completed. Triggered from {}, tradeId={}", source, trade.getId()); if (message != null) { sendAckMessage(message, true, null); } } - private void handleTaskRunnerFault(@Nullable TradeMessage message, String source, String errorMessage) { + void handleTaskRunnerFault(@Nullable TradeMessage message, String source, String errorMessage) { log.error("Task runner failed with error {}. Triggered from {}", errorMessage, source); if (message != null) { From 3cc633f39fb9aac0b07e2c38caca3ec3c81793bb Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 21:30:19 -0500 Subject: [PATCH 071/143] Add check if trade was already taken in the past. If so show a popup at take offer screen. We could deactivate such offers as well but as it is only for exceptional cases I think this way is good enough (would be more effort otherwise). --- .../src/main/java/bisq/core/trade/TradeManager.java | 13 ++++++++++++- .../core/trade/protocol/BuyerAsTakerProtocol.java | 3 ++- .../core/trade/protocol/SellerAsTakerProtocol.java | 3 ++- .../main/resources/i18n/displayStrings.properties | 3 ++- .../main/offer/takeoffer/TakeOfferDataModel.java | 2 ++ 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index fc54866f089..70ee264222a 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -105,6 +105,8 @@ import javax.annotation.Nullable; +import static com.google.common.base.Preconditions.checkArgument; + public class TradeManager implements PersistedDataHost { private static final Logger log = LoggerFactory.getLogger(TradeManager.class); @@ -413,7 +415,10 @@ public void onTakeOffer(Coin amount, boolean useSavingsWallet, TradeResultHandler tradeResultHandler, ErrorMessageHandler errorMessageHandler) { - final OfferAvailabilityModel model = getOfferAvailabilityModel(offer); + + checkArgument(!wasOfferAlreadyUsedInTrade(offer.getId())); + + OfferAvailabilityModel model = getOfferAvailabilityModel(offer); offer.checkOfferAvailability(model, () -> { if (offer.getState() == Offer.State.AVAILABLE) { @@ -775,4 +780,10 @@ else if (now.after(halfTradePeriodDate)) public void persistTrades() { tradableList.persist(); } + + public boolean wasOfferAlreadyUsedInTrade(String offerId) { + return getTradeById(offerId).isPresent() || + failedTradesManager.getTradeById(offerId).isPresent() || + closedTradableManager.getTradableById(offerId).isPresent(); + } } diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 1e08c09ee4f..2d00ea0d000 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -75,7 +75,8 @@ public BuyerAsTakerProtocol(BuyerAsTakerTrade trade) { @Override public void onTakeOffer() { expect(phase(Trade.Phase.INIT) - .with(TakerEvent.TAKE_OFFER)) + .with(TakerEvent.TAKE_OFFER) + .preCondition(!processModel.getTradeManager().wasOfferAlreadyUsedInTrade(trade.getId()))) .setup(tasks( ApplyFilter.class, getVerifyPeersFeePaymentClass(), diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index f3a360d9ef6..3f7f0d9bede 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -71,7 +71,8 @@ public SellerAsTakerProtocol(SellerAsTakerTrade trade) { public void onTakeOffer() { expect(phase(Trade.Phase.INIT) .with(TakerEvent.TAKE_OFFER) - .from(trade.getTradingPeerNodeAddress())) + .from(trade.getTradingPeerNodeAddress()) + .preCondition(!processModel.getTradeManager().wasOfferAlreadyUsedInTrade(trade.getId()))) .setup(tasks( ApplyFilter.class, getVerifyPeersFeePaymentClass(), diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 78b6d9cf458..091c6d90c0f 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -408,7 +408,8 @@ offerbook.warning.tradeLimitNotMatching=Your payment account has been created {0 Your trade limit is: {1}\n\ The min. trade amount of the offer is: {2}.\n\n\ You cannot take that offer at the moment. Once your account is older than 2 months this restriction gets removed. - +offerbook.warning.offerWasAlreadyUsedInTrade=You cannot take that offer because you have taken it already earlier. \ + It might be that the take offer attempt ended up in a failed trade. offerbook.info.sellAtMarketPrice=You will sell at market price (updated every minute). offerbook.info.buyAtMarketPrice=You will buy at market price (updated every minute). diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java index b807d030039..4e143747009 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java @@ -320,6 +320,8 @@ void onTakeOffer(TradeResultHandler tradeResultHandler) { new Popup().warning(Res.get("offerbook.warning.nodeBlocked")).show(); } else if (filterManager.requireUpdateToNewVersionForTrading()) { new Popup().warning(Res.get("offerbook.warning.requireUpdateToNewVersion")).show(); + } else if (tradeManager.wasOfferAlreadyUsedInTrade(offer.getId())) { + new Popup().warning(Res.get("offerbook.warning.offerWasAlreadyUsedInTrade")).show(); } else { tradeManager.onTakeOffer(amount.get(), txFeeFromFeeService, From 612ecd3a6a7bb9dc4b6fb133a4917bdcde2fb44b Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 21:32:27 -0500 Subject: [PATCH 072/143] Rename onFiatPaymentReceived to onPaymentReceived --- .../java/bisq/core/trade/SellerTrade.java | 4 ++-- .../java/bisq/core/trade/TradeManager.java | 20 ++++++++++++++----- .../trade/protocol/SellerAsMakerProtocol.java | 4 ++-- .../trade/protocol/SellerAsTakerProtocol.java | 4 ++-- .../core/trade/protocol/SellerProtocol.java | 2 +- .../trade/txproof/xmr/XmrTxProofService.java | 2 +- .../pendingtrades/PendingTradesDataModel.java | 2 +- 7 files changed, 24 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/SellerTrade.java b/core/src/main/java/bisq/core/trade/SellerTrade.java index 68eed3a1e08..068695c730b 100644 --- a/core/src/main/java/bisq/core/trade/SellerTrade.java +++ b/core/src/main/java/bisq/core/trade/SellerTrade.java @@ -83,9 +83,9 @@ public abstract class SellerTrade extends Trade { btcWalletService); } - public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + public void onPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { checkArgument(tradeProtocol instanceof SellerProtocol, "tradeProtocol NOT instanceof SellerProtocol"); - ((SellerProtocol) tradeProtocol).onFiatPaymentReceived(resultHandler, errorMessageHandler); + ((SellerProtocol) tradeProtocol).onPaymentReceived(resultHandler, errorMessageHandler); } @Override diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 70ee264222a..317cfc7a981 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -232,6 +232,11 @@ public TradeManager(User user, failedTradesManager.setUnfailTradeCallback(this::unfailTrade); } + + /////////////////////////////////////////////////////////////////////////////////////////// + // PersistedDataHost + /////////////////////////////////////////////////////////////////////////////////////////// + @Override public void readPersisted() { tradableList = new TradableList<>(tradableListStorage, "PendingTrades"); @@ -247,7 +252,7 @@ public void readPersisted() { /////////////////////////////////////////////////////////////////////////////////////////// - // Lifecycle + // API /////////////////////////////////////////////////////////////////////////////////////////// public void onAllServicesInitialized() { @@ -278,6 +283,11 @@ public void shutDown() { // Do nothing here } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Private + /////////////////////////////////////////////////////////////////////////////////////////// + private void initPendingTrades() { tradableList.forEach(this::initPendingTrade); pendingTradesInitialized.set(true); @@ -290,10 +300,10 @@ private void initPendingTrade(Trade trade) { trade.updateDepositTxFromWallet(); } - public void onUserConfirmedFiatPaymentReceived(SellerTrade sellerTrade, - ResultHandler resultHandler, - ErrorMessageHandler errorMessageHandler) { - sellerTrade.onFiatPaymentReceived(resultHandler, errorMessageHandler); + public void onPaymentReceived(SellerTrade sellerTrade, + ResultHandler resultHandler, + ErrorMessageHandler errorMessageHandler) { + sellerTrade.onPaymentReceived(resultHandler, errorMessageHandler); } private void onTradesChanged() { diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index 7e38c4db294..b2c7ea7415e 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -132,8 +132,8 @@ protected void handle(CounterCurrencyTransferStartedMessage message, NodeAddress // We keep the handler here in as well to make it more transparent which messages we expect @Override - public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - super.onFiatPaymentReceived(resultHandler, errorMessageHandler); + public void onPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + super.onPaymentReceived(resultHandler, errorMessageHandler); } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 3f7f0d9bede..5ac1ae2562f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -129,8 +129,8 @@ protected void handle(CounterCurrencyTransferStartedMessage message, NodeAddress // We keep the handler here in as well to make it more transparent which messages we expect @Override - public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - super.onFiatPaymentReceived(resultHandler, errorMessageHandler); + public void onPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + super.onPaymentReceived(resultHandler, errorMessageHandler); } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java index e2014b548bc..af9c5690a0b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java @@ -119,7 +119,7 @@ protected void handle(CounterCurrencyTransferStartedMessage message, NodeAddress // User interaction /////////////////////////////////////////////////////////////////////////////////////////// - public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + public void onPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { SellerEvent event = SellerEvent.PAYMENT_RECEIVED; expect(phase(Trade.Phase.FIAT_SENT) .with(event) diff --git a/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java b/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java index 5c83364cabb..51e85bca505 100644 --- a/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java +++ b/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java @@ -263,7 +263,7 @@ private void startRequests(SellerTrade trade) { log.info("We auto-confirm trade {} as our all our services for the tx proof completed successfully", trade.getShortId()); log.info("###########################################################################################"); - trade.onFiatPaymentReceived(() -> { + trade.onPaymentReceived(() -> { }, errorMessage -> { }); } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java index ee6343ef0b0..08aabd9481a 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -192,7 +192,7 @@ public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler er public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { checkNotNull(getTrade(), "trade must not be null"); checkArgument(getTrade() instanceof SellerTrade, "Trade must be instance of SellerTrade"); - tradeManager.onUserConfirmedFiatPaymentReceived((SellerTrade) getTrade(), resultHandler, errorMessageHandler); + tradeManager.onPaymentReceived((SellerTrade) getTrade(), resultHandler, errorMessageHandler); } public void onWithdrawRequest(String toAddress, From a002fb33a5c01ae98c5489f434feb2767f38f188 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 21:33:53 -0500 Subject: [PATCH 073/143] Rename onFiatPaymentStarted to onPaymentStarted --- core/src/main/java/bisq/core/trade/BuyerTrade.java | 4 ++-- .../java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java | 6 +++--- .../java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java | 6 +++--- .../main/java/bisq/core/trade/protocol/BuyerProtocol.java | 2 +- .../bisq/core/trade/protocol/SellerAsMakerProtocol.java | 2 +- .../bisq/core/trade/protocol/SellerAsTakerProtocol.java | 2 +- .../portfolio/pendingtrades/PendingTradesDataModel.java | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/BuyerTrade.java b/core/src/main/java/bisq/core/trade/BuyerTrade.java index 4112252e6d6..c6e75fbc071 100644 --- a/core/src/main/java/bisq/core/trade/BuyerTrade.java +++ b/core/src/main/java/bisq/core/trade/BuyerTrade.java @@ -84,9 +84,9 @@ public abstract class BuyerTrade extends Trade { btcWalletService); } - public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { checkArgument(tradeProtocol instanceof BuyerProtocol, "Check failed: tradeProtocol instanceof BuyerProtocol"); - ((BuyerProtocol) tradeProtocol).onFiatPaymentStarted(resultHandler, errorMessageHandler); + ((BuyerProtocol) tradeProtocol).onPaymentStarted(resultHandler, errorMessageHandler); } @Override diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index a6d32ecf679..00bd26494e0 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -119,10 +119,10 @@ protected void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress pe // User interaction /////////////////////////////////////////////////////////////////////////////////////////// - // We keep the handler here in as well to make it more transparent which messages we expect + // We keep the handler here in as well to make it more transparent which events we expect @Override - public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - super.onFiatPaymentStarted(resultHandler, errorMessageHandler); + public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + super.onPaymentStarted(resultHandler, errorMessageHandler); } diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 2d00ea0d000..ac45bf55a86 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -133,10 +133,10 @@ protected void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress pe // User interaction /////////////////////////////////////////////////////////////////////////////////////////// - // We keep the handler here in as well to make it more transparent which messages we expect + // We keep the handler here in as well to make it more transparent which events we expect @Override - public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - super.onFiatPaymentStarted(resultHandler, errorMessageHandler); + public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + super.onPaymentStarted(resultHandler, errorMessageHandler); } 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 a382e9015e4..5142c8238d5 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java @@ -126,7 +126,7 @@ protected void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress pe // User interaction /////////////////////////////////////////////////////////////////////////////////////////// - public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { BuyerEvent event = BuyerEvent.PAYMENT_SENT; expect(phase(Trade.Phase.DEPOSIT_CONFIRMED) .with(event) diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index b2c7ea7415e..c8b62f6b488 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -130,7 +130,7 @@ protected void handle(CounterCurrencyTransferStartedMessage message, NodeAddress // User interaction /////////////////////////////////////////////////////////////////////////////////////////// - // We keep the handler here in as well to make it more transparent which messages we expect + // We keep the handler here in as well to make it more transparent which events we expect @Override public void onPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { super.onPaymentReceived(resultHandler, errorMessageHandler); diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 5ac1ae2562f..3ec07279797 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -127,7 +127,7 @@ protected void handle(CounterCurrencyTransferStartedMessage message, NodeAddress // User interaction /////////////////////////////////////////////////////////////////////////////////////////// - // We keep the handler here in as well to make it more transparent which messages we expect + // We keep the handler here in as well to make it more transparent which events we expect @Override public void onPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { super.onPaymentReceived(resultHandler, errorMessageHandler); diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java index 08aabd9481a..8ec9432324c 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -186,7 +186,7 @@ public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler er Trade trade = getTrade(); checkNotNull(trade, "trade must not be null"); checkArgument(trade instanceof BuyerTrade, "Check failed: trade instanceof BuyerTrade"); - ((BuyerTrade) trade).onFiatPaymentStarted(resultHandler, errorMessageHandler); + ((BuyerTrade) trade).onPaymentStarted(resultHandler, errorMessageHandler); } public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { From 7023b2acf50fe2883969e9e56211e60f8d9977e0 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 21:35:34 -0500 Subject: [PATCH 074/143] Remove onPaymentReceived method from TradeManager --- core/src/main/java/bisq/core/trade/TradeManager.java | 6 ------ .../portfolio/pendingtrades/PendingTradesDataModel.java | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 317cfc7a981..af84e22229f 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -300,12 +300,6 @@ private void initPendingTrade(Trade trade) { trade.updateDepositTxFromWallet(); } - public void onPaymentReceived(SellerTrade sellerTrade, - ResultHandler resultHandler, - ErrorMessageHandler errorMessageHandler) { - sellerTrade.onPaymentReceived(resultHandler, errorMessageHandler); - } - private void onTradesChanged() { this.numPendingTrades.set(tradableList.getList().size()); } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java index 8ec9432324c..88e2d0affcc 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -192,7 +192,7 @@ public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler er public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { checkNotNull(getTrade(), "trade must not be null"); checkArgument(getTrade() instanceof SellerTrade, "Trade must be instance of SellerTrade"); - tradeManager.onPaymentReceived((SellerTrade) getTrade(), resultHandler, errorMessageHandler); + ((SellerTrade) getTrade()).onPaymentReceived(resultHandler, errorMessageHandler); } public void onWithdrawRequest(String toAddress, From a5f4cb8e85801dfbe9407db54ae68f43fad9167e Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 21:38:06 -0500 Subject: [PATCH 075/143] Refactor: use getTradableList instead of tradableList.getList() --- core/src/main/java/bisq/core/trade/TradeManager.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index af84e22229f..22bbcf81e73 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -268,7 +268,7 @@ public void onUpdatedDataReceived() { } }); - tradableList.getList().addListener((ListChangeListener) change -> onTradesChanged()); + getTradableList().addListener((ListChangeListener) change -> onTradesChanged()); onTradesChanged(); getAddressEntriesForAvailableBalanceStream() @@ -301,7 +301,7 @@ private void initPendingTrade(Trade trade) { } private void onTradesChanged() { - this.numPendingTrades.set(tradableList.getList().size()); + this.numPendingTrades.set(getTradableList().size()); } private void handlePayDepositRequest(InputsForDepositTxRequest inputsForDepositTxRequest, NodeAddress peer) { @@ -766,7 +766,7 @@ public void onMinuteTick() { } private void updateTradePeriodState() { - tradableList.getList().forEach(trade -> { + getTradableList().forEach(trade -> { if (!trade.isPayoutPublished()) { Date maxTradePeriodDate = trade.getMaxTradePeriodDate(); Date halfTradePeriodDate = trade.getHalfTradePeriodDate(); From 6af9cb3dfeb43ea890943830434e4917d5895759 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 21:38:49 -0500 Subject: [PATCH 076/143] Refactor: rename getTradableList to getTradesAsObservableList --- core/src/main/java/bisq/core/app/BisqSetup.java | 2 +- core/src/main/java/bisq/core/btc/Balances.java | 2 +- .../bisq/core/notifications/alerts/TradeEvents.java | 4 ++-- .../core/support/traderchat/TraderChatManager.java | 2 +- core/src/main/java/bisq/core/trade/TradeManager.java | 10 +++++----- .../bisq/core/trade/txproof/xmr/XmrTxProofService.java | 4 ++-- .../src/main/java/bisq/desktop/main/MainViewModel.java | 2 +- .../altcoinaccounts/AltCoinAccountsDataModel.java | 2 +- .../content/fiataccounts/FiatAccountsDataModel.java | 2 +- .../bisq/desktop/main/funds/locked/LockedView.java | 4 ++-- .../bisq/desktop/main/funds/reserved/ReservedView.java | 4 ++-- .../main/funds/transactions/TradableRepository.java | 2 +- .../desktop/main/funds/withdrawal/WithdrawalView.java | 2 +- .../overlays/notifications/NotificationCenter.java | 4 ++-- .../pendingtrades/PendingTradesDataModel.java | 6 +++--- 15 files changed, 26 insertions(+), 26 deletions(-) diff --git a/core/src/main/java/bisq/core/app/BisqSetup.java b/core/src/main/java/bisq/core/app/BisqSetup.java index eb222b700ff..6901eec8faf 100644 --- a/core/src/main/java/bisq/core/app/BisqSetup.java +++ b/core/src/main/java/bisq/core/app/BisqSetup.java @@ -762,7 +762,7 @@ private void initDomainServices() { }, 1); }); - tradeManager.getTradableList().stream() + tradeManager.getTradesAsObservableList().stream() .filter(trade -> trade.getOffer() != null) .forEach(trade -> { String details = null; diff --git a/core/src/main/java/bisq/core/btc/Balances.java b/core/src/main/java/bisq/core/btc/Balances.java index a38904bdb15..537d15db9ab 100644 --- a/core/src/main/java/bisq/core/btc/Balances.java +++ b/core/src/main/java/bisq/core/btc/Balances.java @@ -80,7 +80,7 @@ public Balances(TradeManager tradeManager, public void onAllServicesInitialized() { openOfferManager.getObservableList().addListener((ListChangeListener) c -> updateBalance()); - tradeManager.getTradableList().addListener((ListChangeListener) change -> updateBalance()); + tradeManager.getTradesAsObservableList().addListener((ListChangeListener) change -> updateBalance()); refundManager.getDisputesAsObservableList().addListener((ListChangeListener) c -> updateBalance()); btcWalletService.addBalanceListener(new BalanceListener() { @Override diff --git a/core/src/main/java/bisq/core/notifications/alerts/TradeEvents.java b/core/src/main/java/bisq/core/notifications/alerts/TradeEvents.java index adef19d1b1c..007583885ce 100644 --- a/core/src/main/java/bisq/core/notifications/alerts/TradeEvents.java +++ b/core/src/main/java/bisq/core/notifications/alerts/TradeEvents.java @@ -53,13 +53,13 @@ public TradeEvents(TradeManager tradeManager, KeyRing keyRing, MobileNotificatio } public void onAllServicesInitialized() { - tradeManager.getTradableList().addListener((ListChangeListener) c -> { + tradeManager.getTradesAsObservableList().addListener((ListChangeListener) c -> { c.next(); if (c.wasAdded()) { c.getAddedSubList().forEach(this::setTradePhaseListener); } }); - tradeManager.getTradableList().forEach(this::setTradePhaseListener); + tradeManager.getTradesAsObservableList().forEach(this::setTradePhaseListener); } private void setTradePhaseListener(Trade trade) { diff --git a/core/src/main/java/bisq/core/support/traderchat/TraderChatManager.java b/core/src/main/java/bisq/core/support/traderchat/TraderChatManager.java index a7c404a5346..e4562f48bf6 100644 --- a/core/src/main/java/bisq/core/support/traderchat/TraderChatManager.java +++ b/core/src/main/java/bisq/core/support/traderchat/TraderChatManager.java @@ -102,7 +102,7 @@ public PubKeyRing getPeerPubKeyRing(ChatMessage message) { @Override public List getAllChatMessages() { - return tradeManager.getTradableList().stream() + return tradeManager.getTradesAsObservableList().stream() .flatMap(trade -> trade.getChatMessages().stream()) .collect(Collectors.toList()); } diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 22bbcf81e73..eed3ba79610 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -268,7 +268,7 @@ public void onUpdatedDataReceived() { } }); - getTradableList().addListener((ListChangeListener) change -> onTradesChanged()); + getTradesAsObservableList().addListener((ListChangeListener) change -> onTradesChanged()); onTradesChanged(); getAddressEntriesForAvailableBalanceStream() @@ -301,7 +301,7 @@ private void initPendingTrade(Trade trade) { } private void onTradesChanged() { - this.numPendingTrades.set(getTradableList().size()); + this.numPendingTrades.set(getTradesAsObservableList().size()); } private void handlePayDepositRequest(InputsForDepositTxRequest inputsForDepositTxRequest, NodeAddress peer) { @@ -675,7 +675,7 @@ public void onFailure(TxBroadcastException exception) { // Getters /////////////////////////////////////////////////////////////////////////////////////////// - public ObservableList getTradableList() { + public ObservableList getTradesAsObservableList() { return tradableList.getList(); } @@ -709,7 +709,7 @@ public Stream getAddressEntriesForAvailableBalanceStream() { } public Stream getTradesStreamWithFundsLockedIn() { - return getTradableList().stream() + return getTradesAsObservableList().stream() .filter(Trade::isFundsLockedIn); } @@ -766,7 +766,7 @@ public void onMinuteTick() { } private void updateTradePeriodState() { - getTradableList().forEach(trade -> { + getTradesAsObservableList().forEach(trade -> { if (!trade.isPayoutPublished()) { Date maxTradePeriodDate = trade.getMaxTradePeriodDate(); Date halfTradePeriodDate = trade.getHalfTradePeriodDate(); diff --git a/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java b/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java index 51e85bca505..a8e0294e3fd 100644 --- a/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java +++ b/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java @@ -181,7 +181,7 @@ private void onP2pNetworkAndWalletReady() { }); // We listen on new trades - ObservableList tradableList = tradeManager.getTradableList(); + ObservableList tradableList = tradeManager.getTradesAsObservableList(); tradableList.addListener((ListChangeListener) c -> { c.next(); if (c.wasAdded()) { @@ -238,7 +238,7 @@ private void startRequestsIfValid(SellerTrade trade) { return; } - if (wasTxKeyReUsed(trade, tradeManager.getTradableList())) { + if (wasTxKeyReUsed(trade, tradeManager.getTradesAsObservableList())) { trade.setAssetTxProofResult(AssetTxProofResult.INVALID_DATA .details(Res.get("portfolio.pending.autoConf.state.xmr.txKeyReused"))); return; diff --git a/desktop/src/main/java/bisq/desktop/main/MainViewModel.java b/desktop/src/main/java/bisq/desktop/main/MainViewModel.java index 0af0cb5ba0c..941c28fc051 100644 --- a/desktop/src/main/java/bisq/desktop/main/MainViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/MainViewModel.java @@ -219,7 +219,7 @@ public void onSetupComplete() { if (newValue) { tradeManager.applyTradePeriodState(); - tradeManager.getTradableList().forEach(trade -> { + tradeManager.getTradesAsObservableList().forEach(trade -> { Date maxTradePeriodDate = trade.getMaxTradePeriodDate(); String key; switch (trade.getTradePeriodState()) { diff --git a/desktop/src/main/java/bisq/desktop/main/account/content/altcoinaccounts/AltCoinAccountsDataModel.java b/desktop/src/main/java/bisq/desktop/main/account/content/altcoinaccounts/AltCoinAccountsDataModel.java index 4d315a9293b..99a4570dcf9 100644 --- a/desktop/src/main/java/bisq/desktop/main/account/content/altcoinaccounts/AltCoinAccountsDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/account/content/altcoinaccounts/AltCoinAccountsDataModel.java @@ -130,7 +130,7 @@ public boolean onDeleteAccount(PaymentAccount paymentAccount) { .filter(o -> o.getOffer().getMakerPaymentAccountId().equals(paymentAccount.getId())) .findAny() .isPresent(); - isPaymentAccountUsed = isPaymentAccountUsed || tradeManager.getTradableList().stream() + isPaymentAccountUsed = isPaymentAccountUsed || tradeManager.getTradesAsObservableList().stream() .filter(t -> t.getOffer().getMakerPaymentAccountId().equals(paymentAccount.getId()) || paymentAccount.getId().equals(t.getTakerPaymentAccountId())) .findAny() diff --git a/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsDataModel.java b/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsDataModel.java index a9b5f3baccf..bbc2c86f7f7 100644 --- a/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsDataModel.java @@ -136,7 +136,7 @@ public void onSaveNewAccount(PaymentAccount paymentAccount) { public boolean onDeleteAccount(PaymentAccount paymentAccount) { boolean isPaymentAccountUsed = openOfferManager.getObservableList().stream() .anyMatch(o -> o.getOffer().getMakerPaymentAccountId().equals(paymentAccount.getId())); - isPaymentAccountUsed = isPaymentAccountUsed || tradeManager.getTradableList().stream() + isPaymentAccountUsed = isPaymentAccountUsed || tradeManager.getTradesAsObservableList().stream() .anyMatch(t -> t.getOffer().getMakerPaymentAccountId().equals(paymentAccount.getId()) || paymentAccount.getId().equals(t.getTakerPaymentAccountId())); if (!isPaymentAccountUsed) diff --git a/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedView.java b/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedView.java index dcdc8e4891d..6206a56a3ac 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedView.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedView.java @@ -143,7 +143,7 @@ public void onBalanceChanged(Coin balance, Transaction tx) { @Override protected void activate() { openOfferManager.getObservableList().addListener(openOfferListChangeListener); - tradeManager.getTradableList().addListener(tradeListChangeListener); + tradeManager.getTradesAsObservableList().addListener(tradeListChangeListener); sortedList.comparatorProperty().bind(tableView.comparatorProperty()); tableView.setItems(sortedList); updateList(); @@ -154,7 +154,7 @@ protected void activate() { @Override protected void deactivate() { openOfferManager.getObservableList().removeListener(openOfferListChangeListener); - tradeManager.getTradableList().removeListener(tradeListChangeListener); + tradeManager.getTradesAsObservableList().removeListener(tradeListChangeListener); sortedList.comparatorProperty().unbind(); observableList.forEach(LockedListItem::cleanup); btcWalletService.removeBalanceListener(balanceListener); diff --git a/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedView.java b/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedView.java index fc485d31ebf..3d8c6b10e0c 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedView.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedView.java @@ -143,7 +143,7 @@ public void onBalanceChanged(Coin balance, Transaction tx) { @Override protected void activate() { openOfferManager.getObservableList().addListener(openOfferListChangeListener); - tradeManager.getTradableList().addListener(tradeListChangeListener); + tradeManager.getTradesAsObservableList().addListener(tradeListChangeListener); sortedList.comparatorProperty().bind(tableView.comparatorProperty()); tableView.setItems(sortedList); updateList(); @@ -154,7 +154,7 @@ protected void activate() { @Override protected void deactivate() { openOfferManager.getObservableList().removeListener(openOfferListChangeListener); - tradeManager.getTradableList().removeListener(tradeListChangeListener); + tradeManager.getTradesAsObservableList().removeListener(tradeListChangeListener); sortedList.comparatorProperty().unbind(); observableList.forEach(ReservedListItem::cleanup); btcWalletService.removeBalanceListener(balanceListener); diff --git a/desktop/src/main/java/bisq/desktop/main/funds/transactions/TradableRepository.java b/desktop/src/main/java/bisq/desktop/main/funds/transactions/TradableRepository.java index f81fece8374..d780d79058d 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/transactions/TradableRepository.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/transactions/TradableRepository.java @@ -51,7 +51,7 @@ public class TradableRepository { Set getAll() { return ImmutableSet.builder() .addAll(openOfferManager.getObservableList()) - .addAll(tradeManager.getTradableList()) + .addAll(tradeManager.getTradesAsObservableList()) .addAll(closedTradableManager.getClosedTradables()) .addAll(failedTradesManager.getFailedTrades()) .build(); diff --git a/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java b/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java index 9c5af4c2997..e4750bb07dd 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java @@ -392,7 +392,7 @@ public void onSuccess(@javax.annotation.Nullable Transaction transaction) { log.error("onWithdraw transaction is null"); } - List trades = new ArrayList<>(tradeManager.getTradableList()); + List trades = new ArrayList<>(tradeManager.getTradesAsObservableList()); trades.stream() .filter(Trade::isPayoutPublished) .forEach(trade -> walletService.getAddressEntry(trade.getId(), AddressEntry.Context.TRADE_PAYOUT) diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/notifications/NotificationCenter.java b/desktop/src/main/java/bisq/desktop/main/overlays/notifications/NotificationCenter.java index 01bb8b768e9..1da0754ca52 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/notifications/NotificationCenter.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/notifications/NotificationCenter.java @@ -109,7 +109,7 @@ public NotificationCenter(TradeManager tradeManager, } public void onAllServicesAndViewsInitialized() { - tradeManager.getTradableList().addListener((ListChangeListener) change -> { + tradeManager.getTradesAsObservableList().addListener((ListChangeListener) change -> { change.next(); if (change.wasRemoved()) { change.getRemoved().stream().forEach(trade -> { @@ -147,7 +147,7 @@ public void onAllServicesAndViewsInitialized() { } }); - tradeManager.getTradableList().stream() + tradeManager.getTradesAsObservableList().stream() .forEach(trade -> { String tradeId = trade.getId(); Subscription disputeStateSubscription = EasyBind.subscribe(trade.disputeStateProperty(), diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java index 88e2d0affcc..30bad95c291 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -159,7 +159,7 @@ public PendingTradesDataModel(TradeManager tradeManager, @Override protected void activate() { - tradeManager.getTradableList().addListener(tradesListChangeListener); + tradeManager.getTradesAsObservableList().addListener(tradesListChangeListener); onListChanged(); if (selectedItemProperty.get() != null) notificationCenter.setSelectedTradeId(selectedItemProperty.get().getTrade().getId()); @@ -169,7 +169,7 @@ protected void activate() { @Override protected void deactivate() { - tradeManager.getTradableList().removeListener(tradesListChangeListener); + tradeManager.getTradesAsObservableList().removeListener(tradesListChangeListener); notificationCenter.setSelectedTradeId(null); activated = false; } @@ -373,7 +373,7 @@ public String getReference() { private void onListChanged() { list.clear(); - list.addAll(tradeManager.getTradableList().stream().map(PendingTradesListItem::new).collect(Collectors.toList())); + list.addAll(tradeManager.getTradesAsObservableList().stream().map(PendingTradesListItem::new).collect(Collectors.toList())); // we sort by date, earliest first list.sort((o1, o2) -> o2.getTrade().getDate().compareTo(o1.getTrade().getDate())); From 5d312ae1bada12baaf3e073cd264a64fd8af7208 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 21:43:56 -0500 Subject: [PATCH 077/143] Refactor: add TODOs --- .../main/java/bisq/core/presentation/TradePresentation.java | 3 +++ core/src/main/java/bisq/core/trade/TradeManager.java | 2 ++ 2 files changed, 5 insertions(+) diff --git a/core/src/main/java/bisq/core/presentation/TradePresentation.java b/core/src/main/java/bisq/core/presentation/TradePresentation.java index 678f827b590..e7f43c7f538 100644 --- a/core/src/main/java/bisq/core/presentation/TradePresentation.java +++ b/core/src/main/java/bisq/core/presentation/TradePresentation.java @@ -36,6 +36,9 @@ public class TradePresentation { @Inject public TradePresentation(TradeManager tradeManager) { + // TODO replace for tradeManager.getTradesAsObservableList() once tradableList is refactored to a final field + // (part of the persistence refactor PR) + tradeManager.getNumPendingTrades().addListener((observable, oldValue, newValue) -> { long numPendingTrades = (long) newValue; if (numPendingTrades > 0) diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index eed3ba79610..da6ede7313c 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -300,6 +300,8 @@ private void initPendingTrade(Trade trade) { trade.updateDepositTxFromWallet(); } + // TODO Remove once tradableList is refactored to a final field + // (part of the persistence refactor PR) private void onTradesChanged() { this.numPendingTrades.set(getTradesAsObservableList().size()); } From 86569b1b2d7699bdb38714d9235590da7852df86 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 21:58:32 -0500 Subject: [PATCH 078/143] Apply fluent protocol to MediationProtocol Rename acceptMediationResult to onAcceptMediationResult --- .../dispute/mediation/MediationManager.java | 6 +- .../trade/protocol/MediationProtocol.java | 146 +++++++++--------- .../pendingtrades/steps/TradeStepView.java | 2 +- 3 files changed, 74 insertions(+), 80 deletions(-) diff --git a/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java b/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java index 10ded4ead7d..20387a7a512 100644 --- a/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java +++ b/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java @@ -222,9 +222,9 @@ public NodeAddress getAgentNodeAddress(Dispute dispute) { return dispute.getContract().getMediatorNodeAddress(); } - public void acceptMediationResult(Trade trade, - ResultHandler resultHandler, - ErrorMessageHandler errorMessageHandler) { + public void onAcceptMediationResult(Trade trade, + ResultHandler resultHandler, + ErrorMessageHandler errorMessageHandler) { String tradeId = trade.getId(); Optional optionalDispute = findDispute(tradeId); checkArgument(optionalDispute.isPresent(), "dispute must be present"); diff --git a/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java b/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java index a90ce705690..cd6777b430a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java @@ -56,61 +56,64 @@ protected boolean wasDisputed() { return trade.getDisputeState() != Trade.DisputeState.NO_DISPUTE; } + /////////////////////////////////////////////////////////////////////////////////////////// // User interaction: Trader accepts mediation result /////////////////////////////////////////////////////////////////////////////////////////// // Trader has not yet received the peer's signature but has clicked the accept button. public void onAcceptMediationResult(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - if (trade.getProcessModel().getTradingPeer().getMediatedPayoutTxSignature() != null) { - errorMessageHandler.handleErrorMessage("We have received already the signature from the peer."); - return; - } DisputeEvent event = DisputeEvent.MEDIATION_RESULT_ACCEPTED; - TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess(event); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(event, errorMessage); - }); - taskRunner.addTasks( - ApplyFilter.class, - SignMediatedPayoutTx.class, - SendMediatedPayoutSignatureMessage.class, - SetupMediatedPayoutTxListener.class - ); - taskRunner.run(); + expect(anyPhase(Trade.Phase.DEPOSIT_CONFIRMED, + Trade.Phase.FIAT_SENT, + Trade.Phase.FIAT_RECEIVED) + .with(event) + .preCondition(trade.getProcessModel().getTradingPeer().getMediatedPayoutTxSignature() == null, + () -> errorMessageHandler.handleErrorMessage("We have received already the signature from the peer.")) + .preCondition(trade.getPayoutTx() == null, + () -> errorMessageHandler.handleErrorMessage("Payout tx is already published."))) + .setup(tasks(ApplyFilter.class, + SignMediatedPayoutTx.class, + SendMediatedPayoutSignatureMessage.class, + SetupMediatedPayoutTxListener.class) + .using(new TradeTaskRunner(trade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess(event); + }, + errorMessage -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(event, errorMessage); + })) + .withTimeout(30)) + .executeTasks(); } - // Trader has already received the peer's signature and has clicked the accept button as well. public void onFinalizeMediationResultPayout(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - if (trade.getPayoutTx() != null) { - errorMessageHandler.handleErrorMessage("Payout tx is already published."); - return; - } - DisputeEvent event = DisputeEvent.MEDIATION_RESULT_ACCEPTED; - TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> { - resultHandler.handleResult(); - handleTaskRunnerSuccess(event); - }, - (errorMessage) -> { - errorMessageHandler.handleErrorMessage(errorMessage); - handleTaskRunnerFault(event, errorMessage); - }); - taskRunner.addTasks( - ApplyFilter.class, - SignMediatedPayoutTx.class, - FinalizeMediatedPayoutTx.class, - BroadcastMediatedPayoutTx.class, - SendMediatedPayoutTxPublishedMessage.class - ); - taskRunner.run(); + expect(anyPhase(Trade.Phase.DEPOSIT_CONFIRMED, + Trade.Phase.FIAT_SENT, + Trade.Phase.FIAT_RECEIVED) + .with(event) + .preCondition(trade.getPayoutTx() == null, + () -> errorMessageHandler.handleErrorMessage("Payout tx is already published."))) + .setup(tasks(ApplyFilter.class, + SignMediatedPayoutTx.class, + FinalizeMediatedPayoutTx.class, + BroadcastMediatedPayoutTx.class, + SendMediatedPayoutTxPublishedMessage.class) + .using(new TradeTaskRunner(trade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess(event); + }, + errorMessage -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(event, errorMessage); + })) + .withTimeout(30)) + .executeTasks(); } @@ -119,31 +122,25 @@ public void onFinalizeMediationResultPayout(ResultHandler resultHandler, ErrorMe /////////////////////////////////////////////////////////////////////////////////////////// protected void handle(MediatedPayoutTxSignatureMessage message, NodeAddress peer) { - processModel.setTradeMessage(message); - processModel.setTempTradingPeerNodeAddress(peer); - - TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(message), - errorMessage -> handleTaskRunnerFault(message, errorMessage)); - - taskRunner.addTasks( - ProcessMediatedPayoutSignatureMessage.class - ); - taskRunner.run(); + expect(anyPhase(Trade.Phase.DEPOSIT_CONFIRMED, + Trade.Phase.FIAT_SENT, + Trade.Phase.FIAT_RECEIVED) + .with(message) + .from(peer)) + .setup(tasks(ProcessMediatedPayoutSignatureMessage.class) + .withTimeout(30)) + .executeTasks(); } protected void handle(MediatedPayoutTxPublishedMessage message, NodeAddress peer) { - processModel.setTradeMessage(message); - processModel.setTempTradingPeerNodeAddress(peer); - - TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(message), - errorMessage -> handleTaskRunnerFault(message, errorMessage)); - - taskRunner.addTasks( - ProcessMediatedPayoutTxPublishedMessage.class - ); - taskRunner.run(); + expect(anyPhase(Trade.Phase.DEPOSIT_CONFIRMED, + Trade.Phase.FIAT_SENT, + Trade.Phase.FIAT_RECEIVED) + .with(message) + .from(peer)) + .setup(tasks(ProcessMediatedPayoutTxPublishedMessage.class) + .withTimeout(30)) + .executeTasks(); } @@ -152,17 +149,14 @@ protected void handle(MediatedPayoutTxPublishedMessage message, NodeAddress peer /////////////////////////////////////////////////////////////////////////////////////////// private void handle(PeerPublishedDelayedPayoutTxMessage message, NodeAddress peer) { - processModel.setTradeMessage(message); - processModel.setTempTradingPeerNodeAddress(peer); - - TradeTaskRunner taskRunner = new TradeTaskRunner(trade, - () -> handleTaskRunnerSuccess(message), - errorMessage -> handleTaskRunnerFault(message, errorMessage)); - - taskRunner.addTasks( - ProcessPeerPublishedDelayedPayoutTxMessage.class - ); - taskRunner.run(); + expect(anyPhase(Trade.Phase.DEPOSIT_CONFIRMED, + Trade.Phase.FIAT_SENT, + Trade.Phase.FIAT_RECEIVED) + .with(message) + .from(peer)) + .setup(tasks(ProcessPeerPublishedDelayedPayoutTxMessage.class) + .withTimeout(30)) + .executeTasks(); } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java index 4e8a6c25338..2670d3a9b3e 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java @@ -642,7 +642,7 @@ private void openMediationResultPopup(String headLine) { .instruction(message) .actionButtonText(actionButtonText) .onAction(() -> { - model.dataModel.mediationManager.acceptMediationResult(trade, + model.dataModel.mediationManager.onAcceptMediationResult(trade, () -> { log.info("onAcceptMediationResult completed"); acceptMediationResultPopup = null; From 2fc753bde4a8856089962065983cdf20e3293cf6 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 22:02:43 -0500 Subject: [PATCH 079/143] Rename InputsForDepositTxRequest to TakeOfferRequest The protobuf file is not renamed. This breaks our convention to keep both the same but I think the added clarity for the trade protocol justifies the exception. --- .../network/CoreNetworkProtoResolver.java | 4 +- .../bisq/core/trade/BuyerAsMakerTrade.java | 4 +- .../main/java/bisq/core/trade/MakerTrade.java | 4 +- .../bisq/core/trade/SellerAsMakerTrade.java | 6 +- .../java/bisq/core/trade/TradeManager.java | 30 ++++----- ...itTxRequest.java => TakeOfferRequest.java} | 62 +++++++++---------- .../trade/protocol/BuyerAsMakerProtocol.java | 4 +- .../core/trade/protocol/MakerProtocol.java | 4 +- .../trade/protocol/SellerAsMakerProtocol.java | 4 +- ...kerProcessesInputsForDepositTxRequest.java | 4 +- .../TakerSendInputsForDepositTxRequest.java | 4 +- 11 files changed, 66 insertions(+), 64 deletions(-) rename core/src/main/java/bisq/core/trade/messages/{InputsForDepositTxRequest.java => TakeOfferRequest.java} (83%) diff --git a/core/src/main/java/bisq/core/proto/network/CoreNetworkProtoResolver.java b/core/src/main/java/bisq/core/proto/network/CoreNetworkProtoResolver.java index 8d57a75c14b..0439786d0a6 100644 --- a/core/src/main/java/bisq/core/proto/network/CoreNetworkProtoResolver.java +++ b/core/src/main/java/bisq/core/proto/network/CoreNetworkProtoResolver.java @@ -51,13 +51,13 @@ import bisq.core.trade.messages.DelayedPayoutTxSignatureResponse; import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage; import bisq.core.trade.messages.DepositTxMessage; -import bisq.core.trade.messages.InputsForDepositTxRequest; import bisq.core.trade.messages.InputsForDepositTxResponse; import bisq.core.trade.messages.MediatedPayoutTxPublishedMessage; import bisq.core.trade.messages.MediatedPayoutTxSignatureMessage; import bisq.core.trade.messages.PayoutTxPublishedMessage; import bisq.core.trade.messages.PeerPublishedDelayedPayoutTxMessage; import bisq.core.trade.messages.RefreshTradeStateRequest; +import bisq.core.trade.messages.TakeOfferRequest; import bisq.core.trade.messages.TraderSignedWitnessMessage; import bisq.core.trade.statistics.TradeStatistics; @@ -147,7 +147,7 @@ public NetworkEnvelope fromProto(protobuf.NetworkEnvelope proto) throws Protobuf case REFRESH_TRADE_STATE_REQUEST: return RefreshTradeStateRequest.fromProto(proto.getRefreshTradeStateRequest(), messageVersion); case INPUTS_FOR_DEPOSIT_TX_REQUEST: - return InputsForDepositTxRequest.fromProto(proto.getInputsForDepositTxRequest(), this, messageVersion); + return TakeOfferRequest.fromProto(proto.getInputsForDepositTxRequest(), this, messageVersion); case INPUTS_FOR_DEPOSIT_TX_RESPONSE: return InputsForDepositTxResponse.fromProto(proto.getInputsForDepositTxResponse(), this, messageVersion); case DEPOSIT_TX_MESSAGE: diff --git a/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java b/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java index e6cecc1e4f9..a54e56f4525 100644 --- a/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java +++ b/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java @@ -20,7 +20,7 @@ import bisq.core.btc.wallet.BtcWalletService; import bisq.core.offer.Offer; import bisq.core.proto.CoreProtoResolver; -import bisq.core.trade.messages.InputsForDepositTxRequest; +import bisq.core.trade.messages.TakeOfferRequest; import bisq.core.trade.protocol.BuyerAsMakerProtocol; import bisq.core.trade.protocol.MakerProtocol; @@ -110,7 +110,7 @@ protected void createTradeProtocol() { } @Override - public void handleTakeOfferRequest(InputsForDepositTxRequest message, + public void handleTakeOfferRequest(TakeOfferRequest message, NodeAddress taker, ErrorMessageHandler errorMessageHandler) { ((MakerProtocol) tradeProtocol).handleTakeOfferRequest(message, taker, errorMessageHandler); diff --git a/core/src/main/java/bisq/core/trade/MakerTrade.java b/core/src/main/java/bisq/core/trade/MakerTrade.java index dbfb2421276..d6b0aece875 100644 --- a/core/src/main/java/bisq/core/trade/MakerTrade.java +++ b/core/src/main/java/bisq/core/trade/MakerTrade.java @@ -17,14 +17,14 @@ package bisq.core.trade; -import bisq.core.trade.messages.InputsForDepositTxRequest; +import bisq.core.trade.messages.TakeOfferRequest; import bisq.network.p2p.NodeAddress; import bisq.common.handlers.ErrorMessageHandler; public interface MakerTrade { - void handleTakeOfferRequest(InputsForDepositTxRequest message, + void handleTakeOfferRequest(TakeOfferRequest message, NodeAddress peerNodeAddress, ErrorMessageHandler errorMessageHandler); } diff --git a/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java b/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java index 5e9b5883f9d..9c2ffa76c40 100644 --- a/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java +++ b/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java @@ -20,7 +20,7 @@ import bisq.core.btc.wallet.BtcWalletService; import bisq.core.offer.Offer; import bisq.core.proto.CoreProtoResolver; -import bisq.core.trade.messages.InputsForDepositTxRequest; +import bisq.core.trade.messages.TakeOfferRequest; import bisq.core.trade.protocol.MakerProtocol; import bisq.core.trade.protocol.SellerAsMakerProtocol; @@ -111,7 +111,9 @@ protected void createTradeProtocol() { } @Override - public void handleTakeOfferRequest(InputsForDepositTxRequest message, NodeAddress taker, ErrorMessageHandler errorMessageHandler) { + public void handleTakeOfferRequest(TakeOfferRequest message, + NodeAddress taker, + ErrorMessageHandler errorMessageHandler) { ((MakerProtocol) tradeProtocol).handleTakeOfferRequest(message, taker, errorMessageHandler); } } diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index da6ede7313c..d4f6e70a0ec 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -41,8 +41,8 @@ import bisq.core.trade.closed.ClosedTradableManager; import bisq.core.trade.failed.FailedTradesManager; import bisq.core.trade.handlers.TradeResultHandler; -import bisq.core.trade.messages.InputsForDepositTxRequest; import bisq.core.trade.messages.PeerPublishedDelayedPayoutTxMessage; +import bisq.core.trade.messages.TakeOfferRequest; import bisq.core.trade.messages.TradeMessage; import bisq.core.trade.statistics.ReferralIdService; import bisq.core.trade.statistics.TradeStatisticsManager; @@ -201,8 +201,8 @@ public TradeManager(User user, NetworkEnvelope networkEnvelope = decryptedMessageWithPubKey.getNetworkEnvelope(); // Handler for incoming initial network_messages from taker - if (networkEnvelope instanceof InputsForDepositTxRequest) { - handlePayDepositRequest((InputsForDepositTxRequest) networkEnvelope, peerNodeAddress); + if (networkEnvelope instanceof TakeOfferRequest) { + handlePayDepositRequest((TakeOfferRequest) networkEnvelope, peerNodeAddress); } }); @@ -306,18 +306,18 @@ private void onTradesChanged() { this.numPendingTrades.set(getTradesAsObservableList().size()); } - private void handlePayDepositRequest(InputsForDepositTxRequest inputsForDepositTxRequest, NodeAddress peer) { + private void handlePayDepositRequest(TakeOfferRequest takeOfferRequest, NodeAddress peer) { log.info("Received PayDepositRequest from {} with tradeId {} and uid {}", - peer, inputsForDepositTxRequest.getTradeId(), inputsForDepositTxRequest.getUid()); + peer, takeOfferRequest.getTradeId(), takeOfferRequest.getUid()); try { - Validator.nonEmptyStringOf(inputsForDepositTxRequest.getTradeId()); + Validator.nonEmptyStringOf(takeOfferRequest.getTradeId()); } catch (Throwable t) { - log.warn("Invalid requestDepositTxInputsMessage " + inputsForDepositTxRequest.toString()); + log.warn("Invalid requestDepositTxInputsMessage " + takeOfferRequest.toString()); return; } - Optional openOfferOptional = openOfferManager.getOpenOfferById(inputsForDepositTxRequest.getTradeId()); + Optional openOfferOptional = openOfferManager.getOpenOfferById(takeOfferRequest.getTradeId()); if (openOfferOptional.isPresent() && openOfferOptional.get().getState() == OpenOffer.State.AVAILABLE) { OpenOffer openOffer = openOfferOptional.get(); Offer offer = openOffer.getOffer(); @@ -325,9 +325,9 @@ private void handlePayDepositRequest(InputsForDepositTxRequest inputsForDepositT Trade trade; if (offer.isBuyOffer()) trade = new BuyerAsMakerTrade(offer, - Coin.valueOf(inputsForDepositTxRequest.getTxFee()), - Coin.valueOf(inputsForDepositTxRequest.getTakerFee()), - inputsForDepositTxRequest.isCurrencyForTakerFeeBtc(), + Coin.valueOf(takeOfferRequest.getTxFee()), + Coin.valueOf(takeOfferRequest.getTakerFee()), + takeOfferRequest.isCurrencyForTakerFeeBtc(), openOffer.getArbitratorNodeAddress(), openOffer.getMediatorNodeAddress(), openOffer.getRefundAgentNodeAddress(), @@ -335,9 +335,9 @@ private void handlePayDepositRequest(InputsForDepositTxRequest inputsForDepositT btcWalletService); else trade = new SellerAsMakerTrade(offer, - Coin.valueOf(inputsForDepositTxRequest.getTxFee()), - Coin.valueOf(inputsForDepositTxRequest.getTakerFee()), - inputsForDepositTxRequest.isCurrencyForTakerFeeBtc(), + Coin.valueOf(takeOfferRequest.getTxFee()), + Coin.valueOf(takeOfferRequest.getTakerFee()), + takeOfferRequest.isCurrencyForTakerFeeBtc(), openOffer.getArbitratorNodeAddress(), openOffer.getMediatorNodeAddress(), openOffer.getRefundAgentNodeAddress(), @@ -346,7 +346,7 @@ private void handlePayDepositRequest(InputsForDepositTxRequest inputsForDepositT initTrade(trade, trade.getProcessModel().isUseSavingsWallet(), trade.getProcessModel().getFundsNeededForTrade()); tradableList.add(trade); - ((MakerTrade) trade).handleTakeOfferRequest(inputsForDepositTxRequest, peer, errorMessage -> { + ((MakerTrade) trade).handleTakeOfferRequest(takeOfferRequest, peer, errorMessage -> { if (takeOfferRequestErrorMessageHandler != null) takeOfferRequestErrorMessageHandler.handleErrorMessage(errorMessage); }); diff --git a/core/src/main/java/bisq/core/trade/messages/InputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/messages/TakeOfferRequest.java similarity index 83% rename from core/src/main/java/bisq/core/trade/messages/InputsForDepositTxRequest.java rename to core/src/main/java/bisq/core/trade/messages/TakeOfferRequest.java index a67a879e3db..dc7c09caae7 100644 --- a/core/src/main/java/bisq/core/trade/messages/InputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/messages/TakeOfferRequest.java @@ -41,7 +41,7 @@ @EqualsAndHashCode(callSuper = true) @Value -public final class InputsForDepositTxRequest extends TradeMessage implements DirectMessage { +public final class TakeOfferRequest extends TradeMessage implements DirectMessage { private final NodeAddress senderNodeAddress; private final long tradeAmount; private final long tradePrice; @@ -69,32 +69,32 @@ public final class InputsForDepositTxRequest extends TradeMessage implements Dir private final byte[] accountAgeWitnessSignatureOfOfferId; private final long currentDate; - public InputsForDepositTxRequest(String tradeId, - NodeAddress senderNodeAddress, - long tradeAmount, - long tradePrice, - long txFee, - long takerFee, - boolean isCurrencyForTakerFeeBtc, - List rawTransactionInputs, - long changeOutputValue, - @Nullable String changeOutputAddress, - byte[] takerMultiSigPubKey, - String takerPayoutAddressString, - PubKeyRing takerPubKeyRing, - PaymentAccountPayload takerPaymentAccountPayload, - String takerAccountId, - String takerFeeTxId, - List acceptedArbitratorNodeAddresses, - List acceptedMediatorNodeAddresses, - List acceptedRefundAgentNodeAddresses, - @Nullable NodeAddress arbitratorNodeAddress, - NodeAddress mediatorNodeAddress, - NodeAddress refundAgentNodeAddress, - String uid, - int messageVersion, - byte[] accountAgeWitnessSignatureOfOfferId, - long currentDate) { + public TakeOfferRequest(String tradeId, + NodeAddress senderNodeAddress, + long tradeAmount, + long tradePrice, + long txFee, + long takerFee, + boolean isCurrencyForTakerFeeBtc, + List rawTransactionInputs, + long changeOutputValue, + @Nullable String changeOutputAddress, + byte[] takerMultiSigPubKey, + String takerPayoutAddressString, + PubKeyRing takerPubKeyRing, + PaymentAccountPayload takerPaymentAccountPayload, + String takerAccountId, + String takerFeeTxId, + List acceptedArbitratorNodeAddresses, + List acceptedMediatorNodeAddresses, + List acceptedRefundAgentNodeAddresses, + @Nullable NodeAddress arbitratorNodeAddress, + NodeAddress mediatorNodeAddress, + NodeAddress refundAgentNodeAddress, + String uid, + int messageVersion, + byte[] accountAgeWitnessSignatureOfOfferId, + long currentDate) { super(messageVersion, tradeId, uid); this.senderNodeAddress = senderNodeAddress; this.tradeAmount = tradeAmount; @@ -162,9 +162,9 @@ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() { return getNetworkEnvelopeBuilder().setInputsForDepositTxRequest(builder).build(); } - public static InputsForDepositTxRequest fromProto(protobuf.InputsForDepositTxRequest proto, - CoreProtoResolver coreProtoResolver, - int messageVersion) { + public static TakeOfferRequest fromProto(protobuf.InputsForDepositTxRequest proto, + CoreProtoResolver coreProtoResolver, + int messageVersion) { List rawTransactionInputs = proto.getRawTransactionInputsList().stream() .map(rawTransactionInput -> new RawTransactionInput(rawTransactionInput.getIndex(), rawTransactionInput.getParentTransaction().toByteArray(), rawTransactionInput.getValue())) @@ -176,7 +176,7 @@ public static InputsForDepositTxRequest fromProto(protobuf.InputsForDepositTxReq List acceptedRefundAgentNodeAddresses = proto.getAcceptedRefundAgentNodeAddressesList().stream() .map(NodeAddress::fromProto).collect(Collectors.toList()); - return new InputsForDepositTxRequest(proto.getTradeId(), + return new TakeOfferRequest(proto.getTradeId(), NodeAddress.fromProto(proto.getSenderNodeAddress()), proto.getTradeAmount(), proto.getTradePrice(), diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 00bd26494e0..5b9c38add23 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -21,8 +21,8 @@ import bisq.core.trade.Trade; import bisq.core.trade.messages.DelayedPayoutTxSignatureRequest; import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage; -import bisq.core.trade.messages.InputsForDepositTxRequest; import bisq.core.trade.messages.PayoutTxPublishedMessage; +import bisq.core.trade.messages.TakeOfferRequest; import bisq.core.trade.protocol.tasks.ApplyFilter; import bisq.core.trade.protocol.tasks.TradeTask; import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness; @@ -63,7 +63,7 @@ public BuyerAsMakerProtocol(BuyerAsMakerTrade trade) { /////////////////////////////////////////////////////////////////////////////////////////// @Override - public void handleTakeOfferRequest(InputsForDepositTxRequest message, + public void handleTakeOfferRequest(TakeOfferRequest message, NodeAddress peer, ErrorMessageHandler errorMessageHandler) { expect(phase(Trade.Phase.INIT) diff --git a/core/src/main/java/bisq/core/trade/protocol/MakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/MakerProtocol.java index 349e677a702..fc1e8b04c52 100644 --- a/core/src/main/java/bisq/core/trade/protocol/MakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/MakerProtocol.java @@ -18,14 +18,14 @@ package bisq.core.trade.protocol; -import bisq.core.trade.messages.InputsForDepositTxRequest; +import bisq.core.trade.messages.TakeOfferRequest; import bisq.network.p2p.NodeAddress; import bisq.common.handlers.ErrorMessageHandler; public interface MakerProtocol { - void handleTakeOfferRequest(InputsForDepositTxRequest message, + void handleTakeOfferRequest(TakeOfferRequest message, NodeAddress taker, ErrorMessageHandler errorMessageHandler); } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index c8b62f6b488..3eb21842eda 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -23,7 +23,7 @@ import bisq.core.trade.messages.CounterCurrencyTransferStartedMessage; import bisq.core.trade.messages.DelayedPayoutTxSignatureResponse; import bisq.core.trade.messages.DepositTxMessage; -import bisq.core.trade.messages.InputsForDepositTxRequest; +import bisq.core.trade.messages.TakeOfferRequest; import bisq.core.trade.messages.TradeMessage; import bisq.core.trade.protocol.tasks.ApplyFilter; import bisq.core.trade.protocol.tasks.TradeTask; @@ -64,7 +64,7 @@ public SellerAsMakerProtocol(SellerAsMakerTrade trade) { /////////////////////////////////////////////////////////////////////////////////////////// @Override - public void handleTakeOfferRequest(InputsForDepositTxRequest message, + public void handleTakeOfferRequest(TakeOfferRequest message, NodeAddress peer, ErrorMessageHandler errorMessageHandler) { expect(phase(Trade.Phase.INIT) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java index 404c893c379..5f1a7e56806 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java @@ -21,7 +21,7 @@ import bisq.core.offer.Offer; import bisq.core.support.dispute.mediation.mediator.Mediator; import bisq.core.trade.Trade; -import bisq.core.trade.messages.InputsForDepositTxRequest; +import bisq.core.trade.messages.TakeOfferRequest; import bisq.core.trade.protocol.TradingPeer; import bisq.core.trade.protocol.tasks.TradeTask; import bisq.core.user.User; @@ -51,7 +51,7 @@ public MakerProcessesInputsForDepositTxRequest(TaskRunner taskHandler, Tr protected void run() { try { runInterceptHook(); - InputsForDepositTxRequest request = (InputsForDepositTxRequest) processModel.getTradeMessage(); + TakeOfferRequest request = (TakeOfferRequest) processModel.getTradeMessage(); checkNotNull(request); checkTradeId(processModel.getOfferId(), request); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java index 1170e18074d..5d6a58bdc13 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java @@ -21,7 +21,7 @@ import bisq.core.btc.wallet.BtcWalletService; import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.trade.Trade; -import bisq.core.trade.messages.InputsForDepositTxRequest; +import bisq.core.trade.messages.TakeOfferRequest; import bisq.core.trade.protocol.tasks.TradeTask; import bisq.core.user.User; @@ -99,7 +99,7 @@ protected void run() { byte[] signatureOfNonce = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(), offerId.getBytes(Charsets.UTF_8)); - InputsForDepositTxRequest request = new InputsForDepositTxRequest( + TakeOfferRequest request = new TakeOfferRequest( offerId, processModel.getMyNodeAddress(), tradeAmount.value, From 82749cee70cb4c0fb8841f3090108f31ed0c6cf1 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 22:15:40 -0500 Subject: [PATCH 080/143] Refactor: - Rename handlePayDepositRequest to handleTakeOfferRequest - Add initTrade method without the redundant params - Use early returns in handleTakeOfferRequest --- .../java/bisq/core/trade/TradeManager.java | 62 ++++++++++--------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index d4f6e70a0ec..f2d01a4a7cd 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -199,10 +199,9 @@ public TradeManager(User user, p2PService.addDecryptedDirectMessageListener((decryptedMessageWithPubKey, peerNodeAddress) -> { NetworkEnvelope networkEnvelope = decryptedMessageWithPubKey.getNetworkEnvelope(); - - // Handler for incoming initial network_messages from taker + // The maker received a TakeOfferRequest if (networkEnvelope instanceof TakeOfferRequest) { - handlePayDepositRequest((TakeOfferRequest) networkEnvelope, peerNodeAddress); + handleTakeOfferRequest((TakeOfferRequest) networkEnvelope, peerNodeAddress); } }); @@ -294,9 +293,7 @@ private void initPendingTrades() { } private void initPendingTrade(Trade trade) { - initTrade(trade, trade.getProcessModel().isUseSavingsWallet(), - trade.getProcessModel().getFundsNeededForTrade()); - + initTrade(trade); trade.updateDepositTxFromWallet(); } @@ -306,25 +303,31 @@ private void onTradesChanged() { this.numPendingTrades.set(getTradesAsObservableList().size()); } - private void handlePayDepositRequest(TakeOfferRequest takeOfferRequest, NodeAddress peer) { - log.info("Received PayDepositRequest from {} with tradeId {} and uid {}", + private void handleTakeOfferRequest(TakeOfferRequest takeOfferRequest, NodeAddress peer) { + log.info("Received TakeOfferRequest from {} with tradeId {} and uid {}", peer, takeOfferRequest.getTradeId(), takeOfferRequest.getUid()); try { Validator.nonEmptyStringOf(takeOfferRequest.getTradeId()); } catch (Throwable t) { - log.warn("Invalid requestDepositTxInputsMessage " + takeOfferRequest.toString()); + log.warn("Invalid TakeOfferRequest " + takeOfferRequest.toString()); return; } Optional openOfferOptional = openOfferManager.getOpenOfferById(takeOfferRequest.getTradeId()); - if (openOfferOptional.isPresent() && openOfferOptional.get().getState() == OpenOffer.State.AVAILABLE) { - OpenOffer openOffer = openOfferOptional.get(); - Offer offer = openOffer.getOffer(); - openOfferManager.reserveOpenOffer(openOffer); - Trade trade; - if (offer.isBuyOffer()) - trade = new BuyerAsMakerTrade(offer, + if (!openOfferOptional.isPresent()) { + return; + } + + OpenOffer openOffer = openOfferOptional.get(); + if (openOffer.getState() != OpenOffer.State.AVAILABLE) { + return; + } + + Offer offer = openOffer.getOffer(); + openOfferManager.reserveOpenOffer(openOffer); + Trade trade = offer.isBuyOffer() ? + new BuyerAsMakerTrade(offer, Coin.valueOf(takeOfferRequest.getTxFee()), Coin.valueOf(takeOfferRequest.getTakerFee()), takeOfferRequest.isCurrencyForTakerFeeBtc(), @@ -332,9 +335,8 @@ private void handlePayDepositRequest(TakeOfferRequest takeOfferRequest, NodeAddr openOffer.getMediatorNodeAddress(), openOffer.getRefundAgentNodeAddress(), tradableListStorage, - btcWalletService); - else - trade = new SellerAsMakerTrade(offer, + btcWalletService) : + new SellerAsMakerTrade(offer, Coin.valueOf(takeOfferRequest.getTxFee()), Coin.valueOf(takeOfferRequest.getTakerFee()), takeOfferRequest.isCurrencyForTakerFeeBtc(), @@ -344,16 +346,18 @@ private void handlePayDepositRequest(TakeOfferRequest takeOfferRequest, NodeAddr tradableListStorage, btcWalletService); - initTrade(trade, trade.getProcessModel().isUseSavingsWallet(), trade.getProcessModel().getFundsNeededForTrade()); - tradableList.add(trade); - ((MakerTrade) trade).handleTakeOfferRequest(takeOfferRequest, peer, errorMessage -> { - if (takeOfferRequestErrorMessageHandler != null) - takeOfferRequestErrorMessageHandler.handleErrorMessage(errorMessage); - }); - } else { - // TODO respond - log.debug("We received a take offer request but don't have that offer anymore."); - } + initTrade(trade); + tradableList.add(trade); + ((MakerTrade) trade).handleTakeOfferRequest(takeOfferRequest, peer, errorMessage -> { + if (takeOfferRequestErrorMessageHandler != null) + takeOfferRequestErrorMessageHandler.handleErrorMessage(errorMessage); + }); + } + + private void initTrade(Trade trade) { + initTrade(trade, + trade.getProcessModel().isUseSavingsWallet(), + trade.getProcessModel().getFundsNeededForTrade()); } private void initTrade(Trade trade, boolean useSavingsWallet, Coin fundsNeededForTrade) { From a07fe30ac30b92e8fd3a61471065c84b59283319 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 22:16:25 -0500 Subject: [PATCH 081/143] Refactor: Move method --- .../java/bisq/core/trade/TradeManager.java | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index f2d01a4a7cd..81fdb2cc4cf 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -284,25 +284,9 @@ public void shutDown() { /////////////////////////////////////////////////////////////////////////////////////////// - // Private + // Maker received taker offer request /////////////////////////////////////////////////////////////////////////////////////////// - private void initPendingTrades() { - tradableList.forEach(this::initPendingTrade); - pendingTradesInitialized.set(true); - } - - private void initPendingTrade(Trade trade) { - initTrade(trade); - trade.updateDepositTxFromWallet(); - } - - // TODO Remove once tradableList is refactored to a final field - // (part of the persistence refactor PR) - private void onTradesChanged() { - this.numPendingTrades.set(getTradesAsObservableList().size()); - } - private void handleTakeOfferRequest(TakeOfferRequest takeOfferRequest, NodeAddress peer) { log.info("Received TakeOfferRequest from {} with tradeId {} and uid {}", peer, takeOfferRequest.getTradeId(), takeOfferRequest.getUid()); @@ -354,6 +338,28 @@ private void handleTakeOfferRequest(TakeOfferRequest takeOfferRequest, NodeAddre }); } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Private + /////////////////////////////////////////////////////////////////////////////////////////// + + private void initPendingTrades() { + tradableList.forEach(this::initPendingTrade); + pendingTradesInitialized.set(true); + } + + private void initPendingTrade(Trade trade) { + initTrade(trade); + trade.updateDepositTxFromWallet(); + } + + // TODO Remove once tradableList is refactored to a final field + // (part of the persistence refactor PR) + private void onTradesChanged() { + this.numPendingTrades.set(getTradesAsObservableList().size()); + } + + private void initTrade(Trade trade) { initTrade(trade, trade.getProcessModel().isUseSavingsWallet(), From 96ec87b50afaf8b60279133cff22e88acdaa3be4 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 22:27:19 -0500 Subject: [PATCH 082/143] Refactor: let TradeManager implement DecryptedDirectMessageListener, DecryptedMailboxListener --- .../java/bisq/core/trade/TradeManager.java | 74 +++++++++++-------- 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 81fdb2cc4cf..34f8c519639 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -52,9 +52,12 @@ import bisq.network.p2p.AckMessage; import bisq.network.p2p.AckMessageSourceType; import bisq.network.p2p.BootstrapListener; +import bisq.network.p2p.DecryptedDirectMessageListener; +import bisq.network.p2p.DecryptedMessageWithPubKey; import bisq.network.p2p.NodeAddress; import bisq.network.p2p.P2PService; import bisq.network.p2p.SendMailboxMessageListener; +import bisq.network.p2p.messaging.DecryptedMailboxListener; import bisq.common.ClockWatcher; import bisq.common.config.Config; @@ -107,7 +110,7 @@ import static com.google.common.base.Preconditions.checkArgument; -public class TradeManager implements PersistedDataHost { +public class TradeManager implements PersistedDataHost, DecryptedDirectMessageListener, DecryptedMailboxListener { private static final Logger log = LoggerFactory.getLogger(TradeManager.class); private final User user; @@ -197,37 +200,9 @@ public TradeManager(User user, tradableListStorage = storage; - p2PService.addDecryptedDirectMessageListener((decryptedMessageWithPubKey, peerNodeAddress) -> { - NetworkEnvelope networkEnvelope = decryptedMessageWithPubKey.getNetworkEnvelope(); - // The maker received a TakeOfferRequest - if (networkEnvelope instanceof TakeOfferRequest) { - handleTakeOfferRequest((TakeOfferRequest) networkEnvelope, peerNodeAddress); - } - }); + p2PService.addDecryptedDirectMessageListener(this); + p2PService.addDecryptedMailboxListener(this); - // Might get called at startup after HS is published. Can be before or after initPendingTrades. - p2PService.addDecryptedMailboxListener((decryptedMessageWithPubKey, senderNodeAddress) -> { - NetworkEnvelope networkEnvelope = decryptedMessageWithPubKey.getNetworkEnvelope(); - if (networkEnvelope instanceof TradeMessage) { - TradeMessage tradeMessage = (TradeMessage) networkEnvelope; - String tradeId = tradeMessage.getTradeId(); - Optional tradeOptional = tradableList.stream().filter(e -> e.getId().equals(tradeId)).findAny(); - // The mailbox message will be removed inside the tasks after they are processed successfully - tradeOptional.ifPresent(trade -> trade.addDecryptedMessageWithPubKey(decryptedMessageWithPubKey)); - } else if (networkEnvelope instanceof AckMessage) { - AckMessage ackMessage = (AckMessage) networkEnvelope; - if (ackMessage.getSourceType() == AckMessageSourceType.TRADE_MESSAGE) { - if (ackMessage.isSuccess()) { - log.info("Received AckMessage for {} with tradeId {} and uid {}", - ackMessage.getSourceMsgClassName(), ackMessage.getSourceId(), ackMessage.getSourceUid()); - } else { - log.warn("Received AckMessage with error state for {} with tradeId {} and errorMessage={}", - ackMessage.getSourceMsgClassName(), ackMessage.getSourceId(), ackMessage.getErrorMessage()); - } - p2PService.removeEntryFromMailbox(decryptedMessageWithPubKey); - } - } - }); failedTradesManager.setUnfailTradeCallback(this::unfailTrade); } @@ -250,6 +225,43 @@ public void readPersisted() { } + /////////////////////////////////////////////////////////////////////////////////////////// + // DecryptedDirectMessageListener + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public void onDirectMessage(DecryptedMessageWithPubKey message, NodeAddress peer) { + NetworkEnvelope networkEnvelope = message.getNetworkEnvelope(); + // The maker received a TakeOfferRequest + if (networkEnvelope instanceof TakeOfferRequest) { + handleTakeOfferRequest((TakeOfferRequest) networkEnvelope, peer); + } + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // DecryptedMailboxListener + /////////////////////////////////////////////////////////////////////////////////////////// + + // Might get called at startup after HS is published. Can be before or after initPendingTrades. + @Override + public void onMailboxMessageAdded(DecryptedMessageWithPubKey message, NodeAddress peer) { + NetworkEnvelope networkEnvelope = message.getNetworkEnvelope(); + if (networkEnvelope instanceof TradeMessage) { + TradeMessage tradeMessage = (TradeMessage) networkEnvelope; + // The mailbox message will be removed inside the tasks after they are processed successfully + getTradeById(tradeMessage.getTradeId()) + .ifPresent(trade -> trade.addDecryptedMessageWithPubKey(message)); + } else if (networkEnvelope instanceof AckMessage) { + AckMessage ackMessage = (AckMessage) networkEnvelope; + if (ackMessage.getSourceType() == AckMessageSourceType.TRADE_MESSAGE) { + // We remove here the message not in the trade protocol as it might be that the trade is already + // completed and the protocol is not listening. + p2PService.removeEntryFromMailbox(message); + } + } + } + /////////////////////////////////////////////////////////////////////////////////////////// // API /////////////////////////////////////////////////////////////////////////////////////////// From 4d40ca580c937deb79d83396e821212f9ecfc8d1 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 22:28:31 -0500 Subject: [PATCH 083/143] Refactor: Remove handleTakeOfferRequest method --- .../java/bisq/core/trade/TradeManager.java | 106 ++++++++---------- 1 file changed, 49 insertions(+), 57 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 34f8c519639..36075932c6b 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -234,7 +234,55 @@ public void onDirectMessage(DecryptedMessageWithPubKey message, NodeAddress peer NetworkEnvelope networkEnvelope = message.getNetworkEnvelope(); // The maker received a TakeOfferRequest if (networkEnvelope instanceof TakeOfferRequest) { - handleTakeOfferRequest((TakeOfferRequest) networkEnvelope, peer); + TakeOfferRequest takeOfferRequest = (TakeOfferRequest) networkEnvelope; + log.info("Received TakeOfferRequest from {} with tradeId {} and uid {}", + peer, takeOfferRequest.getTradeId(), takeOfferRequest.getUid()); + + try { + Validator.nonEmptyStringOf(takeOfferRequest.getTradeId()); + } catch (Throwable t) { + log.warn("Invalid TakeOfferRequest " + takeOfferRequest.toString()); + return; + } + + Optional openOfferOptional = openOfferManager.getOpenOfferById(takeOfferRequest.getTradeId()); + if (!openOfferOptional.isPresent()) { + return; + } + + OpenOffer openOffer = openOfferOptional.get(); + if (openOffer.getState() != OpenOffer.State.AVAILABLE) { + return; + } + + Offer offer = openOffer.getOffer(); + openOfferManager.reserveOpenOffer(openOffer); + Trade trade = offer.isBuyOffer() ? + new BuyerAsMakerTrade(offer, + Coin.valueOf(takeOfferRequest.getTxFee()), + Coin.valueOf(takeOfferRequest.getTakerFee()), + takeOfferRequest.isCurrencyForTakerFeeBtc(), + openOffer.getArbitratorNodeAddress(), + openOffer.getMediatorNodeAddress(), + openOffer.getRefundAgentNodeAddress(), + tradableListStorage, + btcWalletService) : + new SellerAsMakerTrade(offer, + Coin.valueOf(takeOfferRequest.getTxFee()), + Coin.valueOf(takeOfferRequest.getTakerFee()), + takeOfferRequest.isCurrencyForTakerFeeBtc(), + openOffer.getArbitratorNodeAddress(), + openOffer.getMediatorNodeAddress(), + openOffer.getRefundAgentNodeAddress(), + tradableListStorage, + btcWalletService); + + initTrade(trade); + tradableList.add(trade); + ((MakerTrade) trade).handleTakeOfferRequest(takeOfferRequest, peer, errorMessage -> { + if (takeOfferRequestErrorMessageHandler != null) + takeOfferRequestErrorMessageHandler.handleErrorMessage(errorMessage); + }); } } @@ -295,62 +343,6 @@ public void shutDown() { } - /////////////////////////////////////////////////////////////////////////////////////////// - // Maker received taker offer request - /////////////////////////////////////////////////////////////////////////////////////////// - - private void handleTakeOfferRequest(TakeOfferRequest takeOfferRequest, NodeAddress peer) { - log.info("Received TakeOfferRequest from {} with tradeId {} and uid {}", - peer, takeOfferRequest.getTradeId(), takeOfferRequest.getUid()); - - try { - Validator.nonEmptyStringOf(takeOfferRequest.getTradeId()); - } catch (Throwable t) { - log.warn("Invalid TakeOfferRequest " + takeOfferRequest.toString()); - return; - } - - Optional openOfferOptional = openOfferManager.getOpenOfferById(takeOfferRequest.getTradeId()); - if (!openOfferOptional.isPresent()) { - return; - } - - OpenOffer openOffer = openOfferOptional.get(); - if (openOffer.getState() != OpenOffer.State.AVAILABLE) { - return; - } - - Offer offer = openOffer.getOffer(); - openOfferManager.reserveOpenOffer(openOffer); - Trade trade = offer.isBuyOffer() ? - new BuyerAsMakerTrade(offer, - Coin.valueOf(takeOfferRequest.getTxFee()), - Coin.valueOf(takeOfferRequest.getTakerFee()), - takeOfferRequest.isCurrencyForTakerFeeBtc(), - openOffer.getArbitratorNodeAddress(), - openOffer.getMediatorNodeAddress(), - openOffer.getRefundAgentNodeAddress(), - tradableListStorage, - btcWalletService) : - new SellerAsMakerTrade(offer, - Coin.valueOf(takeOfferRequest.getTxFee()), - Coin.valueOf(takeOfferRequest.getTakerFee()), - takeOfferRequest.isCurrencyForTakerFeeBtc(), - openOffer.getArbitratorNodeAddress(), - openOffer.getMediatorNodeAddress(), - openOffer.getRefundAgentNodeAddress(), - tradableListStorage, - btcWalletService); - - initTrade(trade); - tradableList.add(trade); - ((MakerTrade) trade).handleTakeOfferRequest(takeOfferRequest, peer, errorMessage -> { - if (takeOfferRequestErrorMessageHandler != null) - takeOfferRequestErrorMessageHandler.handleErrorMessage(errorMessage); - }); - } - - /////////////////////////////////////////////////////////////////////////////////////////// // Private /////////////////////////////////////////////////////////////////////////////////////////// From 346d793d87bfc6551d704440ef6836402ef2658f Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 22:29:52 -0500 Subject: [PATCH 084/143] Refactor: Remove onOfferRemovedFromRemoteOfferBook method --- core/src/main/java/bisq/core/trade/TradeManager.java | 8 -------- .../java/bisq/desktop/main/offer/offerbook/OfferBook.java | 3 +-- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 36075932c6b..13a34f8ac9d 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -391,14 +391,6 @@ private void initTrade(Trade trade, boolean useSavingsWallet, Coin fundsNeededFo fundsNeededForTrade); } - /////////////////////////////////////////////////////////////////////////////////////////// - // Called from Offerbook when offer gets removed from P2P network - /////////////////////////////////////////////////////////////////////////////////////////// - - public void onOfferRemovedFromRemoteOfferBook(Offer offer) { - offer.cancelAvailabilityRequest(); - } - /////////////////////////////////////////////////////////////////////////////////////////// // Take offer diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBook.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBook.java index 8cee9fb458a..b6108d4ef35 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBook.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBook.java @@ -107,8 +107,7 @@ public void removeOffer(Offer offer, TradeManager tradeManager) { // Update state in case that that offer is used in the take offer screen, so it gets updated correctly offer.setState(Offer.State.REMOVED); - // clean up possible references in openOfferManager - tradeManager.onOfferRemovedFromRemoteOfferBook(offer); + offer.cancelAvailabilityRequest(); // We don't use the contains method as the equals method in Offer takes state and errorMessage into account. Optional candidateToRemove = offerBookListItems.stream() .filter(item -> item.getOffer().getId().equals(offer.getId())) From 246d1e3ddfe561f78f95472a041f44665645e936 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 22:31:08 -0500 Subject: [PATCH 085/143] Refactor: Remove onCancelAvailabilityRequest method --- core/src/main/java/bisq/core/trade/TradeManager.java | 8 ++------ .../desktop/main/offer/takeoffer/TakeOfferDataModel.java | 5 +++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 13a34f8ac9d..7e59d0eb551 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -400,7 +400,8 @@ public void checkOfferAvailability(Offer offer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - if (btcWalletService.isUnconfirmedTransactionsLimitHit() || bsqWalletService.isUnconfirmedTransactionsLimitHit()) { + if (btcWalletService.isUnconfirmedTransactionsLimitHit() || + bsqWalletService.isUnconfirmedTransactionsLimitHit()) { String errorMessage = Res.get("shared.unconfirmedTransactionsLimitReached"); errorMessageHandler.handleErrorMessage(errorMessage); log.warn(errorMessage); @@ -410,11 +411,6 @@ public void checkOfferAvailability(Offer offer, offer.checkOfferAvailability(getOfferAvailabilityModel(offer), resultHandler, errorMessageHandler); } - // When closing take offer view, we are not interested in the onCheckOfferAvailability result anymore, so remove from the map - public void onCancelAvailabilityRequest(Offer offer) { - offer.cancelAvailabilityRequest(); - } - // First we check if offer is still available then we create the trade with the protocol public void onTakeOffer(Coin amount, Coin txFee, diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java index 4e143747009..4290faf3b39 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java @@ -179,8 +179,9 @@ protected void activate() { @Override protected void deactivate() { removeListeners(); - if (offer != null) - tradeManager.onCancelAvailabilityRequest(offer); + if (offer != null) { + offer.cancelAvailabilityRequest(); + } } From 1c824f140cc32fab42ea94a5b6cec477aba65f2c Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 22:37:54 -0500 Subject: [PATCH 086/143] Refactor: Cleanups --- .../java/bisq/core/trade/TradeManager.java | 70 +++++++++---------- 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 7e59d0eb551..53ff68b9e24 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -311,7 +311,7 @@ public void onMailboxMessageAdded(DecryptedMessageWithPubKey message, NodeAddres } /////////////////////////////////////////////////////////////////////////////////////////// - // API + // Lifecycle /////////////////////////////////////////////////////////////////////////////////////////// public void onAllServicesInitialized() { @@ -344,7 +344,7 @@ public void shutDown() { /////////////////////////////////////////////////////////////////////////////////////////// - // Private + // Init pending trade /////////////////////////////////////////////////////////////////////////////////////////// private void initPendingTrades() { @@ -357,13 +357,6 @@ private void initPendingTrade(Trade trade) { trade.updateDepositTxFromWallet(); } - // TODO Remove once tradableList is refactored to a final field - // (part of the persistence refactor PR) - private void onTradesChanged() { - this.numPendingTrades.set(getTradesAsObservableList().size()); - } - - private void initTrade(Trade trade) { initTrade(trade, trade.getProcessModel().isUseSavingsWallet(), @@ -458,34 +451,31 @@ private Trade getNewTrade(Coin amount, String paymentAccountId, boolean useSavingsWallet, OfferAvailabilityModel model) { - Trade trade; - if (offer.isBuyOffer()) { - trade = new SellerAsTakerTrade(offer, - amount, - txFee, - takerFee, - isCurrencyForTakerFeeBtc, - tradePrice, - model.getPeerNodeAddress(), - model.getSelectedArbitrator(), - model.getSelectedMediator(), - model.getSelectedRefundAgent(), - tradableListStorage, - btcWalletService); - } else { - trade = new BuyerAsTakerTrade(offer, - amount, - txFee, - takerFee, - isCurrencyForTakerFeeBtc, - tradePrice, - model.getPeerNodeAddress(), - model.getSelectedArbitrator(), - model.getSelectedMediator(), - model.getSelectedRefundAgent(), - tradableListStorage, - btcWalletService); - } + Trade trade = offer.isBuyOffer() ? + new SellerAsTakerTrade(offer, + amount, + txFee, + takerFee, + isCurrencyForTakerFeeBtc, + tradePrice, + model.getPeerNodeAddress(), + model.getSelectedArbitrator(), + model.getSelectedMediator(), + model.getSelectedRefundAgent(), + tradableListStorage, + btcWalletService) : + new BuyerAsTakerTrade(offer, + amount, + txFee, + takerFee, + isCurrencyForTakerFeeBtc, + tradePrice, + model.getPeerNodeAddress(), + model.getSelectedArbitrator(), + model.getSelectedMediator(), + model.getSelectedRefundAgent(), + tradableListStorage, + btcWalletService); trade.setTakerPaymentAccountId(paymentAccountId); initTrade(trade, useSavingsWallet, fundsNeededForTrade); return trade; @@ -785,6 +775,12 @@ else if (now.after(halfTradePeriodDate)) }); } + // TODO Remove once tradableList is refactored to a final field + // (part of the persistence refactor PR) + private void onTradesChanged() { + this.numPendingTrades.set(getTradesAsObservableList().size()); + } + public void persistTrades() { tradableList.persist(); } From 35b758431dd4739cd2c37c2686efc50e4a756975 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 22:50:42 -0500 Subject: [PATCH 087/143] Refactor: Move methods, rename methods --- .../java/bisq/core/trade/TradeManager.java | 233 ++++++++++-------- .../failedtrades/FailedTradesDataModel.java | 2 +- .../pendingtrades/PendingTradesDataModel.java | 2 +- 3 files changed, 128 insertions(+), 109 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 53ff68b9e24..6e7451b03c5 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -342,6 +342,10 @@ public void shutDown() { // Do nothing here } + public void persistTrades() { + tradableList.persist(); + } + /////////////////////////////////////////////////////////////////////////////////////////// // Init pending trade @@ -493,7 +497,7 @@ private OfferAvailabilityModel getOfferAvailabilityModel(Offer offer) { /////////////////////////////////////////////////////////////////////////////////////////// - // Trade + // Complete trade /////////////////////////////////////////////////////////////////////////////////////////// public void onWithdrawRequest(String toAddress, Coin amount, Coin fee, KeyParameter aesKey, @@ -537,55 +541,6 @@ public void onTradeCompleted(Trade trade) { btcWalletService.resetAddressEntriesForPendingTrade(trade.getId()); } - // If trade is in already in critical state (if taker role: taker fee; both roles: after deposit published) - // we move the trade to failedTradesManager - public void moveTradeToFailedTrades(Trade trade) { - removeTrade(trade); - failedTradesManager.add(trade); - } - - public void addFailedTradeToPending(Trade trade) { - if (!trade.isInitialized()) { - initPendingTrade(trade); - } - tradableList.add(trade); - } - - // If trade still has funds locked up it might come back from failed trades - // Aborts unfailing if the address entries needed are not available - private boolean unfailTrade(Trade trade) { - if (!recoverAddresses(trade)) { - log.warn("Failed to recover address during unfail trade"); - return false; - } - - initPendingTrade(trade); - - if (!tradableList.contains(trade)) { - tradableList.add(trade); - } - return true; - } - - // The trade is added to pending trades if the associated address entries are AVAILABLE and - // the relevant entries are changed, otherwise it's not added and no address entries are changed - private boolean recoverAddresses(Trade trade) { - // Find addresses associated with this trade. - var entries = TradeUtils.getAvailableAddresses(trade, btcWalletService, keyRing); - if (entries == null) - return false; - - btcWalletService.recoverAddressEntry(trade.getId(), entries.first, - AddressEntry.Context.MULTI_SIG); - btcWalletService.recoverAddressEntry(trade.getId(), entries.second, - AddressEntry.Context.TRADE_PAYOUT); - return true; - } - - private void removeTrade(Trade trade) { - tradableList.remove(trade); - } - /////////////////////////////////////////////////////////////////////////////////////////// // Dispute @@ -665,46 +620,62 @@ public void onFailure(TxBroadcastException exception) { }); } + /////////////////////////////////////////////////////////////////////////////////////////// - // Getters + // Trade period state /////////////////////////////////////////////////////////////////////////////////////////// - public ObservableList getTradesAsObservableList() { - return tradableList.getList(); - } + public void applyTradePeriodState() { + updateTradePeriodState(); + clockWatcher.addListener(new ClockWatcher.Listener() { + @Override + public void onSecondTick() { + } - public BooleanProperty pendingTradesInitializedProperty() { - return pendingTradesInitialized; + @Override + public void onMinuteTick() { + updateTradePeriodState(); + } + }); } - public boolean isMyOffer(Offer offer) { - return offer.isMyOffer(keyRing); + private void updateTradePeriodState() { + getTradesAsObservableList().forEach(trade -> { + if (!trade.isPayoutPublished()) { + Date maxTradePeriodDate = trade.getMaxTradePeriodDate(); + Date halfTradePeriodDate = trade.getHalfTradePeriodDate(); + if (maxTradePeriodDate != null && halfTradePeriodDate != null) { + Date now = new Date(); + if (now.after(maxTradePeriodDate)) + trade.setTradePeriodState(Trade.TradePeriodState.TRADE_PERIOD_OVER); + else if (now.after(halfTradePeriodDate)) + trade.setTradePeriodState(Trade.TradePeriodState.SECOND_HALF); + } + } + }); } - public boolean isBuyer(Offer offer) { - // If I am the maker, we use the OfferPayload.Direction, otherwise the mirrored direction - if (isMyOffer(offer)) - return offer.isBuyOffer(); - else - return offer.getDirection() == OfferPayload.Direction.SELL; - } - public Optional getTradeById(String tradeId) { - return tradableList.stream().filter(e -> e.getId().equals(tradeId)).findFirst(); + /////////////////////////////////////////////////////////////////////////////////////////// + // Failed trade handling + /////////////////////////////////////////////////////////////////////////////////////////// + + // If trade is in already in critical state (if taker role: taker fee; both roles: after deposit published) + // we move the trade to failedTradesManager + public void movePendingTradeToFailedTrades(Trade trade) { + removeTrade(trade); + failedTradesManager.add(trade); } - public Stream getAddressEntriesForAvailableBalanceStream() { - Stream availableOrPayout = Stream.concat(btcWalletService.getAddressEntries(AddressEntry.Context.TRADE_PAYOUT) - .stream(), btcWalletService.getFundedAvailableAddressEntries().stream()); - Stream available = Stream.concat(availableOrPayout, - btcWalletService.getAddressEntries(AddressEntry.Context.ARBITRATOR).stream()); - available = Stream.concat(available, btcWalletService.getAddressEntries(AddressEntry.Context.OFFER_FUNDING).stream()); - return available.filter(addressEntry -> btcWalletService.getBalanceForAddress(addressEntry.getAddress()).isPositive()); + public void addFailedTradeToPendingTrades(Trade trade) { + if (!trade.isInitialized()) { + initPendingTrade(trade); + } + addTrade(trade); } public Stream getTradesStreamWithFundsLockedIn() { - return getTradesAsObservableList().stream() - .filter(Trade::isFundsLockedIn); + return getTradesAsObservableList().stream().filter(Trade::isFundsLockedIn); } public Set getSetOfFailedOrClosedTradeIdsFromLockedInFunds() throws TradeTxException { @@ -745,44 +716,52 @@ public Set getSetOfFailedOrClosedTradeIdsFromLockedInFunds() throws Trad return tradesIdSet; } - public void applyTradePeriodState() { - updateTradePeriodState(); - clockWatcher.addListener(new ClockWatcher.Listener() { - @Override - public void onSecondTick() { - } + // If trade still has funds locked up it might come back from failed trades + // Aborts unfailing if the address entries needed are not available + private boolean unfailTrade(Trade trade) { + if (!recoverAddresses(trade)) { + log.warn("Failed to recover address during unfail trade"); + return false; + } - @Override - public void onMinuteTick() { - updateTradePeriodState(); - } - }); + initPendingTrade(trade); + + if (!tradableList.contains(trade)) { + tradableList.add(trade); + } + return true; } - private void updateTradePeriodState() { - getTradesAsObservableList().forEach(trade -> { - if (!trade.isPayoutPublished()) { - Date maxTradePeriodDate = trade.getMaxTradePeriodDate(); - Date halfTradePeriodDate = trade.getHalfTradePeriodDate(); - if (maxTradePeriodDate != null && halfTradePeriodDate != null) { - Date now = new Date(); - if (now.after(maxTradePeriodDate)) - trade.setTradePeriodState(Trade.TradePeriodState.TRADE_PERIOD_OVER); - else if (now.after(halfTradePeriodDate)) - trade.setTradePeriodState(Trade.TradePeriodState.SECOND_HALF); - } - } - }); + // The trade is added to pending trades if the associated address entries are AVAILABLE and + // the relevant entries are changed, otherwise it's not added and no address entries are changed + private boolean recoverAddresses(Trade trade) { + // Find addresses associated with this trade. + var entries = TradeUtils.getAvailableAddresses(trade, btcWalletService, keyRing); + if (entries == null) + return false; + + btcWalletService.recoverAddressEntry(trade.getId(), entries.first, + AddressEntry.Context.MULTI_SIG); + btcWalletService.recoverAddressEntry(trade.getId(), entries.second, + AddressEntry.Context.TRADE_PAYOUT); + return true; } - // TODO Remove once tradableList is refactored to a final field - // (part of the persistence refactor PR) - private void onTradesChanged() { - this.numPendingTrades.set(getTradesAsObservableList().size()); + + /////////////////////////////////////////////////////////////////////////////////////////// + // Getters, Utils + /////////////////////////////////////////////////////////////////////////////////////////// + + public ObservableList getTradesAsObservableList() { + return tradableList.getList(); } - public void persistTrades() { - tradableList.persist(); + public BooleanProperty pendingTradesInitializedProperty() { + return pendingTradesInitialized; + } + + public boolean isMyOffer(Offer offer) { + return offer.isMyOffer(keyRing); } public boolean wasOfferAlreadyUsedInTrade(String offerId) { @@ -790,4 +769,44 @@ public boolean wasOfferAlreadyUsedInTrade(String offerId) { failedTradesManager.getTradeById(offerId).isPresent() || closedTradableManager.getTradableById(offerId).isPresent(); } + + public boolean isBuyer(Offer offer) { + // If I am the maker, we use the OfferPayload.Direction, otherwise the mirrored direction + if (isMyOffer(offer)) + return offer.isBuyOffer(); + else + return offer.getDirection() == OfferPayload.Direction.SELL; + } + + public Optional getTradeById(String tradeId) { + return tradableList.stream().filter(e -> e.getId().equals(tradeId)).findFirst(); + } + + + private void removeTrade(Trade trade) { + tradableList.remove(trade); + } + + private void addTrade(Trade trade) { + if (!tradableList.contains(trade)) { + tradableList.add(trade); + } + } + + // TODO Remove once tradableList is refactored to a final field + // (part of the persistence refactor PR) + private void onTradesChanged() { + this.numPendingTrades.set(getTradesAsObservableList().size()); + } + + // TODO move to wallet domain + public Stream getAddressEntriesForAvailableBalanceStream() { + Stream availableAndPayout = Stream.concat(btcWalletService.getAddressEntries(AddressEntry.Context.TRADE_PAYOUT) + .stream(), btcWalletService.getFundedAvailableAddressEntries().stream()); + Stream available = Stream.concat(availableAndPayout, + btcWalletService.getAddressEntries(AddressEntry.Context.ARBITRATOR).stream()); + available = Stream.concat(available, btcWalletService.getAddressEntries(AddressEntry.Context.OFFER_FUNDING).stream()); + return available.filter(addressEntry -> btcWalletService.getBalanceForAddress(addressEntry.getAddress()).isPositive()); + } + } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesDataModel.java index c4e1a227908..06be0410b6f 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesDataModel.java @@ -79,7 +79,7 @@ private void applyList() { public void moveTradeToPendingTrades(Trade trade) { failedTradesManager.removeTrade(trade); - tradeManager.addFailedTradeToPending(trade); + tradeManager.addFailedTradeToPendingTrades(trade); } public void unfailTrade(Trade trade) { diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java index 30bad95c291..293df60f128 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -683,7 +683,7 @@ public boolean isBootstrappedOrShowPopup() { } public void moveTradeToFailedTrades(Trade trade) { - tradeManager.moveTradeToFailedTrades(trade); + tradeManager.movePendingTradeToFailedTrades(trade); } public boolean isSignWitnessTrade() { From 0b81db5a60113a8fc855fd9367fd6edaf109fdb4 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 22:52:54 -0500 Subject: [PATCH 088/143] Refactor: return early --- .../java/bisq/core/trade/TradeManager.java | 103 +++++++++--------- 1 file changed, 53 insertions(+), 50 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 6e7451b03c5..9d58c185f33 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -561,62 +561,66 @@ public void closeDisputedTrade(String tradeId, Trade.DisputeState disputeState) // Publish delayed payout tx /////////////////////////////////////////////////////////////////////////////////////////// + //TODO move to protocol public void publishDelayedPayoutTx(String tradeId, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { getTradeById(tradeId).ifPresent(trade -> { Transaction delayedPayoutTx = trade.getDelayedPayoutTx(); - if (delayedPayoutTx != null) { - // We have spent the funds from the deposit tx with the delayedPayoutTx - btcWalletService.swapTradeEntryToAvailableEntry(trade.getId(), AddressEntry.Context.MULTI_SIG); - // We might receive funds on AddressEntry.Context.TRADE_PAYOUT so we don't swap that - - Transaction committedDelayedPayoutTx = WalletService.maybeAddSelfTxToWallet(delayedPayoutTx, btcWalletService.getWallet()); - - tradeWalletService.broadcastTx(committedDelayedPayoutTx, new TxBroadcaster.Callback() { - @Override - public void onSuccess(Transaction transaction) { - log.info("publishDelayedPayoutTx onSuccess " + transaction); - NodeAddress tradingPeerNodeAddress = trade.getTradingPeerNodeAddress(); - PeerPublishedDelayedPayoutTxMessage msg = new PeerPublishedDelayedPayoutTxMessage(UUID.randomUUID().toString(), - tradeId, - tradingPeerNodeAddress); - p2PService.sendEncryptedMailboxMessage( - tradingPeerNodeAddress, - trade.getProcessModel().getTradingPeer().getPubKeyRing(), - msg, - new SendMailboxMessageListener() { - @Override - public void onArrived() { - resultHandler.handleResult(); - log.info("SendMailboxMessageListener onArrived tradeId={} at peer {}", - tradeId, tradingPeerNodeAddress); - } - - @Override - public void onStoredInMailbox() { - resultHandler.handleResult(); - log.info("SendMailboxMessageListener onStoredInMailbox tradeId={} at peer {}", - tradeId, tradingPeerNodeAddress); - } - - @Override - public void onFault(String errorMessage) { - log.error("SendMailboxMessageListener onFault tradeId={} at peer {}", - tradeId, tradingPeerNodeAddress); - errorMessageHandler.handleErrorMessage(errorMessage); - } + if (delayedPayoutTx == null) { + return; + } + + // We have spent the funds from the deposit tx with the delayedPayoutTx + btcWalletService.swapTradeEntryToAvailableEntry(trade.getId(), AddressEntry.Context.MULTI_SIG); + // We might receive funds on AddressEntry.Context.TRADE_PAYOUT so we don't swap that + + Transaction committedDelayedPayoutTx = WalletService.maybeAddSelfTxToWallet(delayedPayoutTx, btcWalletService.getWallet()); + + tradeWalletService.broadcastTx(committedDelayedPayoutTx, new TxBroadcaster.Callback() { + @Override + public void onSuccess(Transaction transaction) { + log.info("publishDelayedPayoutTx onSuccess " + transaction); + NodeAddress tradingPeerNodeAddress = trade.getTradingPeerNodeAddress(); + PeerPublishedDelayedPayoutTxMessage msg = new PeerPublishedDelayedPayoutTxMessage(UUID.randomUUID().toString(), + tradeId, + tradingPeerNodeAddress); + p2PService.sendEncryptedMailboxMessage( + tradingPeerNodeAddress, + trade.getProcessModel().getTradingPeer().getPubKeyRing(), + msg, + new SendMailboxMessageListener() { + @Override + public void onArrived() { + resultHandler.handleResult(); + log.info("SendMailboxMessageListener onArrived tradeId={} at peer {}", + tradeId, tradingPeerNodeAddress); } - ); - } - @Override - public void onFailure(TxBroadcastException exception) { - log.error("publishDelayedPayoutTx onFailure", exception); - errorMessageHandler.handleErrorMessage(exception.toString()); - } - }); - } + @Override + public void onStoredInMailbox() { + resultHandler.handleResult(); + log.info("SendMailboxMessageListener onStoredInMailbox tradeId={} at peer {}", + tradeId, tradingPeerNodeAddress); + } + + @Override + public void onFault(String errorMessage) { + log.error("SendMailboxMessageListener onFault tradeId={} at peer {}", + tradeId, tradingPeerNodeAddress); + errorMessageHandler.handleErrorMessage(errorMessage); + } + } + ); + } + + @Override + public void onFailure(TxBroadcastException exception) { + log.error("publishDelayedPayoutTx onFailure", exception); + errorMessageHandler.handleErrorMessage(exception.toString()); + } + }); + }); } @@ -782,7 +786,6 @@ public Optional getTradeById(String tradeId) { return tradableList.stream().filter(e -> e.getId().equals(tradeId)).findFirst(); } - private void removeTrade(Trade trade) { tradableList.remove(trade); } From 9f3fe7ad6d52aa2b892026f07391a58b43fba38d Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 22:56:00 -0500 Subject: [PATCH 089/143] Refactor: Move getAddressEntriesForAvailableBalanceStream to btcWalletService Rename WithdrawalView.walletService to btcWalletService --- .../src/main/java/bisq/core/btc/Balances.java | 2 +- .../core/btc/wallet/BtcWalletService.java | 10 +++++++ .../java/bisq/core/trade/TradeManager.java | 13 +--------- .../main/funds/withdrawal/WithdrawalView.java | 26 +++++++++---------- 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/core/src/main/java/bisq/core/btc/Balances.java b/core/src/main/java/bisq/core/btc/Balances.java index 537d15db9ab..e25352d3036 100644 --- a/core/src/main/java/bisq/core/btc/Balances.java +++ b/core/src/main/java/bisq/core/btc/Balances.java @@ -102,7 +102,7 @@ private void updateBalance() { } private void updateAvailableBalance() { - long sum = tradeManager.getAddressEntriesForAvailableBalanceStream() + long sum = btcWalletService.getAddressEntriesForAvailableBalanceStream() .mapToLong(addressEntry -> btcWalletService.getBalanceForAddress(addressEntry.getAddress()).value) .sum(); availableBalance.set(Coin.valueOf(sum)); diff --git a/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java b/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java index bb92c921871..e4f25c4e500 100644 --- a/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java +++ b/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java @@ -59,6 +59,7 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -738,6 +739,15 @@ public Coin getSavingWalletBalance() { .sum()); } + public Stream getAddressEntriesForAvailableBalanceStream() { + Stream availableAndPayout = Stream.concat(getAddressEntries(AddressEntry.Context.TRADE_PAYOUT) + .stream(), getFundedAvailableAddressEntries().stream()); + Stream available = Stream.concat(availableAndPayout, + getAddressEntries(AddressEntry.Context.ARBITRATOR).stream()); + available = Stream.concat(available, getAddressEntries(AddressEntry.Context.OFFER_FUNDING).stream()); + return available.filter(addressEntry -> getBalanceForAddress(addressEntry.getAddress()).isPositive()); + } + /////////////////////////////////////////////////////////////////////////////////////////// // Double spend unconfirmed transaction (unlock in case we got into a tx with a too low mining fee) diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 9d58c185f33..8ca1d980802 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -330,7 +330,7 @@ public void onUpdatedDataReceived() { getTradesAsObservableList().addListener((ListChangeListener) change -> onTradesChanged()); onTradesChanged(); - getAddressEntriesForAvailableBalanceStream() + btcWalletService.getAddressEntriesForAvailableBalanceStream() .filter(addressEntry -> addressEntry.getOfferId() != null) .forEach(addressEntry -> { log.warn("Swapping pending OFFER_FUNDING entries at startup. offerId={}", addressEntry.getOfferId()); @@ -801,15 +801,4 @@ private void addTrade(Trade trade) { private void onTradesChanged() { this.numPendingTrades.set(getTradesAsObservableList().size()); } - - // TODO move to wallet domain - public Stream getAddressEntriesForAvailableBalanceStream() { - Stream availableAndPayout = Stream.concat(btcWalletService.getAddressEntries(AddressEntry.Context.TRADE_PAYOUT) - .stream(), btcWalletService.getFundedAvailableAddressEntries().stream()); - Stream available = Stream.concat(availableAndPayout, - btcWalletService.getAddressEntries(AddressEntry.Context.ARBITRATOR).stream()); - available = Stream.concat(available, btcWalletService.getAddressEntries(AddressEntry.Context.OFFER_FUNDING).stream()); - return available.filter(addressEntry -> btcWalletService.getBalanceForAddress(addressEntry.getAddress()).isPositive()); - } - } diff --git a/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java b/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java index e4750bb07dd..1d7814a341f 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java @@ -125,7 +125,7 @@ public class WithdrawalView extends ActivatableView { private Label amountLabel; private TextField amountTextField, withdrawFromTextField, withdrawToTextField, withdrawMemoTextField; - private final BtcWalletService walletService; + private final BtcWalletService btcWalletService; private final TradeManager tradeManager; private final P2PService p2PService; private final WalletsSetup walletsSetup; @@ -155,7 +155,7 @@ public class WithdrawalView extends ActivatableView { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - private WithdrawalView(BtcWalletService walletService, + private WithdrawalView(BtcWalletService btcWalletService, TradeManager tradeManager, P2PService p2PService, WalletsSetup walletsSetup, @@ -163,7 +163,7 @@ private WithdrawalView(BtcWalletService walletService, Preferences preferences, BtcAddressValidator btcAddressValidator, WalletPasswordWindow walletPasswordWindow) { - this.walletService = walletService; + this.btcWalletService = btcWalletService; this.tradeManager = tradeManager; this.p2PService = p2PService; this.walletsSetup = walletsSetup; @@ -295,7 +295,7 @@ protected void activate() { amountTextField.textProperty().addListener(amountListener); amountTextField.focusedProperty().addListener(amountFocusListener); - walletService.addBalanceListener(balanceListener); + btcWalletService.addBalanceListener(balanceListener); feeToggleGroup.selectedToggleProperty().addListener(feeToggleGroupListener); inputsToggleGroup.selectedToggleProperty().addListener(inputsToggleGroupListener); @@ -313,7 +313,7 @@ protected void activate() { protected void deactivate() { sortedList.comparatorProperty().unbind(); observableList.forEach(WithdrawalListItem::cleanup); - walletService.removeBalanceListener(balanceListener); + btcWalletService.removeBalanceListener(balanceListener); amountTextField.textProperty().removeListener(amountListener); amountTextField.focusedProperty().removeListener(amountFocusListener); feeToggleGroup.selectedToggleProperty().removeListener(feeToggleGroupListener); @@ -329,10 +329,10 @@ private void onWithdraw() { if (GUIUtil.isReadyForTxBroadcastOrShowPopup(p2PService, walletsSetup)) { try { // We do not know sendersAmount if senderPaysFee is true. We repeat fee calculation after first attempt if senderPaysFee is true. - Transaction feeEstimationTransaction = walletService.getFeeEstimationTransactionForMultipleAddresses(fromAddresses, amountAsCoin); + Transaction feeEstimationTransaction = btcWalletService.getFeeEstimationTransactionForMultipleAddresses(fromAddresses, amountAsCoin); if (feeExcluded && feeEstimationTransaction != null) { sendersAmount = amountAsCoin.add(feeEstimationTransaction.getFee()); - feeEstimationTransaction = walletService.getFeeEstimationTransactionForMultipleAddresses(fromAddresses, sendersAmount); + feeEstimationTransaction = btcWalletService.getFeeEstimationTransactionForMultipleAddresses(fromAddresses, sendersAmount); } checkNotNull(feeEstimationTransaction, "feeEstimationTransaction must not be null"); @@ -395,9 +395,9 @@ public void onSuccess(@javax.annotation.Nullable Transaction transaction) { List trades = new ArrayList<>(tradeManager.getTradesAsObservableList()); trades.stream() .filter(Trade::isPayoutPublished) - .forEach(trade -> walletService.getAddressEntry(trade.getId(), AddressEntry.Context.TRADE_PAYOUT) + .forEach(trade -> btcWalletService.getAddressEntry(trade.getId(), AddressEntry.Context.TRADE_PAYOUT) .ifPresent(addressEntry -> { - if (walletService.getBalanceForAddress(addressEntry.getAddress()).isZero()) + if (btcWalletService.getBalanceForAddress(addressEntry.getAddress()).isZero()) tradeManager.onTradeCompleted(trade); })); } @@ -479,15 +479,15 @@ private void openBlockExplorer(WithdrawalListItem item) { private void updateList() { observableList.forEach(WithdrawalListItem::cleanup); - observableList.setAll(tradeManager.getAddressEntriesForAvailableBalanceStream() - .map(addressEntry -> new WithdrawalListItem(addressEntry, walletService, formatter)) + observableList.setAll(btcWalletService.getAddressEntriesForAvailableBalanceStream() + .map(addressEntry -> new WithdrawalListItem(addressEntry, btcWalletService, formatter)) .collect(Collectors.toList())); updateInputSelection(); } private void doWithdraw(Coin amount, Coin fee, FutureCallback callback) { - if (walletService.isEncrypted()) { + if (btcWalletService.isEncrypted()) { UserThread.runAfter(() -> walletPasswordWindow.onAesKey(aesKey -> sendFunds(amount, fee, aesKey, callback)) .show(), 300, TimeUnit.MILLISECONDS); @@ -498,7 +498,7 @@ private void doWithdraw(Coin amount, Coin fee, FutureCallback callb private void sendFunds(Coin amount, Coin fee, KeyParameter aesKey, FutureCallback callback) { try { - walletService.sendFundsForMultipleAddresses(fromAddresses, withdrawToTextField.getText(), amount, fee, null, aesKey, callback); + btcWalletService.sendFundsForMultipleAddresses(fromAddresses, withdrawToTextField.getText(), amount, fee, null, aesKey, callback); reset(); updateList(); } catch (AddressFormatException e) { From 561abd7a499e5a45bfffe9a86bd22a054c86da0c Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 23:07:16 -0500 Subject: [PATCH 090/143] Refactor: Move publishDelayedPayoutTx from TradeManager to MediationProtocol --- .../java/bisq/core/trade/TradeManager.java | 74 ----------------- .../trade/protocol/MediationProtocol.java | 79 +++++++++++++++++++ .../pendingtrades/PendingTradesDataModel.java | 4 +- 3 files changed, 81 insertions(+), 76 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 8ca1d980802..5ba0c7c8d7a 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -19,13 +19,10 @@ import bisq.core.account.witness.AccountAgeWitnessService; import bisq.core.btc.exceptions.AddressEntryException; -import bisq.core.btc.exceptions.TxBroadcastException; import bisq.core.btc.model.AddressEntry; import bisq.core.btc.wallet.BsqWalletService; import bisq.core.btc.wallet.BtcWalletService; import bisq.core.btc.wallet.TradeWalletService; -import bisq.core.btc.wallet.TxBroadcaster; -import bisq.core.btc.wallet.WalletService; import bisq.core.dao.DaoFacade; import bisq.core.filter.FilterManager; import bisq.core.locale.Res; @@ -41,7 +38,6 @@ import bisq.core.trade.closed.ClosedTradableManager; import bisq.core.trade.failed.FailedTradesManager; import bisq.core.trade.handlers.TradeResultHandler; -import bisq.core.trade.messages.PeerPublishedDelayedPayoutTxMessage; import bisq.core.trade.messages.TakeOfferRequest; import bisq.core.trade.messages.TradeMessage; import bisq.core.trade.statistics.ReferralIdService; @@ -56,7 +52,6 @@ import bisq.network.p2p.DecryptedMessageWithPubKey; import bisq.network.p2p.NodeAddress; import bisq.network.p2p.P2PService; -import bisq.network.p2p.SendMailboxMessageListener; import bisq.network.p2p.messaging.DecryptedMailboxListener; import bisq.common.ClockWatcher; @@ -93,7 +88,6 @@ import java.util.Date; import java.util.Optional; import java.util.Set; -import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -557,74 +551,6 @@ public void closeDisputedTrade(String tradeId, Trade.DisputeState disputeState) } - /////////////////////////////////////////////////////////////////////////////////////////// - // Publish delayed payout tx - /////////////////////////////////////////////////////////////////////////////////////////// - - //TODO move to protocol - public void publishDelayedPayoutTx(String tradeId, - ResultHandler resultHandler, - ErrorMessageHandler errorMessageHandler) { - getTradeById(tradeId).ifPresent(trade -> { - Transaction delayedPayoutTx = trade.getDelayedPayoutTx(); - if (delayedPayoutTx == null) { - return; - } - - // We have spent the funds from the deposit tx with the delayedPayoutTx - btcWalletService.swapTradeEntryToAvailableEntry(trade.getId(), AddressEntry.Context.MULTI_SIG); - // We might receive funds on AddressEntry.Context.TRADE_PAYOUT so we don't swap that - - Transaction committedDelayedPayoutTx = WalletService.maybeAddSelfTxToWallet(delayedPayoutTx, btcWalletService.getWallet()); - - tradeWalletService.broadcastTx(committedDelayedPayoutTx, new TxBroadcaster.Callback() { - @Override - public void onSuccess(Transaction transaction) { - log.info("publishDelayedPayoutTx onSuccess " + transaction); - NodeAddress tradingPeerNodeAddress = trade.getTradingPeerNodeAddress(); - PeerPublishedDelayedPayoutTxMessage msg = new PeerPublishedDelayedPayoutTxMessage(UUID.randomUUID().toString(), - tradeId, - tradingPeerNodeAddress); - p2PService.sendEncryptedMailboxMessage( - tradingPeerNodeAddress, - trade.getProcessModel().getTradingPeer().getPubKeyRing(), - msg, - new SendMailboxMessageListener() { - @Override - public void onArrived() { - resultHandler.handleResult(); - log.info("SendMailboxMessageListener onArrived tradeId={} at peer {}", - tradeId, tradingPeerNodeAddress); - } - - @Override - public void onStoredInMailbox() { - resultHandler.handleResult(); - log.info("SendMailboxMessageListener onStoredInMailbox tradeId={} at peer {}", - tradeId, tradingPeerNodeAddress); - } - - @Override - public void onFault(String errorMessage) { - log.error("SendMailboxMessageListener onFault tradeId={} at peer {}", - tradeId, tradingPeerNodeAddress); - errorMessageHandler.handleErrorMessage(errorMessage); - } - } - ); - } - - @Override - public void onFailure(TxBroadcastException exception) { - log.error("publishDelayedPayoutTx onFailure", exception); - errorMessageHandler.handleErrorMessage(exception.toString()); - } - }); - - }); - } - - /////////////////////////////////////////////////////////////////////////////////////////// // Trade period state /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java b/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java index cd6777b430a..b2bfdfcfc57 100644 --- a/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java @@ -17,6 +17,12 @@ package bisq.core.trade.protocol; +import bisq.core.btc.exceptions.TxBroadcastException; +import bisq.core.btc.model.AddressEntry; +import bisq.core.btc.wallet.BtcWalletService; +import bisq.core.btc.wallet.TradeWalletService; +import bisq.core.btc.wallet.TxBroadcaster; +import bisq.core.btc.wallet.WalletService; import bisq.core.trade.Trade; import bisq.core.trade.messages.MediatedPayoutTxPublishedMessage; import bisq.core.trade.messages.MediatedPayoutTxSignatureMessage; @@ -34,10 +40,16 @@ import bisq.core.trade.protocol.tasks.mediation.SignMediatedPayoutTx; import bisq.network.p2p.NodeAddress; +import bisq.network.p2p.P2PService; +import bisq.network.p2p.SendMailboxMessageListener; import bisq.common.handlers.ErrorMessageHandler; import bisq.common.handlers.ResultHandler; +import org.bitcoinj.core.Transaction; + +import java.util.UUID; + import lombok.extern.slf4j.Slf4j; @Slf4j @@ -143,6 +155,73 @@ protected void handle(MediatedPayoutTxPublishedMessage message, NodeAddress peer .executeTasks(); } + /////////////////////////////////////////////////////////////////////////////////////////// + // Delayed payout tx + /////////////////////////////////////////////////////////////////////////////////////////// + + // TODO use task + public void onPublishDelayedPayoutTx(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + Transaction delayedPayoutTx = trade.getDelayedPayoutTx(); + if (delayedPayoutTx == null) { + return; + } + + BtcWalletService btcWalletService = processModel.getBtcWalletService(); + TradeWalletService tradeWalletService = processModel.getTradeWalletService(); + P2PService p2PService = processModel.getP2PService(); + String tradeId = trade.getId(); + + // We have spent the funds from the deposit tx with the delayedPayoutTx + btcWalletService.swapTradeEntryToAvailableEntry(trade.getId(), AddressEntry.Context.MULTI_SIG); + // We might receive funds on AddressEntry.Context.TRADE_PAYOUT so we don't swap that + + Transaction committedDelayedPayoutTx = WalletService.maybeAddSelfTxToWallet(delayedPayoutTx, btcWalletService.getWallet()); + + tradeWalletService.broadcastTx(committedDelayedPayoutTx, new TxBroadcaster.Callback() { + @Override + public void onSuccess(Transaction transaction) { + log.info("publishDelayedPayoutTx onSuccess " + transaction); + NodeAddress tradingPeerNodeAddress = trade.getTradingPeerNodeAddress(); + PeerPublishedDelayedPayoutTxMessage msg = new PeerPublishedDelayedPayoutTxMessage(UUID.randomUUID().toString(), + tradeId, + tradingPeerNodeAddress); + p2PService.sendEncryptedMailboxMessage( + tradingPeerNodeAddress, + trade.getProcessModel().getTradingPeer().getPubKeyRing(), + msg, + new SendMailboxMessageListener() { + @Override + public void onArrived() { + resultHandler.handleResult(); + log.info("SendMailboxMessageListener onArrived tradeId={} at peer {}", + tradeId, tradingPeerNodeAddress); + } + + @Override + public void onStoredInMailbox() { + resultHandler.handleResult(); + log.info("SendMailboxMessageListener onStoredInMailbox tradeId={} at peer {}", + tradeId, tradingPeerNodeAddress); + } + + @Override + public void onFault(String errorMessage) { + log.error("SendMailboxMessageListener onFault tradeId={} at peer {}", + tradeId, tradingPeerNodeAddress); + errorMessageHandler.handleErrorMessage(errorMessage); + } + } + ); + } + + @Override + public void onFailure(TxBroadcastException exception) { + log.error("publishDelayedPayoutTx onFailure", exception); + errorMessageHandler.handleErrorMessage(exception.toString()); + } + }); + } + /////////////////////////////////////////////////////////////////////////////////////////// // Peer has published the delayed payout tx diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java index 293df60f128..909ecb459d1 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -51,6 +51,7 @@ import bisq.core.trade.Trade; import bisq.core.trade.TradeDataValidation; import bisq.core.trade.TradeManager; +import bisq.core.trade.protocol.MediationProtocol; import bisq.core.user.Preferences; import bisq.core.util.FormattingUtils; @@ -641,8 +642,7 @@ private void doOpenDispute(boolean isSupportTicket, Transaction depositTx) { trade.setDisputeState(Trade.DisputeState.REFUND_REQUESTED); //todo add UI spinner as it can take a bit if peer is offline - tradeManager.publishDelayedPayoutTx(tradeId, - () -> { + ((MediationProtocol) trade.getTradeProtocol()).onPublishDelayedPayoutTx(() -> { log.info("DelayedPayoutTx published and message sent to peer"); disputeManager.sendOpenNewDisputeMessage(dispute, false, From fded97fb9c6ca5277f04c426f59f3eb56503b5ac Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 23:55:45 -0500 Subject: [PATCH 091/143] Refactor: Use task runner for peer publish delayed payout tx --- .../trade/protocol/MediationProtocol.java | 96 +++++-------------- .../arbitration/PublishedDelayedPayoutTx.java | 71 ++++++++++++++ ...ndPeerPublishedDelayedPayoutTxMessage.java | 71 ++++++++++++++ 3 files changed, 165 insertions(+), 73 deletions(-) create mode 100644 core/src/main/java/bisq/core/trade/protocol/tasks/arbitration/PublishedDelayedPayoutTx.java create mode 100644 core/src/main/java/bisq/core/trade/protocol/tasks/arbitration/SendPeerPublishedDelayedPayoutTxMessage.java diff --git a/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java b/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java index b2bfdfcfc57..e01899b6571 100644 --- a/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java @@ -17,12 +17,6 @@ package bisq.core.trade.protocol; -import bisq.core.btc.exceptions.TxBroadcastException; -import bisq.core.btc.model.AddressEntry; -import bisq.core.btc.wallet.BtcWalletService; -import bisq.core.btc.wallet.TradeWalletService; -import bisq.core.btc.wallet.TxBroadcaster; -import bisq.core.btc.wallet.WalletService; import bisq.core.trade.Trade; import bisq.core.trade.messages.MediatedPayoutTxPublishedMessage; import bisq.core.trade.messages.MediatedPayoutTxSignatureMessage; @@ -30,6 +24,8 @@ import bisq.core.trade.messages.TradeMessage; import bisq.core.trade.protocol.tasks.ApplyFilter; import bisq.core.trade.protocol.tasks.ProcessPeerPublishedDelayedPayoutTxMessage; +import bisq.core.trade.protocol.tasks.arbitration.PublishedDelayedPayoutTx; +import bisq.core.trade.protocol.tasks.arbitration.SendPeerPublishedDelayedPayoutTxMessage; import bisq.core.trade.protocol.tasks.mediation.BroadcastMediatedPayoutTx; import bisq.core.trade.protocol.tasks.mediation.FinalizeMediatedPayoutTx; import bisq.core.trade.protocol.tasks.mediation.ProcessMediatedPayoutSignatureMessage; @@ -40,16 +36,10 @@ import bisq.core.trade.protocol.tasks.mediation.SignMediatedPayoutTx; import bisq.network.p2p.NodeAddress; -import bisq.network.p2p.P2PService; -import bisq.network.p2p.SendMailboxMessageListener; import bisq.common.handlers.ErrorMessageHandler; import bisq.common.handlers.ResultHandler; -import org.bitcoinj.core.Transaction; - -import java.util.UUID; - import lombok.extern.slf4j.Slf4j; @Slf4j @@ -57,7 +47,8 @@ public class MediationProtocol extends TradeProtocol { enum DisputeEvent implements FluentProtocol.Event { MEDIATION_RESULT_ACCEPTED, - MEDIATION_RESULT_REJECTED + MEDIATION_RESULT_REJECTED, + ARBITRATION_REQUESTED } public MediationProtocol(Trade trade) { @@ -159,67 +150,26 @@ protected void handle(MediatedPayoutTxPublishedMessage message, NodeAddress peer // Delayed payout tx /////////////////////////////////////////////////////////////////////////////////////////// - // TODO use task public void onPublishDelayedPayoutTx(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - Transaction delayedPayoutTx = trade.getDelayedPayoutTx(); - if (delayedPayoutTx == null) { - return; - } - - BtcWalletService btcWalletService = processModel.getBtcWalletService(); - TradeWalletService tradeWalletService = processModel.getTradeWalletService(); - P2PService p2PService = processModel.getP2PService(); - String tradeId = trade.getId(); - - // We have spent the funds from the deposit tx with the delayedPayoutTx - btcWalletService.swapTradeEntryToAvailableEntry(trade.getId(), AddressEntry.Context.MULTI_SIG); - // We might receive funds on AddressEntry.Context.TRADE_PAYOUT so we don't swap that - - Transaction committedDelayedPayoutTx = WalletService.maybeAddSelfTxToWallet(delayedPayoutTx, btcWalletService.getWallet()); - - tradeWalletService.broadcastTx(committedDelayedPayoutTx, new TxBroadcaster.Callback() { - @Override - public void onSuccess(Transaction transaction) { - log.info("publishDelayedPayoutTx onSuccess " + transaction); - NodeAddress tradingPeerNodeAddress = trade.getTradingPeerNodeAddress(); - PeerPublishedDelayedPayoutTxMessage msg = new PeerPublishedDelayedPayoutTxMessage(UUID.randomUUID().toString(), - tradeId, - tradingPeerNodeAddress); - p2PService.sendEncryptedMailboxMessage( - tradingPeerNodeAddress, - trade.getProcessModel().getTradingPeer().getPubKeyRing(), - msg, - new SendMailboxMessageListener() { - @Override - public void onArrived() { - resultHandler.handleResult(); - log.info("SendMailboxMessageListener onArrived tradeId={} at peer {}", - tradeId, tradingPeerNodeAddress); - } - - @Override - public void onStoredInMailbox() { - resultHandler.handleResult(); - log.info("SendMailboxMessageListener onStoredInMailbox tradeId={} at peer {}", - tradeId, tradingPeerNodeAddress); - } - - @Override - public void onFault(String errorMessage) { - log.error("SendMailboxMessageListener onFault tradeId={} at peer {}", - tradeId, tradingPeerNodeAddress); - errorMessageHandler.handleErrorMessage(errorMessage); - } - } - ); - } - - @Override - public void onFailure(TxBroadcastException exception) { - log.error("publishDelayedPayoutTx onFailure", exception); - errorMessageHandler.handleErrorMessage(exception.toString()); - } - }); + DisputeEvent event = DisputeEvent.ARBITRATION_REQUESTED; + expect(anyPhase(Trade.Phase.DEPOSIT_CONFIRMED, + Trade.Phase.FIAT_SENT, + Trade.Phase.FIAT_RECEIVED) + .with(event) + .preCondition(trade.getDelayedPayoutTx() != null)) + .setup(tasks(PublishedDelayedPayoutTx.class, + SendPeerPublishedDelayedPayoutTxMessage.class) + .using(new TradeTaskRunner(trade, + () -> { + resultHandler.handleResult(); + handleTaskRunnerSuccess(event); + }, + errorMessage -> { + errorMessageHandler.handleErrorMessage(errorMessage); + handleTaskRunnerFault(event, errorMessage); + })) + .withTimeout(30)) + .executeTasks(); } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/arbitration/PublishedDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/arbitration/PublishedDelayedPayoutTx.java new file mode 100644 index 00000000000..005dd886115 --- /dev/null +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/arbitration/PublishedDelayedPayoutTx.java @@ -0,0 +1,71 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.trade.protocol.tasks.arbitration; + +import bisq.core.btc.exceptions.TxBroadcastException; +import bisq.core.btc.model.AddressEntry; +import bisq.core.btc.wallet.BtcWalletService; +import bisq.core.btc.wallet.TxBroadcaster; +import bisq.core.btc.wallet.WalletService; +import bisq.core.trade.Trade; +import bisq.core.trade.protocol.tasks.TradeTask; + +import bisq.common.taskrunner.TaskRunner; + +import org.bitcoinj.core.Transaction; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class PublishedDelayedPayoutTx extends TradeTask { + public PublishedDelayedPayoutTx(TaskRunner taskHandler, Trade trade) { + super(taskHandler, trade); + } + + @Override + protected void run() { + try { + runInterceptHook(); + + Transaction delayedPayoutTx = trade.getDelayedPayoutTx(); + BtcWalletService btcWalletService = processModel.getBtcWalletService(); + + // We have spent the funds from the deposit tx with the delayedPayoutTx + btcWalletService.swapTradeEntryToAvailableEntry(trade.getId(), AddressEntry.Context.MULTI_SIG); + // We might receive funds on AddressEntry.Context.TRADE_PAYOUT so we don't swap that + + Transaction committedDelayedPayoutTx = WalletService.maybeAddSelfTxToWallet(delayedPayoutTx, btcWalletService.getWallet()); + + processModel.getTradeWalletService().broadcastTx(committedDelayedPayoutTx, new TxBroadcaster.Callback() { + @Override + public void onSuccess(Transaction transaction) { + log.info("publishDelayedPayoutTx onSuccess " + transaction); + complete(); + } + + @Override + public void onFailure(TxBroadcastException exception) { + log.error("publishDelayedPayoutTx onFailure", exception); + failed(exception.toString()); + } + }); + } catch (Throwable t) { + failed(t); + } + } +} diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/arbitration/SendPeerPublishedDelayedPayoutTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/arbitration/SendPeerPublishedDelayedPayoutTxMessage.java new file mode 100644 index 00000000000..dde273008ac --- /dev/null +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/arbitration/SendPeerPublishedDelayedPayoutTxMessage.java @@ -0,0 +1,71 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.trade.protocol.tasks.arbitration; + +import bisq.core.trade.Trade; +import bisq.core.trade.messages.PeerPublishedDelayedPayoutTxMessage; +import bisq.core.trade.messages.TradeMessage; +import bisq.core.trade.protocol.tasks.SendMailboxMessageTask; + +import bisq.common.taskrunner.TaskRunner; + +import java.util.UUID; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class SendPeerPublishedDelayedPayoutTxMessage extends SendMailboxMessageTask { + + public SendPeerPublishedDelayedPayoutTxMessage(TaskRunner taskHandler, Trade trade) { + super(taskHandler, trade); + } + + @Override + protected TradeMessage getMessage(String id) { + return new PeerPublishedDelayedPayoutTxMessage(UUID.randomUUID().toString(), + trade.getId(), + trade.getTradingPeerNodeAddress()); + } + + @Override + protected void setStateSent() { + } + + @Override + protected void setStateArrived() { + } + + @Override + protected void setStateStoredInMailbox() { + } + + @Override + protected void setStateFault() { + } + + @Override + protected void run() { + try { + runInterceptHook(); + + super.run(); + } catch (Throwable t) { + failed(t); + } + } +} From 191b031f385e6d0f2fc6f16c7793c5fe5d28c8f8 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Fri, 25 Sep 2020 23:56:58 -0500 Subject: [PATCH 092/143] Refactor: Rename MediationProtocol to DisputeProtocol --- .../bisq/core/support/dispute/mediation/MediationManager.java | 4 ++-- .../src/main/java/bisq/core/trade/protocol/BuyerProtocol.java | 2 +- .../protocol/{MediationProtocol.java => DisputeProtocol.java} | 4 ++-- .../main/java/bisq/core/trade/protocol/SellerProtocol.java | 2 +- .../main/portfolio/pendingtrades/PendingTradesDataModel.java | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) rename core/src/main/java/bisq/core/trade/protocol/{MediationProtocol.java => DisputeProtocol.java} (99%) diff --git a/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java b/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java index 20387a7a512..9868c546370 100644 --- a/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java +++ b/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java @@ -37,7 +37,7 @@ import bisq.core.trade.Trade; import bisq.core.trade.TradeManager; import bisq.core.trade.closed.ClosedTradableManager; -import bisq.core.trade.protocol.MediationProtocol; +import bisq.core.trade.protocol.DisputeProtocol; import bisq.core.trade.protocol.ProcessModel; import bisq.network.p2p.AckMessageSourceType; @@ -234,7 +234,7 @@ public void onAcceptMediationResult(Trade trade, ProcessModel processModel = trade.getProcessModel(); processModel.setBuyerPayoutAmountFromMediation(buyerPayoutAmount.value); processModel.setSellerPayoutAmountFromMediation(sellerPayoutAmount.value); - MediationProtocol tradeProtocol = (MediationProtocol) trade.getTradeProtocol(); + DisputeProtocol tradeProtocol = (DisputeProtocol) trade.getTradeProtocol(); trade.setMediationResultState(MediationResultState.MEDIATION_RESULT_ACCEPTED); 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 5142c8238d5..cad6d022ece 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java @@ -42,7 +42,7 @@ import lombok.extern.slf4j.Slf4j; @Slf4j -public abstract class BuyerProtocol extends MediationProtocol { +public abstract class BuyerProtocol extends DisputeProtocol { enum BuyerEvent implements FluentProtocol.Event { STARTUP, PAYMENT_SENT diff --git a/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java b/core/src/main/java/bisq/core/trade/protocol/DisputeProtocol.java similarity index 99% rename from core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java rename to core/src/main/java/bisq/core/trade/protocol/DisputeProtocol.java index e01899b6571..41d4020731e 100644 --- a/core/src/main/java/bisq/core/trade/protocol/MediationProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/DisputeProtocol.java @@ -43,7 +43,7 @@ import lombok.extern.slf4j.Slf4j; @Slf4j -public class MediationProtocol extends TradeProtocol { +public class DisputeProtocol extends TradeProtocol { enum DisputeEvent implements FluentProtocol.Event { MEDIATION_RESULT_ACCEPTED, @@ -51,7 +51,7 @@ enum DisputeEvent implements FluentProtocol.Event { ARBITRATION_REQUESTED } - public MediationProtocol(Trade trade) { + public DisputeProtocol(Trade trade) { super(trade); } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java index af9c5690a0b..b436598240f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java @@ -43,7 +43,7 @@ import lombok.extern.slf4j.Slf4j; @Slf4j -public abstract class SellerProtocol extends MediationProtocol { +public abstract class SellerProtocol extends DisputeProtocol { enum SellerEvent implements FluentProtocol.Event { PAYMENT_RECEIVED } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java index 909ecb459d1..cbbf89fd8f6 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -51,7 +51,7 @@ import bisq.core.trade.Trade; import bisq.core.trade.TradeDataValidation; import bisq.core.trade.TradeManager; -import bisq.core.trade.protocol.MediationProtocol; +import bisq.core.trade.protocol.DisputeProtocol; import bisq.core.user.Preferences; import bisq.core.util.FormattingUtils; @@ -642,7 +642,7 @@ private void doOpenDispute(boolean isSupportTicket, Transaction depositTx) { trade.setDisputeState(Trade.DisputeState.REFUND_REQUESTED); //todo add UI spinner as it can take a bit if peer is offline - ((MediationProtocol) trade.getTradeProtocol()).onPublishDelayedPayoutTx(() -> { + ((DisputeProtocol) trade.getTradeProtocol()).onPublishDelayedPayoutTx(() -> { log.info("DelayedPayoutTx published and message sent to peer"); disputeManager.sendOpenNewDisputeMessage(dispute, false, From 9e5cdada5d2a90e8ee01a3765cae5b306cf730de Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 12:14:10 -0500 Subject: [PATCH 093/143] Remove precondition as trade was added at that moment --- .../java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java | 3 +-- .../java/bisq/core/trade/protocol/SellerAsTakerProtocol.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index ac45bf55a86..5e22e8c166e 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -75,8 +75,7 @@ public BuyerAsTakerProtocol(BuyerAsTakerTrade trade) { @Override public void onTakeOffer() { expect(phase(Trade.Phase.INIT) - .with(TakerEvent.TAKE_OFFER) - .preCondition(!processModel.getTradeManager().wasOfferAlreadyUsedInTrade(trade.getId()))) + .with(TakerEvent.TAKE_OFFER)) .setup(tasks( ApplyFilter.class, getVerifyPeersFeePaymentClass(), diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 3ec07279797..1407caec0b8 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -71,8 +71,7 @@ public SellerAsTakerProtocol(SellerAsTakerTrade trade) { public void onTakeOffer() { expect(phase(Trade.Phase.INIT) .with(TakerEvent.TAKE_OFFER) - .from(trade.getTradingPeerNodeAddress()) - .preCondition(!processModel.getTradeManager().wasOfferAlreadyUsedInTrade(trade.getId()))) + .from(trade.getTradingPeerNodeAddress())) .setup(tasks( ApplyFilter.class, getVerifyPeersFeePaymentClass(), From e61d04284e1574e5ea94941544b6eab3c13142ec Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 12:24:57 -0500 Subject: [PATCH 094/143] Add ProcessModelServiceProvider to provide all the domain services to process model --- core/src/main/java/bisq/core/trade/Trade.java | 55 +----- .../java/bisq/core/trade/TradeManager.java | 45 +---- .../core/trade/protocol/ProcessModel.java | 157 +++++++++++------- .../protocol/ProcessModelServiceProvider.java | 93 +++++++++++ 4 files changed, 198 insertions(+), 152 deletions(-) create mode 100644 core/src/main/java/bisq/core/trade/protocol/ProcessModelServiceProvider.java diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index b4ae19aac9c..19f05f2eb44 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -17,39 +17,26 @@ package bisq.core.trade; -import bisq.core.account.witness.AccountAgeWitnessService; -import bisq.core.btc.wallet.BsqWalletService; import bisq.core.btc.wallet.BtcWalletService; -import bisq.core.btc.wallet.TradeWalletService; -import bisq.core.dao.DaoFacade; -import bisq.core.filter.FilterManager; import bisq.core.locale.CurrencyUtil; import bisq.core.monetary.Price; import bisq.core.monetary.Volume; import bisq.core.offer.Offer; import bisq.core.offer.OfferUtil; -import bisq.core.offer.OpenOfferManager; import bisq.core.payment.payload.PaymentMethod; import bisq.core.proto.CoreProtoResolver; import bisq.core.support.dispute.arbitration.arbitrator.Arbitrator; -import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager; import bisq.core.support.dispute.mediation.MediationResultState; -import bisq.core.support.dispute.mediation.mediator.MediatorManager; import bisq.core.support.dispute.refund.RefundResultState; -import bisq.core.support.dispute.refund.refundagent.RefundAgentManager; import bisq.core.support.messages.ChatMessage; import bisq.core.trade.protocol.ProcessModel; +import bisq.core.trade.protocol.ProcessModelServiceProvider; import bisq.core.trade.protocol.TradeProtocol; -import bisq.core.trade.statistics.ReferralIdService; -import bisq.core.trade.statistics.TradeStatisticsManager; import bisq.core.trade.txproof.AssetTxProofResult; -import bisq.core.user.User; import bisq.network.p2p.DecryptedMessageWithPubKey; import bisq.network.p2p.NodeAddress; -import bisq.network.p2p.P2PService; -import bisq.common.crypto.KeyRing; import bisq.common.crypto.PubKeyRing; import bisq.common.proto.ProtoUtil; import bisq.common.storage.Storage; @@ -644,56 +631,28 @@ public void setTransientFields(Storage storage, BtcWalle this.btcWalletService = btcWalletService; } - public void init(P2PService p2PService, - BtcWalletService btcWalletService, - BsqWalletService bsqWalletService, - TradeWalletService tradeWalletService, - DaoFacade daoFacade, + public void init(ProcessModelServiceProvider processModelServiceProvider, TradeManager tradeManager, - OpenOfferManager openOfferManager, - ReferralIdService referralIdService, - User user, - FilterManager filterManager, - AccountAgeWitnessService accountAgeWitnessService, - TradeStatisticsManager tradeStatisticsManager, - ArbitratorManager arbitratorManager, - MediatorManager mediatorManager, - RefundAgentManager refundAgentManager, - KeyRing keyRing, boolean useSavingsWallet, Coin fundsNeededForTrade) { - processModel.onAllServicesInitialized(checkNotNull(offer, "offer must not be null"), + processModel.init(checkNotNull(offer, "offer must not be null"), + processModelServiceProvider, tradeManager, - openOfferManager, - p2PService, - btcWalletService, - bsqWalletService, - tradeWalletService, - daoFacade, - referralIdService, - user, - filterManager, - accountAgeWitnessService, - tradeStatisticsManager, - arbitratorManager, - mediatorManager, - refundAgentManager, - keyRing, useSavingsWallet, fundsNeededForTrade); - arbitratorManager.getDisputeAgentByNodeAddress(arbitratorNodeAddress).ifPresent(arbitrator -> { + processModelServiceProvider.getArbitratorManager().getDisputeAgentByNodeAddress(arbitratorNodeAddress).ifPresent(arbitrator -> { arbitratorBtcPubKey = arbitrator.getBtcPubKey(); arbitratorPubKeyRing = arbitrator.getPubKeyRing(); persist(); }); - mediatorManager.getDisputeAgentByNodeAddress(mediatorNodeAddress).ifPresent(mediator -> { + processModelServiceProvider.getMediatorManager().getDisputeAgentByNodeAddress(mediatorNodeAddress).ifPresent(mediator -> { mediatorPubKeyRing = mediator.getPubKeyRing(); persist(); }); - refundAgentManager.getDisputeAgentByNodeAddress(refundAgentNodeAddress).ifPresent(refundAgent -> { + processModelServiceProvider.getRefundAgentManager().getDisputeAgentByNodeAddress(refundAgentNodeAddress).ifPresent(refundAgent -> { refundAgentPubKeyRing = refundAgent.getPubKeyRing(); persist(); }); diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 5ba0c7c8d7a..41997c09d29 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -17,14 +17,10 @@ package bisq.core.trade; -import bisq.core.account.witness.AccountAgeWitnessService; import bisq.core.btc.exceptions.AddressEntryException; import bisq.core.btc.model.AddressEntry; import bisq.core.btc.wallet.BsqWalletService; import bisq.core.btc.wallet.BtcWalletService; -import bisq.core.btc.wallet.TradeWalletService; -import bisq.core.dao.DaoFacade; -import bisq.core.filter.FilterManager; import bisq.core.locale.Res; import bisq.core.offer.Offer; import bisq.core.offer.OfferPayload; @@ -34,13 +30,12 @@ import bisq.core.provider.price.PriceFeedService; import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager; import bisq.core.support.dispute.mediation.mediator.MediatorManager; -import bisq.core.support.dispute.refund.refundagent.RefundAgentManager; import bisq.core.trade.closed.ClosedTradableManager; import bisq.core.trade.failed.FailedTradesManager; import bisq.core.trade.handlers.TradeResultHandler; import bisq.core.trade.messages.TakeOfferRequest; import bisq.core.trade.messages.TradeMessage; -import bisq.core.trade.statistics.ReferralIdService; +import bisq.core.trade.protocol.ProcessModelServiceProvider; import bisq.core.trade.statistics.TradeStatisticsManager; import bisq.core.user.User; import bisq.core.util.Validator; @@ -112,21 +107,16 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi private final KeyRing keyRing; private final BtcWalletService btcWalletService; private final BsqWalletService bsqWalletService; - private final TradeWalletService tradeWalletService; private final OpenOfferManager openOfferManager; private final ClosedTradableManager closedTradableManager; private final FailedTradesManager failedTradesManager; private final P2PService p2PService; private final PriceFeedService priceFeedService; - private final FilterManager filterManager; private final TradeStatisticsManager tradeStatisticsManager; - private final ReferralIdService referralIdService; - private final AccountAgeWitnessService accountAgeWitnessService; @Getter private final ArbitratorManager arbitratorManager; private final MediatorManager mediatorManager; - private final RefundAgentManager refundAgentManager; - private final DaoFacade daoFacade; + private final ProcessModelServiceProvider processModelServiceProvider; private final ClockWatcher clockWatcher; private final Storage> tradableListStorage; @@ -152,20 +142,15 @@ public TradeManager(User user, KeyRing keyRing, BtcWalletService btcWalletService, BsqWalletService bsqWalletService, - TradeWalletService tradeWalletService, OpenOfferManager openOfferManager, ClosedTradableManager closedTradableManager, FailedTradesManager failedTradesManager, P2PService p2PService, PriceFeedService priceFeedService, - FilterManager filterManager, TradeStatisticsManager tradeStatisticsManager, - ReferralIdService referralIdService, - AccountAgeWitnessService accountAgeWitnessService, ArbitratorManager arbitratorManager, MediatorManager mediatorManager, - RefundAgentManager refundAgentManager, - DaoFacade daoFacade, + ProcessModelServiceProvider processModelServiceProvider, ClockWatcher clockWatcher, Storage> storage, DumpDelayedPayoutTx dumpDelayedPayoutTx, @@ -174,20 +159,15 @@ public TradeManager(User user, this.keyRing = keyRing; this.btcWalletService = btcWalletService; this.bsqWalletService = bsqWalletService; - this.tradeWalletService = tradeWalletService; this.openOfferManager = openOfferManager; this.closedTradableManager = closedTradableManager; this.failedTradesManager = failedTradesManager; this.p2PService = p2PService; this.priceFeedService = priceFeedService; - this.filterManager = filterManager; this.tradeStatisticsManager = tradeStatisticsManager; - this.referralIdService = referralIdService; - this.accountAgeWitnessService = accountAgeWitnessService; this.arbitratorManager = arbitratorManager; this.mediatorManager = mediatorManager; - this.refundAgentManager = refundAgentManager; - this.daoFacade = daoFacade; + this.processModelServiceProvider = processModelServiceProvider; this.clockWatcher = clockWatcher; this.dumpDelayedPayoutTx = dumpDelayedPayoutTx; this.allowFaultyDelayedTxs = allowFaultyDelayedTxs; @@ -362,22 +342,8 @@ private void initTrade(Trade trade) { } private void initTrade(Trade trade, boolean useSavingsWallet, Coin fundsNeededForTrade) { - trade.init(p2PService, - btcWalletService, - bsqWalletService, - tradeWalletService, - daoFacade, + trade.init(processModelServiceProvider, this, - openOfferManager, - referralIdService, - user, - filterManager, - accountAgeWitnessService, - tradeStatisticsManager, - arbitratorManager, - mediatorManager, - refundAgentManager, - keyRing, useSavingsWallet, fundsNeededForTrade); } @@ -390,7 +356,6 @@ private void initTrade(Trade trade, boolean useSavingsWallet, Coin fundsNeededFo public void checkOfferAvailability(Offer offer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - if (btcWalletService.isUnconfirmedTransactionsLimitHit() || bsqWalletService.isUnconfirmedTransactionsLimitHit()) { String errorMessage = Res.get("shared.unconfirmedTransactionsLimitReached"); diff --git a/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java b/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java index 3a76e460881..15b514563fe 100644 --- a/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java +++ b/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java @@ -73,29 +73,19 @@ // Fields marked as transient are only used during protocol execution which are based on directMessages so we do not // persist them. -//todo clean up older fields as well to make most transient + +/** + * This is the base model for the trade protocol. It is persisted with the trade (non transient fields). + * It uses the {@link ProcessModelServiceProvider} for access to domain services. + */ @Getter @Slf4j public class ProcessModel implements Model, PersistablePayload { // Transient/Immutable (net set in constructor so they are not final, but at init) + transient private ProcessModelServiceProvider provider; transient private TradeManager tradeManager; - transient private OpenOfferManager openOfferManager; - transient private BtcWalletService btcWalletService; - transient private BsqWalletService bsqWalletService; - transient private TradeWalletService tradeWalletService; - transient private DaoFacade daoFacade; transient private Offer offer; - transient private User user; - transient private FilterManager filterManager; - transient private AccountAgeWitnessService accountAgeWitnessService; - transient private TradeStatisticsManager tradeStatisticsManager; - transient private ArbitratorManager arbitratorManager; - transient private MediatorManager mediatorManager; - transient private RefundAgentManager refundAgentManager; - transient private KeyRing keyRing; - transient private P2PService p2PService; - transient private ReferralIdService referralIdService; // Transient/Mutable transient private Transaction takeOfferFeeTx; @@ -117,9 +107,14 @@ public class ProcessModel implements Model, PersistablePayload { // It is used only in a task which would not be executed after restart, so no need to persist it. @Setter transient private ObjectProperty depositTxMessageStateProperty = new SimpleObjectProperty<>(MessageState.UNDEFINED); + @Setter + @Getter + transient private Transaction depositTx; // Persistable Immutable (private setter only used by PB method) + + //todo make final @Setter private TradingPeer tradingPeer = new TradingPeer(); @Setter @@ -169,10 +164,6 @@ public class ProcessModel implements Model, PersistablePayload { @Setter private long sellerPayoutAmountFromMediation; - // Added in v 1.4.0 - @Setter - @Getter - transient private Transaction depositTx; // We want to indicate the user the state of the message delivery of the // CounterCurrencyTransferStartedMessage. As well we do an automatic re-send in case it was not ACKed yet. @@ -252,56 +243,29 @@ public static ProcessModel fromProto(protobuf.ProcessModel proto, CoreProtoResol // API /////////////////////////////////////////////////////////////////////////////////////////// - public void onAllServicesInitialized(Offer offer, - TradeManager tradeManager, - OpenOfferManager openOfferManager, - P2PService p2PService, - BtcWalletService walletService, - BsqWalletService bsqWalletService, - TradeWalletService tradeWalletService, - DaoFacade daoFacade, - ReferralIdService referralIdService, - User user, - FilterManager filterManager, - AccountAgeWitnessService accountAgeWitnessService, - TradeStatisticsManager tradeStatisticsManager, - ArbitratorManager arbitratorManager, - MediatorManager mediatorManager, - RefundAgentManager refundAgentManager, - KeyRing keyRing, - boolean useSavingsWallet, - Coin fundsNeededForTrade) { + public void init(Offer offer, + ProcessModelServiceProvider processModelServiceProvider, + TradeManager tradeManager, + boolean useSavingsWallet, + Coin fundsNeededForTrade) { this.offer = offer; + this.provider = processModelServiceProvider; this.tradeManager = tradeManager; - this.openOfferManager = openOfferManager; - this.btcWalletService = walletService; - this.bsqWalletService = bsqWalletService; - this.tradeWalletService = tradeWalletService; - this.daoFacade = daoFacade; - this.referralIdService = referralIdService; - this.user = user; - this.filterManager = filterManager; - this.accountAgeWitnessService = accountAgeWitnessService; - this.tradeStatisticsManager = tradeStatisticsManager; - this.arbitratorManager = arbitratorManager; - this.mediatorManager = mediatorManager; - this.refundAgentManager = refundAgentManager; - this.keyRing = keyRing; - this.p2PService = p2PService; this.useSavingsWallet = useSavingsWallet; - fundsNeededForTradeAsLong = fundsNeededForTrade.value; + offerId = offer.getId(); - accountId = user.getAccountId(); - pubKeyRing = keyRing.getPubKeyRing(); + accountId = getUser().getAccountId(); + pubKeyRing = getKeyRing().getPubKeyRing(); } + public void removeMailboxMessageAfterProcessing(Trade trade) { if (tradeMessage instanceof MailboxMessage && decryptedMessageWithPubKey != null && decryptedMessageWithPubKey.getNetworkEnvelope().equals(tradeMessage)) { log.debug("Remove decryptedMsgWithPubKey from P2P network. decryptedMsgWithPubKey = " + decryptedMessageWithPubKey); - p2PService.removeEntryFromMailbox(decryptedMessageWithPubKey); + getP2PService().removeEntryFromMailbox(decryptedMessageWithPubKey); trade.removeDecryptedMessageWithPubKey(decryptedMessageWithPubKey); } } @@ -324,9 +288,9 @@ public void setTakeOfferFeeTx(Transaction takeOfferFeeTx) { public PaymentAccountPayload getPaymentAccountPayload(Trade trade) { PaymentAccount paymentAccount; if (trade instanceof MakerTrade) - paymentAccount = user.getPaymentAccount(offer.getMakerPaymentAccountId()); + paymentAccount = getUser().getPaymentAccount(offer.getMakerPaymentAccountId()); else - paymentAccount = user.getPaymentAccount(trade.getTakerPaymentAccountId()); + paymentAccount = getUser().getPaymentAccount(trade.getTakerPaymentAccountId()); return paymentAccount != null ? paymentAccount.getPaymentAccountPayload() : null; } @@ -337,15 +301,15 @@ public Coin getFundsNeededForTrade() { public Transaction resolveTakeOfferFeeTx(Trade trade) { if (takeOfferFeeTx == null) { if (!trade.isCurrencyForTakerFeeBtc()) - takeOfferFeeTx = bsqWalletService.getTransaction(takeOfferFeeTxId); + takeOfferFeeTx = getBsqWalletService().getTransaction(takeOfferFeeTxId); else - takeOfferFeeTx = btcWalletService.getTransaction(takeOfferFeeTxId); + takeOfferFeeTx = getBtcWalletService().getTransaction(takeOfferFeeTxId); } return takeOfferFeeTx; } public NodeAddress getMyNodeAddress() { - return p2PService.getAddress(); + return getP2PService().getAddress(); } void setPaymentStartedAckMessage(AckMessage ackMessage) { @@ -371,6 +335,71 @@ public void setDepositTxMessageState(MessageState messageState) { } void witnessDebugLog(Trade trade) { - accountAgeWitnessService.getAccountAgeWitnessUtils().witnessDebugLog(trade, null); + getAccountAgeWitnessService().getAccountAgeWitnessUtils().witnessDebugLog(trade, null); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Delegates + /////////////////////////////////////////////////////////////////////////////////////////// + + public BtcWalletService getBtcWalletService() { + return provider.getBtcWalletService(); + } + + public AccountAgeWitnessService getAccountAgeWitnessService() { + return provider.getAccountAgeWitnessService(); + } + + public P2PService getP2PService() { + return provider.getP2PService(); + } + + public BsqWalletService getBsqWalletService() { + return provider.getBsqWalletService(); + } + + public TradeWalletService getTradeWalletService() { + return provider.getTradeWalletService(); + } + + public User getUser() { + return provider.getUser(); + } + + public OpenOfferManager getOpenOfferManager() { + return provider.getOpenOfferManager(); + } + + public ReferralIdService getReferralIdService() { + return provider.getReferralIdService(); + } + + public FilterManager getFilterManager() { + return provider.getFilterManager(); + } + + public TradeStatisticsManager getTradeStatisticsManager() { + return provider.getTradeStatisticsManager(); + } + + public ArbitratorManager getArbitratorManager() { + return provider.getArbitratorManager(); + } + + public MediatorManager getMediatorManager() { + return provider.getMediatorManager(); + } + + public RefundAgentManager getRefundAgentManager() { + return provider.getRefundAgentManager(); + } + + public KeyRing getKeyRing() { + return provider.getKeyRing(); + } + + public DaoFacade getDaoFacade() { + return provider.getDaoFacade(); } } diff --git a/core/src/main/java/bisq/core/trade/protocol/ProcessModelServiceProvider.java b/core/src/main/java/bisq/core/trade/protocol/ProcessModelServiceProvider.java new file mode 100644 index 00000000000..37600eccaf3 --- /dev/null +++ b/core/src/main/java/bisq/core/trade/protocol/ProcessModelServiceProvider.java @@ -0,0 +1,93 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.trade.protocol; + +import bisq.core.account.witness.AccountAgeWitnessService; +import bisq.core.btc.wallet.BsqWalletService; +import bisq.core.btc.wallet.BtcWalletService; +import bisq.core.btc.wallet.TradeWalletService; +import bisq.core.dao.DaoFacade; +import bisq.core.filter.FilterManager; +import bisq.core.offer.OpenOfferManager; +import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager; +import bisq.core.support.dispute.mediation.mediator.MediatorManager; +import bisq.core.support.dispute.refund.refundagent.RefundAgentManager; +import bisq.core.trade.statistics.ReferralIdService; +import bisq.core.trade.statistics.TradeStatisticsManager; +import bisq.core.user.User; + +import bisq.network.p2p.P2PService; + +import bisq.common.crypto.KeyRing; + +import javax.inject.Inject; + +import lombok.Getter; + +@Getter +public class ProcessModelServiceProvider { + private final OpenOfferManager openOfferManager; + private final P2PService p2PService; + private final BtcWalletService btcWalletService; + private final BsqWalletService bsqWalletService; + private final TradeWalletService tradeWalletService; + private final DaoFacade daoFacade; + private final ReferralIdService referralIdService; + private final User user; + private final FilterManager filterManager; + private final AccountAgeWitnessService accountAgeWitnessService; + private final TradeStatisticsManager tradeStatisticsManager; + private final ArbitratorManager arbitratorManager; + private final MediatorManager mediatorManager; + private final RefundAgentManager refundAgentManager; + private final KeyRing keyRing; + + @Inject + public ProcessModelServiceProvider(OpenOfferManager openOfferManager, + P2PService p2PService, + BtcWalletService btcWalletService, + BsqWalletService bsqWalletService, + TradeWalletService tradeWalletService, + DaoFacade daoFacade, + ReferralIdService referralIdService, + User user, + FilterManager filterManager, + AccountAgeWitnessService accountAgeWitnessService, + TradeStatisticsManager tradeStatisticsManager, + ArbitratorManager arbitratorManager, + MediatorManager mediatorManager, + RefundAgentManager refundAgentManager, + KeyRing keyRing) { + + this.openOfferManager = openOfferManager; + this.p2PService = p2PService; + this.btcWalletService = btcWalletService; + this.bsqWalletService = bsqWalletService; + this.tradeWalletService = tradeWalletService; + this.daoFacade = daoFacade; + this.referralIdService = referralIdService; + this.user = user; + this.filterManager = filterManager; + this.accountAgeWitnessService = accountAgeWitnessService; + this.tradeStatisticsManager = tradeStatisticsManager; + this.arbitratorManager = arbitratorManager; + this.mediatorManager = mediatorManager; + this.refundAgentManager = refundAgentManager; + this.keyRing = keyRing; + } +} From 0c4af92f8624ab5cf402bb10c0195d5fc2ec055d Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 12:28:38 -0500 Subject: [PATCH 095/143] Refactor: rename methods --- core/src/main/java/bisq/core/trade/TradeManager.java | 6 +++--- .../main/portfolio/failedtrades/FailedTradesDataModel.java | 2 +- .../main/portfolio/failedtrades/FailedTradesView.java | 6 +++++- .../portfolio/pendingtrades/PendingTradesDataModel.java | 4 ++-- .../main/portfolio/pendingtrades/PendingTradesView.java | 2 +- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 41997c09d29..893a6228f4d 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -177,7 +177,7 @@ public TradeManager(User user, p2PService.addDecryptedDirectMessageListener(this); p2PService.addDecryptedMailboxListener(this); - failedTradesManager.setUnfailTradeCallback(this::unfailTrade); + failedTradesManager.setUnfailTradeCallback(this::unFailTrade); } @@ -557,7 +557,7 @@ else if (now.after(halfTradePeriodDate)) // If trade is in already in critical state (if taker role: taker fee; both roles: after deposit published) // we move the trade to failedTradesManager - public void movePendingTradeToFailedTrades(Trade trade) { + public void onMoveInvalidTradeToFailedTrades(Trade trade) { removeTrade(trade); failedTradesManager.add(trade); } @@ -613,7 +613,7 @@ public Set getSetOfFailedOrClosedTradeIdsFromLockedInFunds() throws Trad // If trade still has funds locked up it might come back from failed trades // Aborts unfailing if the address entries needed are not available - private boolean unfailTrade(Trade trade) { + private boolean unFailTrade(Trade trade) { if (!recoverAddresses(trade)) { log.warn("Failed to recover address during unfail trade"); return false; diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesDataModel.java index 06be0410b6f..30a800b5c67 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesDataModel.java @@ -77,7 +77,7 @@ private void applyList() { list.sort((o1, o2) -> o2.getTrade().getDate().compareTo(o1.getTrade().getDate())); } - public void moveTradeToPendingTrades(Trade trade) { + public void onMoveTradeToPendingTrades(Trade trade) { failedTradesManager.removeTrade(trade); tradeManager.addFailedTradeToPendingTrades(trade); } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.java index b5a02c77d8a..41479c0d8cd 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.java @@ -187,12 +187,16 @@ protected void deactivate() { private void onRevertTrade(Trade trade) { new Popup().attention(Res.get("portfolio.failed.revertToPending.popup")) - .onAction(() -> model.dataModel.moveTradeToPendingTrades(trade)) + .onAction(() -> onMoveTradeToPendingTrades(trade)) .actionButtonText(Res.get("shared.yes")) .closeButtonText(Res.get("shared.no")) .show(); } + private void onMoveTradeToPendingTrades(Trade trade) { + model.dataModel.onMoveTradeToPendingTrades(trade); + } + private void setTradeIdColumnCellFactory() { tradeIdColumn.getStyleClass().add("first-column"); tradeIdColumn.setCellValueFactory((offerListItem) -> new ReadOnlyObjectWrapper<>(offerListItem.getValue())); diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java index cbbf89fd8f6..b066785c0ed 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -682,8 +682,8 @@ public boolean isBootstrappedOrShowPopup() { return GUIUtil.isBootstrappedOrShowPopup(p2PService); } - public void moveTradeToFailedTrades(Trade trade) { - tradeManager.movePendingTradeToFailedTrades(trade); + public void onMoveInvalidTradeToFailedTrades(Trade trade) { + tradeManager.onMoveInvalidTradeToFailedTrades(trade); } public boolean isSignWitnessTrade() { diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java index e96c704afda..0bba268e783 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java @@ -323,7 +323,7 @@ private void onMoveInvalidTradeToFailedTrades(Trade trade) { new Popup().width(900).attention(Res.get("portfolio.pending.failedTrade.moveToFailed", getInvalidTradeDetails(trade))) .onAction(() -> { - model.dataModel.moveTradeToFailedTrades(trade); + model.dataModel.onMoveInvalidTradeToFailedTrades(trade); updateMoveTradeToFailedColumnState(); }) .actionButtonText(Res.get("shared.yes")) From 62a71e2173fc02091fca0d9e11b809375fc2a058 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 12:28:52 -0500 Subject: [PATCH 096/143] Remove unused method --- .../src/main/java/bisq/core/btc/wallet/BtcWalletService.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java b/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java index e4f25c4e500..7f5290bedac 100644 --- a/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java +++ b/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java @@ -608,11 +608,6 @@ public AddressEntry getFreshAddressEntry() { return getOrCreateAddressEntry(context, addressEntry); } - public void getNewAddressEntry(String offerId, AddressEntry.Context context) { - AddressEntry entry = new AddressEntry(wallet.freshReceiveKey(), context, offerId); - addressEntryList.addAddressEntry(entry); - } - public void recoverAddressEntry(String offerId, String address, AddressEntry.Context context) { findAddressEntry(address, AddressEntry.Context.AVAILABLE).ifPresent(addressEntry -> addressEntryList.swapAvailableToAddressEntryWithOfferId(addressEntry, context, offerId)); From 2bb4bff41de3d7f9aa40c26e1cf3f87e532fc9ed Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 12:40:09 -0500 Subject: [PATCH 097/143] Refactor: move method, remove unneeded stream call --- .../core/btc/wallet/BtcWalletService.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java b/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java index 7f5290bedac..7e2aa0d26ce 100644 --- a/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java +++ b/core/src/main/java/bisq/core/btc/wallet/BtcWalletService.java @@ -113,7 +113,7 @@ public BtcWalletService(WalletsSetup walletsSetup, void decryptWallet(@NotNull KeyParameter key) { super.decryptWallet(key); - addressEntryList.getAddressEntriesAsListImmutable().stream().forEach(e -> { + addressEntryList.getAddressEntriesAsListImmutable().forEach(e -> { DeterministicKey keyPair = e.getKeyPair(); if (keyPair.isEncrypted()) e.setDeterministicKey(keyPair.decrypt(key)); @@ -591,6 +591,16 @@ public AddressEntry getOrCreateAddressEntry(String offerId, AddressEntry.Context } } + private AddressEntry getOrCreateAddressEntry(AddressEntry.Context context, Optional addressEntry) { + if (addressEntry.isPresent()) { + return addressEntry.get(); + } else { + AddressEntry entry = new AddressEntry(wallet.freshReceiveKey(), context); + addressEntryList.addAddressEntry(entry); + return entry; + } + } + public AddressEntry getArbitratorAddressEntry() { AddressEntry.Context context = AddressEntry.Context.ARBITRATOR; Optional addressEntry = getAddressEntryListAsImmutableList().stream() @@ -613,16 +623,6 @@ public void recoverAddressEntry(String offerId, String address, AddressEntry.Con addressEntryList.swapAvailableToAddressEntryWithOfferId(addressEntry, context, offerId)); } - private AddressEntry getOrCreateAddressEntry(AddressEntry.Context context, Optional addressEntry) { - if (addressEntry.isPresent()) { - return addressEntry.get(); - } else { - AddressEntry entry = new AddressEntry(wallet.freshReceiveKey(), context); - addressEntryList.addAddressEntry(entry); - return entry; - } - } - private Optional findAddressEntry(String address, AddressEntry.Context context) { return getAddressEntryListAsImmutableList().stream() .filter(e -> address.equals(e.getAddressString())) From 766b1e2e1e8bf86c9e8df104a3b56807d0a73e40 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 12:42:17 -0500 Subject: [PATCH 098/143] Add check to not add a duplicate address entry with same offer ID and context. In debugging trade protocol and taking same offer I could generate problems where the multisig entry was twice but with diff. keys, so take offer failed. I remember the error log to have seen in the past and I assume this was a rare bug we encountered when users took again the same offer which failed with an uncritical state earlier. --- .../bisq/core/btc/model/AddressEntryList.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/bisq/core/btc/model/AddressEntryList.java b/core/src/main/java/bisq/core/btc/model/AddressEntryList.java index 913a8e996a1..c25e2e1a8ba 100644 --- a/core/src/main/java/bisq/core/btc/model/AddressEntryList.java +++ b/core/src/main/java/bisq/core/btc/model/AddressEntryList.java @@ -108,11 +108,11 @@ public void onWalletReady(Wallet wallet) { Set toBeRemoved = new HashSet<>(); entrySet.forEach(addressEntry -> { DeterministicKey keyFromPubHash = (DeterministicKey) wallet.findKeyFromPubKeyHash( - addressEntry.getPubKeyHash(), - Script.ScriptType.P2PKH); + addressEntry.getPubKeyHash(), + Script.ScriptType.P2PKH); if (keyFromPubHash != null) { Address addressFromKey = LegacyAddress.fromKey(Config.baseCurrencyNetworkParameters(), - keyFromPubHash); + keyFromPubHash); // We want to ensure key and address matches in case we have address in entry available already if (addressEntry.getAddress() == null || addressFromKey.equals(addressEntry.getAddress())) { addressEntry.setDeterministicKey(keyFromPubHash); @@ -173,6 +173,18 @@ public ImmutableList getAddressEntriesAsListImmutable() { } public void addAddressEntry(AddressEntry addressEntry) { + boolean entryWithSameOfferIdAndContextAlreadyExist = entrySet.stream().anyMatch(e -> { + if (addressEntry.getOfferId() != null) { + return addressEntry.getOfferId().equals(e.getOfferId()) && addressEntry.getContext() == e.getContext(); + } + return false; + }); + if (entryWithSameOfferIdAndContextAlreadyExist) { + log.error("We have an address entry with the same offer ID and context. We do not add the new one. " + + "addressEntry={}, entrySet={}", addressEntry, entrySet); + return; + } + boolean setChangedByAdd = entrySet.add(addressEntry); if (setChangedByAdd) persist(); @@ -181,7 +193,7 @@ public void addAddressEntry(AddressEntry addressEntry) { public void swapToAvailable(AddressEntry addressEntry) { boolean setChangedByRemove = entrySet.remove(addressEntry); boolean setChangedByAdd = entrySet.add(new AddressEntry(addressEntry.getKeyPair(), - AddressEntry.Context.AVAILABLE)); + AddressEntry.Context.AVAILABLE)); if (setChangedByRemove || setChangedByAdd) { persist(); } @@ -215,7 +227,7 @@ private void maybeAddNewAddressEntry(Transaction tx) { .filter(Objects::nonNull) .filter(this::isAddressNotInEntries) .map(address -> (DeterministicKey) wallet.findKeyFromPubKeyHash(address.getHash(), - Script.ScriptType.P2PKH)) + Script.ScriptType.P2PKH)) .filter(Objects::nonNull) .map(deterministicKey -> new AddressEntry(deterministicKey, AddressEntry.Context.AVAILABLE)) .forEach(this::addAddressEntry); From 456f16ddf4b8852ae86f0739c3521891be30c5fa Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 12:51:43 -0500 Subject: [PATCH 099/143] Remove handleTakeOfferRequest delegate method in maker trade --- .../main/java/bisq/core/trade/BuyerAsMakerTrade.java | 10 ---------- core/src/main/java/bisq/core/trade/MakerTrade.java | 9 --------- .../main/java/bisq/core/trade/SellerAsMakerTrade.java | 10 ---------- core/src/main/java/bisq/core/trade/TradeManager.java | 3 ++- .../pendingtrades/PendingTradesViewModel.java | 2 +- 5 files changed, 3 insertions(+), 31 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java b/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java index a54e56f4525..da543c660d7 100644 --- a/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java +++ b/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java @@ -20,13 +20,10 @@ import bisq.core.btc.wallet.BtcWalletService; import bisq.core.offer.Offer; import bisq.core.proto.CoreProtoResolver; -import bisq.core.trade.messages.TakeOfferRequest; import bisq.core.trade.protocol.BuyerAsMakerProtocol; -import bisq.core.trade.protocol.MakerProtocol; import bisq.network.p2p.NodeAddress; -import bisq.common.handlers.ErrorMessageHandler; import bisq.common.storage.Storage; import org.bitcoinj.core.Coin; @@ -108,11 +105,4 @@ public static Tradable fromProto(protobuf.BuyerAsMakerTrade buyerAsMakerTradePro protected void createTradeProtocol() { tradeProtocol = new BuyerAsMakerProtocol(this); } - - @Override - public void handleTakeOfferRequest(TakeOfferRequest message, - NodeAddress taker, - ErrorMessageHandler errorMessageHandler) { - ((MakerProtocol) tradeProtocol).handleTakeOfferRequest(message, taker, errorMessageHandler); - } } diff --git a/core/src/main/java/bisq/core/trade/MakerTrade.java b/core/src/main/java/bisq/core/trade/MakerTrade.java index d6b0aece875..2e0a41182dd 100644 --- a/core/src/main/java/bisq/core/trade/MakerTrade.java +++ b/core/src/main/java/bisq/core/trade/MakerTrade.java @@ -17,14 +17,5 @@ package bisq.core.trade; -import bisq.core.trade.messages.TakeOfferRequest; - -import bisq.network.p2p.NodeAddress; - -import bisq.common.handlers.ErrorMessageHandler; - public interface MakerTrade { - void handleTakeOfferRequest(TakeOfferRequest message, - NodeAddress peerNodeAddress, - ErrorMessageHandler errorMessageHandler); } diff --git a/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java b/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java index 9c2ffa76c40..8617c657448 100644 --- a/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java +++ b/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java @@ -20,13 +20,10 @@ import bisq.core.btc.wallet.BtcWalletService; import bisq.core.offer.Offer; import bisq.core.proto.CoreProtoResolver; -import bisq.core.trade.messages.TakeOfferRequest; -import bisq.core.trade.protocol.MakerProtocol; import bisq.core.trade.protocol.SellerAsMakerProtocol; import bisq.network.p2p.NodeAddress; -import bisq.common.handlers.ErrorMessageHandler; import bisq.common.storage.Storage; import org.bitcoinj.core.Coin; @@ -109,11 +106,4 @@ public static Tradable fromProto(protobuf.SellerAsMakerTrade sellerAsMakerTradeP protected void createTradeProtocol() { tradeProtocol = new SellerAsMakerProtocol(this); } - - @Override - public void handleTakeOfferRequest(TakeOfferRequest message, - NodeAddress taker, - ErrorMessageHandler errorMessageHandler) { - ((MakerProtocol) tradeProtocol).handleTakeOfferRequest(message, taker, errorMessageHandler); - } } diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 893a6228f4d..a47615176f6 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -35,6 +35,7 @@ import bisq.core.trade.handlers.TradeResultHandler; import bisq.core.trade.messages.TakeOfferRequest; import bisq.core.trade.messages.TradeMessage; +import bisq.core.trade.protocol.MakerProtocol; import bisq.core.trade.protocol.ProcessModelServiceProvider; import bisq.core.trade.statistics.TradeStatisticsManager; import bisq.core.user.User; @@ -253,7 +254,7 @@ public void onDirectMessage(DecryptedMessageWithPubKey message, NodeAddress peer initTrade(trade); tradableList.add(trade); - ((MakerTrade) trade).handleTakeOfferRequest(takeOfferRequest, peer, errorMessage -> { + ((MakerProtocol) trade.getTradeProtocol()).handleTakeOfferRequest(takeOfferRequest, peer, errorMessage -> { if (takeOfferRequestErrorMessageHandler != null) takeOfferRequestErrorMessageHandler.handleErrorMessage(errorMessage); }); diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java index ba7b285449c..2e7f538c7e2 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java @@ -369,7 +369,7 @@ public int getNumPastTrades(Trade trade) { /////////////////////////////////////////////////////////////////////////////////////////// private void onTradeStateChanged(Trade.State tradeState) { - log.debug("UI tradeState={}, id={}", + log.info("UI tradeState={}, id={}", tradeState, trade != null ? trade.getShortId() : "trade is null"); From 7e16982b2b7eb249e97460aaa0fa2d8b39fe2490 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 12:53:25 -0500 Subject: [PATCH 100/143] Remove onTakeOffer delegate method in taker trade --- .../src/main/java/bisq/core/trade/BuyerAsTakerTrade.java | 9 --------- .../main/java/bisq/core/trade/SellerAsTakerTrade.java | 9 --------- core/src/main/java/bisq/core/trade/TakerTrade.java | 1 - core/src/main/java/bisq/core/trade/TradeManager.java | 3 ++- 4 files changed, 2 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java b/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java index c2192dec04c..98ed389cca8 100644 --- a/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java +++ b/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java @@ -21,7 +21,6 @@ import bisq.core.offer.Offer; import bisq.core.proto.CoreProtoResolver; import bisq.core.trade.protocol.BuyerAsTakerProtocol; -import bisq.core.trade.protocol.TakerProtocol; import bisq.network.p2p.NodeAddress; @@ -33,8 +32,6 @@ import javax.annotation.Nullable; -import static com.google.common.base.Preconditions.checkArgument; - @Slf4j public final class BuyerAsTakerTrade extends BuyerTrade implements TakerTrade { @@ -112,10 +109,4 @@ public static Tradable fromProto(protobuf.BuyerAsTakerTrade buyerAsTakerTradePro protected void createTradeProtocol() { tradeProtocol = new BuyerAsTakerProtocol(this); } - - @Override - public void onTakeOffer() { - checkArgument(tradeProtocol instanceof TakerProtocol, "tradeProtocol NOT instanceof TakerProtocol"); - ((TakerProtocol) tradeProtocol).onTakeOffer(); - } } diff --git a/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java b/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java index fd75654bdef..8455f50e7ea 100644 --- a/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java +++ b/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java @@ -21,7 +21,6 @@ import bisq.core.offer.Offer; import bisq.core.proto.CoreProtoResolver; import bisq.core.trade.protocol.SellerAsTakerProtocol; -import bisq.core.trade.protocol.TakerProtocol; import bisq.network.p2p.NodeAddress; @@ -33,8 +32,6 @@ import javax.annotation.Nullable; -import static com.google.common.base.Preconditions.checkArgument; - @Slf4j public final class SellerAsTakerTrade extends SellerTrade implements TakerTrade { @@ -112,10 +109,4 @@ public static Tradable fromProto(protobuf.SellerAsTakerTrade sellerAsTakerTradeP protected void createTradeProtocol() { tradeProtocol = new SellerAsTakerProtocol(this); } - - @Override - public void onTakeOffer() { - checkArgument(tradeProtocol instanceof TakerProtocol, "tradeProtocol NOT instanceof TakerProtocol"); - ((TakerProtocol) tradeProtocol).onTakeOffer(); - } } diff --git a/core/src/main/java/bisq/core/trade/TakerTrade.java b/core/src/main/java/bisq/core/trade/TakerTrade.java index 767ba31fe58..a6d82ac8406 100644 --- a/core/src/main/java/bisq/core/trade/TakerTrade.java +++ b/core/src/main/java/bisq/core/trade/TakerTrade.java @@ -18,5 +18,4 @@ package bisq.core.trade; public interface TakerTrade { - void onTakeOffer(); } diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index a47615176f6..d1bca412103 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -37,6 +37,7 @@ import bisq.core.trade.messages.TradeMessage; import bisq.core.trade.protocol.MakerProtocol; import bisq.core.trade.protocol.ProcessModelServiceProvider; +import bisq.core.trade.protocol.TakerProtocol; import bisq.core.trade.statistics.TradeStatisticsManager; import bisq.core.user.User; import bisq.core.util.Validator; @@ -398,7 +399,7 @@ public void onTakeOffer(Coin amount, useSavingsWallet, model); tradableList.add(trade); - ((TakerTrade) trade).onTakeOffer(); + ((TakerProtocol) trade.getTradeProtocol()).onTakeOffer(); tradeResultHandler.handleResult(trade); } }, From a661ce6ed52c3b4aa2cc0811a2768721a40e3354 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 12:55:23 -0500 Subject: [PATCH 101/143] Remove onPaymentStarted delegate method in buyer trade --- core/src/main/java/bisq/core/trade/BuyerTrade.java | 12 +----------- .../pendingtrades/PendingTradesDataModel.java | 3 ++- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/BuyerTrade.java b/core/src/main/java/bisq/core/trade/BuyerTrade.java index c6e75fbc071..28673e34d2f 100644 --- a/core/src/main/java/bisq/core/trade/BuyerTrade.java +++ b/core/src/main/java/bisq/core/trade/BuyerTrade.java @@ -19,12 +19,9 @@ import bisq.core.btc.wallet.BtcWalletService; import bisq.core.offer.Offer; -import bisq.core.trade.protocol.BuyerProtocol; import bisq.network.p2p.NodeAddress; -import bisq.common.handlers.ErrorMessageHandler; -import bisq.common.handlers.ResultHandler; import bisq.common.storage.Storage; import org.bitcoinj.core.Coin; @@ -33,7 +30,6 @@ import javax.annotation.Nullable; -import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @Slf4j @@ -84,16 +80,10 @@ public abstract class BuyerTrade extends Trade { btcWalletService); } - public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - checkArgument(tradeProtocol instanceof BuyerProtocol, "Check failed: tradeProtocol instanceof BuyerProtocol"); - ((BuyerProtocol) tradeProtocol).onPaymentStarted(resultHandler, errorMessageHandler); - } - @Override public Coin getPayoutAmount() { checkNotNull(getTradeAmount(), "Invalid state: getTradeAmount() = null"); - - return getOffer().getBuyerSecurityDeposit().add(getTradeAmount()); + return checkNotNull(getOffer()).getBuyerSecurityDeposit().add(getTradeAmount()); } } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java index b066785c0ed..9bf4c972958 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -51,6 +51,7 @@ import bisq.core.trade.Trade; import bisq.core.trade.TradeDataValidation; import bisq.core.trade.TradeManager; +import bisq.core.trade.protocol.BuyerProtocol; import bisq.core.trade.protocol.DisputeProtocol; import bisq.core.user.Preferences; import bisq.core.util.FormattingUtils; @@ -187,7 +188,7 @@ public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler er Trade trade = getTrade(); checkNotNull(trade, "trade must not be null"); checkArgument(trade instanceof BuyerTrade, "Check failed: trade instanceof BuyerTrade"); - ((BuyerTrade) trade).onPaymentStarted(resultHandler, errorMessageHandler); + ((BuyerProtocol) trade.getTradeProtocol()).onPaymentStarted(resultHandler, errorMessageHandler); } public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { From c39a9b074f4684c43137e3c68d1e43804dfa484e Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 12:56:42 -0500 Subject: [PATCH 102/143] Remove onPaymentReceived delegate method in seller trade --- core/src/main/java/bisq/core/trade/SellerTrade.java | 10 ---------- .../bisq/core/trade/txproof/xmr/XmrTxProofService.java | 3 ++- .../pendingtrades/PendingTradesDataModel.java | 3 ++- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/SellerTrade.java b/core/src/main/java/bisq/core/trade/SellerTrade.java index 068695c730b..95f05ce7a56 100644 --- a/core/src/main/java/bisq/core/trade/SellerTrade.java +++ b/core/src/main/java/bisq/core/trade/SellerTrade.java @@ -19,12 +19,9 @@ import bisq.core.btc.wallet.BtcWalletService; import bisq.core.offer.Offer; -import bisq.core.trade.protocol.SellerProtocol; import bisq.network.p2p.NodeAddress; -import bisq.common.handlers.ErrorMessageHandler; -import bisq.common.handlers.ResultHandler; import bisq.common.storage.Storage; import org.bitcoinj.core.Coin; @@ -33,8 +30,6 @@ import javax.annotation.Nullable; -import static com.google.common.base.Preconditions.checkArgument; - @Slf4j public abstract class SellerTrade extends Trade { SellerTrade(Offer offer, @@ -83,11 +78,6 @@ public abstract class SellerTrade extends Trade { btcWalletService); } - public void onPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - checkArgument(tradeProtocol instanceof SellerProtocol, "tradeProtocol NOT instanceof SellerProtocol"); - ((SellerProtocol) tradeProtocol).onPaymentReceived(resultHandler, errorMessageHandler); - } - @Override public Coin getPayoutAmount() { return getOffer().getSellerSecurityDeposit(); diff --git a/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java b/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java index a8e0294e3fd..cb67652ffbb 100644 --- a/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java +++ b/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java @@ -27,6 +27,7 @@ import bisq.core.trade.TradeManager; import bisq.core.trade.closed.ClosedTradableManager; import bisq.core.trade.failed.FailedTradesManager; +import bisq.core.trade.protocol.SellerProtocol; import bisq.core.trade.txproof.AssetTxProofResult; import bisq.core.trade.txproof.AssetTxProofService; import bisq.core.user.AutoConfirmSettings; @@ -263,7 +264,7 @@ private void startRequests(SellerTrade trade) { log.info("We auto-confirm trade {} as our all our services for the tx proof completed successfully", trade.getShortId()); log.info("###########################################################################################"); - trade.onPaymentReceived(() -> { + ((SellerProtocol) trade.getTradeProtocol()).onPaymentReceived(() -> { }, errorMessage -> { }); } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java index 9bf4c972958..220d7d88cad 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -53,6 +53,7 @@ import bisq.core.trade.TradeManager; import bisq.core.trade.protocol.BuyerProtocol; import bisq.core.trade.protocol.DisputeProtocol; +import bisq.core.trade.protocol.SellerProtocol; import bisq.core.user.Preferences; import bisq.core.util.FormattingUtils; @@ -194,7 +195,7 @@ public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler er public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { checkNotNull(getTrade(), "trade must not be null"); checkArgument(getTrade() instanceof SellerTrade, "Trade must be instance of SellerTrade"); - ((SellerTrade) getTrade()).onPaymentReceived(resultHandler, errorMessageHandler); + ((SellerProtocol) getTrade().getTradeProtocol()).onPaymentReceived(resultHandler, errorMessageHandler); } public void onWithdrawRequest(String toAddress, From 143377b7e5c72f0a3fbf738aa6b656b55319356f Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 13:36:24 -0500 Subject: [PATCH 103/143] Make some fields in ProcessModel final. Make init methods more clear There will be more refactoring commits in that area... --- .../java/bisq/core/trade/SellerTrade.java | 4 +- core/src/main/java/bisq/core/trade/Trade.java | 30 ++++++---- .../java/bisq/core/trade/TradeManager.java | 40 +++++++------ .../core/trade/protocol/ProcessModel.java | 59 ++++++++----------- 4 files changed, 69 insertions(+), 64 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/SellerTrade.java b/core/src/main/java/bisq/core/trade/SellerTrade.java index 95f05ce7a56..2ac507ecaf5 100644 --- a/core/src/main/java/bisq/core/trade/SellerTrade.java +++ b/core/src/main/java/bisq/core/trade/SellerTrade.java @@ -30,6 +30,8 @@ import javax.annotation.Nullable; +import static com.google.common.base.Preconditions.checkNotNull; + @Slf4j public abstract class SellerTrade extends Trade { SellerTrade(Offer offer, @@ -80,7 +82,7 @@ public abstract class SellerTrade extends Trade { @Override public Coin getPayoutAmount() { - return getOffer().getSellerSecurityDeposit(); + return checkNotNull(getOffer()).getSellerSecurityDeposit(); } } diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index 19f05f2eb44..571004a39da 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -285,10 +285,10 @@ public static protobuf.Trade.TradePeriodState toProtoMessage(Trade.TradePeriodSt private final long takerFeeAsLong; @Setter private long takeOfferDate; - @Getter @Setter + @Getter + @Nullable private ProcessModel processModel; - // Mutable @Nullable @Getter @@ -487,7 +487,6 @@ protected Trade(Offer offer, txFeeAsLong = txFee.value; takerFeeAsLong = takerFee.value; takeOfferDate = new Date().getTime(); - processModel = new ProcessModel(); lastRefreshRequestDate = takeOfferDate; refreshInterval = Math.min(offer.getPaymentMethod().getMaxTradePeriod() / 5, MAX_REFRESH_INTERVAL); } @@ -631,15 +630,15 @@ public void setTransientFields(Storage storage, BtcWalle this.btcWalletService = btcWalletService; } - public void init(ProcessModelServiceProvider processModelServiceProvider, - TradeManager tradeManager, - boolean useSavingsWallet, - Coin fundsNeededForTrade) { - processModel.init(checkNotNull(offer, "offer must not be null"), - processModelServiceProvider, + public void setupProcessModel(ProcessModelServiceProvider processModelServiceProvider, + TradeManager tradeManager) { + processModel = getOrCreateProcessModel(processModelServiceProvider); + processModel.applyTransient(processModelServiceProvider, tradeManager, - useSavingsWallet, - fundsNeededForTrade); + checkNotNull(offer)); + } + + public void init(ProcessModelServiceProvider processModelServiceProvider) { processModelServiceProvider.getArbitratorManager().getDisputeAgentByNodeAddress(arbitratorNodeAddress).ifPresent(arbitrator -> { arbitratorBtcPubKey = arbitrator.getBtcPubKey(); @@ -669,6 +668,15 @@ public void init(ProcessModelServiceProvider processModelServiceProvider, isInitialized = true; } + public ProcessModel getOrCreateProcessModel(ProcessModelServiceProvider processModelServiceProvider) { + if (processModel == null) { + processModel = new ProcessModel(checkNotNull(offer).getId(), + processModelServiceProvider.getUser().getAccountId(), + processModelServiceProvider.getKeyRing().getPubKeyRing()); + } + return processModel; + } + /////////////////////////////////////////////////////////////////////////////////////////// // API diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index d1bca412103..945c1e157d7 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -100,6 +100,7 @@ import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; public class TradeManager implements PersistedDataHost, DecryptedDirectMessageListener, DecryptedMailboxListener { private static final Logger log = LoggerFactory.getLogger(TradeManager.class); @@ -253,7 +254,7 @@ public void onDirectMessage(DecryptedMessageWithPubKey message, NodeAddress peer tradableListStorage, btcWalletService); - initTrade(trade); + initNewMakerTrade(trade); tradableList.add(trade); ((MakerProtocol) trade.getTradeProtocol()).handleTakeOfferRequest(takeOfferRequest, peer, errorMessage -> { if (takeOfferRequestErrorMessageHandler != null) @@ -292,14 +293,14 @@ public void onMailboxMessageAdded(DecryptedMessageWithPubKey message, NodeAddres public void onAllServicesInitialized() { if (p2PService.isBootstrapped()) - initPendingTrades(); + initPersistedTrades(); else p2PService.addP2PServiceListener(new BootstrapListener() { @Override public void onUpdatedDataReceived() { // Get called after onMailboxMessageAdded from initial data request // The mailbox message will be removed inside the tasks after they are processed successfully - initPendingTrades(); + initPersistedTrades(); } }); @@ -327,27 +328,30 @@ public void persistTrades() { // Init pending trade /////////////////////////////////////////////////////////////////////////////////////////// - private void initPendingTrades() { - tradableList.forEach(this::initPendingTrade); + private void initPersistedTrades() { + tradableList.forEach(this::initPersistedTrade); pendingTradesInitialized.set(true); } - private void initPendingTrade(Trade trade) { + private void initPersistedTrade(Trade trade) { initTrade(trade); trade.updateDepositTxFromWallet(); } - private void initTrade(Trade trade) { - initTrade(trade, - trade.getProcessModel().isUseSavingsWallet(), - trade.getProcessModel().getFundsNeededForTrade()); + private void initNewMakerTrade(Trade trade) { + initTrade(trade); } - private void initTrade(Trade trade, boolean useSavingsWallet, Coin fundsNeededForTrade) { - trade.init(processModelServiceProvider, - this, - useSavingsWallet, - fundsNeededForTrade); + private void initNewTakerTrade(Trade trade, boolean useSavingsWallet, Coin fundsNeededForTrade) { + initTrade(trade); + + checkNotNull(trade.getProcessModel()).setUseSavingsWallet(useSavingsWallet); + trade.getProcessModel().setFundsNeededForTradeAsLong(fundsNeededForTrade.value); + } + + private void initTrade(Trade trade) { + trade.setupProcessModel(processModelServiceProvider, this); + trade.init(processModelServiceProvider); } @@ -442,7 +446,7 @@ private Trade getNewTrade(Coin amount, tradableListStorage, btcWalletService); trade.setTakerPaymentAccountId(paymentAccountId); - initTrade(trade, useSavingsWallet, fundsNeededForTrade); + initNewTakerTrade(trade, useSavingsWallet, fundsNeededForTrade); return trade; } @@ -566,7 +570,7 @@ public void onMoveInvalidTradeToFailedTrades(Trade trade) { public void addFailedTradeToPendingTrades(Trade trade) { if (!trade.isInitialized()) { - initPendingTrade(trade); + initPersistedTrade(trade); } addTrade(trade); } @@ -621,7 +625,7 @@ private boolean unFailTrade(Trade trade) { return false; } - initPendingTrade(trade); + initPersistedTrade(trade); if (!tradableList.contains(trade)) { tradableList.add(trade); diff --git a/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java b/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java index 15b514563fe..150db21210d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java +++ b/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java @@ -112,17 +112,11 @@ public class ProcessModel implements Model, PersistablePayload { transient private Transaction depositTx; - // Persistable Immutable (private setter only used by PB method) - - //todo make final - @Setter - private TradingPeer tradingPeer = new TradingPeer(); - @Setter - private String offerId; - @Setter - private String accountId; - @Setter - private PubKeyRing pubKeyRing; + // Persistable Immutable + private final TradingPeer tradingPeer; + private final String offerId; + private final String accountId; + private final PubKeyRing pubKeyRing; // Persistable Mutable @Nullable @@ -171,9 +165,25 @@ public class ProcessModel implements Model, PersistablePayload { @Setter private ObjectProperty paymentStartedMessageStateProperty = new SimpleObjectProperty<>(MessageState.UNDEFINED); - public ProcessModel() { + public ProcessModel(String offerId, String accountId, PubKeyRing pubKeyRing) { + this(offerId, accountId, pubKeyRing, new TradingPeer()); } + public ProcessModel(String offerId, String accountId, PubKeyRing pubKeyRing, TradingPeer tradingPeer) { + this.offerId = offerId; + this.accountId = accountId; + this.pubKeyRing = pubKeyRing; + // If tradingPeer was null in persisted data from some error cases we set a new one to not cause nullPointers + this.tradingPeer = tradingPeer != null ? tradingPeer : new TradingPeer(); + } + + public void applyTransient(ProcessModelServiceProvider processModelServiceProvider, + TradeManager tradeManager, + Offer offer) { + this.offer = offer; + this.provider = processModelServiceProvider; + this.tradeManager = tradeManager; + } /////////////////////////////////////////////////////////////////////////////////////////// // PROTO BUFFER @@ -207,11 +217,9 @@ public protobuf.ProcessModel toProtoMessage() { } public static ProcessModel fromProto(protobuf.ProcessModel proto, CoreProtoResolver coreProtoResolver) { - ProcessModel processModel = new ProcessModel(); - processModel.setTradingPeer(proto.hasTradingPeer() ? TradingPeer.fromProto(proto.getTradingPeer(), coreProtoResolver) : null); - processModel.setOfferId(proto.getOfferId()); - processModel.setAccountId(proto.getAccountId()); - processModel.setPubKeyRing(PubKeyRing.fromProto(proto.getPubKeyRing())); + TradingPeer tradingPeer = TradingPeer.fromProto(proto.getTradingPeer(), coreProtoResolver); + PubKeyRing pubKeyRing = PubKeyRing.fromProto(proto.getPubKeyRing()); + ProcessModel processModel = new ProcessModel(proto.getOfferId(), proto.getAccountId(), pubKeyRing, tradingPeer); processModel.setChangeOutputValue(proto.getChangeOutputValue()); processModel.setUseSavingsWallet(proto.getUseSavingsWallet()); processModel.setFundsNeededForTradeAsLong(proto.getFundsNeededForTradeAsLong()); @@ -243,23 +251,6 @@ public static ProcessModel fromProto(protobuf.ProcessModel proto, CoreProtoResol // API /////////////////////////////////////////////////////////////////////////////////////////// - public void init(Offer offer, - ProcessModelServiceProvider processModelServiceProvider, - TradeManager tradeManager, - boolean useSavingsWallet, - Coin fundsNeededForTrade) { - this.offer = offer; - this.provider = processModelServiceProvider; - this.tradeManager = tradeManager; - this.useSavingsWallet = useSavingsWallet; - fundsNeededForTradeAsLong = fundsNeededForTrade.value; - - offerId = offer.getId(); - accountId = getUser().getAccountId(); - pubKeyRing = getKeyRing().getPubKeyRing(); - } - - public void removeMailboxMessageAfterProcessing(Trade trade) { if (tradeMessage instanceof MailboxMessage && decryptedMessageWithPubKey != null && From d6c242922b83190ba5009578387d537723a69734 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 15:52:09 -0500 Subject: [PATCH 104/143] Remove timeouts as it was not used before. --- .../core/trade/protocol/DisputeProtocol.java | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/DisputeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/DisputeProtocol.java index 41d4020731e..0d429965c4e 100644 --- a/core/src/main/java/bisq/core/trade/protocol/DisputeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/DisputeProtocol.java @@ -87,8 +87,7 @@ public void onAcceptMediationResult(ResultHandler resultHandler, ErrorMessageHan errorMessage -> { errorMessageHandler.handleErrorMessage(errorMessage); handleTaskRunnerFault(event, errorMessage); - })) - .withTimeout(30)) + }))) .executeTasks(); } @@ -114,8 +113,7 @@ public void onFinalizeMediationResultPayout(ResultHandler resultHandler, ErrorMe errorMessage -> { errorMessageHandler.handleErrorMessage(errorMessage); handleTaskRunnerFault(event, errorMessage); - })) - .withTimeout(30)) + }))) .executeTasks(); } @@ -130,8 +128,7 @@ protected void handle(MediatedPayoutTxSignatureMessage message, NodeAddress peer Trade.Phase.FIAT_RECEIVED) .with(message) .from(peer)) - .setup(tasks(ProcessMediatedPayoutSignatureMessage.class) - .withTimeout(30)) + .setup(tasks(ProcessMediatedPayoutSignatureMessage.class)) .executeTasks(); } @@ -141,8 +138,7 @@ protected void handle(MediatedPayoutTxPublishedMessage message, NodeAddress peer Trade.Phase.FIAT_RECEIVED) .with(message) .from(peer)) - .setup(tasks(ProcessMediatedPayoutTxPublishedMessage.class) - .withTimeout(30)) + .setup(tasks(ProcessMediatedPayoutTxPublishedMessage.class)) .executeTasks(); } @@ -167,8 +163,7 @@ public void onPublishDelayedPayoutTx(ResultHandler resultHandler, ErrorMessageHa errorMessage -> { errorMessageHandler.handleErrorMessage(errorMessage); handleTaskRunnerFault(event, errorMessage); - })) - .withTimeout(30)) + }))) .executeTasks(); } @@ -183,8 +178,7 @@ private void handle(PeerPublishedDelayedPayoutTxMessage message, NodeAddress pee Trade.Phase.FIAT_RECEIVED) .with(message) .from(peer)) - .setup(tasks(ProcessPeerPublishedDelayedPayoutTxMessage.class) - .withTimeout(30)) + .setup(tasks(ProcessPeerPublishedDelayedPayoutTxMessage.class)) .executeTasks(); } From 27ac2d8e57ef486a736fe890e2cab45a728e4c6d Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 15:52:31 -0500 Subject: [PATCH 105/143] Remove never read field --- .../java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java index c921ca34575..8c90e51c1c1 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java @@ -138,7 +138,7 @@ public class TakeOfferView extends ActivatableViewAndModel amountValueCurrencyBoxTuple = getEditableValueBox(Res.get("takeOffer.amount.prompt")); amountValueCurrencyBox = amountValueCurrencyBoxTuple.first; amountTextField = amountValueCurrencyBoxTuple.second; - amountCurrency = amountValueCurrencyBoxTuple.third; Tuple2 amountInputBoxTuple = getTradeInputBox(amountValueCurrencyBox, model.getAmountDescription()); amountDescriptionLabel = amountInputBoxTuple.first; VBox amountBox = amountInputBoxTuple.second; From 74317636b007eb6dbca7c0dc7f25ee841fbc1da0 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 16:00:03 -0500 Subject: [PATCH 106/143] Apply code inspection suggestions --- core/src/main/java/bisq/core/app/BisqExecutable.java | 2 -- .../main/java/bisq/core/trade/DumpDelayedPayoutTx.java | 4 ++-- core/src/main/java/bisq/core/trade/Trade.java | 7 +++---- core/src/main/java/bisq/core/trade/TradeManager.java | 8 ++------ .../bisq/core/trade/failed/FailedTradesManager.java | 10 +++++----- .../core/trade/messages/RefreshTradeStateRequest.java | 1 + .../trade/messages/TraderSignedWitnessMessage.java | 1 + .../java/bisq/core/trade/protocol/BuyerProtocol.java | 2 +- .../java/bisq/core/trade/protocol/DisputeProtocol.java | 4 ++-- .../java/bisq/core/trade/protocol/SellerProtocol.java | 2 +- .../java/bisq/core/trade/protocol/TradeProtocol.java | 2 +- .../bisq/core/trade/statistics/TradeStatistics2.java | 2 ++ .../core/trade/statistics/TradeStatistics2Store.java | 2 +- .../core/trade/statistics/TradeStatisticsManager.java | 2 +- .../bisq/core/trade/txproof/xmr/XmrTxProofService.java | 2 +- .../portfolio/failedtrades/FailedTradesDataModel.java | 4 ++-- 16 files changed, 26 insertions(+), 29 deletions(-) diff --git a/core/src/main/java/bisq/core/app/BisqExecutable.java b/core/src/main/java/bisq/core/app/BisqExecutable.java index f9961adda23..cba7a634164 100644 --- a/core/src/main/java/bisq/core/app/BisqExecutable.java +++ b/core/src/main/java/bisq/core/app/BisqExecutable.java @@ -25,7 +25,6 @@ import bisq.core.setup.CorePersistedDataHost; import bisq.core.setup.CoreSetup; import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager; -import bisq.core.trade.TradeManager; import bisq.core.trade.txproof.xmr.XmrTxProofService; import bisq.network.p2p.P2PService; @@ -221,7 +220,6 @@ public void gracefulShutDown(ResultHandler resultHandler) { try { injector.getInstance(ArbitratorManager.class).shutDown(); - injector.getInstance(TradeManager.class).shutDown(); injector.getInstance(XmrTxProofService.class).shutDown(); injector.getInstance(DaoSetup.class).shutDown(); injector.getInstance(AvoidStandbyModeService.class).shutDown(); diff --git a/core/src/main/java/bisq/core/trade/DumpDelayedPayoutTx.java b/core/src/main/java/bisq/core/trade/DumpDelayedPayoutTx.java index 76a0e86de9e..3b31f6f8adb 100644 --- a/core/src/main/java/bisq/core/trade/DumpDelayedPayoutTx.java +++ b/core/src/main/java/bisq/core/trade/DumpDelayedPayoutTx.java @@ -40,8 +40,8 @@ public class DumpDelayedPayoutTx { } static class DelayedPayoutHash { - String tradeId; - String delayedPayoutTx; + final String tradeId; + final String delayedPayoutTx; DelayedPayoutHash(String tradeId, String delayedPayoutTx) { this.tradeId = tradeId; diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index 571004a39da..85faf787ad6 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -119,7 +119,7 @@ public enum State { // #################### Phase DEPOSIT_PUBLISHED // We changes order in trade protocol of publishing deposit tx and sending it to the peer. - // Now we send it first to the peer and only if that succeeds we publish it to avoid likelyhood of + // Now we send it first to the peer and only if that succeeds we publish it to avoid likelihood of // failed trades. We do not want to change the order of the enum though so we keep it here as it was originally. SELLER_PUBLISHED_DEPOSIT_TX(Phase.DEPOSIT_PUBLISHED), @@ -438,7 +438,7 @@ public static protobuf.Trade.TradePeriodState toProtoMessage(Trade.TradePeriodSt @Setter private long lastRefreshRequestDate; @Getter - private long refreshInterval; + private final long refreshInterval; private static final long MAX_REFRESH_INTERVAL = 4 * ChronoUnit.HOURS.getDuration().toMillis(); // Added at v1.3.8 @@ -756,8 +756,7 @@ void addDecryptedMessageWithPubKey(DecryptedMessageWithPubKey decryptedMessageWi } public void removeDecryptedMessageWithPubKey(DecryptedMessageWithPubKey decryptedMessageWithPubKey) { - if (decryptedMessageWithPubKeySet.contains(decryptedMessageWithPubKey)) - decryptedMessageWithPubKeySet.remove(decryptedMessageWithPubKey); + decryptedMessageWithPubKeySet.remove(decryptedMessageWithPubKey); } public void addAndPersistChatMessage(ChatMessage chatMessage) { diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 945c1e157d7..0140a89f375 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -180,7 +180,7 @@ public TradeManager(User user, p2PService.addDecryptedDirectMessageListener(this); p2PService.addDecryptedMailboxListener(this); - failedTradesManager.setUnfailTradeCallback(this::unFailTrade); + failedTradesManager.setUnFailTradeCallback(this::unFailTrade); } @@ -315,10 +315,6 @@ public void onUpdatedDataReceived() { }); } - public void shutDown() { - // Do nothing here - } - public void persistTrades() { tradableList.persist(); } @@ -621,7 +617,7 @@ public Set getSetOfFailedOrClosedTradeIdsFromLockedInFunds() throws Trad // Aborts unfailing if the address entries needed are not available private boolean unFailTrade(Trade trade) { if (!recoverAddresses(trade)) { - log.warn("Failed to recover address during unfail trade"); + log.warn("Failed to recover address during unFail trade"); return false; } diff --git a/core/src/main/java/bisq/core/trade/failed/FailedTradesManager.java b/core/src/main/java/bisq/core/trade/failed/FailedTradesManager.java index 1d68dfa4531..29cdd9a7888 100644 --- a/core/src/main/java/bisq/core/trade/failed/FailedTradesManager.java +++ b/core/src/main/java/bisq/core/trade/failed/FailedTradesManager.java @@ -52,7 +52,7 @@ public class FailedTradesManager implements PersistedDataHost { private final Storage> tradableListStorage; private final DumpDelayedPayoutTx dumpDelayedPayoutTx; @Setter - private Function unfailTradeCallback; + private Function unFailTradeCallback; @Inject public FailedTradesManager(KeyRing keyRing, @@ -108,17 +108,17 @@ public Stream getTradesStreamWithFundsLockedIn() { .filter(Trade::isFundsLockedIn); } - public void unfailTrade(Trade trade) { - if (unfailTradeCallback == null) + public void unFailTrade(Trade trade) { + if (unFailTradeCallback == null) return; - if (unfailTradeCallback.apply(trade)) { + if (unFailTradeCallback.apply(trade)) { log.info("Unfailing trade {}", trade.getId()); failedTrades.remove(trade); } } - public String checkUnfail(Trade trade) { + public String checkUnFail(Trade trade) { var addresses = TradeUtils.getTradeAddresses(trade, btcWalletService, keyRing); if (addresses == null) { return "Addresses not found"; diff --git a/core/src/main/java/bisq/core/trade/messages/RefreshTradeStateRequest.java b/core/src/main/java/bisq/core/trade/messages/RefreshTradeStateRequest.java index ff5c82362ed..c2a6da54166 100644 --- a/core/src/main/java/bisq/core/trade/messages/RefreshTradeStateRequest.java +++ b/core/src/main/java/bisq/core/trade/messages/RefreshTradeStateRequest.java @@ -28,6 +28,7 @@ * We do the re-sending of the payment sent message via the BuyerSendCounterCurrencyTransferStartedMessage task on the * buyer side, so seller do not need to do anything interactively. */ +@SuppressWarnings("deprecation") @EqualsAndHashCode(callSuper = true) @Value public class RefreshTradeStateRequest extends TradeMessage implements MailboxMessage { diff --git a/core/src/main/java/bisq/core/trade/messages/TraderSignedWitnessMessage.java b/core/src/main/java/bisq/core/trade/messages/TraderSignedWitnessMessage.java index c1172f08741..56667b1dbf4 100644 --- a/core/src/main/java/bisq/core/trade/messages/TraderSignedWitnessMessage.java +++ b/core/src/main/java/bisq/core/trade/messages/TraderSignedWitnessMessage.java @@ -27,6 +27,7 @@ import lombok.EqualsAndHashCode; import lombok.Value; +@SuppressWarnings("ALL") @EqualsAndHashCode(callSuper = true) @Value public class TraderSignedWitnessMessage extends TradeMessage implements MailboxMessage { 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 cad6d022ece..67ffe0d5dcb 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java @@ -130,7 +130,7 @@ public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler er BuyerEvent event = BuyerEvent.PAYMENT_SENT; expect(phase(Trade.Phase.DEPOSIT_CONFIRMED) .with(event) - .preCondition(!wasDisputed())) + .preCondition(notDisputed())) .setup(tasks(ApplyFilter.class, getVerifyPeersFeePaymentClass(), BuyerSignPayoutTx.class, diff --git a/core/src/main/java/bisq/core/trade/protocol/DisputeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/DisputeProtocol.java index 0d429965c4e..adbcb8ee08f 100644 --- a/core/src/main/java/bisq/core/trade/protocol/DisputeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/DisputeProtocol.java @@ -55,8 +55,8 @@ public DisputeProtocol(Trade trade) { super(trade); } - protected boolean wasDisputed() { - return trade.getDisputeState() != Trade.DisputeState.NO_DISPUTE; + protected boolean notDisputed() { + return trade.getDisputeState() == Trade.DisputeState.NO_DISPUTE; } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java index b436598240f..243df868634 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java @@ -123,7 +123,7 @@ public void onPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler e SellerEvent event = SellerEvent.PAYMENT_RECEIVED; expect(phase(Trade.Phase.FIAT_SENT) .with(event) - .preCondition(!wasDisputed())) + .preCondition(notDisputed())) .setup(tasks( ApplyFilter.class, getVerifyPeersFeePaymentClass(), diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index 252aab97032..26a6a3c0e15 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -44,7 +44,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener { protected final ProcessModel processModel; - protected Trade trade; + protected final Trade trade; private Timer timeoutTimer; diff --git a/core/src/main/java/bisq/core/trade/statistics/TradeStatistics2.java b/core/src/main/java/bisq/core/trade/statistics/TradeStatistics2.java index bb31911d2bd..17a878c270c 100644 --- a/core/src/main/java/bisq/core/trade/statistics/TradeStatistics2.java +++ b/core/src/main/java/bisq/core/trade/statistics/TradeStatistics2.java @@ -67,7 +67,9 @@ public final class TradeStatistics2 implements ProcessOncePersistableNetworkPayload, PersistableNetworkPayload, CapabilityRequiringPayload, Comparable { + @SuppressWarnings("SpellCheckingInspection") public static final String MEDIATOR_ADDRESS = "medAddr"; + @SuppressWarnings("SpellCheckingInspection") public static final String REFUND_AGENT_ADDRESS = "refAddr"; private final OfferPayload.Direction direction; diff --git a/core/src/main/java/bisq/core/trade/statistics/TradeStatistics2Store.java b/core/src/main/java/bisq/core/trade/statistics/TradeStatistics2Store.java index d3ea468907c..db1c7943f28 100644 --- a/core/src/main/java/bisq/core/trade/statistics/TradeStatistics2Store.java +++ b/core/src/main/java/bisq/core/trade/statistics/TradeStatistics2Store.java @@ -40,7 +40,7 @@ @Slf4j public class TradeStatistics2Store implements ThreadedPersistableEnvelope { @Getter - private Map map = new ConcurrentHashMap<>(); + private final Map map = new ConcurrentHashMap<>(); TradeStatistics2Store() { } diff --git a/core/src/main/java/bisq/core/trade/statistics/TradeStatisticsManager.java b/core/src/main/java/bisq/core/trade/statistics/TradeStatisticsManager.java index 4d90fc143c9..a92d8ae3c71 100644 --- a/core/src/main/java/bisq/core/trade/statistics/TradeStatisticsManager.java +++ b/core/src/main/java/bisq/core/trade/statistics/TradeStatisticsManager.java @@ -156,7 +156,7 @@ private void dump() { } static class WrapperTradeStatistics2 { - private TradeStatistics2 tradeStatistics; + private final TradeStatistics2 tradeStatistics; public WrapperTradeStatistics2(TradeStatistics2 tradeStatistics) { this.tradeStatistics = tradeStatistics; diff --git a/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java b/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java index cb67652ffbb..d81c840aab8 100644 --- a/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java +++ b/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java @@ -80,7 +80,7 @@ public class XmrTxProofService implements AssetTxProofService { private final Socks5ProxyProvider socks5ProxyProvider; private final Map servicesByTradeId = new HashMap<>(); private AutoConfirmSettings autoConfirmSettings; - private Map> tradeStateListenerMap = new HashMap<>(); + private final Map> tradeStateListenerMap = new HashMap<>(); private ChangeListener btcPeersListener, btcBlockListener; private BootstrapListener bootstrapListener; private MonadicBinding p2pNetworkAndWalletReady; diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesDataModel.java index 30a800b5c67..5d33f4c16af 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesDataModel.java @@ -83,10 +83,10 @@ public void onMoveTradeToPendingTrades(Trade trade) { } public void unfailTrade(Trade trade) { - failedTradesManager.unfailTrade(trade); + failedTradesManager.unFailTrade(trade); } public String checkUnfail(Trade trade) { - return failedTradesManager.checkUnfail(trade); + return failedTradesManager.checkUnFail(trade); } } From a9ad72d0e4f522ca05fb33875a85e31950b40c31 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 16:21:19 -0500 Subject: [PATCH 107/143] Remove offer at close to avoid that button stays active when taking the offer Cleanups --- .../offer/takeoffer/TakeOfferDataModel.java | 45 +++---------- .../main/offer/takeoffer/TakeOfferView.java | 65 +++++++------------ .../offer/takeoffer/TakeOfferViewModel.java | 2 - 3 files changed, 34 insertions(+), 78 deletions(-) diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java index 4290faf3b39..8e2c92fc536 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java @@ -246,31 +246,6 @@ void initWithData(Offer offer) { @Override public void onBalanceChanged(Coin balance, Transaction tx) { updateBalance(); - - /*if (isMainNet.get()) { - SettableFuture future = blockchainService.requestFee(tx.getTxId().toString()); - Futures.addCallback(future, new FutureCallback() { - public void onSuccess(Coin fee) { - UserThread.execute(() -> setFeeFromFundingTx(fee)); - } - - public void onFailure(@NotNull Throwable throwable) { - UserThread.execute(() -> new Popup<>() - .warning("We did not get a response for the request of the mining fee used " + - "in the funding transaction.\n\n" + - "Are you sure you used a sufficiently high fee of at least " + - formatter.formatCoinWithCode(FeePolicy.getMinRequiredFeeForFundingTx()) + "?") - .actionButtonText("Yes, I used a sufficiently high fee.") - .onAction(() -> setFeeFromFundingTx(FeePolicy.getMinRequiredFeeForFundingTx())) - .closeButtonText("No. Let's cancel that payment.") - .onClose(() -> setFeeFromFundingTx(Coin.NEGATIVE_SATOSHI)) - .show()); - } - }, MoreExecutors.directExecutor()); - } else { - setFeeFromFundingTx(FeePolicy.getMinRequiredFeeForFundingTx()); - isFeeFromFundingTxSufficient.set(feeFromFundingTx.compareTo(FeePolicy.getMinRequiredFeeForFundingTx()) >= 0); - }*/ } }; @@ -293,6 +268,14 @@ void onTabSelected(boolean isSelected) { } public void onClose() { + // We do not wait until the offer got removed by a network remove message but remove it + // directly from the offer book. The broadcast gets now bundled and has 2 sec. delay so the + // removal from the network is a bit slower as it has been before. To avoid that the taker gets + // confused to see the same offer still in the offerbook we remove it manually. This removal has + // only local effect. Other trader might see the offer for a few seconds + // still (but cannot take it). + offerBook.removeOffer(checkNotNull(offer), tradeManager); + btcWalletService.resetAddressEntriesForOpenOffer(offer.getId()); } @@ -333,17 +316,7 @@ void onTakeOffer(TradeResultHandler tradeResultHandler) { offer, paymentAccount.getId(), useSavingsWallet, - trade -> { - // We do not wait until the offer got removed by a network remove message but remove it - // directly from the offer book. The broadcast gets now bundled and has 2 sec. delay so the - // removal from the network is a bit slower as it has been before. To avoid that the taker gets - // confused to see the same offer still in the offerbook we remove it manually. This removal has - // only local effect. Other trader might see the offer for a few seconds - // still (but cannot take it). - offerBook.removeOffer(checkNotNull(trade.getOffer()), tradeManager); - - tradeResultHandler.handleResult(trade); - }, + tradeResultHandler::handleResult, errorMessage -> { log.warn(errorMessage); new Popup().warning(errorMessage).show(); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java index 8c90e51c1c1..0ae302cb6d4 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java @@ -422,25 +422,32 @@ public void onTabSelected(boolean isSelected) { /////////////////////////////////////////////////////////////////////////////////////////// private void onTakeOffer() { - if (model.dataModel.canTakeOffer()) { - if (model.dataModel.isTakerFeeValid()) { - if (!DevEnv.isDevMode()) { - offerDetailsWindow.onTakeOffer(() -> - model.onTakeOffer(() -> { - offerDetailsWindow.hide(); - offerDetailsWindowDisplayed = false; - }) - ).show(model.getOffer(), model.dataModel.getAmount().get(), model.dataModel.tradePrice); - offerDetailsWindowDisplayed = true; - } else { - balanceSubscription.unsubscribe(); - model.onTakeOffer(() -> { - }); - } - } else { - showInsufficientBsqFundsForBtcFeePaymentPopup(); - } + if (!model.dataModel.canTakeOffer()) { + return; + } + + if (!model.dataModel.isTakerFeeValid()) { + showInsufficientBsqFundsForBtcFeePaymentPopup(); + return; + } + + if (DevEnv.isDevMode()) { + balanceSubscription.unsubscribe(); + model.onTakeOffer(() -> { + }); + return; } + + offerDetailsWindow.onTakeOffer(() -> + model.onTakeOffer(() -> { + offerDetailsWindow.hide(); + offerDetailsWindowDisplayed = false; + }) + ).show(model.getOffer(), + model.dataModel.getAmount().get(), + model.dataModel.tradePrice); + + offerDetailsWindowDisplayed = true; } private void onShowPayFundsScreen() { @@ -736,28 +743,6 @@ private void addSubscriptions() { } }); - /* noSufficientFeeBinding = EasyBind.combine(model.dataModel.getIsWalletFunded(), model.dataModel.isMainNet, model.dataModel.isFeeFromFundingTxSufficient, - (getIsWalletFunded(), isMainNet, isFeeSufficient) -> getIsWalletFunded() && isMainNet && !isFeeSufficient); - noSufficientFeeSubscription = noSufficientFeeBinding.subscribe((observable, oldValue, newValue) -> { - if (newValue) - new Popup<>().warning("The mining fee from your funding transaction is not sufficiently high.\n\n" + - "You need to use at least a mining fee of " + - model.formatter.formatCoinWithCode(FeePolicy.getMinRequiredFeeForFundingTx()) + ".\n\n" + - "The fee used in your funding transaction was only " + - model.formatter.formatCoinWithCode(model.dataModel.feeFromFundingTx) + ".\n\n" + - "The trade transactions might take too much time to be included in " + - "a block if the fee is too low.\n" + - "Please check at your external wallet that you set the required fee and " + - "do a funding again with the correct fee.\n\n" + - "In the \"Funds/Open for withdrawal\" section you can withdraw those funds.") - .closeButtonText(Res.get("shared.close")) - .onClose(() -> { - close(); - navigation.navigateTo(MainView.class, FundsView.class, WithdrawalView.class); - }) - .show(); - });*/ - balanceSubscription = EasyBind.subscribe(model.dataModel.getBalance(), balanceTextField::setBalance); } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java index c868ab2d995..5496ca957c5 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java @@ -502,8 +502,6 @@ private void updateButtonDisableState() { && isOfferAvailable.get() && !dataModel.wouldCreateDustForMaker(); isNextButtonDisabled.set(!inputDataValid); - // boolean notSufficientFees = dataModel.isWalletFunded.get() && dataModel.isMainNet.get() && !dataModel.isFeeFromFundingTxSufficient.get(); - // isTakeOfferButtonDisabled.set(takeOfferRequested || !inputDataValid || notSufficientFees); isTakeOfferButtonDisabled.set(takeOfferRequested || !inputDataValid || !dataModel.getIsBtcWalletFunded().get()); } From 3ce1ac92855913fb691767617adc404c9bd5987c Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 17:36:41 -0500 Subject: [PATCH 108/143] Refactor: improve logs --- core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index 26a6a3c0e15..3ec9daf07a0 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -314,6 +314,7 @@ private boolean isMyTradeMessage(TradeMessage message) { private void cleanup() { stopTimeout(); - processModel.getP2PService().removeDecryptedDirectMessageListener(this); + // We do not remove the decryptedDirectMessageListener as in case of not critical failures we want allow to receive + // follow-up messages still } } From 07bcf6c38f6d0a43a0b8fa414d8b22c069f8a8e7 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 17:36:57 -0500 Subject: [PATCH 109/143] Refactor: improve logs --- .../java/bisq/core/trade/protocol/FluentProtocol.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java b/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java index 0edefd3a8a6..03d58daaabd 100644 --- a/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java @@ -273,7 +273,7 @@ private Result getPhaseResult() { event.name() + " event" : ""; if (isPhaseValid) { - String info = MessageFormat.format("We received {0} at phase {1} and state {2}, tradeId={3}", + String info = MessageFormat.format("We received a {0} at phase {1} and state {2}, tradeId={3}", trigger, trade.getPhase(), trade.getState(), @@ -281,7 +281,7 @@ private Result getPhaseResult() { log.info(info); return Result.VALID.info(info); } else { - String info = MessageFormat.format("We received {0} but we are are not in the expected phase. " + + String info = MessageFormat.format("We received a {0} but we are are not in the expected phase. " + "Expected phases={1}, Trade phase={2}, Trade state= {3}, tradeId={4}", trigger, expectedPhases, @@ -304,14 +304,14 @@ private Result getStateResult() { event.name() + " event" : ""; if (isStateValid) { - String info = MessageFormat.format("We received {0} at state {1}, tradeId={2}", + String info = MessageFormat.format("We received a {0} at state {1}, tradeId={2}", trigger, trade.getState(), trade.getId()); log.info(info); return Result.VALID.info(info); } else { - String info = MessageFormat.format("We received {0} but we are are not in the expected state. " + + String info = MessageFormat.format("We received a {0} but we are are not in the expected state. " + "Expected states={1}, Trade state= {2}, tradeId={3}", trigger, expectedStates, From 6c6332d68df3b78ff8abbd40fb8b64a0f52dd662 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 17:37:34 -0500 Subject: [PATCH 110/143] Allow also Trade.Phase.PAYOUT_PUBLISHED in onPaymentReceived to support in failure situations to resend the msg --- core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java index 243df868634..b7ec415ffa4 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java @@ -121,7 +121,7 @@ protected void handle(CounterCurrencyTransferStartedMessage message, NodeAddress public void onPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { SellerEvent event = SellerEvent.PAYMENT_RECEIVED; - expect(phase(Trade.Phase.FIAT_SENT) + expect(anyPhase(Trade.Phase.FIAT_SENT, Trade.Phase.PAYOUT_PUBLISHED) .with(event) .preCondition(notDisputed())) .setup(tasks( From 5309f04b40cd6f1c3cf308194df2ea50b43be5f6 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 18:33:25 -0500 Subject: [PATCH 111/143] DO not deactivate move to failed trades button. Use different text in popup if all txs are valid. Fix icon style issues. --- .../resources/i18n/displayStrings.properties | 8 ++- desktop/src/main/java/bisq/desktop/bisq.css | 26 +++++++-- .../desktop/components/HyperlinkWithIcon.java | 2 +- .../pendingtrades/PendingTradesView.fxml | 4 +- .../pendingtrades/PendingTradesView.java | 55 ++++++++++--------- .../java/bisq/desktop/util/FormBuilder.java | 4 ++ 6 files changed, 63 insertions(+), 36 deletions(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 091c6d90c0f..64b3bd23ca3 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -940,7 +940,13 @@ portfolio.pending.failedTrade.missingContract=The trade contract is not set.\n\n have lost your trade fee. If so, you can request at https://github.com/bisq-network/support/issues for \ getting reimbursed the lost trade fee. portfolio.pending.failedTrade.info.popup=The trade protocol encountered some problems.\n\n{0} -portfolio.pending.failedTrade.moveToFailed=The trade protocol encountered some problems.\n\n{0}\n\n\ +portfolio.pending.failedTrade.txChainInvalid.moveToFailed=The trade protocol encountered a serious problem.\n\n{0}\n\n\ + Do you want to move the trade to failed trades?\n\n\ + You cannot open mediation or arbitration from the failed trades view, but you can move it back to the open \ + trades screen any time. +portfolio.pending.failedTrade.txChainValid.moveToFailed=The trade protocol encountered some problems.\n\n{0}\n\n\ + The trade transactions have been published and funds are locked up. Only move the trade to failed trades if you are \ + really sure. It might prevent options to resolve the problem.\n\n\ Do you want to move the trade to failed trades?\n\n\ You cannot open mediation or arbitration from the failed trades view, but you can move it back to the open \ trades screen any time. diff --git a/desktop/src/main/java/bisq/desktop/bisq.css b/desktop/src/main/java/bisq/desktop/bisq.css index 24245a4d4ef..1b213ab9008 100644 --- a/desktop/src/main/java/bisq/desktop/bisq.css +++ b/desktop/src/main/java/bisq/desktop/bisq.css @@ -85,11 +85,6 @@ -fx-fill: -bs-color-gray-6; } -.error-icon { - -fx-text-fill: -bs-rd-error-red; - -fx-fill: -bs-rd-error-red; -} - .zero-decimals { -fx-text-fill: -bs-color-gray-3; } @@ -1136,6 +1131,27 @@ textfield */ -fx-fill: -bs-text-color; } +.warn-icon { + -fx-text-fill: -bs-yellow; + -fx-fill: -bs-yellow; +} + +.warn-icon:hover { + -fx-text-fill: -bs-yellow; + -fx-fill: -bs-yellow; +} + +.error-icon { + -fx-text-fill: -bs-rd-error-red; + -fx-fill: -bs-rd-error-red; +} + +.error-icon:hover { + -fx-text-fill: -bs-rd-error-red; + -fx-fill: -bs-rd-error-red; +} + + /******************************************************************************* * * * Images * diff --git a/desktop/src/main/java/bisq/desktop/components/HyperlinkWithIcon.java b/desktop/src/main/java/bisq/desktop/components/HyperlinkWithIcon.java index 903d0e6b196..b4a24825e03 100644 --- a/desktop/src/main/java/bisq/desktop/components/HyperlinkWithIcon.java +++ b/desktop/src/main/java/bisq/desktop/components/HyperlinkWithIcon.java @@ -80,7 +80,7 @@ public void hideIcon() { setGraphic(null); } - private void setIcon(Node icon) { + public void setIcon(Node icon) { this.icon = icon; setGraphic(icon); diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.fxml b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.fxml index be897e53c32..b8f27271572 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.fxml +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.fxml @@ -36,10 +36,10 @@ - + - + diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java index 0bba268e783..316c8151aae 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java @@ -52,7 +52,6 @@ import javax.inject.Inject; import javax.inject.Named; -import de.jensd.fx.fontawesome.AwesomeIcon; import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon; import com.jfoenix.controls.JFXBadge; @@ -68,7 +67,6 @@ import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.Button; -import javafx.scene.control.Label; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; @@ -80,6 +78,7 @@ import javafx.scene.layout.Priority; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; +import javafx.scene.text.Text; import javafx.geometry.Insets; import javafx.geometry.Pos; @@ -320,8 +319,12 @@ private boolean isMaybeInvalidTrade(Trade trade) { } private void onMoveInvalidTradeToFailedTrades(Trade trade) { - new Popup().width(900).attention(Res.get("portfolio.pending.failedTrade.moveToFailed", - getInvalidTradeDetails(trade))) + String msg = trade.isTxChainInvalid() ? + Res.get("portfolio.pending.failedTrade.txChainInvalid.moveToFailed", + getInvalidTradeDetails(trade)) : + Res.get("portfolio.pending.failedTrade.txChainValid.moveToFailed", + getInvalidTradeDetails(trade)); + new Popup().width(900).attention(msg) .onAction(() -> { model.dataModel.onMoveInvalidTradeToFailedTrades(trade); updateMoveTradeToFailedColumnState(); @@ -532,10 +535,7 @@ private void updateTableSelection() { // Select and focus selectedItem from model int index = tableView.getItems().indexOf(selectedItemFromModel); UserThread.execute(() -> { - //TODO app wide focus tableView.getSelectionModel().select(index); - //table.requestFocus(); - //UserThread.execute(() -> table.getFocusModel().focus(index)); }); } } @@ -566,16 +566,20 @@ public void updateItem(final PendingTradesListItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { - if (isMaybeInvalidTrade(item.getTrade())) { - field = new HyperlinkWithIcon(item.getTrade().getShortId(), AwesomeIcon.WARNING_SIGN); - field.setOnAction(event -> tradeDetailsWindow.show(item.getTrade())); + Trade trade = item.getTrade(); + if (isMaybeInvalidTrade(trade)) { + field = new HyperlinkWithIcon(trade.getShortId()); + field.setIcon(FormBuilder.getMediumSizeIcon(MaterialDesignIcon.ALERT_CIRCLE_OUTLINE)); + field.setOnAction(event -> tradeDetailsWindow.show(trade)); field.setTooltip(new Tooltip(Res.get("tooltip.invalidTradeState.warning"))); - //FIXME icon does not take red color ;-( - field.getIcon().getStyleClass().clear(); - field.getIcon().getStyleClass().addAll("hyperlink", "error"); + if (trade.isTxChainInvalid()) { + field.getIcon().getStyleClass().addAll("icon", "error-icon"); + } else { + field.getIcon().getStyleClass().addAll("icon", "warn-icon"); + } } else { - field = new HyperlinkWithIcon(item.getTrade().getShortId()); - field.setOnAction(event -> tradeDetailsWindow.show(item.getTrade())); + field = new HyperlinkWithIcon(trade.getShortId()); + field.setOnAction(event -> tradeDetailsWindow.show(trade)); field.setTooltip(new Tooltip(Res.get("tooltip.openPopupForDetails"))); } setGraphic(field); @@ -861,29 +865,26 @@ public void updateItem(PendingTradesListItem newItem, boolean empty) { super.updateItem(newItem, empty); if (!empty && newItem != null && isMaybeInvalidTrade(newItem.getTrade())) { Trade trade = newItem.getTrade(); + Text warnIcon = FormBuilder.getMediumSizeIcon(MaterialDesignIcon.ALERT_CIRCLE_OUTLINE); + Text trashIcon = FormBuilder.getMediumSizeIcon(MaterialDesignIcon.ARROW_RIGHT_BOLD_BOX_OUTLINE); + if (trade.isTxChainInvalid()) { + trashIcon.getStyleClass().addAll("icon", "error-icon"); + warnIcon.getStyleClass().addAll("icon", "error-icon"); + } else { + trashIcon.getStyleClass().addAll("icon", "warn-icon"); + warnIcon.getStyleClass().addAll("icon", "warn-icon"); + } - Label warnIcon = FormBuilder.getIcon(AwesomeIcon.WARNING_SIGN); - warnIcon.getStyleClass().addAll("icon", "error-icon"); JFXButton warnIconButton = new JFXButton("", warnIcon); - warnIconButton.setStyle("-fx-cursor: hand;"); warnIconButton.getStyleClass().add("hidden-icon-button"); warnIconButton.setTooltip(new Tooltip(Res.get("portfolio.pending.failedTrade.warningIcon.tooltip"))); warnIconButton.setOnAction(e -> onShowInfoForInvalidTrade(trade)); - Label trashIcon = FormBuilder.getIcon(AwesomeIcon.TRASH); - trashIcon.getStyleClass().addAll("icon", "error-icon"); JFXButton trashIconButton = new JFXButton("", trashIcon); - trashIconButton.setStyle("-fx-cursor: hand;"); trashIconButton.getStyleClass().add("hidden-icon-button"); trashIconButton.setTooltip(new Tooltip(Res.get("portfolio.pending.failedTrade.moveTradeToFailedIcon.tooltip"))); trashIconButton.setOnAction(e -> onMoveInvalidTradeToFailedTrades(trade)); - // We only allow to move to failed trade if the txs are invalid. - // Otherwise the trade has to be completed. - boolean isTxChainValid = !trade.isTxChainInvalid(); - boolean paidOut = trade.getPayoutTxId() != null; - trashIconButton.setDisable(isTxChainValid || paidOut); - HBox hBox = new HBox(); hBox.setSpacing(0); hBox.getChildren().addAll(warnIconButton, trashIconButton); diff --git a/desktop/src/main/java/bisq/desktop/util/FormBuilder.java b/desktop/src/main/java/bisq/desktop/util/FormBuilder.java index 7a0221ac43e..46db98c0153 100644 --- a/desktop/src/main/java/bisq/desktop/util/FormBuilder.java +++ b/desktop/src/main/java/bisq/desktop/util/FormBuilder.java @@ -2084,6 +2084,10 @@ public static Text getBigIcon(GlyphIcons icon) { return getIcon(icon, "2em"); } + public static Text getMediumSizeIcon(GlyphIcons icon) { + return getIcon(icon, "1.5em"); + } + public static Text getIcon(GlyphIcons icon, String iconSize) { Text textIcon; From f0a30221ab5bbf7f56d30bcc65d060d868e8c2e4 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 19:11:54 -0500 Subject: [PATCH 112/143] Fix bug with showing popup once arbitration has been started --- .../pendingtrades/steps/TradeStepView.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java index 2670d3a9b3e..4149ebb338b 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java @@ -727,13 +727,15 @@ protected boolean isDisputed() { } private void checkIfLockTimeIsOver() { - Transaction delayedPayoutTx = trade.getDelayedPayoutTx(); - if (delayedPayoutTx != null) { - long lockTime = delayedPayoutTx.getLockTime(); - int bestChainHeight = model.dataModel.btcWalletService.getBestChainHeight(); - long remaining = lockTime - bestChainHeight; - if (remaining <= 0) { - openMediationResultPopup(Res.get("portfolio.pending.mediationResult.popup.headline", trade.getShortId())); + if (trade.getDisputeState() == Trade.DisputeState.MEDIATION_CLOSED) { + Transaction delayedPayoutTx = trade.getDelayedPayoutTx(); + if (delayedPayoutTx != null) { + long lockTime = delayedPayoutTx.getLockTime(); + int bestChainHeight = model.dataModel.btcWalletService.getBestChainHeight(); + long remaining = lockTime - bestChainHeight; + if (remaining <= 0) { + openMediationResultPopup(Res.get("portfolio.pending.mediationResult.popup.headline", trade.getShortId())); + } } } } From cabc5af2c630b5d58a9fffb6661cc297ddec768d Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 19:36:07 -0500 Subject: [PATCH 113/143] Make processModel in Trade final and pass in constructor instead of in init method --- .../bisq/core/trade/BuyerAsMakerTrade.java | 11 ++-- .../bisq/core/trade/BuyerAsTakerTrade.java | 11 ++-- .../main/java/bisq/core/trade/BuyerTrade.java | 13 +++-- .../bisq/core/trade/SellerAsMakerTrade.java | 11 ++-- .../bisq/core/trade/SellerAsTakerTrade.java | 11 ++-- .../java/bisq/core/trade/SellerTrade.java | 13 +++-- core/src/main/java/bisq/core/trade/Trade.java | 53 +++++++------------ .../java/bisq/core/trade/TradeManager.java | 21 ++++++-- 8 files changed, 86 insertions(+), 58 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java b/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java index da543c660d7..c4e0145ff2b 100644 --- a/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java +++ b/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java @@ -21,6 +21,7 @@ import bisq.core.offer.Offer; import bisq.core.proto.CoreProtoResolver; import bisq.core.trade.protocol.BuyerAsMakerProtocol; +import bisq.core.trade.protocol.ProcessModel; import bisq.network.p2p.NodeAddress; @@ -47,7 +48,8 @@ public BuyerAsMakerTrade(Offer offer, @Nullable NodeAddress mediatorNodeAddress, @Nullable NodeAddress refundAgentNodeAddress, Storage storage, - BtcWalletService btcWalletService) { + BtcWalletService btcWalletService, + ProcessModel processModel) { super(offer, txFee, takeOfferFee, @@ -56,7 +58,8 @@ public BuyerAsMakerTrade(Offer offer, mediatorNodeAddress, refundAgentNodeAddress, storage, - btcWalletService); + btcWalletService, + processModel); } /////////////////////////////////////////////////////////////////////////////////////////// @@ -76,6 +79,7 @@ public static Tradable fromProto(protobuf.BuyerAsMakerTrade buyerAsMakerTradePro BtcWalletService btcWalletService, CoreProtoResolver coreProtoResolver) { protobuf.Trade proto = buyerAsMakerTradeProto.getTrade(); + ProcessModel processModel = ProcessModel.fromProto(proto.getProcessModel(), coreProtoResolver); BuyerAsMakerTrade trade = new BuyerAsMakerTrade( Offer.fromProto(proto.getOffer()), Coin.valueOf(proto.getTxFeeAsLong()), @@ -85,7 +89,8 @@ public static Tradable fromProto(protobuf.BuyerAsMakerTrade buyerAsMakerTradePro proto.hasMediatorNodeAddress() ? NodeAddress.fromProto(proto.getMediatorNodeAddress()) : null, proto.hasRefundAgentNodeAddress() ? NodeAddress.fromProto(proto.getRefundAgentNodeAddress()) : null, storage, - btcWalletService); + btcWalletService, + processModel); trade.setTradeAmountAsLong(proto.getTradeAmountAsLong()); trade.setTradePrice(proto.getTradePrice()); diff --git a/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java b/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java index 98ed389cca8..32a258103c5 100644 --- a/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java +++ b/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java @@ -21,6 +21,7 @@ import bisq.core.offer.Offer; import bisq.core.proto.CoreProtoResolver; import bisq.core.trade.protocol.BuyerAsTakerProtocol; +import bisq.core.trade.protocol.ProcessModel; import bisq.network.p2p.NodeAddress; @@ -50,7 +51,8 @@ public BuyerAsTakerTrade(Offer offer, @Nullable NodeAddress mediatorNodeAddress, @Nullable NodeAddress refundAgentNodeAddress, Storage storage, - BtcWalletService btcWalletService) { + BtcWalletService btcWalletService, + ProcessModel processModel) { super(offer, tradeAmount, txFee, @@ -62,7 +64,8 @@ public BuyerAsTakerTrade(Offer offer, mediatorNodeAddress, refundAgentNodeAddress, storage, - btcWalletService); + btcWalletService, + processModel); } @@ -83,6 +86,7 @@ public static Tradable fromProto(protobuf.BuyerAsTakerTrade buyerAsTakerTradePro BtcWalletService btcWalletService, CoreProtoResolver coreProtoResolver) { protobuf.Trade proto = buyerAsTakerTradeProto.getTrade(); + ProcessModel processModel = ProcessModel.fromProto(proto.getProcessModel(), coreProtoResolver); return fromProto(new BuyerAsTakerTrade( Offer.fromProto(proto.getOffer()), Coin.valueOf(proto.getTradeAmountAsLong()), @@ -95,7 +99,8 @@ public static Tradable fromProto(protobuf.BuyerAsTakerTrade buyerAsTakerTradePro proto.hasMediatorNodeAddress() ? NodeAddress.fromProto(proto.getMediatorNodeAddress()) : null, proto.hasRefundAgentNodeAddress() ? NodeAddress.fromProto(proto.getRefundAgentNodeAddress()) : null, storage, - btcWalletService), + btcWalletService, + processModel), proto, coreProtoResolver); } diff --git a/core/src/main/java/bisq/core/trade/BuyerTrade.java b/core/src/main/java/bisq/core/trade/BuyerTrade.java index 28673e34d2f..7e4a8672299 100644 --- a/core/src/main/java/bisq/core/trade/BuyerTrade.java +++ b/core/src/main/java/bisq/core/trade/BuyerTrade.java @@ -19,6 +19,7 @@ import bisq.core.btc.wallet.BtcWalletService; import bisq.core.offer.Offer; +import bisq.core.trade.protocol.ProcessModel; import bisq.network.p2p.NodeAddress; @@ -45,7 +46,8 @@ public abstract class BuyerTrade extends Trade { @Nullable NodeAddress mediatorNodeAddress, @Nullable NodeAddress refundAgentNodeAddress, Storage storage, - BtcWalletService btcWalletService) { + BtcWalletService btcWalletService, + ProcessModel processModel) { super(offer, tradeAmount, txFee, @@ -57,7 +59,8 @@ public abstract class BuyerTrade extends Trade { mediatorNodeAddress, refundAgentNodeAddress, storage, - btcWalletService); + btcWalletService, + processModel); } BuyerTrade(Offer offer, @@ -68,7 +71,8 @@ public abstract class BuyerTrade extends Trade { @Nullable NodeAddress mediatorNodeAddress, @Nullable NodeAddress refundAgentNodeAddress, Storage storage, - BtcWalletService btcWalletService) { + BtcWalletService btcWalletService, + ProcessModel processModel) { super(offer, txFee, takerFee, @@ -77,7 +81,8 @@ public abstract class BuyerTrade extends Trade { mediatorNodeAddress, refundAgentNodeAddress, storage, - btcWalletService); + btcWalletService, + processModel); } @Override diff --git a/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java b/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java index 8617c657448..a02d9a851fc 100644 --- a/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java +++ b/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java @@ -20,6 +20,7 @@ import bisq.core.btc.wallet.BtcWalletService; import bisq.core.offer.Offer; import bisq.core.proto.CoreProtoResolver; +import bisq.core.trade.protocol.ProcessModel; import bisq.core.trade.protocol.SellerAsMakerProtocol; import bisq.network.p2p.NodeAddress; @@ -47,7 +48,8 @@ public SellerAsMakerTrade(Offer offer, @Nullable NodeAddress mediatorNodeAddress, @Nullable NodeAddress refundAgentNodeAddress, Storage storage, - BtcWalletService btcWalletService) { + BtcWalletService btcWalletService, + ProcessModel processModel) { super(offer, txFee, takerFee, @@ -56,7 +58,8 @@ public SellerAsMakerTrade(Offer offer, mediatorNodeAddress, refundAgentNodeAddress, storage, - btcWalletService); + btcWalletService, + processModel); } @@ -77,6 +80,7 @@ public static Tradable fromProto(protobuf.SellerAsMakerTrade sellerAsMakerTradeP BtcWalletService btcWalletService, CoreProtoResolver coreProtoResolver) { protobuf.Trade proto = sellerAsMakerTradeProto.getTrade(); + ProcessModel processModel = ProcessModel.fromProto(proto.getProcessModel(), coreProtoResolver); SellerAsMakerTrade trade = new SellerAsMakerTrade( Offer.fromProto(proto.getOffer()), Coin.valueOf(proto.getTxFeeAsLong()), @@ -86,7 +90,8 @@ public static Tradable fromProto(protobuf.SellerAsMakerTrade sellerAsMakerTradeP proto.hasMediatorNodeAddress() ? NodeAddress.fromProto(proto.getMediatorNodeAddress()) : null, proto.hasRefundAgentNodeAddress() ? NodeAddress.fromProto(proto.getRefundAgentNodeAddress()) : null, storage, - btcWalletService); + btcWalletService, + processModel); trade.setTradeAmountAsLong(proto.getTradeAmountAsLong()); trade.setTradePrice(proto.getTradePrice()); diff --git a/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java b/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java index 8455f50e7ea..7330f591f83 100644 --- a/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java +++ b/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java @@ -20,6 +20,7 @@ import bisq.core.btc.wallet.BtcWalletService; import bisq.core.offer.Offer; import bisq.core.proto.CoreProtoResolver; +import bisq.core.trade.protocol.ProcessModel; import bisq.core.trade.protocol.SellerAsTakerProtocol; import bisq.network.p2p.NodeAddress; @@ -50,7 +51,8 @@ public SellerAsTakerTrade(Offer offer, @Nullable NodeAddress mediatorNodeAddress, @Nullable NodeAddress refundAgentNodeAddress, Storage storage, - BtcWalletService btcWalletService) { + BtcWalletService btcWalletService, + ProcessModel processModel) { super(offer, tradeAmount, txFee, @@ -62,7 +64,8 @@ public SellerAsTakerTrade(Offer offer, mediatorNodeAddress, refundAgentNodeAddress, storage, - btcWalletService); + btcWalletService, + processModel); } @@ -83,6 +86,7 @@ public static Tradable fromProto(protobuf.SellerAsTakerTrade sellerAsTakerTradeP BtcWalletService btcWalletService, CoreProtoResolver coreProtoResolver) { protobuf.Trade proto = sellerAsTakerTradeProto.getTrade(); + ProcessModel processModel = ProcessModel.fromProto(proto.getProcessModel(), coreProtoResolver); return fromProto(new SellerAsTakerTrade( Offer.fromProto(proto.getOffer()), Coin.valueOf(proto.getTradeAmountAsLong()), @@ -95,7 +99,8 @@ public static Tradable fromProto(protobuf.SellerAsTakerTrade sellerAsTakerTradeP proto.hasMediatorNodeAddress() ? NodeAddress.fromProto(proto.getMediatorNodeAddress()) : null, proto.hasRefundAgentNodeAddress() ? NodeAddress.fromProto(proto.getRefundAgentNodeAddress()) : null, storage, - btcWalletService), + btcWalletService, + processModel), proto, coreProtoResolver); } diff --git a/core/src/main/java/bisq/core/trade/SellerTrade.java b/core/src/main/java/bisq/core/trade/SellerTrade.java index 2ac507ecaf5..6701c8b5a0b 100644 --- a/core/src/main/java/bisq/core/trade/SellerTrade.java +++ b/core/src/main/java/bisq/core/trade/SellerTrade.java @@ -19,6 +19,7 @@ import bisq.core.btc.wallet.BtcWalletService; import bisq.core.offer.Offer; +import bisq.core.trade.protocol.ProcessModel; import bisq.network.p2p.NodeAddress; @@ -45,7 +46,8 @@ public abstract class SellerTrade extends Trade { @Nullable NodeAddress mediatorNodeAddress, @Nullable NodeAddress refundAgentNodeAddress, Storage storage, - BtcWalletService btcWalletService) { + BtcWalletService btcWalletService, + ProcessModel processModel) { super(offer, tradeAmount, txFee, @@ -57,7 +59,8 @@ public abstract class SellerTrade extends Trade { mediatorNodeAddress, refundAgentNodeAddress, storage, - btcWalletService); + btcWalletService, + processModel); } SellerTrade(Offer offer, @@ -68,7 +71,8 @@ public abstract class SellerTrade extends Trade { @Nullable NodeAddress mediatorNodeAddress, @Nullable NodeAddress refundAgentNodeAddress, Storage storage, - BtcWalletService btcWalletService) { + BtcWalletService btcWalletService, + ProcessModel processModel) { super(offer, txFee, takeOfferFee, @@ -77,7 +81,8 @@ public abstract class SellerTrade extends Trade { mediatorNodeAddress, refundAgentNodeAddress, storage, - btcWalletService); + btcWalletService, + processModel); } @Override diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index 85faf787ad6..95df46e497d 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -274,7 +274,8 @@ public static protobuf.Trade.TradePeriodState toProtoMessage(Trade.TradePeriodSt // Persistable // Immutable - @Nullable + @Getter + private final ProcessModel processModel; @Getter private final Offer offer; @Getter @@ -285,10 +286,7 @@ public static protobuf.Trade.TradePeriodState toProtoMessage(Trade.TradePeriodSt private final long takerFeeAsLong; @Setter private long takeOfferDate; - @Setter - @Getter - @Nullable - private ProcessModel processModel; + // Mutable @Nullable @Getter @@ -473,16 +471,18 @@ protected Trade(Offer offer, @Nullable NodeAddress mediatorNodeAddress, @Nullable NodeAddress refundAgentNodeAddress, Storage storage, - BtcWalletService btcWalletService) { + BtcWalletService btcWalletService, + ProcessModel processModel) { this.offer = offer; this.txFee = txFee; this.takerFee = takerFee; this.isCurrencyForTakerFeeBtc = isCurrencyForTakerFeeBtc; - this.storage = storage; - this.btcWalletService = btcWalletService; this.arbitratorNodeAddress = arbitratorNodeAddress; this.mediatorNodeAddress = mediatorNodeAddress; this.refundAgentNodeAddress = refundAgentNodeAddress; + this.storage = storage; + this.btcWalletService = btcWalletService; + this.processModel = processModel; txFeeAsLong = txFee.value; takerFeeAsLong = takerFee.value; @@ -505,7 +505,8 @@ protected Trade(Offer offer, @Nullable NodeAddress mediatorNodeAddress, @Nullable NodeAddress refundAgentNodeAddress, Storage storage, - BtcWalletService btcWalletService) { + BtcWalletService btcWalletService, + ProcessModel processModel) { this(offer, txFee, @@ -515,7 +516,8 @@ protected Trade(Offer offer, mediatorNodeAddress, refundAgentNodeAddress, storage, - btcWalletService); + btcWalletService, + processModel); this.tradePrice = tradePrice; this.tradingPeerNodeAddress = tradingPeerNodeAddress; @@ -530,7 +532,7 @@ protected Trade(Offer offer, @Override public Message toProtoMessage() { protobuf.Trade.Builder builder = protobuf.Trade.newBuilder() - .setOffer(checkNotNull(offer).toProtoMessage()) + .setOffer(offer.toProtoMessage()) .setIsCurrencyForTakerFeeBtc(isCurrencyForTakerFeeBtc) .setTxFeeAsLong(txFeeAsLong) .setTakerFeeAsLong(takerFeeAsLong) @@ -577,7 +579,6 @@ public Message toProtoMessage() { public static Trade fromProto(Trade trade, protobuf.Trade proto, CoreProtoResolver coreProtoResolver) { trade.setTakeOfferDate(proto.getTakeOfferDate()); - trade.setProcessModel(ProcessModel.fromProto(proto.getProcessModel(), coreProtoResolver)); trade.setState(State.fromProto(proto.getState())); trade.setDisputeState(DisputeState.fromProto(proto.getDisputeState())); trade.setTradePeriodState(TradePeriodState.fromProto(proto.getTradePeriodState())); @@ -630,28 +631,23 @@ public void setTransientFields(Storage storage, BtcWalle this.btcWalletService = btcWalletService; } - public void setupProcessModel(ProcessModelServiceProvider processModelServiceProvider, - TradeManager tradeManager) { - processModel = getOrCreateProcessModel(processModelServiceProvider); - processModel.applyTransient(processModelServiceProvider, - tradeManager, - checkNotNull(offer)); + public void setupProcessModel(ProcessModelServiceProvider serviceProvider, TradeManager tradeManager) { + processModel.applyTransient(serviceProvider, tradeManager, offer); } - public void init(ProcessModelServiceProvider processModelServiceProvider) { - - processModelServiceProvider.getArbitratorManager().getDisputeAgentByNodeAddress(arbitratorNodeAddress).ifPresent(arbitrator -> { + public void init(ProcessModelServiceProvider serviceProvider) { + serviceProvider.getArbitratorManager().getDisputeAgentByNodeAddress(arbitratorNodeAddress).ifPresent(arbitrator -> { arbitratorBtcPubKey = arbitrator.getBtcPubKey(); arbitratorPubKeyRing = arbitrator.getPubKeyRing(); persist(); }); - processModelServiceProvider.getMediatorManager().getDisputeAgentByNodeAddress(mediatorNodeAddress).ifPresent(mediator -> { + serviceProvider.getMediatorManager().getDisputeAgentByNodeAddress(mediatorNodeAddress).ifPresent(mediator -> { mediatorPubKeyRing = mediator.getPubKeyRing(); persist(); }); - processModelServiceProvider.getRefundAgentManager().getDisputeAgentByNodeAddress(refundAgentNodeAddress).ifPresent(refundAgent -> { + serviceProvider.getRefundAgentManager().getDisputeAgentByNodeAddress(refundAgentNodeAddress).ifPresent(refundAgent -> { refundAgentPubKeyRing = refundAgent.getPubKeyRing(); persist(); }); @@ -668,15 +664,6 @@ public void init(ProcessModelServiceProvider processModelServiceProvider) { isInitialized = true; } - public ProcessModel getOrCreateProcessModel(ProcessModelServiceProvider processModelServiceProvider) { - if (processModel == null) { - processModel = new ProcessModel(checkNotNull(offer).getId(), - processModelServiceProvider.getUser().getAccountId(), - processModelServiceProvider.getKeyRing().getPubKeyRing()); - } - return processModel; - } - /////////////////////////////////////////////////////////////////////////////////////////// // API @@ -1132,7 +1119,7 @@ public String getErrorMessage() { } public boolean isTxChainInvalid() { - return checkNotNull(offer).getOfferFeePaymentTxId() == null || + return offer.getOfferFeePaymentTxId() == null || getTakerFeeTxId() == null || getDepositTxId() == null || getDelayedPayoutTxBytes() == null; diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 0140a89f375..7e8c42f23ff 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -36,6 +36,7 @@ import bisq.core.trade.messages.TakeOfferRequest; import bisq.core.trade.messages.TradeMessage; import bisq.core.trade.protocol.MakerProtocol; +import bisq.core.trade.protocol.ProcessModel; import bisq.core.trade.protocol.ProcessModelServiceProvider; import bisq.core.trade.protocol.TakerProtocol; import bisq.core.trade.statistics.TradeStatisticsManager; @@ -243,7 +244,8 @@ public void onDirectMessage(DecryptedMessageWithPubKey message, NodeAddress peer openOffer.getMediatorNodeAddress(), openOffer.getRefundAgentNodeAddress(), tradableListStorage, - btcWalletService) : + btcWalletService, + getNewProcessModel(offer)) : new SellerAsMakerTrade(offer, Coin.valueOf(takeOfferRequest.getTxFee()), Coin.valueOf(takeOfferRequest.getTakerFee()), @@ -252,7 +254,8 @@ public void onDirectMessage(DecryptedMessageWithPubKey message, NodeAddress peer openOffer.getMediatorNodeAddress(), openOffer.getRefundAgentNodeAddress(), tradableListStorage, - btcWalletService); + btcWalletService, + getNewProcessModel(offer)); initNewMakerTrade(trade); tradableList.add(trade); @@ -341,7 +344,7 @@ private void initNewMakerTrade(Trade trade) { private void initNewTakerTrade(Trade trade, boolean useSavingsWallet, Coin fundsNeededForTrade) { initTrade(trade); - checkNotNull(trade.getProcessModel()).setUseSavingsWallet(useSavingsWallet); + trade.getProcessModel().setUseSavingsWallet(useSavingsWallet); trade.getProcessModel().setFundsNeededForTradeAsLong(fundsNeededForTrade.value); } @@ -428,7 +431,8 @@ private Trade getNewTrade(Coin amount, model.getSelectedMediator(), model.getSelectedRefundAgent(), tradableListStorage, - btcWalletService) : + btcWalletService, + getNewProcessModel(offer)) : new BuyerAsTakerTrade(offer, amount, txFee, @@ -440,12 +444,19 @@ private Trade getNewTrade(Coin amount, model.getSelectedMediator(), model.getSelectedRefundAgent(), tradableListStorage, - btcWalletService); + btcWalletService, + getNewProcessModel(offer)); trade.setTakerPaymentAccountId(paymentAccountId); initNewTakerTrade(trade, useSavingsWallet, fundsNeededForTrade); return trade; } + private ProcessModel getNewProcessModel(Offer offer) { + return new ProcessModel(checkNotNull(offer).getId(), + processModelServiceProvider.getUser().getAccountId(), + processModelServiceProvider.getKeyRing().getPubKeyRing()); + } + private OfferAvailabilityModel getOfferAvailabilityModel(Offer offer) { return new OfferAvailabilityModel( offer, From 84a498273266ed7a0c0949ef79061b7401a73ff3 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 21:34:28 -0500 Subject: [PATCH 114/143] Remove TradeProtocol from Trade We keep the TradeProtocol now in TradeManager in a hashmap. As TradeProtocol constructors get called now earlier we need to add an onInitialized method which signals that the TradeProtocol is ready. The processModel needs to get set the transient fields after construction. --- .../dispute/mediation/MediationManager.java | 2 +- .../bisq/core/trade/BuyerAsMakerTrade.java | 11 - .../bisq/core/trade/BuyerAsTakerTrade.java | 11 - .../bisq/core/trade/SellerAsMakerTrade.java | 11 - .../bisq/core/trade/SellerAsTakerTrade.java | 11 - core/src/main/java/bisq/core/trade/Trade.java | 35 +-- .../java/bisq/core/trade/TradeManager.java | 259 +++++++++--------- .../trade/protocol/BuyerAsTakerProtocol.java | 4 + .../core/trade/protocol/BuyerProtocol.java | 4 + .../trade/protocol/SellerAsTakerProtocol.java | 4 + .../core/trade/protocol/TradeProtocol.java | 27 +- .../trade/protocol/TradeProtocolFactory.java | 40 +++ .../trade/txproof/xmr/XmrTxProofService.java | 2 +- .../java/bisq/desktop/main/MainViewModel.java | 3 +- .../pendingtrades/PendingTradesDataModel.java | 12 +- .../pendingtrades/steps/TradeStepView.java | 8 +- 16 files changed, 225 insertions(+), 219 deletions(-) create mode 100644 core/src/main/java/bisq/core/trade/protocol/TradeProtocolFactory.java diff --git a/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java b/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java index 9868c546370..09b40f513b7 100644 --- a/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java +++ b/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java @@ -234,7 +234,7 @@ public void onAcceptMediationResult(Trade trade, ProcessModel processModel = trade.getProcessModel(); processModel.setBuyerPayoutAmountFromMediation(buyerPayoutAmount.value); processModel.setSellerPayoutAmountFromMediation(sellerPayoutAmount.value); - DisputeProtocol tradeProtocol = (DisputeProtocol) trade.getTradeProtocol(); + DisputeProtocol tradeProtocol = (DisputeProtocol) tradeManager.getTradeProtocol(trade); trade.setMediationResultState(MediationResultState.MEDIATION_RESULT_ACCEPTED); diff --git a/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java b/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java index c4e0145ff2b..cf7b6d09094 100644 --- a/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java +++ b/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java @@ -20,7 +20,6 @@ import bisq.core.btc.wallet.BtcWalletService; import bisq.core.offer.Offer; import bisq.core.proto.CoreProtoResolver; -import bisq.core.trade.protocol.BuyerAsMakerProtocol; import bisq.core.trade.protocol.ProcessModel; import bisq.network.p2p.NodeAddress; @@ -100,14 +99,4 @@ public static Tradable fromProto(protobuf.BuyerAsMakerTrade buyerAsMakerTradePro proto, coreProtoResolver); } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // API - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - protected void createTradeProtocol() { - tradeProtocol = new BuyerAsMakerProtocol(this); - } } diff --git a/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java b/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java index 32a258103c5..3e0283c20ee 100644 --- a/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java +++ b/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java @@ -20,7 +20,6 @@ import bisq.core.btc.wallet.BtcWalletService; import bisq.core.offer.Offer; import bisq.core.proto.CoreProtoResolver; -import bisq.core.trade.protocol.BuyerAsTakerProtocol; import bisq.core.trade.protocol.ProcessModel; import bisq.network.p2p.NodeAddress; @@ -104,14 +103,4 @@ public static Tradable fromProto(protobuf.BuyerAsTakerTrade buyerAsTakerTradePro proto, coreProtoResolver); } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // API - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - protected void createTradeProtocol() { - tradeProtocol = new BuyerAsTakerProtocol(this); - } } diff --git a/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java b/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java index a02d9a851fc..903e934dbb2 100644 --- a/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java +++ b/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java @@ -21,7 +21,6 @@ import bisq.core.offer.Offer; import bisq.core.proto.CoreProtoResolver; import bisq.core.trade.protocol.ProcessModel; -import bisq.core.trade.protocol.SellerAsMakerProtocol; import bisq.network.p2p.NodeAddress; @@ -101,14 +100,4 @@ public static Tradable fromProto(protobuf.SellerAsMakerTrade sellerAsMakerTradeP proto, coreProtoResolver); } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // API - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - protected void createTradeProtocol() { - tradeProtocol = new SellerAsMakerProtocol(this); - } } diff --git a/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java b/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java index 7330f591f83..870f04c3e11 100644 --- a/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java +++ b/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java @@ -21,7 +21,6 @@ import bisq.core.offer.Offer; import bisq.core.proto.CoreProtoResolver; import bisq.core.trade.protocol.ProcessModel; -import bisq.core.trade.protocol.SellerAsTakerProtocol; import bisq.network.p2p.NodeAddress; @@ -104,14 +103,4 @@ public static Tradable fromProto(protobuf.SellerAsTakerTrade sellerAsTakerTradeP proto, coreProtoResolver); } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // API - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - protected void createTradeProtocol() { - tradeProtocol = new SellerAsTakerProtocol(this); - } } diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index 95df46e497d..f3c36215c1e 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -31,7 +31,6 @@ import bisq.core.support.messages.ChatMessage; import bisq.core.trade.protocol.ProcessModel; import bisq.core.trade.protocol.ProcessModelServiceProvider; -import bisq.core.trade.protocol.TradeProtocol; import bisq.core.trade.txproof.AssetTxProofResult; import bisq.network.p2p.DecryptedMessageWithPubKey; @@ -384,8 +383,6 @@ public static protobuf.Trade.TradePeriodState toProtoMessage(Trade.TradePeriodSt transient final private StringProperty errorMessageProperty = new SimpleStringProperty(); // Mutable - @Getter - transient protected TradeProtocol tradeProtocol; @Nullable transient private Transaction depositTx; @Getter @@ -402,6 +399,7 @@ public static protobuf.Trade.TradePeriodState toProtoMessage(Trade.TradePeriodSt transient private ObjectProperty tradeAmountProperty; transient private ObjectProperty tradeVolumeProperty; + @Getter final transient private Set decryptedMessageWithPubKeySet = new HashSet<>(); // Added in v1.1.6 @@ -631,10 +629,6 @@ public void setTransientFields(Storage storage, BtcWalle this.btcWalletService = btcWalletService; } - public void setupProcessModel(ProcessModelServiceProvider serviceProvider, TradeManager tradeManager) { - processModel.applyTransient(serviceProvider, tradeManager, offer); - } - public void init(ProcessModelServiceProvider serviceProvider) { serviceProvider.getArbitratorManager().getDisputeAgentByNodeAddress(arbitratorNodeAddress).ifPresent(arbitrator -> { arbitratorBtcPubKey = arbitrator.getBtcPubKey(); @@ -652,15 +646,6 @@ public void init(ProcessModelServiceProvider serviceProvider) { persist(); }); - createTradeProtocol(); - - // If we have already received a msg we apply it. - // removeDecryptedMsgWithPubKey will be called synchronous after apply. We don't have threaded context - // or async calls there. - // Clone to avoid ConcurrentModificationException. We remove items at the applyMailboxMessage call... - HashSet set = new HashSet<>(decryptedMessageWithPubKeySet); - set.forEach(msg -> tradeProtocol.applyMailboxMessage(msg)); - isInitialized = true; } @@ -727,21 +712,6 @@ public Transaction getDelayedPayoutTx(BtcWalletService btcWalletService) { return delayedPayoutTx; } - // We don't need to persist the msg as if we don't apply it it will not be removed from the P2P network and we - // will receive it again on next startup. This might happen in edge cases when the user shuts down after we - // received the msg but before the init is called. - void addDecryptedMessageWithPubKey(DecryptedMessageWithPubKey decryptedMessageWithPubKey) { - if (!decryptedMessageWithPubKeySet.contains(decryptedMessageWithPubKey)) { - decryptedMessageWithPubKeySet.add(decryptedMessageWithPubKey); - - // If we have already initialized we apply. - // removeDecryptedMsgWithPubKey will be called synchronous after apply. We don't have threaded context - // or async calls there. - if (tradeProtocol != null) - tradeProtocol.applyMailboxMessage(decryptedMessageWithPubKey); - } - } - public void removeDecryptedMessageWithPubKey(DecryptedMessageWithPubKey decryptedMessageWithPubKey) { decryptedMessageWithPubKeySet.remove(decryptedMessageWithPubKey); } @@ -795,8 +765,6 @@ public void onComplete() { // Abstract /////////////////////////////////////////////////////////////////////////////////////////// - protected abstract void createTradeProtocol(); - public abstract Coin getPayoutAmount(); @@ -1234,7 +1202,6 @@ public String toString() { ",\n disputeStateProperty=" + disputeStateProperty + ",\n tradePeriodStateProperty=" + tradePeriodStateProperty + ",\n errorMessageProperty=" + errorMessageProperty + - ",\n tradeProtocol=" + tradeProtocol + ",\n depositTx=" + depositTx + ",\n delayedPayoutTx=" + delayedPayoutTx + ",\n payoutTx=" + payoutTx + diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 7e8c42f23ff..900e4db64cc 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -39,6 +39,8 @@ import bisq.core.trade.protocol.ProcessModel; import bisq.core.trade.protocol.ProcessModelServiceProvider; import bisq.core.trade.protocol.TakerProtocol; +import bisq.core.trade.protocol.TradeProtocol; +import bisq.core.trade.protocol.TradeProtocolFactory; import bisq.core.trade.statistics.TradeStatisticsManager; import bisq.core.user.User; import bisq.core.util.Validator; @@ -84,6 +86,8 @@ import org.bouncycastle.crypto.params.KeyParameter; import java.util.Date; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; @@ -124,9 +128,10 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi private final ClockWatcher clockWatcher; private final Storage> tradableListStorage; + private final Map tradeProtocolByTradeId = new HashMap<>(); private TradableList tradableList; @Getter - private final BooleanProperty pendingTradesInitialized = new SimpleBooleanProperty(); + private final BooleanProperty persistedTradesInitialized = new SimpleBooleanProperty(); @Setter @Nullable private ErrorMessageHandler takeOfferRequestErrorMessageHandler; @@ -210,60 +215,68 @@ public void readPersisted() { @Override public void onDirectMessage(DecryptedMessageWithPubKey message, NodeAddress peer) { NetworkEnvelope networkEnvelope = message.getNetworkEnvelope(); - // The maker received a TakeOfferRequest if (networkEnvelope instanceof TakeOfferRequest) { - TakeOfferRequest takeOfferRequest = (TakeOfferRequest) networkEnvelope; - log.info("Received TakeOfferRequest from {} with tradeId {} and uid {}", - peer, takeOfferRequest.getTradeId(), takeOfferRequest.getUid()); - - try { - Validator.nonEmptyStringOf(takeOfferRequest.getTradeId()); - } catch (Throwable t) { - log.warn("Invalid TakeOfferRequest " + takeOfferRequest.toString()); - return; - } + handleTakeOfferRequest(peer, (TakeOfferRequest) networkEnvelope); + } + } - Optional openOfferOptional = openOfferManager.getOpenOfferById(takeOfferRequest.getTradeId()); - if (!openOfferOptional.isPresent()) { - return; - } + // The maker received a TakeOfferRequest + private void handleTakeOfferRequest(NodeAddress peer, TakeOfferRequest takeOfferRequest) { + log.info("Received TakeOfferRequest from {} with tradeId {} and uid {}", + peer, takeOfferRequest.getTradeId(), takeOfferRequest.getUid()); - OpenOffer openOffer = openOfferOptional.get(); - if (openOffer.getState() != OpenOffer.State.AVAILABLE) { - return; - } + try { + Validator.nonEmptyStringOf(takeOfferRequest.getTradeId()); + } catch (Throwable t) { + log.warn("Invalid TakeOfferRequest " + takeOfferRequest.toString()); + return; + } - Offer offer = openOffer.getOffer(); - openOfferManager.reserveOpenOffer(openOffer); - Trade trade = offer.isBuyOffer() ? - new BuyerAsMakerTrade(offer, - Coin.valueOf(takeOfferRequest.getTxFee()), - Coin.valueOf(takeOfferRequest.getTakerFee()), - takeOfferRequest.isCurrencyForTakerFeeBtc(), - openOffer.getArbitratorNodeAddress(), - openOffer.getMediatorNodeAddress(), - openOffer.getRefundAgentNodeAddress(), - tradableListStorage, - btcWalletService, - getNewProcessModel(offer)) : - new SellerAsMakerTrade(offer, - Coin.valueOf(takeOfferRequest.getTxFee()), - Coin.valueOf(takeOfferRequest.getTakerFee()), - takeOfferRequest.isCurrencyForTakerFeeBtc(), - openOffer.getArbitratorNodeAddress(), - openOffer.getMediatorNodeAddress(), - openOffer.getRefundAgentNodeAddress(), - tradableListStorage, - btcWalletService, - getNewProcessModel(offer)); - - initNewMakerTrade(trade); - tradableList.add(trade); - ((MakerProtocol) trade.getTradeProtocol()).handleTakeOfferRequest(takeOfferRequest, peer, errorMessage -> { - if (takeOfferRequestErrorMessageHandler != null) - takeOfferRequestErrorMessageHandler.handleErrorMessage(errorMessage); - }); + Optional openOfferOptional = openOfferManager.getOpenOfferById(takeOfferRequest.getTradeId()); + if (!openOfferOptional.isPresent()) { + return; + } + + OpenOffer openOffer = openOfferOptional.get(); + if (openOffer.getState() != OpenOffer.State.AVAILABLE) { + return; + } + + Offer offer = openOffer.getOffer(); + openOfferManager.reserveOpenOffer(openOffer); + Trade trade; + if (offer.isBuyOffer()) { + trade = new BuyerAsMakerTrade(offer, + Coin.valueOf(takeOfferRequest.getTxFee()), + Coin.valueOf(takeOfferRequest.getTakerFee()), + takeOfferRequest.isCurrencyForTakerFeeBtc(), + openOffer.getArbitratorNodeAddress(), + openOffer.getMediatorNodeAddress(), + openOffer.getRefundAgentNodeAddress(), + tradableListStorage, + btcWalletService, + getNewProcessModel(offer)); + } else { + trade = new SellerAsMakerTrade(offer, + Coin.valueOf(takeOfferRequest.getTxFee()), + Coin.valueOf(takeOfferRequest.getTakerFee()), + takeOfferRequest.isCurrencyForTakerFeeBtc(), + openOffer.getArbitratorNodeAddress(), + openOffer.getMediatorNodeAddress(), + openOffer.getRefundAgentNodeAddress(), + tradableListStorage, + btcWalletService, + getNewProcessModel(offer)); } + TradeProtocol tradeProtocol = TradeProtocolFactory.getNewTradeProtocol(trade); + tradeProtocolByTradeId.put(trade.getId(), tradeProtocol); + tradableList.add(trade); + initTradeAndProtocol(trade, tradeProtocol); + + ((MakerProtocol) tradeProtocol).handleTakeOfferRequest(takeOfferRequest, peer, errorMessage -> { + if (takeOfferRequestErrorMessageHandler != null) + takeOfferRequestErrorMessageHandler.handleErrorMessage(errorMessage); + }); } @@ -277,9 +290,23 @@ public void onMailboxMessageAdded(DecryptedMessageWithPubKey message, NodeAddres NetworkEnvelope networkEnvelope = message.getNetworkEnvelope(); if (networkEnvelope instanceof TradeMessage) { TradeMessage tradeMessage = (TradeMessage) networkEnvelope; - // The mailbox message will be removed inside the tasks after they are processed successfully getTradeById(tradeMessage.getTradeId()) - .ifPresent(trade -> trade.addDecryptedMessageWithPubKey(message)); + .ifPresent(trade -> { + // We don't need to persist the msg as if we don't processes the message it will not be + // removed from the P2P network and we will receive it again on next startup. + // This might happen in edge cases when the user shuts down after we received the msg but + // before it is processed. + //TODO + Set decryptedMessageWithPubKeySet = trade.getDecryptedMessageWithPubKeySet(); + if (!decryptedMessageWithPubKeySet.contains(message)) { + decryptedMessageWithPubKeySet.add(message); + + // The message will be removed after processed + TradeProtocol tradeProtocol = getTradeProtocol(trade); + tradeProtocol.applyMailboxMessage(message); + } + + }); } else if (networkEnvelope instanceof AckMessage) { AckMessage ackMessage = (AckMessage) networkEnvelope; if (ackMessage.getSourceType() == AckMessageSourceType.TRADE_MESSAGE) { @@ -322,6 +349,16 @@ public void persistTrades() { tradableList.persist(); } + public TradeProtocol getTradeProtocol(Trade trade) { + if (tradeProtocolByTradeId.containsKey(trade.getId())) { + return tradeProtocolByTradeId.get(trade.getId()); + } else { + TradeProtocol tradeProtocol = TradeProtocolFactory.getNewTradeProtocol(trade); + tradeProtocolByTradeId.put(trade.getId(), tradeProtocol); + return tradeProtocol; + } + } + /////////////////////////////////////////////////////////////////////////////////////////// // Init pending trade @@ -329,27 +366,16 @@ public void persistTrades() { private void initPersistedTrades() { tradableList.forEach(this::initPersistedTrade); - pendingTradesInitialized.set(true); + persistedTradesInitialized.set(true); } private void initPersistedTrade(Trade trade) { - initTrade(trade); + initTradeAndProtocol(trade, getTradeProtocol(trade)); trade.updateDepositTxFromWallet(); } - private void initNewMakerTrade(Trade trade) { - initTrade(trade); - } - - private void initNewTakerTrade(Trade trade, boolean useSavingsWallet, Coin fundsNeededForTrade) { - initTrade(trade); - - trade.getProcessModel().setUseSavingsWallet(useSavingsWallet); - trade.getProcessModel().setFundsNeededForTradeAsLong(fundsNeededForTrade.value); - } - - private void initTrade(Trade trade) { - trade.setupProcessModel(processModelServiceProvider, this); + private void initTradeAndProtocol(Trade trade, TradeProtocol tradeProtocol) { + tradeProtocol.initialize(processModelServiceProvider, this, trade.getOffer()); trade.init(processModelServiceProvider); } @@ -391,66 +417,53 @@ public void onTakeOffer(Coin amount, offer.checkOfferAvailability(model, () -> { if (offer.getState() == Offer.State.AVAILABLE) { - Trade trade = getNewTrade(amount, - txFee, - takerFee, - isCurrencyForTakerFeeBtc, - tradePrice, - fundsNeededForTrade, - offer, - paymentAccountId, - useSavingsWallet, - model); + Trade trade; + if (offer.isBuyOffer()) { + trade = new SellerAsTakerTrade(offer, + amount, + txFee, + takerFee, + isCurrencyForTakerFeeBtc, + tradePrice, + model.getPeerNodeAddress(), + model.getSelectedArbitrator(), + model.getSelectedMediator(), + model.getSelectedRefundAgent(), + tradableListStorage, + btcWalletService, + getNewProcessModel(offer)); + } else { + trade = new BuyerAsTakerTrade(offer, + amount, + txFee, + takerFee, + isCurrencyForTakerFeeBtc, + tradePrice, + model.getPeerNodeAddress(), + model.getSelectedArbitrator(), + model.getSelectedMediator(), + model.getSelectedRefundAgent(), + tradableListStorage, + btcWalletService, + getNewProcessModel(offer)); + } + trade.getProcessModel().setUseSavingsWallet(useSavingsWallet); + trade.getProcessModel().setFundsNeededForTradeAsLong(fundsNeededForTrade.value); + trade.setTakerPaymentAccountId(paymentAccountId); + + TradeProtocol tradeProtocol = TradeProtocolFactory.getNewTradeProtocol(trade); + tradeProtocolByTradeId.put(trade.getId(), tradeProtocol); tradableList.add(trade); - ((TakerProtocol) trade.getTradeProtocol()).onTakeOffer(); + + initTradeAndProtocol(trade, tradeProtocol); + + ((TakerProtocol) tradeProtocol).onTakeOffer(); tradeResultHandler.handleResult(trade); } }, errorMessageHandler); } - private Trade getNewTrade(Coin amount, - Coin txFee, - Coin takerFee, - boolean isCurrencyForTakerFeeBtc, - long tradePrice, - Coin fundsNeededForTrade, - Offer offer, - String paymentAccountId, - boolean useSavingsWallet, - OfferAvailabilityModel model) { - Trade trade = offer.isBuyOffer() ? - new SellerAsTakerTrade(offer, - amount, - txFee, - takerFee, - isCurrencyForTakerFeeBtc, - tradePrice, - model.getPeerNodeAddress(), - model.getSelectedArbitrator(), - model.getSelectedMediator(), - model.getSelectedRefundAgent(), - tradableListStorage, - btcWalletService, - getNewProcessModel(offer)) : - new BuyerAsTakerTrade(offer, - amount, - txFee, - takerFee, - isCurrencyForTakerFeeBtc, - tradePrice, - model.getPeerNodeAddress(), - model.getSelectedArbitrator(), - model.getSelectedMediator(), - model.getSelectedRefundAgent(), - tradableListStorage, - btcWalletService, - getNewProcessModel(offer)); - trade.setTakerPaymentAccountId(paymentAccountId); - initNewTakerTrade(trade, useSavingsWallet, fundsNeededForTrade); - return trade; - } - private ProcessModel getNewProcessModel(Offer offer) { return new ProcessModel(checkNotNull(offer).getId(), processModelServiceProvider.getUser().getAccountId(), @@ -483,7 +496,7 @@ public void onSuccess(@javax.annotation.Nullable Transaction transaction) { log.debug("onWithdraw onSuccess tx ID:" + transaction.getTxId().toString()); onTradeCompleted(trade); trade.setState(Trade.State.WITHDRAW_COMPLETED); - trade.getTradeProtocol().onWithdrawCompleted(); + getTradeProtocol(trade).onWithdrawCompleted(); resultHandler.handleResult(); } } @@ -664,8 +677,8 @@ public ObservableList getTradesAsObservableList() { return tradableList.getList(); } - public BooleanProperty pendingTradesInitializedProperty() { - return pendingTradesInitialized; + public BooleanProperty persistedTradesInitializedProperty() { + return persistedTradesInitialized; } public boolean isMyOffer(Offer offer) { diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 5e22e8c166e..5424ff2c6f7 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -62,7 +62,11 @@ public class BuyerAsTakerProtocol extends BuyerProtocol implements TakerProtocol public BuyerAsTakerProtocol(BuyerAsTakerTrade trade) { super(trade); + } + @Override + protected void onInitialized() { + super.onInitialized(); Offer offer = checkNotNull(trade.getOffer()); processModel.getTradingPeer().setPubKeyRing(offer.getPubKeyRing()); } 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 67ffe0d5dcb..e69e4a6872a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java @@ -54,7 +54,11 @@ enum BuyerEvent implements FluentProtocol.Event { public BuyerProtocol(BuyerTrade trade) { super(trade); + } + @Override + protected void onInitialized() { + super.onInitialized(); // We get called the constructor with any possible state and phase. As we don't want to log an error for such // cases we use the alternative 'given' method instead of 'expect'. given(phase(Trade.Phase.TAKER_FEE_PUBLISHED) diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 1407caec0b8..592ec32189a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -57,7 +57,11 @@ public class SellerAsTakerProtocol extends SellerProtocol implements TakerProtoc public SellerAsTakerProtocol(SellerAsTakerTrade trade) { super(trade); + } + @Override + protected void onInitialized() { + super.onInitialized(); Offer offer = checkNotNull(trade.getOffer()); processModel.getTradingPeer().setPubKeyRing(offer.getPubKeyRing()); } diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index 3ec9daf07a0..3f53833b3bd 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -17,7 +17,9 @@ package bisq.core.trade.protocol; +import bisq.core.offer.Offer; import bisq.core.trade.Trade; +import bisq.core.trade.TradeManager; import bisq.core.trade.messages.CounterCurrencyTransferStartedMessage; import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage; import bisq.core.trade.messages.TradeMessage; @@ -36,6 +38,8 @@ import bisq.common.proto.network.NetworkEnvelope; import bisq.common.taskrunner.Task; +import java.util.HashSet; + import lombok.extern.slf4j.Slf4j; import javax.annotation.Nullable; @@ -46,6 +50,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener { protected final ProcessModel processModel; protected final Trade trade; private Timer timeoutTimer; + private boolean initialized; /////////////////////////////////////////////////////////////////////////////////////////// @@ -55,10 +60,6 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener { public TradeProtocol(Trade trade) { this.trade = trade; this.processModel = trade.getProcessModel(); - - if (!trade.isWithdrawn()) { - processModel.getP2PService().addDecryptedDirectMessageListener(this); - } } @@ -66,12 +67,28 @@ public TradeProtocol(Trade trade) { // API /////////////////////////////////////////////////////////////////////////////////////////// + public void initialize(ProcessModelServiceProvider serviceProvider, TradeManager tradeManager, Offer offer) { + processModel.applyTransient(serviceProvider, tradeManager, offer); + initialized = true; + onInitialized(); + } + + protected void onInitialized() { + if (!trade.isWithdrawn()) { + processModel.getP2PService().addDecryptedDirectMessageListener(this); + } + + // Apply mailbox messages + // Clone to avoid ConcurrentModificationException. We remove items at the applyMailboxMessage call... + new HashSet<>(trade.getDecryptedMessageWithPubKeySet()).forEach(this::applyMailboxMessage); + } + public void onWithdrawCompleted() { cleanup(); } public void applyMailboxMessage(DecryptedMessageWithPubKey message) { - if (isPubKeyValid(message)) { + if (initialized && isPubKeyValid(message)) { NetworkEnvelope networkEnvelope = message.getNetworkEnvelope(); if (networkEnvelope instanceof MailboxMessage && networkEnvelope instanceof TradeMessage) { diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocolFactory.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocolFactory.java new file mode 100644 index 00000000000..fe521e99186 --- /dev/null +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocolFactory.java @@ -0,0 +1,40 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.trade.protocol; + +import bisq.core.trade.BuyerAsMakerTrade; +import bisq.core.trade.BuyerAsTakerTrade; +import bisq.core.trade.SellerAsMakerTrade; +import bisq.core.trade.SellerAsTakerTrade; +import bisq.core.trade.Trade; + +public class TradeProtocolFactory { + public static TradeProtocol getNewTradeProtocol(Trade trade) { + if (trade instanceof BuyerAsMakerTrade) { + return new BuyerAsMakerProtocol((BuyerAsMakerTrade) trade); + } else if (trade instanceof BuyerAsTakerTrade) { + return new BuyerAsTakerProtocol((BuyerAsTakerTrade) trade); + } else if (trade instanceof SellerAsMakerTrade) { + return new SellerAsMakerProtocol((SellerAsMakerTrade) trade); + } else if (trade instanceof SellerAsTakerTrade) { + return new SellerAsTakerProtocol((SellerAsTakerTrade) trade); + } else { + throw new IllegalStateException("Trade not of expected type. Trade=" + trade); + } + } +} diff --git a/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java b/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java index d81c840aab8..e954c83e32f 100644 --- a/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java +++ b/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofService.java @@ -264,7 +264,7 @@ private void startRequests(SellerTrade trade) { log.info("We auto-confirm trade {} as our all our services for the tx proof completed successfully", trade.getShortId()); log.info("###########################################################################################"); - ((SellerProtocol) trade.getTradeProtocol()).onPaymentReceived(() -> { + ((SellerProtocol) tradeManager.getTradeProtocol(trade)).onPaymentReceived(() -> { }, errorMessage -> { }); } diff --git a/desktop/src/main/java/bisq/desktop/main/MainViewModel.java b/desktop/src/main/java/bisq/desktop/main/MainViewModel.java index 941c28fc051..e3ead2949b1 100644 --- a/desktop/src/main/java/bisq/desktop/main/MainViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/MainViewModel.java @@ -214,7 +214,8 @@ public MainViewModel(BisqSetup bisqSetup, @Override public void onSetupComplete() { // We handle the trade period here as we display a global popup if we reached dispute time - tradesAndUIReady = EasyBind.combine(isSplashScreenRemoved, tradeManager.pendingTradesInitializedProperty(), (a, b) -> a && b); + tradesAndUIReady = EasyBind.combine(isSplashScreenRemoved, tradeManager.persistedTradesInitializedProperty(), + (a, b) -> a && b); tradesAndUIReady.subscribe((observable, oldValue, newValue) -> { if (newValue) { tradeManager.applyTradePeriodState(); diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java index 220d7d88cad..0bc6c95f466 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -189,13 +189,14 @@ public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler er Trade trade = getTrade(); checkNotNull(trade, "trade must not be null"); checkArgument(trade instanceof BuyerTrade, "Check failed: trade instanceof BuyerTrade"); - ((BuyerProtocol) trade.getTradeProtocol()).onPaymentStarted(resultHandler, errorMessageHandler); + ((BuyerProtocol) tradeManager.getTradeProtocol(trade)).onPaymentStarted(resultHandler, errorMessageHandler); } public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - checkNotNull(getTrade(), "trade must not be null"); - checkArgument(getTrade() instanceof SellerTrade, "Trade must be instance of SellerTrade"); - ((SellerProtocol) getTrade().getTradeProtocol()).onPaymentReceived(resultHandler, errorMessageHandler); + Trade trade = getTrade(); + checkNotNull(trade, "trade must not be null"); + checkArgument(trade instanceof SellerTrade, "Trade must be instance of SellerTrade"); + ((SellerProtocol) tradeManager.getTradeProtocol(trade)).onPaymentReceived(resultHandler, errorMessageHandler); } public void onWithdrawRequest(String toAddress, @@ -643,8 +644,7 @@ private void doOpenDispute(boolean isSupportTicket, Transaction depositTx) { trade.setDisputeState(Trade.DisputeState.REFUND_REQUESTED); - //todo add UI spinner as it can take a bit if peer is offline - ((DisputeProtocol) trade.getTradeProtocol()).onPublishDelayedPayoutTx(() -> { + ((DisputeProtocol) tradeManager.getTradeProtocol(trade)).onPublishDelayedPayoutTx(() -> { log.info("DelayedPayoutTx published and message sent to peer"); disputeManager.sendOpenNewDisputeMessage(dispute, false, diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java index 4149ebb338b..bfae6900381 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java @@ -222,17 +222,17 @@ public void onUpdatedDataReceived() { infoLabel.setText(getInfoText()); } - BooleanProperty pendingTradesInitialized = model.dataModel.tradeManager.getPendingTradesInitialized(); - if (pendingTradesInitialized.get()) { + BooleanProperty initialized = model.dataModel.tradeManager.getPersistedTradesInitialized(); + if (initialized.get()) { onPendingTradesInitialized(); } else { pendingTradesInitializedListener = (observable, oldValue, newValue) -> { if (newValue) { onPendingTradesInitialized(); - UserThread.execute(() -> pendingTradesInitialized.removeListener(pendingTradesInitializedListener)); + UserThread.execute(() -> initialized.removeListener(pendingTradesInitializedListener)); } }; - pendingTradesInitialized.addListener(pendingTradesInitializedListener); + initialized.addListener(pendingTradesInitializedListener); } } From 6deeecb8464918e48bbce3fca45443ca11621ba6 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sat, 26 Sep 2020 23:38:01 -0500 Subject: [PATCH 115/143] Move handling of mailbox messages from TradeManager to TradeProtocol Make removal of mailbox messages automated in TradeProtocol --- core/src/main/java/bisq/core/trade/Trade.java | 10 -- .../java/bisq/core/trade/TradeManager.java | 44 +-------- .../messages/RefreshTradeStateRequest.java | 3 +- .../messages/TraderSignedWitnessMessage.java | 4 + .../core/trade/protocol/BuyerProtocol.java | 2 +- .../core/trade/protocol/ProcessModel.java | 14 --- .../core/trade/protocol/SellerProtocol.java | 2 +- .../core/trade/protocol/TradeProtocol.java | 99 ++++++++++++++----- ...ssPeerPublishedDelayedPayoutTxMessage.java | 4 - ...essDepositTxAndDelayedPayoutTxMessage.java | 2 - .../BuyerProcessPayoutTxPublishedMessage.java | 2 - ...ProcessMediatedPayoutSignatureMessage.java | 2 - ...ocessMediatedPayoutTxPublishedMessage.java | 2 - ...CounterCurrencyTransferStartedMessage.java | 2 - .../java/bisq/network/p2p/P2PService.java | 8 +- 15 files changed, 91 insertions(+), 109 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index f3c36215c1e..a4f49efa4c5 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -33,7 +33,6 @@ import bisq.core.trade.protocol.ProcessModelServiceProvider; import bisq.core.trade.txproof.AssetTxProofResult; -import bisq.network.p2p.DecryptedMessageWithPubKey; import bisq.network.p2p.NodeAddress; import bisq.common.crypto.PubKeyRing; @@ -69,9 +68,7 @@ import java.time.temporal.ChronoUnit; import java.util.Date; -import java.util.HashSet; import java.util.Optional; -import java.util.Set; import java.util.stream.Collectors; import lombok.Getter; @@ -399,8 +396,6 @@ public static protobuf.Trade.TradePeriodState toProtoMessage(Trade.TradePeriodSt transient private ObjectProperty tradeAmountProperty; transient private ObjectProperty tradeVolumeProperty; - @Getter - final transient private Set decryptedMessageWithPubKeySet = new HashSet<>(); // Added in v1.1.6 @Getter @@ -712,10 +707,6 @@ public Transaction getDelayedPayoutTx(BtcWalletService btcWalletService) { return delayedPayoutTx; } - public void removeDecryptedMessageWithPubKey(DecryptedMessageWithPubKey decryptedMessageWithPubKey) { - decryptedMessageWithPubKeySet.remove(decryptedMessageWithPubKey); - } - public void addAndPersistChatMessage(ChatMessage chatMessage) { if (!chatMessages.contains(chatMessage)) { chatMessages.add(chatMessage); @@ -1208,7 +1199,6 @@ public String toString() { ",\n tradeAmount=" + tradeAmount + ",\n tradeAmountProperty=" + tradeAmountProperty + ",\n tradeVolumeProperty=" + tradeVolumeProperty + - ",\n decryptedMessageWithPubKeySet=" + decryptedMessageWithPubKeySet + ",\n mediationResultState=" + mediationResultState + ",\n mediationResultStateProperty=" + mediationResultStateProperty + ",\n lockTime=" + lockTime + diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 900e4db64cc..30c98ce5fe4 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -34,7 +34,6 @@ import bisq.core.trade.failed.FailedTradesManager; import bisq.core.trade.handlers.TradeResultHandler; import bisq.core.trade.messages.TakeOfferRequest; -import bisq.core.trade.messages.TradeMessage; import bisq.core.trade.protocol.MakerProtocol; import bisq.core.trade.protocol.ProcessModel; import bisq.core.trade.protocol.ProcessModelServiceProvider; @@ -45,14 +44,11 @@ import bisq.core.user.User; import bisq.core.util.Validator; -import bisq.network.p2p.AckMessage; -import bisq.network.p2p.AckMessageSourceType; import bisq.network.p2p.BootstrapListener; import bisq.network.p2p.DecryptedDirectMessageListener; import bisq.network.p2p.DecryptedMessageWithPubKey; import bisq.network.p2p.NodeAddress; import bisq.network.p2p.P2PService; -import bisq.network.p2p.messaging.DecryptedMailboxListener; import bisq.common.ClockWatcher; import bisq.common.config.Config; @@ -107,7 +103,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -public class TradeManager implements PersistedDataHost, DecryptedDirectMessageListener, DecryptedMailboxListener { +public class TradeManager implements PersistedDataHost, DecryptedDirectMessageListener { private static final Logger log = LoggerFactory.getLogger(TradeManager.class); private final User user; @@ -184,7 +180,6 @@ public TradeManager(User user, tradableListStorage = storage; p2PService.addDecryptedDirectMessageListener(this); - p2PService.addDecryptedMailboxListener(this); failedTradesManager.setUnFailTradeCallback(this::unFailTrade); } @@ -280,43 +275,6 @@ private void handleTakeOfferRequest(NodeAddress peer, TakeOfferRequest takeOffer } - /////////////////////////////////////////////////////////////////////////////////////////// - // DecryptedMailboxListener - /////////////////////////////////////////////////////////////////////////////////////////// - - // Might get called at startup after HS is published. Can be before or after initPendingTrades. - @Override - public void onMailboxMessageAdded(DecryptedMessageWithPubKey message, NodeAddress peer) { - NetworkEnvelope networkEnvelope = message.getNetworkEnvelope(); - if (networkEnvelope instanceof TradeMessage) { - TradeMessage tradeMessage = (TradeMessage) networkEnvelope; - getTradeById(tradeMessage.getTradeId()) - .ifPresent(trade -> { - // We don't need to persist the msg as if we don't processes the message it will not be - // removed from the P2P network and we will receive it again on next startup. - // This might happen in edge cases when the user shuts down after we received the msg but - // before it is processed. - //TODO - Set decryptedMessageWithPubKeySet = trade.getDecryptedMessageWithPubKeySet(); - if (!decryptedMessageWithPubKeySet.contains(message)) { - decryptedMessageWithPubKeySet.add(message); - - // The message will be removed after processed - TradeProtocol tradeProtocol = getTradeProtocol(trade); - tradeProtocol.applyMailboxMessage(message); - } - - }); - } else if (networkEnvelope instanceof AckMessage) { - AckMessage ackMessage = (AckMessage) networkEnvelope; - if (ackMessage.getSourceType() == AckMessageSourceType.TRADE_MESSAGE) { - // We remove here the message not in the trade protocol as it might be that the trade is already - // completed and the protocol is not listening. - p2PService.removeEntryFromMailbox(message); - } - } - } - /////////////////////////////////////////////////////////////////////////////////////////// // Lifecycle /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/core/src/main/java/bisq/core/trade/messages/RefreshTradeStateRequest.java b/core/src/main/java/bisq/core/trade/messages/RefreshTradeStateRequest.java index c2a6da54166..f865ea58de2 100644 --- a/core/src/main/java/bisq/core/trade/messages/RefreshTradeStateRequest.java +++ b/core/src/main/java/bisq/core/trade/messages/RefreshTradeStateRequest.java @@ -28,7 +28,8 @@ * We do the re-sending of the payment sent message via the BuyerSendCounterCurrencyTransferStartedMessage task on the * buyer side, so seller do not need to do anything interactively. */ -@SuppressWarnings("deprecation") +@Deprecated +@SuppressWarnings("ALL") @EqualsAndHashCode(callSuper = true) @Value public class RefreshTradeStateRequest extends TradeMessage implements MailboxMessage { diff --git a/core/src/main/java/bisq/core/trade/messages/TraderSignedWitnessMessage.java b/core/src/main/java/bisq/core/trade/messages/TraderSignedWitnessMessage.java index 56667b1dbf4..bae708b577a 100644 --- a/core/src/main/java/bisq/core/trade/messages/TraderSignedWitnessMessage.java +++ b/core/src/main/java/bisq/core/trade/messages/TraderSignedWitnessMessage.java @@ -27,6 +27,10 @@ import lombok.EqualsAndHashCode; import lombok.Value; +/** + * Not used anymore since v1.4.0 + */ +@Deprecated @SuppressWarnings("ALL") @EqualsAndHashCode(callSuper = true) @Value 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 e69e4a6872a..2e7c4d9ac26 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java @@ -111,7 +111,7 @@ protected void handle(DepositTxAndDelayedPayoutTxMessage message, NodeAddress pe "arrive and the peer repeats sending us the message. We send another ACK msg."); stopTimeout(); sendAckMessage(message, true, null); - processModel.removeMailboxMessageAfterProcessing(trade); + removeMailboxMessageAfterProcessing(message); })) .setup(tasks(BuyerProcessDepositTxAndDelayedPayoutTxMessage.class, BuyerVerifiesFinalDelayedPayoutTx.class, diff --git a/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java b/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java index 150db21210d..445dc025454 100644 --- a/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java +++ b/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java @@ -42,8 +42,6 @@ import bisq.core.user.User; import bisq.network.p2p.AckMessage; -import bisq.network.p2p.DecryptedMessageWithPubKey; -import bisq.network.p2p.MailboxMessage; import bisq.network.p2p.NodeAddress; import bisq.network.p2p.P2PService; @@ -91,8 +89,6 @@ public class ProcessModel implements Model, PersistablePayload { transient private Transaction takeOfferFeeTx; @Setter transient private TradeMessage tradeMessage; - @Setter - transient private DecryptedMessageWithPubKey decryptedMessageWithPubKey; // Added in v1.2.0 @Setter @@ -251,16 +247,6 @@ public static ProcessModel fromProto(protobuf.ProcessModel proto, CoreProtoResol // API /////////////////////////////////////////////////////////////////////////////////////////// - public void removeMailboxMessageAfterProcessing(Trade trade) { - if (tradeMessage instanceof MailboxMessage && - decryptedMessageWithPubKey != null && - decryptedMessageWithPubKey.getNetworkEnvelope().equals(tradeMessage)) { - log.debug("Remove decryptedMsgWithPubKey from P2P network. decryptedMsgWithPubKey = " + decryptedMessageWithPubKey); - getP2PService().removeEntryFromMailbox(decryptedMessageWithPubKey); - trade.removeDecryptedMessageWithPubKey(decryptedMessageWithPubKey); - } - } - @Override public void persist() { log.warn("persist is not implemented in that class"); diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java index b7ec415ffa4..d8a06cfd4d7 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java @@ -106,7 +106,7 @@ protected void handle(CounterCurrencyTransferStartedMessage message, NodeAddress "so we ignore the message. This can happen if the ACK message to the peer did not " + "arrive and the peer repeats sending us the message. We send another ACK msg."); sendAckMessage(message, true, null); - processModel.removeMailboxMessageAfterProcessing(trade); + removeMailboxMessageAfterProcessing(message); })) .setup(tasks( SellerProcessCounterCurrencyTransferStartedMessage.class, diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index 3f53833b3bd..cacb643f69d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -31,6 +31,7 @@ import bisq.network.p2p.MailboxMessage; import bisq.network.p2p.NodeAddress; import bisq.network.p2p.SendMailboxMessageListener; +import bisq.network.p2p.messaging.DecryptedMailboxListener; import bisq.common.Timer; import bisq.common.UserThread; @@ -38,19 +39,18 @@ import bisq.common.proto.network.NetworkEnvelope; import bisq.common.taskrunner.Task; -import java.util.HashSet; +import java.security.PublicKey; import lombok.extern.slf4j.Slf4j; import javax.annotation.Nullable; @Slf4j -public abstract class TradeProtocol implements DecryptedDirectMessageListener { +public abstract class TradeProtocol implements DecryptedDirectMessageListener, DecryptedMailboxListener { protected final ProcessModel processModel; protected final Trade trade; private Timer timeoutTimer; - private boolean initialized; /////////////////////////////////////////////////////////////////////////////////////////// @@ -69,7 +69,6 @@ public TradeProtocol(Trade trade) { public void initialize(ProcessModelServiceProvider serviceProvider, TradeManager tradeManager, Offer offer) { processModel.applyTransient(serviceProvider, tradeManager, offer); - initialized = true; onInitialized(); } @@ -77,29 +76,16 @@ protected void onInitialized() { if (!trade.isWithdrawn()) { processModel.getP2PService().addDecryptedDirectMessageListener(this); } - - // Apply mailbox messages - // Clone to avoid ConcurrentModificationException. We remove items at the applyMailboxMessage call... - new HashSet<>(trade.getDecryptedMessageWithPubKeySet()).forEach(this::applyMailboxMessage); + processModel.getP2PService().addDecryptedMailboxListener(this); + processModel.getP2PService().getMailboxMap().values() + .stream().map(e -> e.second) + .forEach(this::handleDecryptedMessageWithPubKey); } public void onWithdrawCompleted() { cleanup(); } - public void applyMailboxMessage(DecryptedMessageWithPubKey message) { - if (initialized && isPubKeyValid(message)) { - NetworkEnvelope networkEnvelope = message.getNetworkEnvelope(); - if (networkEnvelope instanceof MailboxMessage && - networkEnvelope instanceof TradeMessage) { - processModel.setDecryptedMessageWithPubKey(message); - TradeMessage tradeMessage = (TradeMessage) networkEnvelope; - NodeAddress peerNodeAddress = ((MailboxMessage) networkEnvelope).getSenderNodeAddress(); - onMailboxMessage(tradeMessage, peerNodeAddress); - } - } - } - protected void onMailboxMessage(TradeMessage message, NodeAddress peerNodeAddress) { log.info("Received {} as MailboxMessage from {} with tradeId {} and uid {}", message.getClass().getSimpleName(), peerNodeAddress, message.getTradeId(), message.getUid()); @@ -117,11 +103,75 @@ public void onDirectMessage(DecryptedMessageWithPubKey message, NodeAddress peer if (networkEnvelope instanceof TradeMessage && isMyTradeMessage((TradeMessage) networkEnvelope)) { onTradeMessage((TradeMessage) networkEnvelope, peer); } else if (networkEnvelope instanceof AckMessage) { - onAckMessage((AckMessage) networkEnvelope, peer); + AckMessage ackMessage = (AckMessage) networkEnvelope; + if (ackMessage.getSourceType() == AckMessageSourceType.TRADE_MESSAGE) { + onAckMessage((AckMessage) networkEnvelope, peer); + } } } } + /////////////////////////////////////////////////////////////////////////////////////////// + // DecryptedMailboxListener + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public void onMailboxMessageAdded(DecryptedMessageWithPubKey message, NodeAddress peer) { + handleDecryptedMessageWithPubKey(message, peer); + } + + private void handleDecryptedMessageWithPubKey(DecryptedMessageWithPubKey decryptedMessageWithPubKey) { + MailboxMessage mailboxMessage = (MailboxMessage) decryptedMessageWithPubKey.getNetworkEnvelope(); + NodeAddress senderNodeAddress = mailboxMessage.getSenderNodeAddress(); + handleDecryptedMessageWithPubKey(decryptedMessageWithPubKey, senderNodeAddress); + } + + protected void handleDecryptedMessageWithPubKey(DecryptedMessageWithPubKey decryptedMessageWithPubKey, + NodeAddress peer) { + if (!isPubKeyValid(decryptedMessageWithPubKey)) { + return; + } + + NetworkEnvelope networkEnvelope = decryptedMessageWithPubKey.getNetworkEnvelope(); + if (networkEnvelope instanceof TradeMessage) { + TradeMessage tradeMessage = (TradeMessage) networkEnvelope; + if (!isMyTradeMessage(tradeMessage)) { + return; + } + + if (trade.isWithdrawn()) { + processModel.getP2PService().removeEntryFromMailbox(decryptedMessageWithPubKey); + log.info("Remove {} from the P2P network.", tradeMessage.getClass().getSimpleName()); + return; + } + + onMailboxMessage(tradeMessage, peer); + } else if (networkEnvelope instanceof AckMessage) { + AckMessage ackMessage = (AckMessage) networkEnvelope; + if (ackMessage.getSourceType() == AckMessageSourceType.TRADE_MESSAGE && + ackMessage.getSourceId().equals(trade.getId())) { + if (!trade.isWithdrawn()) { + onAckMessage((AckMessage) networkEnvelope, peer); + } + processModel.getP2PService().removeEntryFromMailbox(decryptedMessageWithPubKey); + log.info("Remove {} from the P2P network.", ackMessage.getClass().getSimpleName()); + } + } + } + + public void removeMailboxMessageAfterProcessing(TradeMessage tradeMessage) { + if (tradeMessage instanceof MailboxMessage && + processModel.getTradingPeer() != null && + processModel.getTradingPeer().getPubKeyRing() != null && + processModel.getTradingPeer().getPubKeyRing().getSignaturePubKey() != null) { + PublicKey sigPubKey = processModel.getTradingPeer().getPubKeyRing().getSignaturePubKey(); + // We reconstruct the DecryptedMessageWithPubKey from the message and the peers signature pubKey + DecryptedMessageWithPubKey decryptedMessageWithPubKey = new DecryptedMessageWithPubKey(tradeMessage, sigPubKey); + processModel.getP2PService().removeEntryFromMailbox(decryptedMessageWithPubKey); + log.info("Remove {} from the P2P network.", tradeMessage.getClass().getSimpleName()); + } + } + /////////////////////////////////////////////////////////////////////////////////////////// // Abstract @@ -313,6 +363,11 @@ private void handleTaskRunnerSuccess(@Nullable TradeMessage message, String sour log.info("TaskRunner successfully completed. Triggered from {}, tradeId={}", source, trade.getId()); if (message != null) { sendAckMessage(message, true, null); + + // Once a taskRunner is completed we remove the mailbox message. To not remove it directly at the task + // adds some resilience in case of minor errors, so after a restart the mailbox message can be applied + // again. + removeMailboxMessageAfterProcessing(message); } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessPeerPublishedDelayedPayoutTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessPeerPublishedDelayedPayoutTxMessage.java index 385e8638507..a104b433b8e 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessPeerPublishedDelayedPayoutTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessPeerPublishedDelayedPayoutTxMessage.java @@ -52,13 +52,9 @@ protected void run() { Transaction delayedPayoutTx = checkNotNull(trade.getDelayedPayoutTx()); WalletService.maybeAddSelfTxToWallet(delayedPayoutTx, processModel.getBtcWalletService().getWallet()); - // todo trade.setState - complete(); } catch (Throwable t) { failed(t); - } finally { - processModel.removeMailboxMessageAfterProcessing(trade); } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java index 2bfea25a9cf..dfecf3abde9 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessDepositTxAndDelayedPayoutTxMessage.java @@ -76,8 +76,6 @@ protected void run() { complete(); } catch (Throwable t) { failed(t); - } finally { - processModel.removeMailboxMessageAfterProcessing(trade); } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessPayoutTxPublishedMessage.java index f82bb916be4..45cd777a217 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/buyer/BuyerProcessPayoutTxPublishedMessage.java @@ -76,8 +76,6 @@ protected void run() { complete(); } catch (Throwable t) { failed(t); - } finally { - processModel.removeMailboxMessageAfterProcessing(trade); } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutSignatureMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutSignatureMessage.java index a049d0932d9..ea1a02a02a2 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutSignatureMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutSignatureMessage.java @@ -54,8 +54,6 @@ protected void run() { complete(); } catch (Throwable t) { failed(t); - } finally { - processModel.removeMailboxMessageAfterProcessing(trade); } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutTxPublishedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutTxPublishedMessage.java index 9fdcc4b75c9..226fefbb5af 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutTxPublishedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/mediation/ProcessMediatedPayoutTxPublishedMessage.java @@ -77,8 +77,6 @@ protected void run() { complete(); } catch (Throwable t) { failed(t); - } finally { - processModel.removeMailboxMessageAfterProcessing(trade); } } } diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessCounterCurrencyTransferStartedMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessCounterCurrencyTransferStartedMessage.java index d2a12964452..5f8d6bc50ec 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessCounterCurrencyTransferStartedMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerProcessCounterCurrencyTransferStartedMessage.java @@ -64,8 +64,6 @@ protected void run() { complete(); } catch (Throwable t) { failed(t); - } finally { - processModel.removeMailboxMessageAfterProcessing(trade); } } } diff --git a/p2p/src/main/java/bisq/network/p2p/P2PService.java b/p2p/src/main/java/bisq/network/p2p/P2PService.java index 8eb0df0903c..4d2a5ef9025 100644 --- a/p2p/src/main/java/bisq/network/p2p/P2PService.java +++ b/p2p/src/main/java/bisq/network/p2p/P2PService.java @@ -52,6 +52,7 @@ import bisq.common.proto.ProtobufferException; import bisq.common.proto.network.NetworkEnvelope; import bisq.common.proto.persistable.PersistedDataHost; +import bisq.common.util.Tuple2; import com.google.inject.Inject; @@ -116,7 +117,8 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis private final Set decryptedDirectMessageListeners = new CopyOnWriteArraySet<>(); private final Set decryptedMailboxListeners = new CopyOnWriteArraySet<>(); private final Set p2pServiceListeners = new CopyOnWriteArraySet<>(); - private final Map mailboxMap = new HashMap<>(); + @Getter + private final Map> mailboxMap = new HashMap<>(); private final Set shutDownResultHandlers = new CopyOnWriteArraySet<>(); private final BooleanProperty hiddenServicePublished = new SimpleBooleanProperty(); private final BooleanProperty preliminaryDataReceived = new SimpleBooleanProperty(); @@ -531,7 +533,7 @@ private void processMailboxEntry(ProtectedMailboxStorageEntry protectedMailboxSt NodeAddress senderNodeAddress = mailboxMessage.getSenderNodeAddress(); checkNotNull(senderNodeAddress, "senderAddress must not be null for mailbox network_messages"); - mailboxMap.put(mailboxMessage.getUid(), protectedMailboxStorageEntry); + mailboxMap.put(mailboxMessage.getUid(), new Tuple2<>(protectedMailboxStorageEntry, decryptedMessageWithPubKey)); log.info("Received a {} mailbox message with messageUid {} and senderAddress {}", mailboxMessage.getClass().getSimpleName(), mailboxMessage.getUid(), senderNodeAddress); decryptedMailboxListeners.forEach( e -> e.onMailboxMessageAdded(decryptedMessageWithPubKey, senderNodeAddress)); @@ -741,7 +743,7 @@ private void delayedRemoveEntryFromMailbox(DecryptedMessageWithPubKey decryptedM MailboxMessage mailboxMessage = (MailboxMessage) decryptedMessageWithPubKey.getNetworkEnvelope(); String uid = mailboxMessage.getUid(); if (mailboxMap.containsKey(uid)) { - ProtectedMailboxStorageEntry mailboxData = mailboxMap.get(uid); + ProtectedMailboxStorageEntry mailboxData = mailboxMap.get(uid).first; if (mailboxData != null && mailboxData.getProtectedStoragePayload() instanceof MailboxStoragePayload) { MailboxStoragePayload expirableMailboxStoragePayload = (MailboxStoragePayload) mailboxData.getProtectedStoragePayload(); PublicKey receiversPubKey = mailboxData.getReceiversPubKey(); From d08591551b3a02ee9d5fbb8be995b2fb85fb6014 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sun, 27 Sep 2020 01:26:48 -0500 Subject: [PATCH 116/143] Add state listeners to warn icon columns to get correct state updates --- core/src/main/java/bisq/core/trade/Trade.java | 6 +- .../java/bisq/core/trade/TradeManager.java | 9 +- .../core/trade/protocol/ProcessModel.java | 5 +- .../pendingtrades/PendingTradesView.java | 85 +++++++++++++------ 4 files changed, 72 insertions(+), 33 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index a4f49efa4c5..ec77baf4b58 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -624,7 +624,7 @@ public void setTransientFields(Storage storage, BtcWalle this.btcWalletService = btcWalletService; } - public void init(ProcessModelServiceProvider serviceProvider) { + public void initialize(ProcessModelServiceProvider serviceProvider) { serviceProvider.getArbitratorManager().getDisputeAgentByNodeAddress(arbitratorNodeAddress).ifPresent(arbitrator -> { arbitratorBtcPubKey = arbitrator.getBtcPubKey(); arbitratorPubKeyRing = arbitrator.getPubKeyRing(); @@ -773,7 +773,9 @@ public void setStateIfValidTransitionTo(State newState) { } public void setState(State state) { - log.info("Set new state at {} (id={}): {}", this.getClass().getSimpleName(), getShortId(), state); + if (isInitialized) { + log.info("Set new state at {} (id={}): {}", this.getClass().getSimpleName(), getShortId(), state); + } if (state.getPhase().ordinal() < this.state.getPhase().ordinal()) { String message = "We got a state change to a previous phase.\n" + "Old state is: " + this.state + ". New state is: " + state; diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 30c98ce5fe4..0bc90e701e7 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -280,17 +280,16 @@ private void handleTakeOfferRequest(NodeAddress peer, TakeOfferRequest takeOffer /////////////////////////////////////////////////////////////////////////////////////////// public void onAllServicesInitialized() { - if (p2PService.isBootstrapped()) + if (p2PService.isBootstrapped()) { initPersistedTrades(); - else + } else { p2PService.addP2PServiceListener(new BootstrapListener() { @Override public void onUpdatedDataReceived() { - // Get called after onMailboxMessageAdded from initial data request - // The mailbox message will be removed inside the tasks after they are processed successfully initPersistedTrades(); } }); + } getTradesAsObservableList().addListener((ListChangeListener) change -> onTradesChanged()); onTradesChanged(); @@ -334,7 +333,7 @@ private void initPersistedTrade(Trade trade) { private void initTradeAndProtocol(Trade trade, TradeProtocol tradeProtocol) { tradeProtocol.initialize(processModelServiceProvider, this, trade.getOffer()); - trade.init(processModelServiceProvider); + trade.initialize(processModelServiceProvider); } diff --git a/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java b/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java index 445dc025454..ee7338b0944 100644 --- a/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java +++ b/core/src/main/java/bisq/core/trade/protocol/ProcessModel.java @@ -173,14 +173,15 @@ public ProcessModel(String offerId, String accountId, PubKeyRing pubKeyRing, Tra this.tradingPeer = tradingPeer != null ? tradingPeer : new TradingPeer(); } - public void applyTransient(ProcessModelServiceProvider processModelServiceProvider, + public void applyTransient(ProcessModelServiceProvider provider, TradeManager tradeManager, Offer offer) { this.offer = offer; - this.provider = processModelServiceProvider; + this.provider = provider; this.tradeManager = tradeManager; } + /////////////////////////////////////////////////////////////////////////////////////////// // PROTO BUFFER /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java index 316c8151aae..187300946bc 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java @@ -559,35 +559,44 @@ private void setTradeIdColumnCellFactory() { public TableCell call(TableColumn column) { return new TableCell<>() { - private HyperlinkWithIcon field; + private Trade trade; + private ChangeListener listener; @Override public void updateItem(final PendingTradesListItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { - Trade trade = item.getTrade(); - if (isMaybeInvalidTrade(trade)) { - field = new HyperlinkWithIcon(trade.getShortId()); - field.setIcon(FormBuilder.getMediumSizeIcon(MaterialDesignIcon.ALERT_CIRCLE_OUTLINE)); - field.setOnAction(event -> tradeDetailsWindow.show(trade)); - field.setTooltip(new Tooltip(Res.get("tooltip.invalidTradeState.warning"))); - if (trade.isTxChainInvalid()) { - field.getIcon().getStyleClass().addAll("icon", "error-icon"); - } else { - field.getIcon().getStyleClass().addAll("icon", "warn-icon"); - } + trade = item.getTrade(); + listener = (observable, oldValue, newValue) -> update(); + trade.stateProperty().addListener(listener); + update(); + } else { + setGraphic(null); + if (trade != null && listener != null) { + trade.stateProperty().removeListener(listener); + } + } + } + + private void update() { + HyperlinkWithIcon field; + if (isMaybeInvalidTrade(trade)) { + field = new HyperlinkWithIcon(trade.getShortId()); + field.setIcon(FormBuilder.getMediumSizeIcon(MaterialDesignIcon.ALERT_CIRCLE_OUTLINE)); + field.setOnAction(event -> tradeDetailsWindow.show(trade)); + field.setTooltip(new Tooltip(Res.get("tooltip.invalidTradeState.warning"))); + if (trade.isTxChainInvalid()) { + field.getIcon().getStyleClass().addAll("icon", "error-icon"); } else { - field = new HyperlinkWithIcon(trade.getShortId()); - field.setOnAction(event -> tradeDetailsWindow.show(trade)); - field.setTooltip(new Tooltip(Res.get("tooltip.openPopupForDetails"))); + field.getIcon().getStyleClass().addAll("icon", "warn-icon"); } - setGraphic(field); } else { - setGraphic(null); - if (field != null) - field.setOnAction(null); + field = new HyperlinkWithIcon(trade.getShortId()); + field.setOnAction(event -> tradeDetailsWindow.show(trade)); + field.setTooltip(new Tooltip(Res.get("tooltip.openPopupForDetails"))); } + setGraphic(field); } }; } @@ -859,12 +868,25 @@ private TableColumn setRemoveTrade public TableCell call(TableColumn column) { return new TableCell<>() { + private Trade trade; + private JFXButton warnIconButton, trashIconButton; + private ChangeListener listener; @Override public void updateItem(PendingTradesListItem newItem, boolean empty) { super.updateItem(newItem, empty); - if (!empty && newItem != null && isMaybeInvalidTrade(newItem.getTrade())) { - Trade trade = newItem.getTrade(); + if (!empty && newItem != null) { + trade = newItem.getTrade(); + listener = (observable, oldValue, newValue) -> update(); + trade.stateProperty().addListener(listener); + update(); + } else { + cleanup(); + } + } + + private void update() { + if (isMaybeInvalidTrade(trade)) { Text warnIcon = FormBuilder.getMediumSizeIcon(MaterialDesignIcon.ALERT_CIRCLE_OUTLINE); Text trashIcon = FormBuilder.getMediumSizeIcon(MaterialDesignIcon.ARROW_RIGHT_BOLD_BOX_OUTLINE); if (trade.isTxChainInvalid()) { @@ -875,12 +897,12 @@ public void updateItem(PendingTradesListItem newItem, boolean empty) { warnIcon.getStyleClass().addAll("icon", "warn-icon"); } - JFXButton warnIconButton = new JFXButton("", warnIcon); + warnIconButton = new JFXButton("", warnIcon); warnIconButton.getStyleClass().add("hidden-icon-button"); warnIconButton.setTooltip(new Tooltip(Res.get("portfolio.pending.failedTrade.warningIcon.tooltip"))); warnIconButton.setOnAction(e -> onShowInfoForInvalidTrade(trade)); - JFXButton trashIconButton = new JFXButton("", trashIcon); + trashIconButton = new JFXButton("", trashIcon); trashIconButton.getStyleClass().add("hidden-icon-button"); trashIconButton.setTooltip(new Tooltip(Res.get("portfolio.pending.failedTrade.moveTradeToFailedIcon.tooltip"))); trashIconButton.setOnAction(e -> onMoveInvalidTradeToFailedTrades(trade)); @@ -890,8 +912,23 @@ public void updateItem(PendingTradesListItem newItem, boolean empty) { hBox.getChildren().addAll(warnIconButton, trashIconButton); setGraphic(hBox); } else { - setGraphic(null); + cleanup(); + } + + updateMoveTradeToFailedColumnState(); + } + + private void cleanup() { + if (warnIconButton != null) { + warnIconButton.setOnAction(null); + } + if (trashIconButton != null) { + trashIconButton.setOnAction(null); + } + if (listener != null && trade != null) { + trade.stateProperty().removeListener(listener); } + setGraphic(null); } }; } From 28a85c1ce56564a17347632f8d804ca88124803f Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sun, 27 Sep 2020 02:04:35 -0500 Subject: [PATCH 117/143] Fix display strings --- core/src/main/resources/i18n/displayStrings.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 64b3bd23ca3..ff61b9ca5d6 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -833,9 +833,9 @@ portfolio.pending.error.depositTxNull=The deposit transaction is null. You canno without a valid deposit transaction. Please go to \"Settings/Network info\" and do a SPV resync.\n\n\ For further help please contact the Bisq support channel at the Bisq Keybase team. portfolio.pending.mediationResult.error.depositTxNull=The deposit transaction is null. You can move the \ - trade to the failed trades screen by clicking the trash can icon. + trade to the failed trades. portfolio.pending.mediationResult.error.delayedPayoutTxNull=The delayed payout transaction is null. You can move the \ - trade to the failed trades screen by clicking the trash can icon. + trade to the failed trades. portfolio.pending.error.depositTxNotConfirmed=The deposit transaction is not confirmed. You can not open an arbitration dispute \ with an unconfirmed deposit transaction. Please wait until it is confirmed or go to \"Settings/Network info\" and do a SPV resync.\n\n\ For further help please contact the Bisq support channel at the Bisq Keybase team. @@ -963,7 +963,7 @@ portfolio.failed.Failed=Failed portfolio.failed.unfail=Before proceeding, make sure you have a backup of your data directory!\n\ Do you want to move this trade back to open trades?\n\ This is a way to unlock funds stuck in a failed trade. -portfolio.failed.cantUnfail=This trade cannot be moved back to pending trades at the moment. \n\ +portfolio.failed.cantUnfail=This trade cannot be moved back to open trades at the moment. \n\ Try again after completion of trade(s) {0} portfolio.failed.depositTxNull=The trade cannot be reverted to a open trade. Deposit transaction is null. portfolio.failed.delayedPayoutTxNull=The trade cannot be reverted to a open trade. Delayed payout transaction is null. From 2191693946a2919ac6c4af9e0eb7940f7e4dc0e1 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sun, 27 Sep 2020 02:13:39 -0500 Subject: [PATCH 118/143] Apply stupid Codacy rule https://stackoverflow.com/questions/1750435/comparing-java-enum-members-or-equals ``` enum Color { BLACK, WHITE }; Color nothing = null; if (nothing == Color.BLACK); // runs fine if (nothing.equals(Color.BLACK)); // throws NullPointerException ``` ``` enum Color { BLACK, WHITE }; enum Chiral { LEFT, RIGHT }; if (Color.BLACK.equals(Chiral.LEFT)); // compiles fine if (Color.BLACK == Chiral.LEFT); // DOESN'T COMPILE!!! Incompatible types! ``` "To summarize, the arguments for using == on enum are: It works. It's faster. It's safer at run-time. It's safer at compile-time. " --- core/src/main/java/bisq/core/trade/Trade.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index ec77baf4b58..8e5d3490b22 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -193,7 +193,7 @@ public static protobuf.Trade.State toProtoMessage(Trade.State state) { public boolean isValidTransitionTo(State newState) { Phase newPhase = newState.getPhase(); Phase currentPhase = this.getPhase(); - return currentPhase.isValidTransitionTo(newPhase) || newPhase == currentPhase; + return currentPhase.isValidTransitionTo(newPhase) || newPhase.equals(currentPhase); } } From b31f5b7b23915656bd5a3eeba9d67f9057eec97e Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Sun, 27 Sep 2020 02:16:27 -0500 Subject: [PATCH 119/143] Another stupid codacy enforcement --- .../desktop/main/portfolio/pendingtrades/PendingTradesView.java | 1 + 1 file changed, 1 insertion(+) diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java index 187300946bc..8f7b2d0a651 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java @@ -683,6 +683,7 @@ public void updateItem(final PendingTradesListItem item, boolean empty) { String volume = DisplayUtils.formatVolumeWithCode(item.getTrade().getTradeVolume()); setGraphic(new AutoTooltipLabel(volume)); } catch (Throwable ignore) { + log.debug(ignore.toString()); // Stupidity to make Codacy happy } } else setGraphic(null); From ad83183cbaa9ca13906c66216ff0b90f8d2dd8fd Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 28 Sep 2020 18:05:09 -0500 Subject: [PATCH 120/143] Revert copyright text from un-intended change --- .../java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java | 2 +- .../java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 5b9c38add23..269d4856f37 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -11,7 +11,7 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public * License for more details. * - * You should have with a copy of the GNU Affero General Public License + * You should have received a copy of the GNU Affero General Public License * along with Bisq. If not, see . */ diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 5424ff2c6f7..9286944deec 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -11,7 +11,7 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public * License for more details. * - * You should have with a copy of the GNU Affero General Public License + * You should have received a copy of the GNU Affero General Public License * along with Bisq. If not, see . */ From eec13cd2768dc609e2759375273208a873fbddde Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 28 Sep 2020 18:08:07 -0500 Subject: [PATCH 121/143] Refactor: Return early if not valid --- .../core/trade/protocol/FluentProtocol.java | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java b/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java index 03d58daaabd..bf054e99c4c 100644 --- a/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/FluentProtocol.java @@ -85,27 +85,30 @@ public FluentProtocol run(Runnable runnable) { public FluentProtocol executeTasks() { Condition.Result result = condition.getResult(); - if (result.isValid) { - if (setup.getTimeoutSec() > 0) { - tradeProtocol.startTimeout(setup.getTimeoutSec()); + if (!result.isValid) { + if (resultHandler != null) { + resultHandler.accept(result); } + return this; + } - NodeAddress peer = condition.getPeer(); - if (peer != null) { - tradeProtocol.processModel.setTempTradingPeerNodeAddress(peer); - } + if (setup.getTimeoutSec() > 0) { + tradeProtocol.startTimeout(setup.getTimeoutSec()); + } - TradeMessage message = condition.getMessage(); - if (message != null) { - tradeProtocol.processModel.setTradeMessage(message); - } + NodeAddress peer = condition.getPeer(); + if (peer != null) { + tradeProtocol.processModel.setTempTradingPeerNodeAddress(peer); + } - TradeTaskRunner taskRunner = setup.getTaskRunner(message, condition.getEvent()); - taskRunner.addTasks(setup.getTasks()); - taskRunner.run(); - } else if (resultHandler != null) { - resultHandler.accept(result); + TradeMessage message = condition.getMessage(); + if (message != null) { + tradeProtocol.processModel.setTradeMessage(message); } + + TradeTaskRunner taskRunner = setup.getTaskRunner(message, condition.getEvent()); + taskRunner.addTasks(setup.getTasks()); + taskRunner.run(); return this; } From 0258205211f76133063141a8e61d0cca4bd1d843 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Mon, 28 Sep 2020 18:10:42 -0500 Subject: [PATCH 122/143] Fix typos --- .../tasks/maker/MakerProcessesInputsForDepositTxRequest.java | 2 +- .../seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java index 5f1a7e56806..b85390f271a 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java @@ -71,7 +71,7 @@ protected void run() { // We set the taker fee only in the processModel yet not in the trade as the tx was only created but not // published yet. Once it was published we move it to trade. The takerFeeTx should be sent in a later - // message bu that cannot be changed due backward compatibility issues. It is a left over from the + // message but that cannot be changed due backward compatibility issues. It is a left over from the // old trade protocol. processModel.setTakeOfferFeeTxId(nonEmptyStringOf(request.getTakerFeeTxId())); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java index fc3bf6b6d0c..e46a88fcdc1 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/seller/SellerSendsDepositTxAndDelayedPayoutTxMessage.java @@ -40,7 +40,7 @@ * in case that does not happen in 4 seconds or if the message was stored in mailbox or failed. We keep repeating that * with doubling the interval each time and until the MAX_RESEND_ATTEMPTS is reached. If never successful we fail and * do not continue the protocol with publishing the deposit tx. That way we avoid that a deposit tx is published but the - * buyer does not has the delayed payout tx and would not be able to open arbitration. + * buyer does not have the delayed payout tx and would not be able to open arbitration. */ @Slf4j public class SellerSendsDepositTxAndDelayedPayoutTxMessage extends SendMailboxMessageTask { From 6be21fa86c89d27669f9efa45bf5f28d473a6259 Mon Sep 17 00:00:00 2001 From: chimp1984 <54558767+chimp1984@users.noreply.github.com> Date: Tue, 29 Sep 2020 01:02:11 -0500 Subject: [PATCH 123/143] Update core/src/main/resources/i18n/displayStrings.properties Co-authored-by: m52go --- core/src/main/resources/i18n/displayStrings.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index ff61b9ca5d6..5c8786a6fb6 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -408,8 +408,8 @@ offerbook.warning.tradeLimitNotMatching=Your payment account has been created {0 Your trade limit is: {1}\n\ The min. trade amount of the offer is: {2}.\n\n\ You cannot take that offer at the moment. Once your account is older than 2 months this restriction gets removed. -offerbook.warning.offerWasAlreadyUsedInTrade=You cannot take that offer because you have taken it already earlier. \ - It might be that the take offer attempt ended up in a failed trade. +offerbook.warning.offerWasAlreadyUsedInTrade=You cannot take this offer because you already took it earlier. \ + It could be that your previous take-offer attempt resulted in a failed trade. offerbook.info.sellAtMarketPrice=You will sell at market price (updated every minute). offerbook.info.buyAtMarketPrice=You will buy at market price (updated every minute). From 285003743da60c29931df7ba4660722a2fb67bae Mon Sep 17 00:00:00 2001 From: chimp1984 <54558767+chimp1984@users.noreply.github.com> Date: Tue, 29 Sep 2020 01:02:49 -0500 Subject: [PATCH 124/143] Update core/src/main/resources/i18n/displayStrings.properties Co-authored-by: m52go --- core/src/main/resources/i18n/displayStrings.properties | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 5c8786a6fb6..2c05db8ecda 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -562,8 +562,9 @@ portfolio.tab.failed=Failed portfolio.tab.editOpenOffer=Edit offer portfolio.pending.invalidDelayedPayoutTx=There is an issue with a missing or invalid transaction.\n\n\ - Please do NOT send the Altcoin or Fiat payment but contact the Bisq \ - developers at 'https://bisq.community' or the Keybase channel for further assistance.\n\n\ + Please do NOT send the fiat or altcoin payment. Contact Bisq \ + developers on Keybase (https://keybase.io/team/bisq) or on the \ + forum (https://bisq.community) for further assistance.\n\n\ Error message: {0} portfolio.pending.step1.waitForConf=Wait for blockchain confirmation From c448b1b58d69f02d653e8faa73c9512de42657c6 Mon Sep 17 00:00:00 2001 From: chimp1984 <54558767+chimp1984@users.noreply.github.com> Date: Tue, 29 Sep 2020 01:03:01 -0500 Subject: [PATCH 125/143] Update core/src/main/resources/i18n/displayStrings.properties Co-authored-by: m52go --- core/src/main/resources/i18n/displayStrings.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 2c05db8ecda..1b734af5628 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -836,7 +836,7 @@ portfolio.pending.error.depositTxNull=The deposit transaction is null. You canno portfolio.pending.mediationResult.error.depositTxNull=The deposit transaction is null. You can move the \ trade to the failed trades. portfolio.pending.mediationResult.error.delayedPayoutTxNull=The delayed payout transaction is null. You can move the \ - trade to the failed trades. + trade to failed trades. portfolio.pending.error.depositTxNotConfirmed=The deposit transaction is not confirmed. You can not open an arbitration dispute \ with an unconfirmed deposit transaction. Please wait until it is confirmed or go to \"Settings/Network info\" and do a SPV resync.\n\n\ For further help please contact the Bisq support channel at the Bisq Keybase team. From 08e2a2e0b0d49b562436162881b4280f042c62f8 Mon Sep 17 00:00:00 2001 From: chimp1984 <54558767+chimp1984@users.noreply.github.com> Date: Tue, 29 Sep 2020 01:03:18 -0500 Subject: [PATCH 126/143] Update core/src/main/resources/i18n/displayStrings.properties Co-authored-by: m52go --- core/src/main/resources/i18n/displayStrings.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 1b734af5628..01e2fcd2cd4 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -907,8 +907,8 @@ portfolio.pending.mediationResult.popup.openArbitration=Reject and request arbit portfolio.pending.mediationResult.popup.alreadyAccepted=You've already accepted portfolio.pending.failedTrade.taker.missingTakerFeeTx=The taker fee transaction is missing.\n\n\ - Without that the trade cannot be completed. No funds have been locked up and no trade fee has been paid. \ - You can move the trade to failed trades. + Without this tx, the trade cannot be completed. No funds have been locked and no trade fee has been paid. \ + You can move this trade to failed trades. portfolio.pending.failedTrade.maker.missingTakerFeeTx=The peer's taker fee transaction is missing.\n\n\ Without that the trade cannot be completed. No funds have been locked up. \ Your offer is still available for other traders so you have not lost the maker fee. \ From 126f99668dbb52b56b0e19ab9bb808a5a99fbff4 Mon Sep 17 00:00:00 2001 From: chimp1984 <54558767+chimp1984@users.noreply.github.com> Date: Tue, 29 Sep 2020 01:03:30 -0500 Subject: [PATCH 127/143] Update core/src/main/resources/i18n/displayStrings.properties Co-authored-by: m52go --- core/src/main/resources/i18n/displayStrings.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 01e2fcd2cd4..6aaa0e5924b 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -943,7 +943,7 @@ portfolio.pending.failedTrade.missingContract=The trade contract is not set.\n\n portfolio.pending.failedTrade.info.popup=The trade protocol encountered some problems.\n\n{0} portfolio.pending.failedTrade.txChainInvalid.moveToFailed=The trade protocol encountered a serious problem.\n\n{0}\n\n\ Do you want to move the trade to failed trades?\n\n\ - You cannot open mediation or arbitration from the failed trades view, but you can move it back to the open \ + You cannot open mediation or arbitration from the failed trades view, but you can move a failed trade back to the open \ trades screen any time. portfolio.pending.failedTrade.txChainValid.moveToFailed=The trade protocol encountered some problems.\n\n{0}\n\n\ The trade transactions have been published and funds are locked up. Only move the trade to failed trades if you are \ From e3cc62ed602dd326aafa19c783ae394b0a3ec035 Mon Sep 17 00:00:00 2001 From: chimp1984 <54558767+chimp1984@users.noreply.github.com> Date: Tue, 29 Sep 2020 01:03:41 -0500 Subject: [PATCH 128/143] Update core/src/main/resources/i18n/displayStrings.properties Co-authored-by: m52go --- core/src/main/resources/i18n/displayStrings.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 6aaa0e5924b..0878df94b79 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -946,10 +946,10 @@ portfolio.pending.failedTrade.txChainInvalid.moveToFailed=The trade protocol enc You cannot open mediation or arbitration from the failed trades view, but you can move a failed trade back to the open \ trades screen any time. portfolio.pending.failedTrade.txChainValid.moveToFailed=The trade protocol encountered some problems.\n\n{0}\n\n\ - The trade transactions have been published and funds are locked up. Only move the trade to failed trades if you are \ + The trade transactions have been published and funds are locked. Only move the trade to failed trades if you are \ really sure. It might prevent options to resolve the problem.\n\n\ Do you want to move the trade to failed trades?\n\n\ - You cannot open mediation or arbitration from the failed trades view, but you can move it back to the open \ + You cannot open mediation or arbitration from the failed trades view, but you can move a failed trade back to the open \ trades screen any time. portfolio.pending.failedTrade.moveTradeToFailedIcon.tooltip=Move trade to failed trades portfolio.pending.failedTrade.warningIcon.tooltip=Click to open details about the issues of that trade From dc15c7dfa7e45cc62f42bab38dd5e09f4085b5ed Mon Sep 17 00:00:00 2001 From: chimp1984 <54558767+chimp1984@users.noreply.github.com> Date: Tue, 29 Sep 2020 01:03:53 -0500 Subject: [PATCH 129/143] Update core/src/main/resources/i18n/displayStrings.properties Co-authored-by: m52go --- core/src/main/resources/i18n/displayStrings.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 0878df94b79..02c2cd22d73 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -953,7 +953,7 @@ portfolio.pending.failedTrade.txChainValid.moveToFailed=The trade protocol encou trades screen any time. portfolio.pending.failedTrade.moveTradeToFailedIcon.tooltip=Move trade to failed trades portfolio.pending.failedTrade.warningIcon.tooltip=Click to open details about the issues of that trade -portfolio.failed.revertToPending.popup=Do you want to move the trade to open trades? +portfolio.failed.revertToPending.popup=Do you want to move this trade to open trades? portfolio.failed.revertToPending=Move trade to open trades portfolio.closed.completed=Completed From 1fef02e6f1e058a3d8bf8a833e9e638341d1cf74 Mon Sep 17 00:00:00 2001 From: chimp1984 <54558767+chimp1984@users.noreply.github.com> Date: Tue, 29 Sep 2020 01:04:04 -0500 Subject: [PATCH 130/143] Update core/src/main/resources/i18n/displayStrings.properties Co-authored-by: m52go --- core/src/main/resources/i18n/displayStrings.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 02c2cd22d73..e09cfe2b768 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -3028,7 +3028,7 @@ addressTextField.openWallet.failed=Opening a default Bitcoin wallet application peerInfoIcon.tooltip={0}\nTag: {1} txIdTextField.copyIcon.tooltip=Copy transaction ID to clipboard -txIdTextField.blockExplorerIcon.tooltip=Open a blockchain explorer with that transaction ID +txIdTextField.blockExplorerIcon.tooltip=Open a blockchain explorer with this transaction ID txIdTextField.missingTx.warning.tooltip=Missing required transaction From 4e2ccf249b20f96e99b0101817bf1f474c3ede79 Mon Sep 17 00:00:00 2001 From: chimp1984 <54558767+chimp1984@users.noreply.github.com> Date: Tue, 29 Sep 2020 01:04:17 -0500 Subject: [PATCH 131/143] Update core/src/main/resources/i18n/displayStrings.properties Co-authored-by: m52go --- core/src/main/resources/i18n/displayStrings.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index e09cfe2b768..cbb62375771 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -952,7 +952,7 @@ portfolio.pending.failedTrade.txChainValid.moveToFailed=The trade protocol encou You cannot open mediation or arbitration from the failed trades view, but you can move a failed trade back to the open \ trades screen any time. portfolio.pending.failedTrade.moveTradeToFailedIcon.tooltip=Move trade to failed trades -portfolio.pending.failedTrade.warningIcon.tooltip=Click to open details about the issues of that trade +portfolio.pending.failedTrade.warningIcon.tooltip=Click to open details about the issues of this trade portfolio.failed.revertToPending.popup=Do you want to move this trade to open trades? portfolio.failed.revertToPending=Move trade to open trades From 92902102ec7f62913d3a728b09c28c6000f6d489 Mon Sep 17 00:00:00 2001 From: chimp1984 <54558767+chimp1984@users.noreply.github.com> Date: Tue, 29 Sep 2020 01:04:27 -0500 Subject: [PATCH 132/143] Update core/src/main/resources/i18n/displayStrings.properties Co-authored-by: m52go --- core/src/main/resources/i18n/displayStrings.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index cbb62375771..43e9297e70d 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -834,7 +834,7 @@ portfolio.pending.error.depositTxNull=The deposit transaction is null. You canno without a valid deposit transaction. Please go to \"Settings/Network info\" and do a SPV resync.\n\n\ For further help please contact the Bisq support channel at the Bisq Keybase team. portfolio.pending.mediationResult.error.depositTxNull=The deposit transaction is null. You can move the \ - trade to the failed trades. + trade to failed trades. portfolio.pending.mediationResult.error.delayedPayoutTxNull=The delayed payout transaction is null. You can move the \ trade to failed trades. portfolio.pending.error.depositTxNotConfirmed=The deposit transaction is not confirmed. You can not open an arbitration dispute \ From 77ae1bddfa27de7eae964f3eeb7a982d55327a5e Mon Sep 17 00:00:00 2001 From: chimp1984 <54558767+chimp1984@users.noreply.github.com> Date: Tue, 29 Sep 2020 01:04:45 -0500 Subject: [PATCH 133/143] Update core/src/main/resources/i18n/displayStrings.properties Co-authored-by: m52go --- core/src/main/resources/i18n/displayStrings.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 43e9297e70d..aa7d4613fce 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -910,9 +910,9 @@ portfolio.pending.failedTrade.taker.missingTakerFeeTx=The taker fee transaction Without this tx, the trade cannot be completed. No funds have been locked and no trade fee has been paid. \ You can move this trade to failed trades. portfolio.pending.failedTrade.maker.missingTakerFeeTx=The peer's taker fee transaction is missing.\n\n\ - Without that the trade cannot be completed. No funds have been locked up. \ - Your offer is still available for other traders so you have not lost the maker fee. \ - You can move the trade to failed trades. + Without this tx, the trade cannot be completed. No funds have been locked. \ + Your offer is still available to other traders, so you have not lost the maker fee. \ + You can move this trade to failed trades. portfolio.pending.failedTrade.missingDepositTx=The deposit transaction (the 2of2 Multisig transaction) is missing.\n\n\ Without that the trade cannot be completed. No funds have been locked up but your trade fee has been paid. \ You can request at https://github.com/bisq-network/support/issues for getting reimbursed the lost trade fee. \ From 6c114b44e828a684c68e2ea8cf7e4a948b356f3c Mon Sep 17 00:00:00 2001 From: chimp1984 <54558767+chimp1984@users.noreply.github.com> Date: Tue, 29 Sep 2020 01:05:21 -0500 Subject: [PATCH 134/143] Update core/src/main/resources/i18n/displayStrings.properties Co-authored-by: m52go --- core/src/main/resources/i18n/displayStrings.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index aa7d4613fce..2a6444ab04d 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -913,10 +913,10 @@ portfolio.pending.failedTrade.maker.missingTakerFeeTx=The peer's taker fee trans Without this tx, the trade cannot be completed. No funds have been locked. \ Your offer is still available to other traders, so you have not lost the maker fee. \ You can move this trade to failed trades. -portfolio.pending.failedTrade.missingDepositTx=The deposit transaction (the 2of2 Multisig transaction) is missing.\n\n\ - Without that the trade cannot be completed. No funds have been locked up but your trade fee has been paid. \ - You can request at https://github.com/bisq-network/support/issues for getting reimbursed the lost trade fee. \ - You can move the trade to failed trades. +portfolio.pending.failedTrade.missingDepositTx=The deposit transaction (the 2-of-2 multisig transaction) is missing.\n\n\ + Without this tx, the trade cannot be completed. No funds have been locked but your trade fee has been paid. \ + You can make a request to be reimbursed the trade fee here: https://github.com/bisq-network/support/issues. \n\n\ + Feel free to move this trade to failed trades. portfolio.pending.failedTrade.buyer.existingDepositTxButMissingDelayedPayoutTx=The delayed payout transaction is missing.\n\n\ Without that arbitration cannot be opened. The funds have been locked up in the deposit transaction and you must not \ send the fiat or altcoin payment to the BTC seller. Open a mediation ticket by clicking cmd+o (or ctrl+o). \ From c3d3e5230e5364861cf34f2ecf3a8e1c95279bb0 Mon Sep 17 00:00:00 2001 From: chimp1984 <54558767+chimp1984@users.noreply.github.com> Date: Tue, 29 Sep 2020 01:05:46 -0500 Subject: [PATCH 135/143] Update core/src/main/resources/i18n/displayStrings.properties Co-authored-by: m52go --- .../main/resources/i18n/displayStrings.properties | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 2a6444ab04d..256497ea954 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -917,12 +917,14 @@ portfolio.pending.failedTrade.missingDepositTx=The deposit transaction (the 2-of Without this tx, the trade cannot be completed. No funds have been locked but your trade fee has been paid. \ You can make a request to be reimbursed the trade fee here: https://github.com/bisq-network/support/issues. \n\n\ Feel free to move this trade to failed trades. -portfolio.pending.failedTrade.buyer.existingDepositTxButMissingDelayedPayoutTx=The delayed payout transaction is missing.\n\n\ - Without that arbitration cannot be opened. The funds have been locked up in the deposit transaction and you must not \ - send the fiat or altcoin payment to the BTC seller. Open a mediation ticket by clicking cmd+o (or ctrl+o). \ - The mediator should make a suggested payout so that the seller receives their trade amount back and both traders get \ - back their security deposit. That way there is no security risk and only the trade fee is lost. \ - You can request at https://github.com/bisq-network/support/issues for getting reimbursed the lost trade fee. +portfolio.pending.failedTrade.buyer.existingDepositTxButMissingDelayedPayoutTx=The delayed payout transaction is missing, \ + but funds have been locked in the deposit transaction.\n\n\ + Please do NOT send the fiat or altcoin payment to the BTC seller, because without the delayed payout tx, arbitration \ + cannot be opened. Instead, open a mediation ticket with Cmd/Ctrl+o. \ + The mediator should suggest that both peers each get back the the full amount of their security deposits \ + (with seller receiving full trade amount back as well). \ + This way, there is no security risk, and only trade fees are lost. \n\n\ + You can request a reimbursement for lost trade fees here: https://github.com/bisq-network/support/issues. portfolio.pending.failedTrade.seller.existingDepositTxButMissingDelayedPayoutTx=The delayed payout transaction is missing.\n\n\ Without that arbitration cannot be opened. The funds have been locked up in the deposit transaction. If the buyer is \ also missing the delayed payout transaction he is instructed to not send the payment but open a mediation ticket. \ From 9cf368c449f74bcb0f690078f74dde92b763cc44 Mon Sep 17 00:00:00 2001 From: chimp1984 <54558767+chimp1984@users.noreply.github.com> Date: Tue, 29 Sep 2020 01:06:09 -0500 Subject: [PATCH 136/143] Update core/src/main/resources/i18n/displayStrings.properties Co-authored-by: m52go --- .../main/resources/i18n/displayStrings.properties | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 256497ea954..dd1752a19a4 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -925,13 +925,14 @@ portfolio.pending.failedTrade.buyer.existingDepositTxButMissingDelayedPayoutTx=T (with seller receiving full trade amount back as well). \ This way, there is no security risk, and only trade fees are lost. \n\n\ You can request a reimbursement for lost trade fees here: https://github.com/bisq-network/support/issues. -portfolio.pending.failedTrade.seller.existingDepositTxButMissingDelayedPayoutTx=The delayed payout transaction is missing.\n\n\ - Without that arbitration cannot be opened. The funds have been locked up in the deposit transaction. If the buyer is \ - also missing the delayed payout transaction he is instructed to not send the payment but open a mediation ticket. \ - You should open a mediation ticket as well by clicking cmd+o (or ctrl+o). \ - In case that the buyer has not sent the payment the mediator should make a suggested payout so that you receive \ - your trade amount back and both traders get back their security deposit. Otherwise the trade amount should go to the buyer. \ - You can request at https://github.com/bisq-network/support/issues for getting reimbursed the lost trade fee. +portfolio.pending.failedTrade.seller.existingDepositTxButMissingDelayedPayoutTx=The delayed payout transaction is missing \ + but funds have been locked in the deposit transaction.\n\n\ + If the buyer is also missing the delayed payout transaction, they will be instructed to NOT send the payment and open \ + a mediation ticket instead. You should also open a mediation ticket with Cmd/Ctrl+o. \n\n\ + If the buyer has not sent payment yet, the mediator should suggest that both peers each get back the full amount of \ + their security deposits (with seller receiving full trade amount back as well). \ + Otherwise the trade amount should go to the buyer. \n\n\ + You can request a reimbursement for lost trade fees here: https://github.com/bisq-network/support/issues. portfolio.pending.failedTrade.errorMsgSet=There have been an error during the trade protocol execution.\n\n\ Error: {0}\n\n\ This error might not be critical and the trade could be completed normally. If you are unsure you can open a mediation \ From e071d5e02574081e95c420456cb49f78de735f51 Mon Sep 17 00:00:00 2001 From: chimp1984 <54558767+chimp1984@users.noreply.github.com> Date: Tue, 29 Sep 2020 01:06:28 -0500 Subject: [PATCH 137/143] Update core/src/main/resources/i18n/displayStrings.properties Co-authored-by: m52go --- core/src/main/resources/i18n/displayStrings.properties | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index dd1752a19a4..df890e5f3cc 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -933,12 +933,12 @@ portfolio.pending.failedTrade.seller.existingDepositTxButMissingDelayedPayoutTx= their security deposits (with seller receiving full trade amount back as well). \ Otherwise the trade amount should go to the buyer. \n\n\ You can request a reimbursement for lost trade fees here: https://github.com/bisq-network/support/issues. -portfolio.pending.failedTrade.errorMsgSet=There have been an error during the trade protocol execution.\n\n\ +portfolio.pending.failedTrade.errorMsgSet=There was an error during trade protocol execution.\n\n\ Error: {0}\n\n\ - This error might not be critical and the trade could be completed normally. If you are unsure you can open a mediation \ - ticket to get advice from the Bisq mediators. If the error was critical and the trade cannot be completed you might \ - have lost your trade fee. If so, you can request at https://github.com/bisq-network/support/issues for \ - getting reimbursed the lost trade fee. + It might be that this error is not critical, and the trade can be completed normally. If you are unsure, open a mediation \ + ticket to get advice from Bisq mediators. \n\n\ + If the error was critical and the trade cannot be completed, you might have lost your trade fee. \ + Request a reimbursement for lost trade fees here: https://github.com/bisq-network/support/issues. portfolio.pending.failedTrade.missingContract=The trade contract is not set.\n\n\ The trade cannot be completed and you might \ have lost your trade fee. If so, you can request at https://github.com/bisq-network/support/issues for \ From 25e64cd6b59c6a46614400f63d8ecc1ebbb96dca Mon Sep 17 00:00:00 2001 From: chimp1984 <54558767+chimp1984@users.noreply.github.com> Date: Tue, 29 Sep 2020 01:06:44 -0500 Subject: [PATCH 138/143] Update core/src/main/resources/i18n/displayStrings.properties Co-authored-by: m52go --- core/src/main/resources/i18n/displayStrings.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index df890e5f3cc..0e9dbafcbce 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -941,8 +941,8 @@ portfolio.pending.failedTrade.errorMsgSet=There was an error during trade protoc Request a reimbursement for lost trade fees here: https://github.com/bisq-network/support/issues. portfolio.pending.failedTrade.missingContract=The trade contract is not set.\n\n\ The trade cannot be completed and you might \ - have lost your trade fee. If so, you can request at https://github.com/bisq-network/support/issues for \ - getting reimbursed the lost trade fee. + have lost your trade fee. If so, you can request a reimbursement for lost trade fees here: \ + https://github.com/bisq-network/support/issues. portfolio.pending.failedTrade.info.popup=The trade protocol encountered some problems.\n\n{0} portfolio.pending.failedTrade.txChainInvalid.moveToFailed=The trade protocol encountered a serious problem.\n\n{0}\n\n\ Do you want to move the trade to failed trades?\n\n\ From 24e1155eeaaac9bb9a3a21e81e7db1284af72dc0 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 30 Sep 2020 13:44:15 -0500 Subject: [PATCH 139/143] Set peers pubkey at constructor instead of onInitialized --- .../java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java | 4 ---- .../java/bisq/core/trade/protocol/SellerAsTakerProtocol.java | 5 ----- 2 files changed, 9 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 9286944deec..41de427050c 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -62,11 +62,7 @@ public class BuyerAsTakerProtocol extends BuyerProtocol implements TakerProtocol public BuyerAsTakerProtocol(BuyerAsTakerTrade trade) { super(trade); - } - @Override - protected void onInitialized() { - super.onInitialized(); Offer offer = checkNotNull(trade.getOffer()); processModel.getTradingPeer().setPubKeyRing(offer.getPubKeyRing()); } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index 592ec32189a..afcd654d824 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -57,11 +57,6 @@ public class SellerAsTakerProtocol extends SellerProtocol implements TakerProtoc public SellerAsTakerProtocol(SellerAsTakerTrade trade) { super(trade); - } - - @Override - protected void onInitialized() { - super.onInitialized(); Offer offer = checkNotNull(trade.getOffer()); processModel.getTradingPeer().setPubKeyRing(offer.getPubKeyRing()); } From 7e847cd95b433035055d7cd1c79019393672aec4 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Wed, 30 Sep 2020 13:45:27 -0500 Subject: [PATCH 140/143] Only check pubKey for trade messages. Before we got it called for instance when the mediator sent the dispute-opened-by-peer msg, causing an error as its mediators key not peers key. We need to check first for the message type and then apply the check. --- .../core/trade/protocol/TradeProtocol.java | 87 +++++++++---------- 1 file changed, 43 insertions(+), 44 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index cacb643f69d..f27fa0804af 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -98,19 +98,19 @@ protected void onMailboxMessage(TradeMessage message, NodeAddress peerNodeAddres @Override public void onDirectMessage(DecryptedMessageWithPubKey message, NodeAddress peer) { - if (isPubKeyValid(message)) { - NetworkEnvelope networkEnvelope = message.getNetworkEnvelope(); - if (networkEnvelope instanceof TradeMessage && isMyTradeMessage((TradeMessage) networkEnvelope)) { - onTradeMessage((TradeMessage) networkEnvelope, peer); - } else if (networkEnvelope instanceof AckMessage) { - AckMessage ackMessage = (AckMessage) networkEnvelope; - if (ackMessage.getSourceType() == AckMessageSourceType.TRADE_MESSAGE) { - onAckMessage((AckMessage) networkEnvelope, peer); - } - } + NetworkEnvelope networkEnvelope = message.getNetworkEnvelope(); + if (networkEnvelope instanceof TradeMessage && + isMyMessage((TradeMessage) networkEnvelope) && + isPubKeyValid(message)) { + onTradeMessage((TradeMessage) networkEnvelope, peer); + } else if (networkEnvelope instanceof AckMessage && + isMyMessage((AckMessage) networkEnvelope) && + isPubKeyValid(message)) { + onAckMessage((AckMessage) networkEnvelope, peer); } } + /////////////////////////////////////////////////////////////////////////////////////////// // DecryptedMailboxListener /////////////////////////////////////////////////////////////////////////////////////////// @@ -128,17 +128,14 @@ private void handleDecryptedMessageWithPubKey(DecryptedMessageWithPubKey decrypt protected void handleDecryptedMessageWithPubKey(DecryptedMessageWithPubKey decryptedMessageWithPubKey, NodeAddress peer) { - if (!isPubKeyValid(decryptedMessageWithPubKey)) { - return; - } - NetworkEnvelope networkEnvelope = decryptedMessageWithPubKey.getNetworkEnvelope(); - if (networkEnvelope instanceof TradeMessage) { + if (networkEnvelope instanceof TradeMessage && + isMyMessage((TradeMessage) networkEnvelope) && + isPubKeyValid(decryptedMessageWithPubKey)) { TradeMessage tradeMessage = (TradeMessage) networkEnvelope; - if (!isMyTradeMessage(tradeMessage)) { - return; - } + // We only remove here if we have already completed the trade. + // Otherwise removal is done after successfully applied the task runner. if (trade.isWithdrawn()) { processModel.getP2PService().removeEntryFromMailbox(decryptedMessageWithPubKey); log.info("Remove {} from the P2P network.", tradeMessage.getClass().getSimpleName()); @@ -146,16 +143,16 @@ protected void handleDecryptedMessageWithPubKey(DecryptedMessageWithPubKey decry } onMailboxMessage(tradeMessage, peer); - } else if (networkEnvelope instanceof AckMessage) { - AckMessage ackMessage = (AckMessage) networkEnvelope; - if (ackMessage.getSourceType() == AckMessageSourceType.TRADE_MESSAGE && - ackMessage.getSourceId().equals(trade.getId())) { - if (!trade.isWithdrawn()) { - onAckMessage((AckMessage) networkEnvelope, peer); - } - processModel.getP2PService().removeEntryFromMailbox(decryptedMessageWithPubKey); - log.info("Remove {} from the P2P network.", ackMessage.getClass().getSimpleName()); + } else if (networkEnvelope instanceof AckMessage && + isMyMessage((AckMessage) networkEnvelope) && + isPubKeyValid(decryptedMessageWithPubKey)) { + if (!trade.isWithdrawn()) { + // We only apply the msg if we have not already completed the trade + onAckMessage((AckMessage) networkEnvelope, peer); } + // In any case we remove the msg + processModel.getP2PService().removeEntryFromMailbox(decryptedMessageWithPubKey); + log.info("Remove {} from the P2P network.", networkEnvelope.getClass().getSimpleName()); } } @@ -223,23 +220,20 @@ public final FluentProtocol.Setup tasks(Class>... tasks) { /////////////////////////////////////////////////////////////////////////////////////////// private void onAckMessage(AckMessage ackMessage, NodeAddress peer) { - if (ackMessage.getSourceType() == AckMessageSourceType.TRADE_MESSAGE && - ackMessage.getSourceId().equals(trade.getId())) { - // We handle the ack for CounterCurrencyTransferStartedMessage and DepositTxAndDelayedPayoutTxMessage - // as we support automatic re-send of the msg in case it was not ACKed after a certain time - if (ackMessage.getSourceMsgClassName().equals(CounterCurrencyTransferStartedMessage.class.getSimpleName())) { - processModel.setPaymentStartedAckMessage(ackMessage); - } else if (ackMessage.getSourceMsgClassName().equals(DepositTxAndDelayedPayoutTxMessage.class.getSimpleName())) { - processModel.setDepositTxSentAckMessage(ackMessage); - } + // We handle the ack for CounterCurrencyTransferStartedMessage and DepositTxAndDelayedPayoutTxMessage + // as we support automatic re-send of the msg in case it was not ACKed after a certain time + if (ackMessage.getSourceMsgClassName().equals(CounterCurrencyTransferStartedMessage.class.getSimpleName())) { + processModel.setPaymentStartedAckMessage(ackMessage); + } else if (ackMessage.getSourceMsgClassName().equals(DepositTxAndDelayedPayoutTxMessage.class.getSimpleName())) { + processModel.setDepositTxSentAckMessage(ackMessage); + } - if (ackMessage.isSuccess()) { - log.info("Received AckMessage for {} from {} with tradeId {} and uid {}", - ackMessage.getSourceMsgClassName(), peer, trade.getId(), ackMessage.getSourceUid()); - } else { - log.warn("Received AckMessage with error state for {} from {} with tradeId {} and errorMessage={}", - ackMessage.getSourceMsgClassName(), peer, trade.getId(), ackMessage.getErrorMessage()); - } + if (ackMessage.isSuccess()) { + log.info("Received AckMessage for {} from {} with tradeId {} and uid {}", + ackMessage.getSourceMsgClassName(), peer, trade.getId(), ackMessage.getSourceUid()); + } else { + log.warn("Received AckMessage with error state for {} from {} with tradeId {} and errorMessage={}", + ackMessage.getSourceMsgClassName(), peer, trade.getId(), ackMessage.getErrorMessage()); } } @@ -380,10 +374,15 @@ void handleTaskRunnerFault(@Nullable TradeMessage message, String source, String cleanup(); } - private boolean isMyTradeMessage(TradeMessage message) { + private boolean isMyMessage(TradeMessage message) { return message.getTradeId().equals(trade.getId()); } + private boolean isMyMessage(AckMessage ackMessage) { + return ackMessage.getSourceType() == AckMessageSourceType.TRADE_MESSAGE && + ackMessage.getSourceId().equals(trade.getId()); + } + private void cleanup() { stopTimeout(); // We do not remove the decryptedDirectMessageListener as in case of not critical failures we want allow to receive From 0af9e133a4c1db65e06ad0307c9037e3449dcbd7 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Thu, 1 Oct 2020 09:42:33 -0500 Subject: [PATCH 141/143] Cleanups --- common/src/main/java/bisq/common/proto/ProtoUtil.java | 1 - core/src/main/java/bisq/core/app/BisqSetup.java | 1 - core/src/main/java/bisq/core/btc/model/AddressEntryList.java | 3 +-- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/common/src/main/java/bisq/common/proto/ProtoUtil.java b/common/src/main/java/bisq/common/proto/ProtoUtil.java index f734526534e..e8471a4d823 100644 --- a/common/src/main/java/bisq/common/proto/ProtoUtil.java +++ b/common/src/main/java/bisq/common/proto/ProtoUtil.java @@ -72,7 +72,6 @@ public static > E enumFromProto(Class enumType, String name String enumName = name != null ? name : "UNDEFINED"; E result = Enums.getIfPresent(enumType, enumName).orNull(); if (result == null) { - log.debug("Invalid value for enum " + enumType.getSimpleName() + ": " + enumName); result = Enums.getIfPresent(enumType, "UNDEFINED").orNull(); log.debug("We try to lookup for an enum entry with name 'UNDEFINED' and use that if available, " + "otherwise the enum is null. enum={}", result); diff --git a/core/src/main/java/bisq/core/app/BisqSetup.java b/core/src/main/java/bisq/core/app/BisqSetup.java index 6901eec8faf..53464237dea 100644 --- a/core/src/main/java/bisq/core/app/BisqSetup.java +++ b/core/src/main/java/bisq/core/app/BisqSetup.java @@ -789,7 +789,6 @@ private void initDomainServices() { } }); - arbitratorManager.onAllServicesInitialized(); mediatorManager.onAllServicesInitialized(); refundAgentManager.onAllServicesInitialized(); diff --git a/core/src/main/java/bisq/core/btc/model/AddressEntryList.java b/core/src/main/java/bisq/core/btc/model/AddressEntryList.java index c25e2e1a8ba..d6741af0f57 100644 --- a/core/src/main/java/bisq/core/btc/model/AddressEntryList.java +++ b/core/src/main/java/bisq/core/btc/model/AddressEntryList.java @@ -111,8 +111,7 @@ public void onWalletReady(Wallet wallet) { addressEntry.getPubKeyHash(), Script.ScriptType.P2PKH); if (keyFromPubHash != null) { - Address addressFromKey = LegacyAddress.fromKey(Config.baseCurrencyNetworkParameters(), - keyFromPubHash); + Address addressFromKey = LegacyAddress.fromKey(Config.baseCurrencyNetworkParameters(), keyFromPubHash); // We want to ensure key and address matches in case we have address in entry available already if (addressEntry.getAddress() == null || addressFromKey.equals(addressEntry.getAddress())) { addressEntry.setDeterministicKey(keyFromPubHash); From 8a3cacd867f7ca8d9a5b1bc42d3afc9bff961f5c Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Thu, 1 Oct 2020 09:45:19 -0500 Subject: [PATCH 142/143] Revert renaming from InputsForDepositTxRequest to TakeOfferRequest Prefer to keep it in sync with protobuf entry. --- .../network/CoreNetworkProtoResolver.java | 4 +- .../java/bisq/core/trade/TradeManager.java | 32 +++++----- ...st.java => InputsForDepositTxRequest.java} | 62 +++++++++---------- .../trade/protocol/BuyerAsMakerProtocol.java | 4 +- .../core/trade/protocol/MakerProtocol.java | 4 +- .../trade/protocol/SellerAsMakerProtocol.java | 4 +- ...kerProcessesInputsForDepositTxRequest.java | 4 +- .../TakerSendInputsForDepositTxRequest.java | 4 +- 8 files changed, 59 insertions(+), 59 deletions(-) rename core/src/main/java/bisq/core/trade/messages/{TakeOfferRequest.java => InputsForDepositTxRequest.java} (83%) diff --git a/core/src/main/java/bisq/core/proto/network/CoreNetworkProtoResolver.java b/core/src/main/java/bisq/core/proto/network/CoreNetworkProtoResolver.java index 0439786d0a6..8d57a75c14b 100644 --- a/core/src/main/java/bisq/core/proto/network/CoreNetworkProtoResolver.java +++ b/core/src/main/java/bisq/core/proto/network/CoreNetworkProtoResolver.java @@ -51,13 +51,13 @@ import bisq.core.trade.messages.DelayedPayoutTxSignatureResponse; import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage; import bisq.core.trade.messages.DepositTxMessage; +import bisq.core.trade.messages.InputsForDepositTxRequest; import bisq.core.trade.messages.InputsForDepositTxResponse; import bisq.core.trade.messages.MediatedPayoutTxPublishedMessage; import bisq.core.trade.messages.MediatedPayoutTxSignatureMessage; import bisq.core.trade.messages.PayoutTxPublishedMessage; import bisq.core.trade.messages.PeerPublishedDelayedPayoutTxMessage; import bisq.core.trade.messages.RefreshTradeStateRequest; -import bisq.core.trade.messages.TakeOfferRequest; import bisq.core.trade.messages.TraderSignedWitnessMessage; import bisq.core.trade.statistics.TradeStatistics; @@ -147,7 +147,7 @@ public NetworkEnvelope fromProto(protobuf.NetworkEnvelope proto) throws Protobuf case REFRESH_TRADE_STATE_REQUEST: return RefreshTradeStateRequest.fromProto(proto.getRefreshTradeStateRequest(), messageVersion); case INPUTS_FOR_DEPOSIT_TX_REQUEST: - return TakeOfferRequest.fromProto(proto.getInputsForDepositTxRequest(), this, messageVersion); + return InputsForDepositTxRequest.fromProto(proto.getInputsForDepositTxRequest(), this, messageVersion); case INPUTS_FOR_DEPOSIT_TX_RESPONSE: return InputsForDepositTxResponse.fromProto(proto.getInputsForDepositTxResponse(), this, messageVersion); case DEPOSIT_TX_MESSAGE: diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 0bc90e701e7..58bba982cfb 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -33,7 +33,7 @@ import bisq.core.trade.closed.ClosedTradableManager; import bisq.core.trade.failed.FailedTradesManager; import bisq.core.trade.handlers.TradeResultHandler; -import bisq.core.trade.messages.TakeOfferRequest; +import bisq.core.trade.messages.InputsForDepositTxRequest; import bisq.core.trade.protocol.MakerProtocol; import bisq.core.trade.protocol.ProcessModel; import bisq.core.trade.protocol.ProcessModelServiceProvider; @@ -210,24 +210,24 @@ public void readPersisted() { @Override public void onDirectMessage(DecryptedMessageWithPubKey message, NodeAddress peer) { NetworkEnvelope networkEnvelope = message.getNetworkEnvelope(); - if (networkEnvelope instanceof TakeOfferRequest) { - handleTakeOfferRequest(peer, (TakeOfferRequest) networkEnvelope); + if (networkEnvelope instanceof InputsForDepositTxRequest) { + handleTakeOfferRequest(peer, (InputsForDepositTxRequest) networkEnvelope); } } // The maker received a TakeOfferRequest - private void handleTakeOfferRequest(NodeAddress peer, TakeOfferRequest takeOfferRequest) { - log.info("Received TakeOfferRequest from {} with tradeId {} and uid {}", - peer, takeOfferRequest.getTradeId(), takeOfferRequest.getUid()); + private void handleTakeOfferRequest(NodeAddress peer, InputsForDepositTxRequest inputsForDepositTxRequest) { + log.info("Received inputsForDepositTxRequest from {} with tradeId {} and uid {}", + peer, inputsForDepositTxRequest.getTradeId(), inputsForDepositTxRequest.getUid()); try { - Validator.nonEmptyStringOf(takeOfferRequest.getTradeId()); + Validator.nonEmptyStringOf(inputsForDepositTxRequest.getTradeId()); } catch (Throwable t) { - log.warn("Invalid TakeOfferRequest " + takeOfferRequest.toString()); + log.warn("Invalid inputsForDepositTxRequest " + inputsForDepositTxRequest.toString()); return; } - Optional openOfferOptional = openOfferManager.getOpenOfferById(takeOfferRequest.getTradeId()); + Optional openOfferOptional = openOfferManager.getOpenOfferById(inputsForDepositTxRequest.getTradeId()); if (!openOfferOptional.isPresent()) { return; } @@ -242,9 +242,9 @@ private void handleTakeOfferRequest(NodeAddress peer, TakeOfferRequest takeOffer Trade trade; if (offer.isBuyOffer()) { trade = new BuyerAsMakerTrade(offer, - Coin.valueOf(takeOfferRequest.getTxFee()), - Coin.valueOf(takeOfferRequest.getTakerFee()), - takeOfferRequest.isCurrencyForTakerFeeBtc(), + Coin.valueOf(inputsForDepositTxRequest.getTxFee()), + Coin.valueOf(inputsForDepositTxRequest.getTakerFee()), + inputsForDepositTxRequest.isCurrencyForTakerFeeBtc(), openOffer.getArbitratorNodeAddress(), openOffer.getMediatorNodeAddress(), openOffer.getRefundAgentNodeAddress(), @@ -253,9 +253,9 @@ private void handleTakeOfferRequest(NodeAddress peer, TakeOfferRequest takeOffer getNewProcessModel(offer)); } else { trade = new SellerAsMakerTrade(offer, - Coin.valueOf(takeOfferRequest.getTxFee()), - Coin.valueOf(takeOfferRequest.getTakerFee()), - takeOfferRequest.isCurrencyForTakerFeeBtc(), + Coin.valueOf(inputsForDepositTxRequest.getTxFee()), + Coin.valueOf(inputsForDepositTxRequest.getTakerFee()), + inputsForDepositTxRequest.isCurrencyForTakerFeeBtc(), openOffer.getArbitratorNodeAddress(), openOffer.getMediatorNodeAddress(), openOffer.getRefundAgentNodeAddress(), @@ -268,7 +268,7 @@ private void handleTakeOfferRequest(NodeAddress peer, TakeOfferRequest takeOffer tradableList.add(trade); initTradeAndProtocol(trade, tradeProtocol); - ((MakerProtocol) tradeProtocol).handleTakeOfferRequest(takeOfferRequest, peer, errorMessage -> { + ((MakerProtocol) tradeProtocol).handleTakeOfferRequest(inputsForDepositTxRequest, peer, errorMessage -> { if (takeOfferRequestErrorMessageHandler != null) takeOfferRequestErrorMessageHandler.handleErrorMessage(errorMessage); }); diff --git a/core/src/main/java/bisq/core/trade/messages/TakeOfferRequest.java b/core/src/main/java/bisq/core/trade/messages/InputsForDepositTxRequest.java similarity index 83% rename from core/src/main/java/bisq/core/trade/messages/TakeOfferRequest.java rename to core/src/main/java/bisq/core/trade/messages/InputsForDepositTxRequest.java index dc7c09caae7..a67a879e3db 100644 --- a/core/src/main/java/bisq/core/trade/messages/TakeOfferRequest.java +++ b/core/src/main/java/bisq/core/trade/messages/InputsForDepositTxRequest.java @@ -41,7 +41,7 @@ @EqualsAndHashCode(callSuper = true) @Value -public final class TakeOfferRequest extends TradeMessage implements DirectMessage { +public final class InputsForDepositTxRequest extends TradeMessage implements DirectMessage { private final NodeAddress senderNodeAddress; private final long tradeAmount; private final long tradePrice; @@ -69,32 +69,32 @@ public final class TakeOfferRequest extends TradeMessage implements DirectMessag private final byte[] accountAgeWitnessSignatureOfOfferId; private final long currentDate; - public TakeOfferRequest(String tradeId, - NodeAddress senderNodeAddress, - long tradeAmount, - long tradePrice, - long txFee, - long takerFee, - boolean isCurrencyForTakerFeeBtc, - List rawTransactionInputs, - long changeOutputValue, - @Nullable String changeOutputAddress, - byte[] takerMultiSigPubKey, - String takerPayoutAddressString, - PubKeyRing takerPubKeyRing, - PaymentAccountPayload takerPaymentAccountPayload, - String takerAccountId, - String takerFeeTxId, - List acceptedArbitratorNodeAddresses, - List acceptedMediatorNodeAddresses, - List acceptedRefundAgentNodeAddresses, - @Nullable NodeAddress arbitratorNodeAddress, - NodeAddress mediatorNodeAddress, - NodeAddress refundAgentNodeAddress, - String uid, - int messageVersion, - byte[] accountAgeWitnessSignatureOfOfferId, - long currentDate) { + public InputsForDepositTxRequest(String tradeId, + NodeAddress senderNodeAddress, + long tradeAmount, + long tradePrice, + long txFee, + long takerFee, + boolean isCurrencyForTakerFeeBtc, + List rawTransactionInputs, + long changeOutputValue, + @Nullable String changeOutputAddress, + byte[] takerMultiSigPubKey, + String takerPayoutAddressString, + PubKeyRing takerPubKeyRing, + PaymentAccountPayload takerPaymentAccountPayload, + String takerAccountId, + String takerFeeTxId, + List acceptedArbitratorNodeAddresses, + List acceptedMediatorNodeAddresses, + List acceptedRefundAgentNodeAddresses, + @Nullable NodeAddress arbitratorNodeAddress, + NodeAddress mediatorNodeAddress, + NodeAddress refundAgentNodeAddress, + String uid, + int messageVersion, + byte[] accountAgeWitnessSignatureOfOfferId, + long currentDate) { super(messageVersion, tradeId, uid); this.senderNodeAddress = senderNodeAddress; this.tradeAmount = tradeAmount; @@ -162,9 +162,9 @@ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() { return getNetworkEnvelopeBuilder().setInputsForDepositTxRequest(builder).build(); } - public static TakeOfferRequest fromProto(protobuf.InputsForDepositTxRequest proto, - CoreProtoResolver coreProtoResolver, - int messageVersion) { + public static InputsForDepositTxRequest fromProto(protobuf.InputsForDepositTxRequest proto, + CoreProtoResolver coreProtoResolver, + int messageVersion) { List rawTransactionInputs = proto.getRawTransactionInputsList().stream() .map(rawTransactionInput -> new RawTransactionInput(rawTransactionInput.getIndex(), rawTransactionInput.getParentTransaction().toByteArray(), rawTransactionInput.getValue())) @@ -176,7 +176,7 @@ public static TakeOfferRequest fromProto(protobuf.InputsForDepositTxRequest prot List acceptedRefundAgentNodeAddresses = proto.getAcceptedRefundAgentNodeAddressesList().stream() .map(NodeAddress::fromProto).collect(Collectors.toList()); - return new TakeOfferRequest(proto.getTradeId(), + return new InputsForDepositTxRequest(proto.getTradeId(), NodeAddress.fromProto(proto.getSenderNodeAddress()), proto.getTradeAmount(), proto.getTradePrice(), diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index 269d4856f37..5e1c7cafff7 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -21,8 +21,8 @@ import bisq.core.trade.Trade; import bisq.core.trade.messages.DelayedPayoutTxSignatureRequest; import bisq.core.trade.messages.DepositTxAndDelayedPayoutTxMessage; +import bisq.core.trade.messages.InputsForDepositTxRequest; import bisq.core.trade.messages.PayoutTxPublishedMessage; -import bisq.core.trade.messages.TakeOfferRequest; import bisq.core.trade.protocol.tasks.ApplyFilter; import bisq.core.trade.protocol.tasks.TradeTask; import bisq.core.trade.protocol.tasks.VerifyPeersAccountAgeWitness; @@ -63,7 +63,7 @@ public BuyerAsMakerProtocol(BuyerAsMakerTrade trade) { /////////////////////////////////////////////////////////////////////////////////////////// @Override - public void handleTakeOfferRequest(TakeOfferRequest message, + public void handleTakeOfferRequest(InputsForDepositTxRequest message, NodeAddress peer, ErrorMessageHandler errorMessageHandler) { expect(phase(Trade.Phase.INIT) diff --git a/core/src/main/java/bisq/core/trade/protocol/MakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/MakerProtocol.java index fc1e8b04c52..349e677a702 100644 --- a/core/src/main/java/bisq/core/trade/protocol/MakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/MakerProtocol.java @@ -18,14 +18,14 @@ package bisq.core.trade.protocol; -import bisq.core.trade.messages.TakeOfferRequest; +import bisq.core.trade.messages.InputsForDepositTxRequest; import bisq.network.p2p.NodeAddress; import bisq.common.handlers.ErrorMessageHandler; public interface MakerProtocol { - void handleTakeOfferRequest(TakeOfferRequest message, + void handleTakeOfferRequest(InputsForDepositTxRequest message, NodeAddress taker, ErrorMessageHandler errorMessageHandler); } diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index 3eb21842eda..c8b62f6b488 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -23,7 +23,7 @@ import bisq.core.trade.messages.CounterCurrencyTransferStartedMessage; import bisq.core.trade.messages.DelayedPayoutTxSignatureResponse; import bisq.core.trade.messages.DepositTxMessage; -import bisq.core.trade.messages.TakeOfferRequest; +import bisq.core.trade.messages.InputsForDepositTxRequest; import bisq.core.trade.messages.TradeMessage; import bisq.core.trade.protocol.tasks.ApplyFilter; import bisq.core.trade.protocol.tasks.TradeTask; @@ -64,7 +64,7 @@ public SellerAsMakerProtocol(SellerAsMakerTrade trade) { /////////////////////////////////////////////////////////////////////////////////////////// @Override - public void handleTakeOfferRequest(TakeOfferRequest message, + public void handleTakeOfferRequest(InputsForDepositTxRequest message, NodeAddress peer, ErrorMessageHandler errorMessageHandler) { expect(phase(Trade.Phase.INIT) diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java index b85390f271a..1c7f4be239b 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/maker/MakerProcessesInputsForDepositTxRequest.java @@ -21,7 +21,7 @@ import bisq.core.offer.Offer; import bisq.core.support.dispute.mediation.mediator.Mediator; import bisq.core.trade.Trade; -import bisq.core.trade.messages.TakeOfferRequest; +import bisq.core.trade.messages.InputsForDepositTxRequest; import bisq.core.trade.protocol.TradingPeer; import bisq.core.trade.protocol.tasks.TradeTask; import bisq.core.user.User; @@ -51,7 +51,7 @@ public MakerProcessesInputsForDepositTxRequest(TaskRunner taskHandler, Tr protected void run() { try { runInterceptHook(); - TakeOfferRequest request = (TakeOfferRequest) processModel.getTradeMessage(); + InputsForDepositTxRequest request = (InputsForDepositTxRequest) processModel.getTradeMessage(); checkNotNull(request); checkTradeId(processModel.getOfferId(), request); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java index 5d6a58bdc13..1170e18074d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/taker/TakerSendInputsForDepositTxRequest.java @@ -21,7 +21,7 @@ import bisq.core.btc.wallet.BtcWalletService; import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.trade.Trade; -import bisq.core.trade.messages.TakeOfferRequest; +import bisq.core.trade.messages.InputsForDepositTxRequest; import bisq.core.trade.protocol.tasks.TradeTask; import bisq.core.user.User; @@ -99,7 +99,7 @@ protected void run() { byte[] signatureOfNonce = Sig.sign(processModel.getKeyRing().getSignatureKeyPair().getPrivate(), offerId.getBytes(Charsets.UTF_8)); - TakeOfferRequest request = new TakeOfferRequest( + InputsForDepositTxRequest request = new InputsForDepositTxRequest( offerId, processModel.getMyNodeAddress(), tradeAmount.value, From 9fce06832d25fed88180658e837539ec61e26fb0 Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Thu, 1 Oct 2020 09:46:11 -0500 Subject: [PATCH 143/143] Rename baseCurrencyNetworkParameters to networkParameters --- common/src/main/java/bisq/common/config/Config.java | 4 ++-- core/src/main/java/bisq/core/app/CoreModule.java | 2 +- core/src/main/java/bisq/core/btc/nodes/LocalBitcoinNode.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/bisq/common/config/Config.java b/common/src/main/java/bisq/common/config/Config.java index 2659853f2ce..08445a746e9 100644 --- a/common/src/main/java/bisq/common/config/Config.java +++ b/common/src/main/java/bisq/common/config/Config.java @@ -154,7 +154,7 @@ public class Config { public final List bannedPriceRelayNodes; public final List bannedSeedNodes; public final BaseCurrencyNetwork baseCurrencyNetwork; - public final NetworkParameters baseCurrencyNetworkParameters; + public final NetworkParameters networkParameters; public final boolean ignoreLocalBtcNode; public final String bitcoinRegtestHost; public final boolean daoActivated; @@ -702,7 +702,7 @@ public Config(String defaultAppName, File defaultUserDataDir, String... args) { this.bannedPriceRelayNodes = options.valuesOf(bannedPriceRelayNodesOpt); this.bannedSeedNodes = options.valuesOf(bannedSeedNodesOpt); this.baseCurrencyNetwork = (BaseCurrencyNetwork) options.valueOf(baseCurrencyNetworkOpt); - this.baseCurrencyNetworkParameters = baseCurrencyNetwork.getParameters(); + this.networkParameters = baseCurrencyNetwork.getParameters(); this.ignoreLocalBtcNode = options.valueOf(ignoreLocalBtcNodeOpt); this.bitcoinRegtestHost = options.valueOf(bitcoinRegtestHostOpt); this.torrcFile = options.has(torrcFileOpt) ? options.valueOf(torrcFileOpt).toFile() : null; diff --git a/core/src/main/java/bisq/core/app/CoreModule.java b/core/src/main/java/bisq/core/app/CoreModule.java index e207ae033bf..8f300705323 100644 --- a/core/src/main/java/bisq/core/app/CoreModule.java +++ b/core/src/main/java/bisq/core/app/CoreModule.java @@ -65,7 +65,7 @@ protected void configure() { bind(File.class).annotatedWith(named(STORAGE_DIR)).toInstance(config.storageDir); - CoinFormatter btcFormatter = new ImmutableCoinFormatter(config.baseCurrencyNetworkParameters.getMonetaryFormat()); + CoinFormatter btcFormatter = new ImmutableCoinFormatter(config.networkParameters.getMonetaryFormat()); bind(CoinFormatter.class).annotatedWith(named(FormattingUtils.BTC_FORMATTER_KEY)).toInstance(btcFormatter); bind(File.class).annotatedWith(named(KEY_STORAGE_DIR)).toInstance(config.keyStorageDir); diff --git a/core/src/main/java/bisq/core/btc/nodes/LocalBitcoinNode.java b/core/src/main/java/bisq/core/btc/nodes/LocalBitcoinNode.java index 7c4e955dd4e..358de89a124 100644 --- a/core/src/main/java/bisq/core/btc/nodes/LocalBitcoinNode.java +++ b/core/src/main/java/bisq/core/btc/nodes/LocalBitcoinNode.java @@ -6,9 +6,9 @@ import javax.inject.Inject; import javax.inject.Singleton; -import java.net.Socket; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.Socket; import java.io.IOException; @@ -34,7 +34,7 @@ public class LocalBitcoinNode { @Inject public LocalBitcoinNode(Config config) { this.config = config; - this.port = config.baseCurrencyNetworkParameters.getPort(); + this.port = config.networkParameters.getPort(); } /**