From fff0fa0186bf2dbf264b4af50d0eb2562514d1fa Mon Sep 17 00:00:00 2001 From: woodser <13068859+woodser@users.noreply.github.com> Date: Wed, 5 Mar 2025 08:20:24 -0500 Subject: [PATCH 1/4] add short name for paysafe --- core/src/main/resources/i18n/displayStrings.properties | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index d8111b7b9c..b499950537 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -3201,14 +3201,16 @@ DOMESTIC_WIRE_TRANSFER=Domestic Wire Transfer # suppress inspection "UnusedProperty" BSQ_SWAP=BSQ Swap -# Deprecated: Cannot be deleted as it would break old trade history entries # suppress inspection "UnusedProperty" OK_PAY=OKPay # suppress inspection "UnusedProperty" CASH_APP=Cash App # suppress inspection "UnusedProperty" VENMO=Venmo +# suppress inspection "UnusedProperty" PAYPAL=PayPal +# suppress inspection "UnusedProperty" +PAYSAFE=Paysafe # suppress inspection "UnusedProperty" UPHOLD_SHORT=Uphold @@ -3304,9 +3306,10 @@ OK_PAY_SHORT=OKPay CASH_APP_SHORT=Cash App # suppress inspection "UnusedProperty" VENMO_SHORT=Venmo +# suppress inspection "UnusedProperty" PAYPAL_SHORT=PayPal # suppress inspection "UnusedProperty" -PAYSAFE=Paysafe +PAYSAFE_SHORT=Paysafe #################################################################### From 5720ee74b041e1378740706e322046c5c6774299 Mon Sep 17 00:00:00 2001 From: woodser <13068859+woodser@users.noreply.github.com> Date: Wed, 5 Mar 2025 08:39:03 -0500 Subject: [PATCH 2/4] run trade charts view listeners on user thread to fix npe --- .../main/market/trades/TradesChartsView.java | 73 ++++++++++--------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/desktop/src/main/java/haveno/desktop/main/market/trades/TradesChartsView.java b/desktop/src/main/java/haveno/desktop/main/market/trades/TradesChartsView.java index dee3591bc8..97fcce06d1 100644 --- a/desktop/src/main/java/haveno/desktop/main/market/trades/TradesChartsView.java +++ b/desktop/src/main/java/haveno/desktop/main/market/trades/TradesChartsView.java @@ -208,29 +208,29 @@ public class TradesChartsView extends ActivatableViewAndModel { + timeUnitChangeListener = (observable, oldValue, newValue) -> UserThread.execute(() -> { if (newValue != null) { model.setTickUnit((TradesChartsViewModel.TickUnit) newValue.getUserData()); priceAxisX.setTickLabelFormatter(getTimeAxisStringConverter()); volumeAxisX.setTickLabelFormatter(getTimeAxisStringConverter()); volumeInUsdAxisX.setTickLabelFormatter(getTimeAxisStringConverter()); } - }; - priceAxisYWidthListener = (observable, oldValue, newValue) -> { + }); + priceAxisYWidthListener = (observable, oldValue, newValue) -> UserThread.execute(() -> { priceAxisYWidth = (double) newValue; layoutChart(); - }; - volumeAxisYWidthListener = (observable, oldValue, newValue) -> { + }); + volumeAxisYWidthListener = (observable, oldValue, newValue) -> UserThread.execute(() -> { volumeAxisYWidth = (double) newValue; layoutChart(); - }; - tradeStatisticsByCurrencyListener = c -> { + }); + tradeStatisticsByCurrencyListener = c -> UserThread.execute(() -> { nrOfTradeStatisticsLabel.setText(Res.get("market.trades.nrOfTrades", model.tradeStatisticsByCurrency.size())); fillList(); - }; - parentHeightListener = (observable, oldValue, newValue) -> layout(); + }); + parentHeightListener = (observable, oldValue, newValue) -> UserThread.execute(this::layout); - priceColumnLabelListener = (o, oldVal, newVal) -> priceColumn.setGraphic(new AutoTooltipLabel(newVal)); + priceColumnLabelListener = (o, oldVal, newVal) -> UserThread.execute(() -> priceColumn.setGraphic(new AutoTooltipLabel(newVal))); // Need to render on next frame as otherwise there are issues in the chart rendering itemsChangeListener = c -> UserThread.execute(this::updateChartData); @@ -238,31 +238,34 @@ public class TradesChartsView extends ActivatableViewAndModel { - priceChart.setVisible(!showAll); - priceChart.setManaged(!showAll); - priceColumn.setSortable(!showAll); + UserThread.execute(() -> { + priceChart.setVisible(!showAll); + priceChart.setManaged(!showAll); + priceColumn.setSortable(!showAll); - if (showAll) { - volumeColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.amount"))); - priceColumnLabel.set(Res.get("shared.price")); - if (!tableView.getColumns().contains(marketColumn)) - tableView.getColumns().add(1, marketColumn); + if (showAll) { + volumeColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.amount"))); + priceColumnLabel.set(Res.get("shared.price")); + if (!tableView.getColumns().contains(marketColumn)) + tableView.getColumns().add(1, marketColumn); + + volumeChart.setPrefHeight(volumeChart.getMaxHeight()); + volumeInUsdChart.setPrefHeight(volumeInUsdChart.getMaxHeight()); + } else { + volumeChart.setPrefHeight(volumeChart.getMinHeight()); + volumeInUsdChart.setPrefHeight(volumeInUsdChart.getMinHeight()); + priceSeries.setName(selectedTradeCurrency.getName()); + String code = selectedTradeCurrency.getCode(); + volumeColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.amountWithCur", code))); + + priceColumnLabel.set(CurrencyUtil.getPriceWithCurrencyCode(code)); + + tableView.getColumns().remove(marketColumn); + } + + layout(); + }); - volumeChart.setPrefHeight(volumeChart.getMaxHeight()); - volumeInUsdChart.setPrefHeight(volumeInUsdChart.getMaxHeight()); - } else { - volumeChart.setPrefHeight(volumeChart.getMinHeight()); - volumeInUsdChart.setPrefHeight(volumeInUsdChart.getMinHeight()); - priceSeries.setName(selectedTradeCurrency.getName()); - String code = selectedTradeCurrency.getCode(); - volumeColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.amountWithCur", code))); - - priceColumnLabel.set(CurrencyUtil.getPriceWithCurrencyCode(code)); - - tableView.getColumns().remove(marketColumn); - } - - layout(); return null; }); } @@ -286,14 +289,14 @@ public class TradesChartsView extends ActivatableViewAndModel { + currencyComboBox.setOnChangeConfirmed(e -> UserThread.execute(() -> { if (currencyComboBox.getEditor().getText().isEmpty()) currencyComboBox.getSelectionModel().select(SHOW_ALL); CurrencyListItem selectedItem = currencyComboBox.getSelectionModel().getSelectedItem(); if (selectedItem != null) { model.onSetTradeCurrency(selectedItem.tradeCurrency); } - }); + })); toggleGroup.getToggles().get(model.tickUnit.ordinal()).setSelected(true); From 580e5b672cc4b9238391294ba15a592d29d96f7c Mon Sep 17 00:00:00 2001 From: woodser <13068859+woodser@users.noreply.github.com> Date: Wed, 5 Mar 2025 08:39:31 -0500 Subject: [PATCH 3/4] add lock to submit tx to pool for verification and sync on shut down --- .../java/haveno/core/xmr/wallet/XmrWalletService.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java b/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java index 95669e9e0b..045897ed37 100644 --- a/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java +++ b/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java @@ -68,7 +68,6 @@ import java.util.stream.Stream; import javafx.beans.property.LongProperty; import javafx.beans.property.ReadOnlyDoubleProperty; import javafx.beans.value.ChangeListener; -import lombok.Getter; import monero.common.MoneroError; import monero.common.MoneroRpcConnection; import monero.common.MoneroRpcError; @@ -145,8 +144,7 @@ public class XmrWalletService extends XmrWalletBase { private TradeManager tradeManager; private ExecutorService syncWalletThreadPool = Executors.newFixedThreadPool(10); // TODO: adjust based on connection type - @Getter - public final Object lock = new Object(); + private final Object lock = new Object(); private TaskLooper pollLooper; private boolean pollInProgress; private Long pollPeriodMs; @@ -740,7 +738,7 @@ public class XmrWalletService extends XmrWalletBase { MoneroDaemonRpc daemon = getDaemon(); MoneroWallet wallet = getWallet(); MoneroTx tx = null; - synchronized (daemon) { + synchronized (lock) { try { // verify tx not submitted to pool @@ -926,7 +924,7 @@ public class XmrWalletService extends XmrWalletBase { } // shut down threads - synchronized (getLock()) { + synchronized (lock) { List shutDownThreads = new ArrayList<>(); shutDownThreads.add(() -> ThreadUtils.shutDown(THREAD_ID)); ThreadUtils.awaitTasks(shutDownThreads); From 52bf1edf79a3981f6ffb896a82d4fff1fde825fe Mon Sep 17 00:00:00 2001 From: woodser <13068859+woodser@users.noreply.github.com> Date: Wed, 5 Mar 2025 11:19:41 -0500 Subject: [PATCH 4/4] Revert "direct bind tor node uses configured socks5 proxy" (#1635) This reverts commit fc42f6314eb593b129ff0bb028c585ce677e0e6d. --- .../java/haveno/network/p2p/NetworkNodeProvider.java | 6 ++---- .../p2p/network/TorNetworkNodeDirectBind.java | 12 +++++------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/p2p/src/main/java/haveno/network/p2p/NetworkNodeProvider.java b/p2p/src/main/java/haveno/network/p2p/NetworkNodeProvider.java index fa1aa61470..798d162357 100644 --- a/p2p/src/main/java/haveno/network/p2p/NetworkNodeProvider.java +++ b/p2p/src/main/java/haveno/network/p2p/NetworkNodeProvider.java @@ -22,7 +22,6 @@ import com.google.inject.Provider; import com.google.inject.name.Named; import haveno.common.config.Config; import haveno.common.proto.network.NetworkProtoResolver; -import haveno.network.Socks5ProxyProvider; import haveno.network.p2p.network.BanFilter; import haveno.network.p2p.network.BridgeAddressProvider; import haveno.network.p2p.network.LocalhostNetworkNode; @@ -56,8 +55,7 @@ public class NetworkNodeProvider implements Provider { @Named(Config.TOR_CONTROL_PASSWORD) String password, @Nullable @Named(Config.TOR_CONTROL_COOKIE_FILE) File cookieFile, @Named(Config.TOR_STREAM_ISOLATION) boolean streamIsolation, - @Named(Config.TOR_CONTROL_USE_SAFE_COOKIE_AUTH) boolean useSafeCookieAuthentication, - Socks5ProxyProvider socks5ProxyProvider) { + @Named(Config.TOR_CONTROL_USE_SAFE_COOKIE_AUTH) boolean useSafeCookieAuthentication) { if (useLocalhostForP2P) { networkNode = new LocalhostNetworkNode(port, networkProtoResolver, banFilter, maxConnections); } else { @@ -74,7 +72,7 @@ public class NetworkNodeProvider implements Provider { if (torMode instanceof NewTor || torMode instanceof RunningTor) { networkNode = new TorNetworkNodeNetlayer(port, networkProtoResolver, torMode, banFilter, maxConnections, streamIsolation, controlHost); } else { - networkNode = new TorNetworkNodeDirectBind(port, networkProtoResolver, banFilter, maxConnections, hiddenServiceAddress, socks5ProxyProvider); + networkNode = new TorNetworkNodeDirectBind(port, networkProtoResolver, banFilter, maxConnections, hiddenServiceAddress); } } } diff --git a/p2p/src/main/java/haveno/network/p2p/network/TorNetworkNodeDirectBind.java b/p2p/src/main/java/haveno/network/p2p/network/TorNetworkNodeDirectBind.java index 6ccd5b1314..8333af3f8b 100644 --- a/p2p/src/main/java/haveno/network/p2p/network/TorNetworkNodeDirectBind.java +++ b/p2p/src/main/java/haveno/network/p2p/network/TorNetworkNodeDirectBind.java @@ -1,7 +1,6 @@ package haveno.network.p2p.network; import haveno.common.util.Hex; -import haveno.network.Socks5ProxyProvider; import haveno.network.p2p.NodeAddress; import haveno.common.UserThread; @@ -10,6 +9,7 @@ import haveno.common.proto.network.NetworkProtoResolver; import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy; import java.net.Socket; +import java.net.InetAddress; import java.net.ServerSocket; import java.io.IOException; @@ -25,18 +25,16 @@ import static com.google.common.base.Preconditions.checkArgument; @Slf4j public class TorNetworkNodeDirectBind extends TorNetworkNode { + private static final int TOR_DATA_PORT = 9050; // TODO: config option? private final String serviceAddress; - private final Socks5ProxyProvider socks5ProxyProvider; public TorNetworkNodeDirectBind(int servicePort, NetworkProtoResolver networkProtoResolver, @Nullable BanFilter banFilter, int maxConnections, - String hiddenServiceAddress, - Socks5ProxyProvider socks5ProxyProvider) { + String hiddenServiceAddress) { super(servicePort, networkProtoResolver, banFilter, maxConnections); this.serviceAddress = hiddenServiceAddress; - this.socks5ProxyProvider = socks5ProxyProvider; } @Override @@ -49,7 +47,7 @@ public class TorNetworkNodeDirectBind extends TorNetworkNode { @Override public Socks5Proxy getSocksProxy() { - Socks5Proxy proxy = new Socks5Proxy(socks5ProxyProvider.getSocks5Proxy().getInetAddress(), socks5ProxyProvider.getSocks5Proxy().getPort()); // TODO: can/should we return the same socks5 proxy directly? + Socks5Proxy proxy = new Socks5Proxy(InetAddress.getLoopbackAddress(), TOR_DATA_PORT); proxy.resolveAddrLocally(false); return proxy; } @@ -59,7 +57,7 @@ public class TorNetworkNodeDirectBind extends TorNetworkNode { // https://datatracker.ietf.org/doc/html/rfc1928 SOCKS5 Protocol try { checkArgument(peerNodeAddress.getHostName().endsWith(".onion"), "PeerAddress is not an onion address"); - Socket sock = new Socket(getSocksProxy().getInetAddress(), getSocksProxy().getPort()); + Socket sock = new Socket(InetAddress.getLoopbackAddress(), TOR_DATA_PORT); sock.getOutputStream().write(Hex.decode("050100")); String response = Hex.encode(sock.getInputStream().readNBytes(2)); if (!response.equalsIgnoreCase("0500")) {