From c9235299a8067a5986ed491c0a7d9176b4d2cd65 Mon Sep 17 00:00:00 2001 From: jmacxx <47253594+jmacxx@users.noreply.github.com> Date: Sun, 16 Jan 2022 11:38:14 -0600 Subject: [PATCH 1/2] Postpone accessing preferences BridgeAddressProvider until needed by Tor. Previously they would be accessed too early when preferences had not yet been read from disk. Now we access them when Tor is started. --- .../java/bisq/network/p2p/NetworkNodeProvider.java | 2 +- .../main/java/bisq/network/p2p/network/NewTor.java | 7 ++++--- .../network/p2p/network/TorNetworkNodeTest.java | 13 +++++++++---- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/p2p/src/main/java/bisq/network/p2p/NetworkNodeProvider.java b/p2p/src/main/java/bisq/network/p2p/NetworkNodeProvider.java index e8cf8d92385..03652b970f5 100644 --- a/p2p/src/main/java/bisq/network/p2p/NetworkNodeProvider.java +++ b/p2p/src/main/java/bisq/network/p2p/NetworkNodeProvider.java @@ -80,7 +80,7 @@ private TorMode getTorMode(BridgeAddressProvider bridgeAddressProvider, boolean useSafeCookieAuthentication) { return controlPort != Config.UNSPECIFIED_PORT ? new RunningTor(torDir, controlPort, password, cookieFile, useSafeCookieAuthentication) : - new NewTor(torDir, torrcFile, torrcOptions, bridgeAddressProvider.getBridgeAddresses()); + new NewTor(torDir, torrcFile, torrcOptions, bridgeAddressProvider); } @Override diff --git a/p2p/src/main/java/bisq/network/p2p/network/NewTor.java b/p2p/src/main/java/bisq/network/p2p/network/NewTor.java index 33f6d9ca69a..7cd6589cc86 100644 --- a/p2p/src/main/java/bisq/network/p2p/network/NewTor.java +++ b/p2p/src/main/java/bisq/network/p2p/network/NewTor.java @@ -51,19 +51,20 @@ public class NewTor extends TorMode { private final File torrcFile; private final String torrcOptions; - private final Collection bridgeEntries; + private final BridgeAddressProvider bridgeAddressProvider; - public NewTor(File torWorkingDirectory, @Nullable File torrcFile, String torrcOptions, Collection bridgeEntries) { + public NewTor(File torWorkingDirectory, @Nullable File torrcFile, String torrcOptions, BridgeAddressProvider bridgeAddressProvider) { super(torWorkingDirectory); this.torrcFile = torrcFile; this.torrcOptions = torrcOptions; - this.bridgeEntries = bridgeEntries; + this.bridgeAddressProvider = bridgeAddressProvider; } @Override public Tor getTor() throws IOException, TorCtlException { long ts1 = new Date().getTime(); + Collection bridgeEntries = bridgeAddressProvider.getBridgeAddresses(); if (bridgeEntries != null) log.info("Using bridges: {}", bridgeEntries.stream().collect(Collectors.joining(","))); diff --git a/p2p/src/test/java/bisq/network/p2p/network/TorNetworkNodeTest.java b/p2p/src/test/java/bisq/network/p2p/network/TorNetworkNodeTest.java index 3b544da4e59..33bc3d79126 100644 --- a/p2p/src/test/java/bisq/network/p2p/network/TorNetworkNodeTest.java +++ b/p2p/src/test/java/bisq/network/p2p/network/TorNetworkNodeTest.java @@ -29,6 +29,7 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.List; import java.util.concurrent.CountDownLatch; import org.slf4j.Logger; @@ -55,7 +56,7 @@ public void testTorNodeBeforeSecondReady() throws InterruptedException, IOExcept latch = new CountDownLatch(1); int port = 9001; TorNetworkNode node1 = new TorNetworkNode(port, TestUtils.getNetworkProtoResolver(), false, - new NewTor(new File("torNode_" + port), null, "", new ArrayList()), null); + new NewTor(new File("torNode_" + port), null, "", this::getBridgeAddresses), null); node1.start(new SetupListener() { @Override public void onTorNodeReady() { @@ -82,7 +83,7 @@ public void onRequestCustomBridges() { latch = new CountDownLatch(1); int port2 = 9002; TorNetworkNode node2 = new TorNetworkNode(port2, TestUtils.getNetworkProtoResolver(), false, - new NewTor(new File("torNode_" + port), null, "", new ArrayList()), null); + new NewTor(new File("torNode_" + port), null, "", this::getBridgeAddresses), null); node2.start(new SetupListener() { @Override public void onTorNodeReady() { @@ -140,7 +141,7 @@ public void testTorNodeAfterBothReady() throws InterruptedException, IOException latch = new CountDownLatch(2); int port = 9001; TorNetworkNode node1 = new TorNetworkNode(port, TestUtils.getNetworkProtoResolver(), false, - new NewTor(new File("torNode_" + port), null, "", new ArrayList()), null); + new NewTor(new File("torNode_" + port), null, "", this::getBridgeAddresses), null); node1.start(new SetupListener() { @Override public void onTorNodeReady() { @@ -166,7 +167,7 @@ public void onRequestCustomBridges() { int port2 = 9002; TorNetworkNode node2 = new TorNetworkNode(port2, TestUtils.getNetworkProtoResolver(), false, - new NewTor(new File("torNode_" + port), null, "", new ArrayList()), null); + new NewTor(new File("torNode_" + port), null, "", this::getBridgeAddresses), null); node2.start(new SetupListener() { @Override public void onTorNodeReady() { @@ -217,4 +218,8 @@ public void onFailure(@NotNull Throwable throwable) { node2.shutDown(latch::countDown); latch.await(); } + + public List getBridgeAddresses() { + return new ArrayList<>(); + } } From 684fd39c7556df85d1e1dcde3719f97dd31c2c12 Mon Sep 17 00:00:00 2001 From: jmacxx <47253594+jmacxx@users.noreply.github.com> Date: Sun, 16 Jan 2022 11:52:44 -0600 Subject: [PATCH 2/2] Force persistence write when editing Tor Bridge settings. This is necessary because Tor settings are edited before the app has completed startup and normally persistence is prohibited. --- .../common/persistence/PersistenceManager.java | 18 ++++++++++++++---- .../main/java/bisq/core/user/Preferences.java | 8 ++++---- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/common/src/main/java/bisq/common/persistence/PersistenceManager.java b/common/src/main/java/bisq/common/persistence/PersistenceManager.java index ba9d62625be..77a777d8203 100644 --- a/common/src/main/java/bisq/common/persistence/PersistenceManager.java +++ b/common/src/main/java/bisq/common/persistence/PersistenceManager.java @@ -410,7 +410,16 @@ private void maybeStartTimerForPersistence() { } } + public void forcePersistNow() { + // Tor Bridges settings are edited before app init completes, require persistNow to be forced, see writeToDisk() + persistNow(null, true); + } + public void persistNow(@Nullable Runnable completeHandler) { + persistNow(completeHandler, false); + } + + private void persistNow(@Nullable Runnable completeHandler, boolean force) { long ts = System.currentTimeMillis(); try { // The serialisation is done on the user thread to avoid threading issue with potential mutations of the @@ -420,7 +429,7 @@ public void persistNow(@Nullable Runnable completeHandler) { // For the write to disk task we use a thread. We do not have any issues anymore if the persistable objects // gets mutated while the thread is running as we have serialized it already and do not operate on the // reference to the persistable object. - getWriteToDiskExecutor().execute(() -> writeToDisk(serialized, completeHandler)); + getWriteToDiskExecutor().execute(() -> writeToDisk(serialized, completeHandler, force)); long duration = System.currentTimeMillis() - ts; if (duration > 100) { @@ -433,10 +442,11 @@ public void persistNow(@Nullable Runnable completeHandler) { } } - public void writeToDisk(protobuf.PersistableEnvelope serialized, @Nullable Runnable completeHandler) { - if (!allServicesInitialized.get()) { + private void writeToDisk(protobuf.PersistableEnvelope serialized, @Nullable Runnable completeHandler, boolean force) { + if (!allServicesInitialized.get() && !force) { log.warn("Application has not completed start up yet so we do not permit writing data to disk."); - UserThread.execute(completeHandler); + if (completeHandler != null) + UserThread.execute(completeHandler); return; } diff --git a/core/src/main/java/bisq/core/user/Preferences.java b/core/src/main/java/bisq/core/user/Preferences.java index 70eef439fb2..7ae65616c35 100644 --- a/core/src/main/java/bisq/core/user/Preferences.java +++ b/core/src/main/java/bisq/core/user/Preferences.java @@ -679,7 +679,7 @@ public void setResyncSpvRequested(boolean resyncSpvRequested) { public void setBridgeAddresses(List bridgeAddresses) { prefPayload.setBridgeAddresses(bridgeAddresses); // We call that before shutdown so we dont want a delay here - requestPersistence(); + persistenceManager.forcePersistNow(); } // Only used from PB but keep it explicit as it may be used from the client and then we want to persist @@ -690,17 +690,17 @@ public void setPeerTagMap(Map peerTagMap) { public void setBridgeOptionOrdinal(int bridgeOptionOrdinal) { prefPayload.setBridgeOptionOrdinal(bridgeOptionOrdinal); - requestPersistence(); + persistenceManager.forcePersistNow(); } public void setTorTransportOrdinal(int torTransportOrdinal) { prefPayload.setTorTransportOrdinal(torTransportOrdinal); - requestPersistence(); + persistenceManager.forcePersistNow(); } public void setCustomBridges(String customBridges) { prefPayload.setCustomBridges(customBridges); - requestPersistence(); + persistenceManager.forcePersistNow(); } public void setBitcoinNodesOptionOrdinal(int bitcoinNodesOptionOrdinal) {