do not start local node when credentialed local node running

rename isMoneroNodeRunning() to isMoneroNodeOnline()
This commit is contained in:
woodser 2022-07-15 13:31:57 -04:00
parent e06fb1a3af
commit 14ada60c25
7 changed files with 74 additions and 61 deletions

View file

@ -247,8 +247,8 @@ public class CoreApi {
// Monero node // Monero node
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
public boolean isMoneroNodeRunning() { public boolean isMoneroNodeOnline() {
return coreMoneroNodeService.isMoneroNodeRunning(); return coreMoneroNodeService.isOnline();
} }
public MoneroNodeSettings getMoneroNodeSettings() { public MoneroNodeSettings getMoneroNodeSettings() {

View file

@ -5,6 +5,7 @@ import bisq.common.config.Config;
import bisq.core.btc.model.EncryptedConnectionList; import bisq.core.btc.model.EncryptedConnectionList;
import bisq.core.btc.setup.DownloadListener; import bisq.core.btc.setup.DownloadListener;
import bisq.core.btc.setup.WalletsSetup; import bisq.core.btc.setup.WalletsSetup;
import bisq.core.trade.TradeUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@ -237,7 +238,7 @@ public final class CoreMoneroConnectionsService {
public long getDefaultRefreshPeriodMs() { public long getDefaultRefreshPeriodMs() {
if (daemon == null) return REFRESH_PERIOD_LOCAL_MS; if (daemon == null) return REFRESH_PERIOD_LOCAL_MS;
else { else {
boolean isLocal = CoreMoneroNodeService.isLocalHost(daemon.getRpcConnection().getUri()); boolean isLocal = TradeUtils.isLocalHost(daemon.getRpcConnection().getUri());
if (isLocal) { if (isLocal) {
updateDaemonInfo(); updateDaemonInfo();
if (lastInfo != null && (lastInfo.isBusySyncing() || (lastInfo.getHeightWithoutBootstrap() != null && lastInfo.getHeightWithoutBootstrap() > 0 && lastInfo.getHeightWithoutBootstrap() < lastInfo.getHeight()))) return REFRESH_PERIOD_REMOTE_MS; // refresh slower if syncing or bootstrapped if (lastInfo != null && (lastInfo.isBusySyncing() || (lastInfo.getHeightWithoutBootstrap() != null && lastInfo.getHeightWithoutBootstrap() > 0 && lastInfo.getHeightWithoutBootstrap() < lastInfo.getHeight()))) return REFRESH_PERIOD_REMOTE_MS; // refresh slower if syncing or bootstrapped
@ -321,6 +322,11 @@ public final class CoreMoneroConnectionsService {
var currentConnectionUri = connectionList.getCurrentConnectionUri(); var currentConnectionUri = connectionList.getCurrentConnectionUri();
if (currentConnectionUri.isPresent()) connectionManager.setConnection(currentConnectionUri.get()); if (currentConnectionUri.isPresent()) connectionManager.setConnection(currentConnectionUri.get());
// set monero connection from startup arguments
if (!isInitialized && !"".equals(config.xmrNode)) {
connectionManager.setConnection(new MoneroRpcConnection(config.xmrNode, config.xmrNodeUsername, config.xmrNodePassword).setPriority(1));
}
// restore configuration // restore configuration
connectionManager.setAutoSwitch(connectionList.getAutoSwitch()); connectionManager.setAutoSwitch(connectionList.getAutoSwitch());
long refreshPeriod = connectionList.getRefreshPeriod(); long refreshPeriod = connectionList.getRefreshPeriod();
@ -331,11 +337,6 @@ public final class CoreMoneroConnectionsService {
// run once // run once
if (!isInitialized) { if (!isInitialized) {
// set monero connection from startup arguments
if (!"".equals(config.xmrNode)) {
connectionManager.setConnection(new MoneroRpcConnection(config.xmrNode, config.xmrNodeUsername, config.xmrNodePassword).setPriority(1));
}
// register connection change listener // register connection change listener
connectionManager.addListener(this::onConnectionChanged); connectionManager.addListener(this::onConnectionChanged);
@ -358,10 +359,10 @@ public final class CoreMoneroConnectionsService {
isInitialized = true; isInitialized = true;
} }
// start local node if offline and last connection is local // if offline and last connection is local, start local node if offline
currentConnectionUri.ifPresent(uri -> { currentConnectionUri.ifPresent(uri -> {
try { try {
if (CoreMoneroNodeService.isLocalHost(uri) && !nodeService.isMoneroNodeRunning()) { if (!connectionManager.isConnected() && TradeUtils.isLocalHost(uri) && !nodeService.isOnline()) {
nodeService.startMoneroNode(); nodeService.startMoneroNode();
} }
} catch (Exception e) { } catch (Exception e) {
@ -369,8 +370,10 @@ public final class CoreMoneroConnectionsService {
} }
}); });
// connect to local node if available // prefer to connect to local node unless prevented by configuration
if (nodeService.isMoneroNodeRunning() && (!connectionManager.isConnected() || connectionManager.getAutoSwitch())) { if (("".equals(config.xmrNode) || TradeUtils.isLocalHost(config.xmrNode)) &&
(!connectionManager.isConnected() || connectionManager.getAutoSwitch()) &&
nodeService.isConnected()) {
MoneroRpcConnection connection = connectionManager.getConnectionByUri(nodeService.getDaemon().getRpcConnection().getUri()); MoneroRpcConnection connection = connectionManager.getConnectionByUri(nodeService.getDaemon().getRpcConnection().getUri());
if (connection != null) { if (connection != null) {
connection.checkConnection(connectionManager.getTimeout()); connection.checkConnection(connectionManager.getTimeout());

View file

@ -16,6 +16,7 @@
*/ */
package bisq.core.api; package bisq.core.api;
import bisq.core.trade.TradeUtils;
import bisq.core.user.Preferences; import bisq.core.user.Preferences;
import bisq.core.xmr.MoneroNodeSettings; import bisq.core.xmr.MoneroNodeSettings;
import bisq.common.config.BaseCurrencyNetwork; import bisq.common.config.BaseCurrencyNetwork;
@ -24,8 +25,6 @@ import bisq.common.config.Config;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.net.URI;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -34,7 +33,6 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import monero.common.MoneroError;
import monero.daemon.MoneroDaemonRpc; import monero.daemon.MoneroDaemonRpc;
/** /**
@ -44,8 +42,6 @@ import monero.daemon.MoneroDaemonRpc;
@Singleton @Singleton
public class CoreMoneroNodeService { public class CoreMoneroNodeService {
private static final String LOOPBACK_HOST = "127.0.0.1"; // local loopback address to host Monero node
private static final String LOCALHOST = "localhost";
private static final String MONERO_NETWORK_TYPE = Config.baseCurrencyNetwork().getNetwork().toLowerCase(); private static final String MONERO_NETWORK_TYPE = Config.baseCurrencyNetwork().getNetwork().toLowerCase();
private static final String MONEROD_PATH = System.getProperty("user.dir") + File.separator + ".localnet" + File.separator + "monerod"; private static final String MONEROD_PATH = System.getProperty("user.dir") + File.separator + ".localnet" + File.separator + "monerod";
private static final String MONEROD_DATADIR = Config.baseCurrencyNetwork() == BaseCurrencyNetwork.XMR_LOCAL ? System.getProperty("user.dir") + File.separator + ".localnet" + File.separator + Config.baseCurrencyNetwork().toString().toLowerCase() + File.separator + "node1" : null; private static final String MONEROD_DATADIR = Config.baseCurrencyNetwork() == BaseCurrencyNetwork.XMR_LOCAL ? System.getProperty("user.dir") + File.separator + ".localnet" + File.separator + Config.baseCurrencyNetwork().toString().toLowerCase() + File.separator + "node1" : null;
@ -72,19 +68,7 @@ public class CoreMoneroNodeService {
else if (Config.baseCurrencyNetwork().isTestnet()) rpcPort = 28081; else if (Config.baseCurrencyNetwork().isTestnet()) rpcPort = 28081;
else if (Config.baseCurrencyNetwork().isStagenet()) rpcPort = 38081; else if (Config.baseCurrencyNetwork().isStagenet()) rpcPort = 38081;
else throw new RuntimeException("Base network is not local testnet, stagenet, or mainnet"); else throw new RuntimeException("Base network is not local testnet, stagenet, or mainnet");
this.daemon = new MoneroDaemonRpc("http://" + LOOPBACK_HOST + ":" + rpcPort); this.daemon = new MoneroDaemonRpc("http://" + TradeUtils.LOOPBACK_HOST + ":" + rpcPort);
}
/**
* Returns whether the given URI is on local host. // TODO: move to utils
*/
public static boolean isLocalHost(String uri) {
try {
String host = new URI(uri).getHost();
return host.equals(CoreMoneroNodeService.LOOPBACK_HOST) || host.equals(CoreMoneroNodeService.LOCALHOST);
} catch (Exception e) {
throw new RuntimeException(e);
}
} }
public void addListener(MoneroNodeServiceListener listener) { public void addListener(MoneroNodeServiceListener listener) {
@ -96,23 +80,30 @@ public class CoreMoneroNodeService {
} }
/** /**
* Returns the client of the local monero node. * Return the client of the local Monero node.
*/ */
public MoneroDaemonRpc getDaemon() { public MoneroDaemonRpc getDaemon() {
return daemon; return daemon;
} }
/** private boolean checkConnection() {
* Returns whether a local monero node is running. return daemon.getRpcConnection().checkConnection(5000);
*/
public boolean isMoneroNodeRunning() {
//return daemon.isConnected(); // TODO: daemonRpc.isConnected() should use getVersion() instead of getHeight() which throws when unsynced
try {
daemon.getVersion();
return true;
} catch (MoneroError e) {
return false;
} }
/**
* Check if local Monero node is online.
*/
public boolean isOnline() {
checkConnection();
return daemon.getRpcConnection().isOnline();
}
/**
* Check if connected to local Monero node.
*/
public boolean isConnected() {
checkConnection();
return daemon.getRpcConnection().isConnected();
} }
public MoneroNodeSettings getMoneroNodeSettings() { public MoneroNodeSettings getMoneroNodeSettings() {
@ -120,7 +111,7 @@ public class CoreMoneroNodeService {
} }
/** /**
* Starts a local monero node from settings. * Start a local Monero node from settings.
*/ */
public void startMoneroNode() throws IOException { public void startMoneroNode() throws IOException {
var settings = preferences.getMoneroNodeSettings(); var settings = preferences.getMoneroNodeSettings();
@ -128,11 +119,11 @@ public class CoreMoneroNodeService {
} }
/** /**
* Starts a local monero node. Throws MoneroError if the node cannot be started. * Start local Monero node. Throws MoneroError if the node cannot be started.
* Persists the settings to preferences if the node started successfully. * Persist the settings to preferences if the node started successfully.
*/ */
public void startMoneroNode(MoneroNodeSettings settings) throws IOException { public void startMoneroNode(MoneroNodeSettings settings) throws IOException {
if (isMoneroNodeRunning()) throw new IllegalStateException("Local Monero node already running"); if (isOnline()) throw new IllegalStateException("Local Monero node already online");
log.info("Starting local Monero node: " + settings); log.info("Starting local Monero node: " + settings);
@ -160,11 +151,11 @@ public class CoreMoneroNodeService {
} }
/** /**
* Stops the current local monero node if we own its process. * Stop the current local Monero node if we own its process.
* Does not remove the last MoneroNodeSettings. * Does not remove the last MoneroNodeSettings.
*/ */
public void stopMoneroNode() { public void stopMoneroNode() {
if (!isMoneroNodeRunning()) throw new IllegalStateException("Local Monero node is not running"); if (!isOnline()) throw new IllegalStateException("Local Monero node is not running");
if (daemon.getProcess() == null || !daemon.getProcess().isAlive()) throw new IllegalStateException("Cannot stop local Monero node because we don't own its process"); // TODO (woodser): remove isAlive() check after monero-java 0.5.4 which nullifies internal process if (daemon.getProcess() == null || !daemon.getProcess().isAlive()) throw new IllegalStateException("Cannot stop local Monero node because we don't own its process"); // TODO (woodser): remove isAlive() check after monero-java 0.5.4 which nullifies internal process
daemon.stopProcess(); daemon.stopProcess();
for (var listener : listeners) listener.onNodeStopped(); for (var listener : listeners) listener.onNodeStopped();

View file

@ -451,7 +451,7 @@ public class XmrWalletService {
try { try {
log.info("Creating wallet " + config.getPath()); log.info("Creating wallet " + config.getPath());
walletRpc.createWallet(config); walletRpc.createWallet(config);
log.info("Syncing wallet " + config.getPath()); log.info("Syncing wallet " + config.getPath() + " in background");
walletRpc.startSyncing(connectionsService.getDefaultRefreshPeriodMs()); walletRpc.startSyncing(connectionsService.getDefaultRefreshPeriodMs());
return walletRpc; return walletRpc;
} catch (Exception e) { } catch (Exception e) {
@ -473,10 +473,13 @@ public class XmrWalletService {
walletRpc.openWallet(config); walletRpc.openWallet(config);
// start syncing wallet in background // start syncing wallet in background
log.info("Syncing wallet " + config.getPath() + " in background");
walletRpc.startSyncing(connectionsService.getDefaultRefreshPeriodMs()); walletRpc.startSyncing(connectionsService.getDefaultRefreshPeriodMs());
// sync wallet (blocks) // sync wallet (blocks)
walletRpc.sync(); log.info("Syncing wallet " + config.getPath());
walletRpc.sync(); // TODO: does this initiate 2 syncs back-to-back?
log.info("Done syncing wallet " + config.getPath());
return walletRpc; return walletRpc;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();

View file

@ -27,6 +27,7 @@ import bisq.core.offer.OfferPayload;
import bisq.core.support.dispute.arbitration.arbitrator.Arbitrator; import bisq.core.support.dispute.arbitration.arbitrator.Arbitrator;
import bisq.core.trade.messages.InitTradeRequest; import bisq.core.trade.messages.InitTradeRequest;
import bisq.core.util.JsonUtil; import bisq.core.util.JsonUtil;
import java.net.URI;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
@ -35,6 +36,9 @@ import java.util.concurrent.CountDownLatch;
*/ */
public class TradeUtils { public class TradeUtils {
public static final String LOOPBACK_HOST = "127.0.0.1"; // local loopback address to host Monero node
public static final String LOCALHOST = "localhost";
/** /**
* Get address to collect trade fees. * Get address to collect trade fees.
* *
@ -55,6 +59,18 @@ public class TradeUtils {
} }
} }
/**
* Check if the given URI is on local host.
*/
public static boolean isLocalHost(String uri) {
try {
String host = new URI(uri).getHost();
return host.equals(LOOPBACK_HOST) || host.equals(LOCALHOST);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/** /**
* Check if the arbitrator signature for an offer is valid. * Check if the arbitrator signature for an offer is valid.
* *

View file

@ -21,8 +21,8 @@ import bisq.core.xmr.MoneroNodeSettings;
import bisq.proto.grpc.GetMoneroNodeSettingsReply; import bisq.proto.grpc.GetMoneroNodeSettingsReply;
import bisq.proto.grpc.GetMoneroNodeSettingsRequest; import bisq.proto.grpc.GetMoneroNodeSettingsRequest;
import bisq.proto.grpc.IsMoneroNodeRunningReply; import bisq.proto.grpc.IsMoneroNodeOnlineReply;
import bisq.proto.grpc.IsMoneroNodeRunningRequest; import bisq.proto.grpc.IsMoneroNodeOnlineRequest;
import bisq.proto.grpc.MoneroNodeGrpc.MoneroNodeImplBase; import bisq.proto.grpc.MoneroNodeGrpc.MoneroNodeImplBase;
import bisq.proto.grpc.StartMoneroNodeReply; import bisq.proto.grpc.StartMoneroNodeReply;
import bisq.proto.grpc.StartMoneroNodeRequest; import bisq.proto.grpc.StartMoneroNodeRequest;
@ -42,7 +42,7 @@ import lombok.extern.slf4j.Slf4j;
import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor; import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor;
import static bisq.proto.grpc.MoneroNodeGrpc.getStartMoneroNodeMethod; import static bisq.proto.grpc.MoneroNodeGrpc.getStartMoneroNodeMethod;
import static bisq.proto.grpc.MoneroNodeGrpc.getStopMoneroNodeMethod; import static bisq.proto.grpc.MoneroNodeGrpc.getStopMoneroNodeMethod;
import static bisq.proto.grpc.MoneroNodeGrpc.getIsMoneroNodeRunningMethod; import static bisq.proto.grpc.MoneroNodeGrpc.getIsMoneroNodeOnlineMethod;
import static bisq.proto.grpc.MoneroNodeGrpc.getGetMoneroNodeSettingsMethod; import static bisq.proto.grpc.MoneroNodeGrpc.getGetMoneroNodeSettingsMethod;
import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.concurrent.TimeUnit.SECONDS;
@ -63,11 +63,11 @@ public class GrpcMoneroNodeService extends MoneroNodeImplBase {
} }
@Override @Override
public void isMoneroNodeRunning(IsMoneroNodeRunningRequest request, public void isMoneroNodeOnline(IsMoneroNodeOnlineRequest request,
StreamObserver<IsMoneroNodeRunningReply> responseObserver) { StreamObserver<IsMoneroNodeOnlineReply> responseObserver) {
try { try {
var reply = IsMoneroNodeRunningReply.newBuilder() var reply = IsMoneroNodeOnlineReply.newBuilder()
.setIsRunning(coreApi.isMoneroNodeRunning()) .setIsRunning(coreApi.isMoneroNodeOnline())
.build(); .build();
responseObserver.onNext(reply); responseObserver.onNext(reply);
responseObserver.onCompleted(); responseObserver.onCompleted();
@ -146,7 +146,7 @@ public class GrpcMoneroNodeService extends MoneroNodeImplBase {
.or(() -> Optional.of(CallRateMeteringInterceptor.valueOf( .or(() -> Optional.of(CallRateMeteringInterceptor.valueOf(
new HashMap<>() {{ new HashMap<>() {{
int allowedCallsPerTimeWindow = 10; int allowedCallsPerTimeWindow = 10;
put(getIsMoneroNodeRunningMethod().getFullMethodName(), new GrpcCallRateMeter(allowedCallsPerTimeWindow, SECONDS)); put(getIsMoneroNodeOnlineMethod().getFullMethodName(), new GrpcCallRateMeter(allowedCallsPerTimeWindow, SECONDS));
put(getGetMoneroNodeSettingsMethod().getFullMethodName(), new GrpcCallRateMeter(allowedCallsPerTimeWindow, SECONDS)); put(getGetMoneroNodeSettingsMethod().getFullMethodName(), new GrpcCallRateMeter(allowedCallsPerTimeWindow, SECONDS));
put(getStartMoneroNodeMethod().getFullMethodName(), new GrpcCallRateMeter(allowedCallsPerTimeWindow, SECONDS)); put(getStartMoneroNodeMethod().getFullMethodName(), new GrpcCallRateMeter(allowedCallsPerTimeWindow, SECONDS));
put(getStopMoneroNodeMethod().getFullMethodName(), new GrpcCallRateMeter(allowedCallsPerTimeWindow, SECONDS)); put(getStopMoneroNodeMethod().getFullMethodName(), new GrpcCallRateMeter(allowedCallsPerTimeWindow, SECONDS));

View file

@ -387,7 +387,7 @@ message SetAutoSwitchReply {}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
service MoneroNode { service MoneroNode {
rpc IsMoneroNodeRunning (IsMoneroNodeRunningRequest) returns (IsMoneroNodeRunningReply) { rpc IsMoneroNodeOnline (IsMoneroNodeOnlineRequest) returns (IsMoneroNodeOnlineReply) {
} }
rpc GetMoneroNodeSettings (GetMoneroNodeSettingsRequest) returns (GetMoneroNodeSettingsReply) { rpc GetMoneroNodeSettings (GetMoneroNodeSettingsRequest) returns (GetMoneroNodeSettingsReply) {
} }
@ -397,10 +397,10 @@ service MoneroNode {
} }
} }
message IsMoneroNodeRunningRequest { message IsMoneroNodeOnlineRequest {
} }
message IsMoneroNodeRunningReply { message IsMoneroNodeOnlineReply {
bool is_running = 1; bool is_running = 1;
} }