From b237513c16b09924d4ac880e7ec09e3f98b66ba2 Mon Sep 17 00:00:00 2001 From: woodser Date: Wed, 17 Jan 2024 20:31:42 -0500 Subject: [PATCH 1/4] fixes for local monerod --- core/src/main/java/haveno/core/api/XmrConnectionService.java | 4 +--- core/src/main/java/haveno/core/api/XmrLocalNode.java | 2 ++ core/src/main/java/haveno/core/xmr/XmrNodeSettings.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/haveno/core/api/XmrConnectionService.java b/core/src/main/java/haveno/core/api/XmrConnectionService.java index 0cc66c7475d..5b48c41a0eb 100644 --- a/core/src/main/java/haveno/core/api/XmrConnectionService.java +++ b/core/src/main/java/haveno/core/api/XmrConnectionService.java @@ -3,7 +3,6 @@ import haveno.common.ThreadUtils; import haveno.common.UserThread; import haveno.common.app.DevEnv; -import haveno.common.config.BaseCurrencyNetwork; import haveno.common.config.Config; import haveno.core.trade.HavenoUtils; import haveno.core.user.Preferences; @@ -612,8 +611,7 @@ private void pollDaemonInfo() { chainHeight.set(lastInfo.getHeight()); // update sync progress - boolean isTestnet = Config.baseCurrencyNetwork() == BaseCurrencyNetwork.XMR_LOCAL; - if (lastInfo.isSynchronized() || isTestnet) doneDownload(); // TODO: skipping synchronized check for testnet because tests cannot sync 3rd local node, see "Can manage Monero daemon connections" + if (lastInfo.isSynchronized()) doneDownload(); else if (lastInfo.isBusySyncing()) { long targetHeight = lastInfo.getTargetHeight(); long blocksLeft = targetHeight - lastInfo.getHeight(); diff --git a/core/src/main/java/haveno/core/api/XmrLocalNode.java b/core/src/main/java/haveno/core/api/XmrLocalNode.java index c927ae3f50e..799427ea630 100644 --- a/core/src/main/java/haveno/core/api/XmrLocalNode.java +++ b/core/src/main/java/haveno/core/api/XmrLocalNode.java @@ -61,6 +61,8 @@ public class XmrLocalNode { MONEROD_ARGS.add(MONEROD_PATH); MONEROD_ARGS.add("--no-igd"); MONEROD_ARGS.add("--hide-my-port"); + MONEROD_ARGS.add("--p2p-bind-ip"); + MONEROD_ARGS.add(HavenoUtils.LOOPBACK_HOST); if (!Config.baseCurrencyNetwork().isMainnet()) MONEROD_ARGS.add("--" + Config.baseCurrencyNetwork().getNetwork().toLowerCase()); } diff --git a/core/src/main/java/haveno/core/xmr/XmrNodeSettings.java b/core/src/main/java/haveno/core/xmr/XmrNodeSettings.java index 8be7a575fdc..14a58104cea 100644 --- a/core/src/main/java/haveno/core/xmr/XmrNodeSettings.java +++ b/core/src/main/java/haveno/core/xmr/XmrNodeSettings.java @@ -50,7 +50,7 @@ public static XmrNodeSettings fromProto(protobuf.XmrNodeSettings proto) { public protobuf.XmrNodeSettings toProtoMessage() { protobuf.XmrNodeSettings.Builder builder = protobuf.XmrNodeSettings.newBuilder(); Optional.ofNullable(blockchainPath).ifPresent(e -> builder.setBlockchainPath(blockchainPath)); - Optional.ofNullable(bootstrapUrl).ifPresent(e -> builder.setBlockchainPath(bootstrapUrl)); + Optional.ofNullable(bootstrapUrl).ifPresent(e -> builder.setBootstrapUrl(bootstrapUrl)); Optional.ofNullable(startupFlags).ifPresent(e -> builder.addAllStartupFlags(startupFlags)); return builder.build(); } From caa92f6bdefd6c877d84c8bde5c1f2978b0a7a58 Mon Sep 17 00:00:00 2001 From: woodser Date: Wed, 17 Jan 2024 20:28:28 -0500 Subject: [PATCH 2/4] cancel pending price request on select new provider --- .../core/provider/price/PriceFeedService.java | 16 +++++++++------- .../java/haveno/network/http/HttpClient.java | 2 ++ .../haveno/network/http/HttpClientImpl.java | 18 ++++++++++++++++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/haveno/core/provider/price/PriceFeedService.java b/core/src/main/java/haveno/core/provider/price/PriceFeedService.java index 28cab49234e..eca0c8fb977 100644 --- a/core/src/main/java/haveno/core/provider/price/PriceFeedService.java +++ b/core/src/main/java/haveno/core/provider/price/PriceFeedService.java @@ -143,7 +143,7 @@ public void requestPrices() { public void awaitExternalPrices() { CountDownLatch latch = new CountDownLatch(1); ChangeListener listener = (observable, oldValue, newValue) -> { - if (hasExternalPrices()) latch.countDown(); + if (hasExternalPrices() && latch.getCount() != 0) latch.countDown(); }; updateCounter.addListener(listener); if (hasExternalPrices()) { @@ -277,12 +277,14 @@ private void retryWithNewProvider() { // returns true if provider selection loops back to beginning private boolean setNewPriceProvider() { + httpClient.cancelPendingRequest(); boolean looped = providersRepository.selectNextProviderBaseUrl(); - if (!providersRepository.getBaseUrl().isEmpty()) + if (!providersRepository.getBaseUrl().isEmpty()) { priceProvider = new PriceProvider(httpClient, providersRepository.getBaseUrl()); - else + } else { log.warn("We cannot create a new priceProvider because new base url is empty."); - return looped; + } + return looped; } @Nullable @@ -293,7 +295,7 @@ public MarketPrice getMarketPrice(String currencyCode) { } private void setHavenoMarketPrice(String currencyCode, Price price) { - UserThread.await(() -> { + UserThread.execute(() -> { synchronized (cache) { if (!cache.containsKey(currencyCode) || !cache.get(currencyCode).isExternallyProvidedPrice()) { cache.put(currencyCode, new MarketPrice(currencyCode, @@ -374,7 +376,7 @@ public void applyLatestHavenoMarketPrice(Set tradeStatisticsSe */ public synchronized Map requestAllPrices() throws ExecutionException, InterruptedException, TimeoutException, CancellationException { CountDownLatch latch = new CountDownLatch(1); - ChangeListener listener = (observable, oldValue, newValue) -> { latch.countDown(); }; + ChangeListener listener = (observable, oldValue, newValue) -> { if (latch.getCount() != 0) latch.countDown(); }; updateCounter.addListener(listener); requestAllPricesError = null; requestPrices(); @@ -442,7 +444,7 @@ private boolean applyPriceToConsumer() { faultHandler.handleFault(errorMessage, new PriceRequestException(errorMessage)); } - UserThread.await(() -> updateCounter.set(updateCounter.get() + 1)); + UserThread.execute(() -> updateCounter.set(updateCounter.get() + 1)); return result; } diff --git a/p2p/src/main/java/haveno/network/http/HttpClient.java b/p2p/src/main/java/haveno/network/http/HttpClient.java index 7027ddaefca..92add888362 100644 --- a/p2p/src/main/java/haveno/network/http/HttpClient.java +++ b/p2p/src/main/java/haveno/network/http/HttpClient.java @@ -39,5 +39,7 @@ String post(String param, boolean hasPendingRequest(); + void cancelPendingRequest(); + void shutDown(); } diff --git a/p2p/src/main/java/haveno/network/http/HttpClientImpl.java b/p2p/src/main/java/haveno/network/http/HttpClientImpl.java index 17185d60e1b..b28072efe6b 100644 --- a/p2p/src/main/java/haveno/network/http/HttpClientImpl.java +++ b/p2p/src/main/java/haveno/network/http/HttpClientImpl.java @@ -135,6 +135,24 @@ private String doRequest(String param, } } + public void cancelPendingRequest() { + if (!hasPendingRequest) return; + try { + if (connection != null) { + connection.getInputStream().close(); + connection.disconnect(); + connection = null; + } + if (closeableHttpClient != null) { + closeableHttpClient.close(); + closeableHttpClient = null; + } + } catch (IOException err) { + // igbnore + } + hasPendingRequest = false; + } + private String requestWithoutProxy(String baseUrl, String param, HttpMethod httpMethod, From b33c8cbc21907370f100fe46306e95fd468fcca7 Mon Sep 17 00:00:00 2001 From: woodser Date: Wed, 17 Jan 2024 20:36:24 -0500 Subject: [PATCH 3/4] shut down OpenOfferManager thread pool before completing shut down --- .../main/java/haveno/core/offer/OpenOfferManager.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/haveno/core/offer/OpenOfferManager.java b/core/src/main/java/haveno/core/offer/OpenOfferManager.java index 9cc40983390..030b06d810f 100644 --- a/core/src/main/java/haveno/core/offer/OpenOfferManager.java +++ b/core/src/main/java/haveno/core/offer/OpenOfferManager.java @@ -324,6 +324,7 @@ public void shutDown(@Nullable Runnable completeHandler) { // Force broadcaster to send out immediately, otherwise we could have a 2 sec delay until the // bundled messages sent out. broadcaster.flush(); + shutDownThreadPool(); if (completeHandler != null) { // For typical number of offers we are tolerant with delay to give enough time to broadcast. @@ -335,12 +336,18 @@ public void shutDown(@Nullable Runnable completeHandler) { }, THREAD_ID); } else { broadcaster.flush(); + shutDownThreadPool(); if (completeHandler != null) completeHandler.run(); } + } - // shut down pool - ThreadUtils.shutDown(THREAD_ID, SHUTDOWN_TIMEOUT_MS); + private void shutDownThreadPool() { + try { + ThreadUtils.shutDown(THREAD_ID, SHUTDOWN_TIMEOUT_MS); + } catch (Exception e) { + log.error("Error shutting down OpenOfferManager thread pool", e); + } } public void removeAllOpenOffers(@Nullable Runnable completeHandler) { From 2a982ae777427cd06925f204c9a99e63c0764b8b Mon Sep 17 00:00:00 2001 From: woodser Date: Wed, 17 Jan 2024 20:28:28 -0500 Subject: [PATCH 4/4] init offer address entry off user thread to prevent blocking --- .../main/offer/MutableOfferDataModel.java | 18 +++++++++--------- .../main/offer/MutableOfferViewModel.java | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java index 2c1e3a3b593..e81c13b2c0a 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java @@ -95,7 +95,6 @@ public abstract class MutableOfferDataModel extends OfferDataModel { private final CoinFormatter btcFormatter; private final Navigation navigation; private final String offerId; - private final XmrBalanceListener xmrBalanceListener; private final SetChangeListener paymentAccountsChangeListener; protected OfferDirection direction; @@ -128,6 +127,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel { protected long triggerPrice; @Getter protected boolean reserveExactAmount; + private XmrBalanceListener xmrBalanceListener; /////////////////////////////////////////////////////////////////////////////////////////// @@ -163,20 +163,12 @@ public MutableOfferDataModel(CreateOfferService createOfferService, offerId = OfferUtil.getRandomOfferId(); shortOfferId = Utilities.getShortId(offerId); - addressEntry = xmrWalletService.getOrCreateAddressEntry(offerId, XmrAddressEntry.Context.OFFER_FUNDING); reserveExactAmount = preferences.getSplitOfferOutput(); useMarketBasedPrice.set(preferences.isUsePercentageBasedPrice()); buyerSecurityDepositPct.set(Restrictions.getMinBuyerSecurityDepositAsPercent()); - xmrBalanceListener = new XmrBalanceListener(getAddressEntry().getSubaddressIndex()) { - @Override - public void onBalanceChanged(BigInteger balance) { - updateBalance(); - } - }; - paymentAccountsChangeListener = change -> fillPaymentAccounts(); } @@ -212,6 +204,14 @@ private void removeListeners() { // called before activate() public boolean initWithData(OfferDirection direction, TradeCurrency tradeCurrency) { + addressEntry = xmrWalletService.getOrCreateAddressEntry(offerId, XmrAddressEntry.Context.OFFER_FUNDING); + xmrBalanceListener = new XmrBalanceListener(getAddressEntry().getSubaddressIndex()) { + @Override + public void onBalanceChanged(BigInteger balance) { + updateBalance(); + } + }; + this.direction = direction; this.tradeCurrency = tradeCurrency; diff --git a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferViewModel.java b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferViewModel.java index 6e486c234c4..4d41777a240 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferViewModel.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferViewModel.java @@ -210,9 +210,6 @@ public MutableOfferViewModel(M dataModel, paymentLabel = Res.get("createOffer.fundsBox.paymentLabel", dataModel.shortOfferId); - if (dataModel.getAddressEntry() != null) { - addressAsString = dataModel.getAddressEntry().getAddressString(); - } createListeners(); } @@ -568,6 +565,9 @@ private void removeListeners() { boolean initWithData(OfferDirection direction, TradeCurrency tradeCurrency) { boolean result = dataModel.initWithData(direction, tradeCurrency); + if (dataModel.getAddressEntry() != null) { + addressAsString = dataModel.getAddressEntry().getAddressString(); + } if (dataModel.paymentAccount != null) xmrValidator.setMaxValue(dataModel.paymentAccount.getPaymentMethod().getMaxTradeLimit(dataModel.getTradeCurrencyCode().get())); xmrValidator.setMaxTradeLimit(BigInteger.valueOf(dataModel.getMaxTradeLimit()));