mirror of
https://github.com/haveno-dex/haveno.git
synced 2024-10-01 01:35:48 -04:00
support tor connection to monero network through monero-java
cleanup startup routine for stability remove call to `get_connections` increase wallet startup timeout to 1 hour increase app startup timeout to 5 minutes skip checkstyle in make commands
This commit is contained in:
parent
8305c62510
commit
fd69f4250b
26
Makefile
26
Makefile
@ -16,11 +16,14 @@ haveno:
|
|||||||
|
|
||||||
# build haveno without tests
|
# build haveno without tests
|
||||||
skip-tests: localnet
|
skip-tests: localnet
|
||||||
./gradlew build -x test
|
./gradlew build -x test -x checkstyleMain -x checkstyleTest
|
||||||
|
|
||||||
# quick build desktop and daemon apps without tests
|
# quick build desktop and daemon apps without tests
|
||||||
haveno-apps:
|
haveno-apps:
|
||||||
./gradlew :core:compileJava :desktop:build -x test
|
./gradlew :core:compileJava :desktop:build -x test -x checkstyleMain -x checkstyleTest
|
||||||
|
|
||||||
|
refresh-deps:
|
||||||
|
./gradlew --write-verification-metadata sha256 && ./gradlew build --refresh-keys --refresh-dependencies -x test -x checkstyleMain -x checkstyleTest
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
# create a new screen session named 'localnet'
|
# create a new screen session named 'localnet'
|
||||||
@ -84,6 +87,17 @@ monerod-local2:
|
|||||||
--rpc-access-control-origins http://localhost:8080 \
|
--rpc-access-control-origins http://localhost:8080 \
|
||||||
--fixed-difficulty 300
|
--fixed-difficulty 300
|
||||||
|
|
||||||
|
funding-wallet-stagenet:
|
||||||
|
./.localnet/monero-wallet-rpc \
|
||||||
|
--rpc-bind-port 18084 \
|
||||||
|
--rpc-login rpc_user:abc123 \
|
||||||
|
--rpc-access-control-origins http://localhost:8080 \
|
||||||
|
--wallet-dir ./.localnet \
|
||||||
|
--daemon-ssl-allow-any-cert \
|
||||||
|
--daemon-address http://127.0.0.1:38081
|
||||||
|
|
||||||
|
#--proxy 127.0.0.1:49775 \
|
||||||
|
|
||||||
funding-wallet-local:
|
funding-wallet-local:
|
||||||
./.localnet/monero-wallet-rpc \
|
./.localnet/monero-wallet-rpc \
|
||||||
--testnet \
|
--testnet \
|
||||||
@ -214,10 +228,11 @@ arbitrator-daemon-stagenet:
|
|||||||
--appName=haveno-XMR_STAGENET_arbitrator \
|
--appName=haveno-XMR_STAGENET_arbitrator \
|
||||||
--apiPassword=apitest \
|
--apiPassword=apitest \
|
||||||
--apiPort=9998 \
|
--apiPort=9998 \
|
||||||
--passwordRequired=false
|
--passwordRequired=false \
|
||||||
|
--xmrNode=http://127.0.0.1:38081
|
||||||
|
|
||||||
|
# Arbitrator needs to be registered before making trades
|
||||||
arbitrator-desktop-stagenet:
|
arbitrator-desktop-stagenet:
|
||||||
# Arbitrator needs to be registered before making trades
|
|
||||||
./haveno-desktop$(APP_EXT) \
|
./haveno-desktop$(APP_EXT) \
|
||||||
--baseCurrencyNetwork=XMR_STAGENET \
|
--baseCurrencyNetwork=XMR_STAGENET \
|
||||||
--useLocalhostForP2P=false \
|
--useLocalhostForP2P=false \
|
||||||
@ -225,7 +240,8 @@ arbitrator-desktop-stagenet:
|
|||||||
--nodePort=4444 \
|
--nodePort=4444 \
|
||||||
--appName=haveno-XMR_STAGENET_arbitrator \
|
--appName=haveno-XMR_STAGENET_arbitrator \
|
||||||
--apiPassword=apitest \
|
--apiPassword=apitest \
|
||||||
--apiPort=9998
|
--apiPort=9998 \
|
||||||
|
--xmrNode=http://127.0.0.1:38081
|
||||||
|
|
||||||
user1-daemon-stagenet:
|
user1-daemon-stagenet:
|
||||||
./haveno-daemon$(APP_EXT) \
|
./haveno-daemon$(APP_EXT) \
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package haveno.core.api;
|
package haveno.core.api;
|
||||||
|
|
||||||
|
import haveno.common.UserThread;
|
||||||
import haveno.common.app.DevEnv;
|
import haveno.common.app.DevEnv;
|
||||||
import haveno.common.config.BaseCurrencyNetwork;
|
import haveno.common.config.BaseCurrencyNetwork;
|
||||||
import haveno.common.config.Config;
|
import haveno.common.config.Config;
|
||||||
@ -7,6 +8,7 @@ import haveno.core.trade.HavenoUtils;
|
|||||||
import haveno.core.xmr.model.EncryptedConnectionList;
|
import haveno.core.xmr.model.EncryptedConnectionList;
|
||||||
import haveno.core.xmr.setup.DownloadListener;
|
import haveno.core.xmr.setup.DownloadListener;
|
||||||
import haveno.core.xmr.setup.WalletsSetup;
|
import haveno.core.xmr.setup.WalletsSetup;
|
||||||
|
import haveno.network.Socks5ProxyProvider;
|
||||||
import javafx.beans.property.IntegerProperty;
|
import javafx.beans.property.IntegerProperty;
|
||||||
import javafx.beans.property.LongProperty;
|
import javafx.beans.property.LongProperty;
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
@ -20,7 +22,6 @@ import lombok.Getter;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import monero.common.MoneroConnectionManager;
|
import monero.common.MoneroConnectionManager;
|
||||||
import monero.common.MoneroConnectionManagerListener;
|
import monero.common.MoneroConnectionManagerListener;
|
||||||
import monero.common.MoneroError;
|
|
||||||
import monero.common.MoneroRpcConnection;
|
import monero.common.MoneroRpcConnection;
|
||||||
import monero.common.TaskLooper;
|
import monero.common.TaskLooper;
|
||||||
import monero.daemon.MoneroDaemonRpc;
|
import monero.daemon.MoneroDaemonRpc;
|
||||||
@ -34,6 +35,7 @@ import java.util.Arrays;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -60,7 +62,7 @@ public final class CoreMoneroConnectionsService {
|
|||||||
new MoneroRpcConnection("http://stagenet.melo.tools:38081").setPriority(2),
|
new MoneroRpcConnection("http://stagenet.melo.tools:38081").setPriority(2),
|
||||||
new MoneroRpcConnection("http://node.sethforprivacy.com:38089").setPriority(2),
|
new MoneroRpcConnection("http://node.sethforprivacy.com:38089").setPriority(2),
|
||||||
new MoneroRpcConnection("http://node2.sethforprivacy.com:38089").setPriority(2),
|
new MoneroRpcConnection("http://node2.sethforprivacy.com:38089").setPriority(2),
|
||||||
new MoneroRpcConnection("http://ct36dsbe3oubpbebpxmiqz4uqk6zb6nhmkhoekileo4fts23rvuse2qd.onion:38081").setPriority(2)
|
new MoneroRpcConnection("http://plowsof3t5hogddwabaeiyrno25efmzfxyro2vligremt7sxpsclfaid.onion:38089").setPriority(2)
|
||||||
));
|
));
|
||||||
DEFAULT_CONNECTIONS.put(BaseCurrencyNetwork.XMR_MAINNET, Arrays.asList(
|
DEFAULT_CONNECTIONS.put(BaseCurrencyNetwork.XMR_MAINNET, Arrays.asList(
|
||||||
new MoneroRpcConnection("http://127.0.0.1:18081").setPriority(1),
|
new MoneroRpcConnection("http://127.0.0.1:18081").setPriority(1),
|
||||||
@ -84,6 +86,7 @@ public final class CoreMoneroConnectionsService {
|
|||||||
private final IntegerProperty numPeers = new SimpleIntegerProperty(0);
|
private final IntegerProperty numPeers = new SimpleIntegerProperty(0);
|
||||||
private final LongProperty chainHeight = new SimpleLongProperty(0);
|
private final LongProperty chainHeight = new SimpleLongProperty(0);
|
||||||
private final DownloadListener downloadListener = new DownloadListener();
|
private final DownloadListener downloadListener = new DownloadListener();
|
||||||
|
private Socks5ProxyProvider socks5ProxyProvider;
|
||||||
|
|
||||||
private MoneroDaemonRpc daemon;
|
private MoneroDaemonRpc daemon;
|
||||||
@Getter
|
@Getter
|
||||||
@ -98,16 +101,15 @@ public final class CoreMoneroConnectionsService {
|
|||||||
CoreAccountService accountService,
|
CoreAccountService accountService,
|
||||||
CoreMoneroNodeService nodeService,
|
CoreMoneroNodeService nodeService,
|
||||||
MoneroConnectionManager connectionManager,
|
MoneroConnectionManager connectionManager,
|
||||||
EncryptedConnectionList connectionList) {
|
EncryptedConnectionList connectionList,
|
||||||
|
Socks5ProxyProvider socks5ProxyProvider) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.coreContext = coreContext;
|
this.coreContext = coreContext;
|
||||||
this.accountService = accountService;
|
this.accountService = accountService;
|
||||||
this.nodeService = nodeService;
|
this.nodeService = nodeService;
|
||||||
this.connectionManager = connectionManager;
|
this.connectionManager = connectionManager;
|
||||||
this.connectionList = connectionList;
|
this.connectionList = connectionList;
|
||||||
|
this.socks5ProxyProvider = socks5ProxyProvider;
|
||||||
// initialize immediately if monerod configured
|
|
||||||
if (!"".equals(config.xmrNode)) initialize();
|
|
||||||
|
|
||||||
// initialize after account open and basic setup
|
// initialize after account open and basic setup
|
||||||
walletsSetup.addSetupTaskHandler(() -> { // TODO: use something better than legacy WalletSetup for notification to initialize
|
walletsSetup.addSetupTaskHandler(() -> { // TODO: use something better than legacy WalletSetup for notification to initialize
|
||||||
@ -145,6 +147,10 @@ public final class CoreMoneroConnectionsService {
|
|||||||
return this.daemon;
|
return this.daemon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getProxyUri() {
|
||||||
|
return socks5ProxyProvider.getSocks5Proxy() == null ? null : socks5ProxyProvider.getSocks5Proxy().getInetAddress().getHostAddress() + ":" + socks5ProxyProvider.getSocks5Proxy().getPort();
|
||||||
|
}
|
||||||
|
|
||||||
public void addListener(MoneroConnectionManagerListener listener) {
|
public void addListener(MoneroConnectionManagerListener listener) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
connectionManager.addListener(listener);
|
connectionManager.addListener(listener);
|
||||||
@ -319,30 +325,41 @@ public final class CoreMoneroConnectionsService {
|
|||||||
private void initialize() {
|
private void initialize() {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
|
|
||||||
// reset connection manager's connections and listeners
|
// reset connection manager
|
||||||
connectionManager.reset();
|
connectionManager.reset();
|
||||||
|
connectionManager.setTimeout(REFRESH_PERIOD_REMOTE_MS);
|
||||||
|
|
||||||
// load connections
|
// load connections
|
||||||
connectionList.getConnections().forEach(connectionManager::addConnection);
|
log.info("TOR proxy URI: " + getProxyUri());
|
||||||
|
for (MoneroRpcConnection connection : connectionList.getConnections()) {
|
||||||
|
if (connection.isOnion()) connection.setProxyUri(getProxyUri());
|
||||||
|
connectionManager.addConnection(connection);
|
||||||
|
}
|
||||||
log.info("Read " + connectionList.getConnections().size() + " connections from disk");
|
log.info("Read " + connectionList.getConnections().size() + " connections from disk");
|
||||||
|
|
||||||
// add default connections
|
// add default connections
|
||||||
for (MoneroRpcConnection connection : DEFAULT_CONNECTIONS.get(Config.baseCurrencyNetwork())) {
|
for (MoneroRpcConnection connection : DEFAULT_CONNECTIONS.get(Config.baseCurrencyNetwork())) {
|
||||||
if (connectionList.hasConnection(connection.getUri())) continue;
|
if (connectionList.hasConnection(connection.getUri())) continue;
|
||||||
|
if (connection.isOnion()) connection.setProxyUri(getProxyUri());
|
||||||
addConnection(connection);
|
addConnection(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore last used connection if present
|
// restore last used connection if unconfigured and present
|
||||||
var currentConnectionUri = connectionList.getCurrentConnectionUri();
|
Optional<String> currentConnectionUri = null;
|
||||||
if (currentConnectionUri.isPresent()) connectionManager.setConnection(currentConnectionUri.get());
|
if ("".equals(config.xmrNode)) {
|
||||||
|
currentConnectionUri = connectionList.getCurrentConnectionUri();
|
||||||
|
if (currentConnectionUri.isPresent()) connectionManager.setConnection(currentConnectionUri.get());
|
||||||
|
} else if (!isInitialized) {
|
||||||
|
|
||||||
// set monero connection from startup arguments
|
// set monero connection from startup arguments
|
||||||
if (!isInitialized && !"".equals(config.xmrNode)) {
|
MoneroRpcConnection connection = new MoneroRpcConnection(config.xmrNode, config.xmrNodeUsername, config.xmrNodePassword).setPriority(1);
|
||||||
connectionManager.setConnection(new MoneroRpcConnection(config.xmrNode, config.xmrNodeUsername, config.xmrNodePassword).setPriority(1));
|
if (connection.isOnion()) connection.setProxyUri(getProxyUri());
|
||||||
|
connectionManager.setConnection(connection);
|
||||||
|
currentConnectionUri = Optional.of(connection.getUri());
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore configuration
|
// restore configuration and check connection
|
||||||
connectionManager.setAutoSwitch(connectionList.getAutoSwitch());
|
if ("".equals(config.xmrNode)) connectionManager.setAutoSwitch(connectionList.getAutoSwitch());
|
||||||
long refreshPeriod = connectionList.getRefreshPeriod();
|
long refreshPeriod = connectionList.getRefreshPeriod();
|
||||||
if (refreshPeriod > 0) connectionManager.startCheckingConnection(refreshPeriod);
|
if (refreshPeriod > 0) connectionManager.startCheckingConnection(refreshPeriod);
|
||||||
else if (refreshPeriod == 0) connectionManager.startCheckingConnection();
|
else if (refreshPeriod == 0) connectionManager.startCheckingConnection();
|
||||||
@ -351,9 +368,6 @@ public final class CoreMoneroConnectionsService {
|
|||||||
// run once
|
// run once
|
||||||
if (!isInitialized) {
|
if (!isInitialized) {
|
||||||
|
|
||||||
// register connection change listener
|
|
||||||
connectionManager.addListener(this::onConnectionChanged);
|
|
||||||
|
|
||||||
// register local node listener
|
// register local node listener
|
||||||
nodeService.addListener(new MoneroNodeServiceListener() {
|
nodeService.addListener(new MoneroNodeServiceListener() {
|
||||||
@Override
|
@Override
|
||||||
@ -369,8 +383,6 @@ public final class CoreMoneroConnectionsService {
|
|||||||
checkConnection();
|
checkConnection();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
isInitialized = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if offline and last connection is local, start local node if offline
|
// if offline and last connection is local, start local node if offline
|
||||||
@ -385,7 +397,7 @@ public final class CoreMoneroConnectionsService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// prefer to connect to local node unless prevented by configuration
|
// prefer to connect to local node unless prevented by configuration
|
||||||
if (("".equals(config.xmrNode) || HavenoUtils.isLocalHost(config.xmrNode)) &&
|
if ("".equals(config.xmrNode) &&
|
||||||
(!connectionManager.isConnected() || connectionManager.getAutoSwitch()) &&
|
(!connectionManager.isConnected() || connectionManager.getAutoSwitch()) &&
|
||||||
nodeService.isConnected()) {
|
nodeService.isConnected()) {
|
||||||
MoneroRpcConnection connection = connectionManager.getConnectionByUri(nodeService.getDaemon().getRpcConnection().getUri());
|
MoneroRpcConnection connection = connectionManager.getConnectionByUri(nodeService.getDaemon().getRpcConnection().getUri());
|
||||||
@ -401,12 +413,19 @@ public final class CoreMoneroConnectionsService {
|
|||||||
connectionManager.setConnection(connectionManager.getBestAvailableConnection());
|
connectionManager.setConnection(connectionManager.getBestAvailableConnection());
|
||||||
}
|
}
|
||||||
|
|
||||||
// update connection
|
// register connection change listener
|
||||||
|
if (!isInitialized) {
|
||||||
|
connectionManager.addListener(this::onConnectionChanged);
|
||||||
|
isInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// announce connection
|
||||||
onConnectionChanged(connectionManager.getConnection());
|
onConnectionChanged(connectionManager.getConnection());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onConnectionChanged(MoneroRpcConnection currentConnection) {
|
private void onConnectionChanged(MoneroRpcConnection currentConnection) {
|
||||||
|
// TODO: ignore if shutdown
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
if (currentConnection == null) {
|
if (currentConnection == null) {
|
||||||
daemon = null;
|
daemon = null;
|
||||||
@ -422,12 +441,17 @@ public final class CoreMoneroConnectionsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void startPollingDaemon() {
|
private void startPollingDaemon() {
|
||||||
if (updateDaemonLooper != null) updateDaemonLooper.stop();
|
synchronized (lock) {
|
||||||
updateDaemonInfo();
|
|
||||||
updateDaemonLooper = new TaskLooper(() -> {
|
|
||||||
updateDaemonInfo();
|
updateDaemonInfo();
|
||||||
});
|
if (updateDaemonLooper != null) updateDaemonLooper.stop();
|
||||||
updateDaemonLooper.start(getDefaultRefreshPeriodMs());
|
UserThread.runAfter(() -> {
|
||||||
|
synchronized (lock) {
|
||||||
|
if (updateDaemonLooper != null) updateDaemonLooper.stop();
|
||||||
|
updateDaemonLooper = new TaskLooper(() -> updateDaemonInfo());
|
||||||
|
updateDaemonLooper.start(getDefaultRefreshPeriodMs());
|
||||||
|
}
|
||||||
|
}, getDefaultRefreshPeriodMs() / 1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateDaemonInfo() {
|
private void updateDaemonInfo() {
|
||||||
@ -438,12 +462,18 @@ public final class CoreMoneroConnectionsService {
|
|||||||
//System.out.println(JsonUtils.serialize(lastInfo));
|
//System.out.println(JsonUtils.serialize(lastInfo));
|
||||||
//System.out.println(JsonUtils.serialize(daemon.getSyncInfo()));
|
//System.out.println(JsonUtils.serialize(daemon.getSyncInfo()));
|
||||||
chainHeight.set(lastInfo.getTargetHeight() == 0 ? lastInfo.getHeight() : lastInfo.getTargetHeight());
|
chainHeight.set(lastInfo.getTargetHeight() == 0 ? lastInfo.getHeight() : lastInfo.getTargetHeight());
|
||||||
try {
|
|
||||||
peers.set(getOnlinePeers());
|
// set peer connections
|
||||||
} catch (MoneroError err) {
|
// TODO: peers often uknown due to restricted RPC call, skipping call to get peer connections
|
||||||
peers.set(new ArrayList<MoneroPeer>()); // TODO: peers unknown due to restricted RPC call
|
// try {
|
||||||
}
|
// peers.set(getOnlinePeers());
|
||||||
numPeers.set(peers.get().size());
|
// } catch (Exception err) {
|
||||||
|
// // TODO: peers unknown due to restricted RPC call
|
||||||
|
// }
|
||||||
|
// numPeers.set(peers.get().size());
|
||||||
|
numPeers.set(lastInfo.getNumOutgoingConnections() + lastInfo.getNumIncomingConnections());
|
||||||
|
peers.set(new ArrayList<MoneroPeer>());
|
||||||
|
|
||||||
if (lastErrorTimestamp != null) {
|
if (lastErrorTimestamp != null) {
|
||||||
log.info("Successfully fetched daemon info after previous error");
|
log.info("Successfully fetched daemon info after previous error");
|
||||||
lastErrorTimestamp = null;
|
lastErrorTimestamp = null;
|
||||||
|
@ -17,11 +17,9 @@
|
|||||||
|
|
||||||
package haveno.core.app;
|
package haveno.core.app;
|
||||||
|
|
||||||
import ch.qos.logback.classic.Level;
|
|
||||||
import haveno.common.Timer;
|
import haveno.common.Timer;
|
||||||
import haveno.common.UserThread;
|
import haveno.common.UserThread;
|
||||||
import haveno.common.app.DevEnv;
|
import haveno.common.app.DevEnv;
|
||||||
import haveno.common.app.Log;
|
|
||||||
import haveno.common.app.Version;
|
import haveno.common.app.Version;
|
||||||
import haveno.common.config.BaseCurrencyNetwork;
|
import haveno.common.config.BaseCurrencyNetwork;
|
||||||
import haveno.common.config.Config;
|
import haveno.common.config.Config;
|
||||||
@ -102,7 +100,7 @@ public class HavenoSetup {
|
|||||||
private static final String VERSION_FILE_NAME = "version";
|
private static final String VERSION_FILE_NAME = "version";
|
||||||
private static final String RESYNC_SPV_FILE_NAME = "resyncSpv";
|
private static final String RESYNC_SPV_FILE_NAME = "resyncSpv";
|
||||||
|
|
||||||
private static final long STARTUP_TIMEOUT_MINUTES = 4;
|
private static final long STARTUP_TIMEOUT_MINUTES = 5;
|
||||||
|
|
||||||
private final DomainInitialisation domainInitialisation;
|
private final DomainInitialisation domainInitialisation;
|
||||||
private final P2PNetworkSetup p2PNetworkSetup;
|
private final P2PNetworkSetup p2PNetworkSetup;
|
||||||
@ -403,9 +401,9 @@ public class HavenoSetup {
|
|||||||
if (displayTorNetworkSettingsHandler != null)
|
if (displayTorNetworkSettingsHandler != null)
|
||||||
displayTorNetworkSettingsHandler.accept(true);
|
displayTorNetworkSettingsHandler.accept(true);
|
||||||
|
|
||||||
log.info("Set log level for org.berndpruenster.netlayer classes to DEBUG to show more details for " +
|
// log.info("Set log level for org.berndpruenster.netlayer classes to DEBUG to show more details for " +
|
||||||
"Tor network connection issues");
|
// "Tor network connection issues");
|
||||||
Log.setCustomLogLevel("org.berndpruenster.netlayer", Level.DEBUG);
|
// Log.setCustomLogLevel("org.berndpruenster.netlayer", Level.DEBUG);
|
||||||
|
|
||||||
}, STARTUP_TIMEOUT_MINUTES, TimeUnit.MINUTES);
|
}, STARTUP_TIMEOUT_MINUTES, TimeUnit.MINUTES);
|
||||||
|
|
||||||
@ -444,7 +442,7 @@ public class HavenoSetup {
|
|||||||
checkForInvalidMakerFeeTxs();
|
checkForInvalidMakerFeeTxs();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
() -> walletInitialized.set(true));
|
() -> {});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initDomainServices() {
|
private void initDomainServices() {
|
||||||
|
@ -142,12 +142,12 @@ public class P2PNetworkSetup {
|
|||||||
bootstrapState.set(Res.get("mainView.bootstrapState.torNodeCreated"));
|
bootstrapState.set(Res.get("mainView.bootstrapState.torNodeCreated"));
|
||||||
p2PNetworkIconId.set("image-connection-tor");
|
p2PNetworkIconId.set("image-connection-tor");
|
||||||
|
|
||||||
// invoke handler to initialize wallet
|
|
||||||
initWalletServiceHandler.run();
|
|
||||||
|
|
||||||
// We want to get early connected to the price relay so we call it already now
|
// We want to get early connected to the price relay so we call it already now
|
||||||
priceFeedService.setCurrencyCodeOnInit();
|
priceFeedService.setCurrencyCodeOnInit();
|
||||||
priceFeedService.requestPrices();
|
priceFeedService.requestPrices();
|
||||||
|
|
||||||
|
// invoke handler to initialize wallet
|
||||||
|
initWalletServiceHandler.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -424,7 +424,7 @@ public class HavenoUtils {
|
|||||||
public static boolean isLocalHost(String uri) {
|
public static boolean isLocalHost(String uri) {
|
||||||
try {
|
try {
|
||||||
String host = new URI(uri).getHost();
|
String host = new URI(uri).getHost();
|
||||||
return host.equals(LOOPBACK_HOST) || host.equals(LOCALHOST);
|
return LOOPBACK_HOST.equals(host) || LOCALHOST.equals(host);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
@ -1662,12 +1662,16 @@ public abstract class Trade implements Tradable, Model {
|
|||||||
private void setWalletRefreshPeriod(long walletRefreshPeriod) {
|
private void setWalletRefreshPeriod(long walletRefreshPeriod) {
|
||||||
if (this.isShutDown) return;
|
if (this.isShutDown) return;
|
||||||
if (this.walletRefreshPeriod != null && this.walletRefreshPeriod == walletRefreshPeriod) return;
|
if (this.walletRefreshPeriod != null && this.walletRefreshPeriod == walletRefreshPeriod) return;
|
||||||
log.info("Setting wallet refresh rate for {} {} to {}", getClass().getSimpleName(), getId(), walletRefreshPeriod);
|
|
||||||
this.walletRefreshPeriod = walletRefreshPeriod;
|
this.walletRefreshPeriod = walletRefreshPeriod;
|
||||||
getWallet().startSyncing(getWalletRefreshPeriod()); // TODO (monero-project): wallet rpc waits until last sync period finishes before starting new sync period
|
synchronized (walletLock) {
|
||||||
if (txPollLooper != null) {
|
if (getWallet() != null) {
|
||||||
txPollLooper.stop();
|
log.info("Setting wallet refresh rate for {} {} to {}", getClass().getSimpleName(), getId(), walletRefreshPeriod);
|
||||||
txPollLooper = null;
|
getWallet().startSyncing(getWalletRefreshPeriod()); // TODO (monero-project): wallet rpc waits until last sync period finishes before starting new sync period
|
||||||
|
}
|
||||||
|
if (txPollLooper != null) {
|
||||||
|
txPollLooper.stop();
|
||||||
|
txPollLooper = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
startPolling();
|
startPolling();
|
||||||
}
|
}
|
||||||
|
@ -349,7 +349,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
|||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
unreservedFrozenKeyImages.removeAll(reservedKeyImages);
|
unreservedFrozenKeyImages.removeAll(reservedKeyImages);
|
||||||
if (!unreservedFrozenKeyImages.isEmpty()) {
|
if (!unreservedFrozenKeyImages.isEmpty()) {
|
||||||
log.info("Thawing outputs which are not reserved for offer or trade: " + unreservedFrozenKeyImages);
|
log.warn("Thawing outputs which are not reserved for offer or trade: " + unreservedFrozenKeyImages);
|
||||||
xmrWalletService.thawOutputs(unreservedFrozenKeyImages);
|
xmrWalletService.thawOutputs(unreservedFrozenKeyImages);
|
||||||
xmrWalletService.saveMainWallet();
|
xmrWalletService.saveMainWallet();
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ public class WalletsSetup {
|
|||||||
@Getter
|
@Getter
|
||||||
public final BooleanProperty walletsSetupFailed = new SimpleBooleanProperty();
|
public final BooleanProperty walletsSetupFailed = new SimpleBooleanProperty();
|
||||||
|
|
||||||
private static final long STARTUP_TIMEOUT = 180;
|
private static final long STARTUP_TIMEOUT_SECONDS = 3600; // 1 hour
|
||||||
private static final String SPV_CHAIN_FILE_NAME = "haveno.spvchain";
|
private static final String SPV_CHAIN_FILE_NAME = "haveno.spvchain";
|
||||||
|
|
||||||
private final RegTestHost regTestHost;
|
private final RegTestHost regTestHost;
|
||||||
@ -167,7 +167,7 @@ public class WalletsSetup {
|
|||||||
|
|
||||||
Timer timeoutTimer = UserThread.runAfter(() ->
|
Timer timeoutTimer = UserThread.runAfter(() ->
|
||||||
exceptionHandler.handleException(new TimeoutException("Wallet did not initialize in " +
|
exceptionHandler.handleException(new TimeoutException("Wallet did not initialize in " +
|
||||||
STARTUP_TIMEOUT + " seconds.")), STARTUP_TIMEOUT);
|
STARTUP_TIMEOUT_SECONDS + " seconds.")), STARTUP_TIMEOUT_SECONDS);
|
||||||
|
|
||||||
backupWallets();
|
backupWallets();
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ public class XmrWalletService {
|
|||||||
public MoneroWalletRpc createWallet(String walletName) {
|
public MoneroWalletRpc createWallet(String walletName) {
|
||||||
log.info("{}.createWallet({})", getClass().getSimpleName(), walletName);
|
log.info("{}.createWallet({})", getClass().getSimpleName(), walletName);
|
||||||
if (isShutDown) throw new IllegalStateException("Cannot create wallet because shutting down");
|
if (isShutDown) throw new IllegalStateException("Cannot create wallet because shutting down");
|
||||||
return createWallet(new MoneroWalletConfig()
|
return createWalletRpc(new MoneroWalletConfig()
|
||||||
.setPath(walletName)
|
.setPath(walletName)
|
||||||
.setPassword(getWalletPassword()),
|
.setPassword(getWalletPassword()),
|
||||||
null);
|
null);
|
||||||
@ -220,7 +220,7 @@ public class XmrWalletService {
|
|||||||
public MoneroWalletRpc openWallet(String walletName) {
|
public MoneroWalletRpc openWallet(String walletName) {
|
||||||
log.info("{}.openWallet({})", getClass().getSimpleName(), walletName);
|
log.info("{}.openWallet({})", getClass().getSimpleName(), walletName);
|
||||||
if (isShutDown) throw new IllegalStateException("Cannot open wallet because shutting down");
|
if (isShutDown) throw new IllegalStateException("Cannot open wallet because shutting down");
|
||||||
return openWallet(new MoneroWalletConfig()
|
return openWalletRpc(new MoneroWalletConfig()
|
||||||
.setPath(walletName)
|
.setPath(walletName)
|
||||||
.setPassword(getWalletPassword()),
|
.setPassword(getWalletPassword()),
|
||||||
null);
|
null);
|
||||||
@ -546,51 +546,49 @@ public class XmrWalletService {
|
|||||||
|
|
||||||
private void maybeInitMainWallet() {
|
private void maybeInitMainWallet() {
|
||||||
if (wallet != null) throw new RuntimeException("Main wallet is already initialized");
|
if (wallet != null) throw new RuntimeException("Main wallet is already initialized");
|
||||||
|
MoneroDaemonRpc daemon = connectionsService.getDaemon();
|
||||||
|
log.info("Initializing main wallet with " + (daemon == null ? "daemon: null" : "monerod uri=" + daemon.getRpcConnection().getUri() + ", height=" + connectionsService.getLastInfo().getHeight()));
|
||||||
|
|
||||||
// open or create wallet
|
// open or create wallet
|
||||||
MoneroWalletConfig walletConfig = new MoneroWalletConfig().setPath(MONERO_WALLET_NAME).setPassword(getWalletPassword());
|
MoneroWalletConfig walletConfig = new MoneroWalletConfig().setPath(MONERO_WALLET_NAME).setPassword(getWalletPassword());
|
||||||
if (MoneroUtils.walletExists(xmrWalletFile.getPath())) {
|
if (MoneroUtils.walletExists(xmrWalletFile.getPath())) {
|
||||||
wallet = openWallet(walletConfig, rpcBindPort);
|
wallet = openWalletRpc(walletConfig, rpcBindPort);
|
||||||
} else if (connectionsService.getConnection() != null && Boolean.TRUE.equals(connectionsService.getConnection().isConnected())) {
|
} else if (connectionsService.getConnection() != null && Boolean.TRUE.equals(connectionsService.getConnection().isConnected())) {
|
||||||
wallet = createWallet(walletConfig, rpcBindPort);
|
wallet = createWalletRpc(walletConfig, rpcBindPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wallet is not initialized until connected to a daemon
|
// handle when wallet initialized and synced
|
||||||
if (wallet != null) {
|
if (wallet != null) {
|
||||||
if (connectionsService.getDaemon() == null) System.out.println("Daemon: null");
|
log.info("Monero wallet uri={}, path={}", wallet.getRpcConnection().getUri(), wallet.getPath());
|
||||||
else {
|
|
||||||
System.out.println("Daemon uri: " + connectionsService.getDaemon().getRpcConnection().getUri());
|
|
||||||
System.out.println("Daemon height: " + connectionsService.getDaemon().getInfo().getHeight());
|
|
||||||
}
|
|
||||||
System.out.println("Monero wallet uri: " + wallet.getRpcConnection().getUri());
|
|
||||||
System.out.println("Monero wallet path: " + wallet.getPath());
|
|
||||||
System.out.println("Monero wallet primary address: " + wallet.getPrimaryAddress());
|
|
||||||
|
|
||||||
// sync wallet which updates app startup state
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
// sync main wallet
|
||||||
log.info("Syncing main wallet");
|
log.info("Syncing main wallet");
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
wallet.sync(); // blocking
|
wallet.sync(); // blocking
|
||||||
log.info("Done syncing main wallet in " + (System.currentTimeMillis() - time) + " ms");
|
log.info("Done syncing main wallet in " + (System.currentTimeMillis() - time) + " ms");
|
||||||
wallet.startSyncing(connectionsService.getDefaultRefreshPeriodMs());
|
wallet.startSyncing(connectionsService.getDefaultRefreshPeriodMs());
|
||||||
connectionsService.doneDownload(); // TODO: using this to signify both daemon and wallet synced, refactor sync handling of both
|
if (getMoneroNetworkType() != MoneroNetworkType.MAINNET) log.info("Monero wallet balance={}, unlocked balance={}", wallet.getBalance(0), wallet.getUnlockedBalance(0));
|
||||||
saveMainWallet(false); // skip backup on open
|
|
||||||
|
// TODO: using this to signify both daemon and wallet synced, refactor sync handling of both
|
||||||
|
connectionsService.doneDownload();
|
||||||
|
|
||||||
|
// save but skip backup on initialization
|
||||||
|
saveMainWallet(false);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("Error syncing main wallet: {}", e.getMessage());
|
log.warn("Error syncing main wallet: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("Monero wallet balance: " + wallet.getBalance(0));
|
|
||||||
System.out.println("Monero wallet unlocked balance: " + wallet.getUnlockedBalance(0));
|
|
||||||
|
|
||||||
// notify setup that main wallet is initialized
|
// notify setup that main wallet is initialized
|
||||||
havenoSetup.getWalletInitialized().set(true); // TODO: change to listener pattern?
|
// TODO: move to try..catch? refactor startup to call this and sync off main thread?
|
||||||
|
havenoSetup.getWalletInitialized().set(true); // TODO: change to listener pattern
|
||||||
|
|
||||||
// register internal listener to notify external listeners
|
// register internal listener to notify external listeners
|
||||||
wallet.addListener(new XmrWalletListener());
|
wallet.addListener(new XmrWalletListener());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MoneroWalletRpc createWallet(MoneroWalletConfig config, Integer port) {
|
private MoneroWalletRpc createWalletRpc(MoneroWalletConfig config, Integer port) {
|
||||||
|
|
||||||
// must be connected to daemon
|
// must be connected to daemon
|
||||||
MoneroRpcConnection connection = connectionsService.getConnection();
|
MoneroRpcConnection connection = connectionsService.getConnection();
|
||||||
@ -602,10 +600,15 @@ public class XmrWalletService {
|
|||||||
|
|
||||||
// create wallet
|
// create wallet
|
||||||
try {
|
try {
|
||||||
log.info("Creating wallet " + config.getPath());
|
|
||||||
|
// prevent wallet rpc from syncing
|
||||||
|
walletRpc.stopSyncing();
|
||||||
|
|
||||||
|
// create wallet
|
||||||
|
log.info("Creating wallet " + config.getPath() + " connected to daemon " + connection.getUri());
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
walletRpc.createWallet(config);
|
walletRpc.createWallet(config);
|
||||||
log.info("Done creating wallet " + walletRpc.getPath() + " in " + (System.currentTimeMillis() - time) + " ms");
|
log.info("Done creating wallet " + config.getPath() + " in " + (System.currentTimeMillis() - time) + " ms");
|
||||||
return walletRpc;
|
return walletRpc;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -614,17 +617,21 @@ public class XmrWalletService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MoneroWalletRpc openWallet(MoneroWalletConfig config, Integer port) {
|
private MoneroWalletRpc openWalletRpc(MoneroWalletConfig config, Integer port) {
|
||||||
|
|
||||||
// start monero-wallet-rpc instance
|
// start monero-wallet-rpc instance
|
||||||
MoneroWalletRpc walletRpc = startWalletRpcInstance(port);
|
MoneroWalletRpc walletRpc = startWalletRpcInstance(port);
|
||||||
|
|
||||||
// open wallet
|
// open wallet
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
// prevent wallet rpc from syncing
|
||||||
|
walletRpc.stopSyncing();
|
||||||
|
|
||||||
|
// open wallet
|
||||||
log.info("Opening wallet " + config.getPath());
|
log.info("Opening wallet " + config.getPath());
|
||||||
walletRpc.openWallet(config);
|
walletRpc.openWallet(config.setServer(connectionsService.getConnection()));
|
||||||
walletRpc.setDaemonConnection(connectionsService.getConnection());
|
log.info("Done opening wallet " + config.getPath());
|
||||||
log.info("Done opening wallet " + walletRpc.getPath());
|
|
||||||
return walletRpc;
|
return walletRpc;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -655,6 +662,10 @@ public class XmrWalletService {
|
|||||||
if (connection != null) {
|
if (connection != null) {
|
||||||
cmd.add("--daemon-address");
|
cmd.add("--daemon-address");
|
||||||
cmd.add(connection.getUri());
|
cmd.add(connection.getUri());
|
||||||
|
if (connection.isOnion() && connection.getProxyUri() != null) {
|
||||||
|
cmd.add("--proxy");
|
||||||
|
cmd.add(connection.getProxyUri());
|
||||||
|
}
|
||||||
if (connection.getUsername() != null) {
|
if (connection.getUsername() != null) {
|
||||||
cmd.add("--daemon-login");
|
cmd.add("--daemon-login");
|
||||||
cmd.add(connection.getUsername() + ":" + connection.getPassword());
|
cmd.add(connection.getUsername() + ":" + connection.getPassword());
|
||||||
@ -669,7 +680,9 @@ public class XmrWalletService {
|
|||||||
return MONERO_WALLET_RPC_MANAGER.startInstance(cmd);
|
return MONERO_WALLET_RPC_MANAGER.startInstance(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: monero-wallet-rpc needs restarted if applying tor proxy
|
||||||
private void setDaemonConnection(MoneroRpcConnection connection) {
|
private void setDaemonConnection(MoneroRpcConnection connection) {
|
||||||
|
if (isShutDown) return;
|
||||||
log.info("Setting wallet daemon connection: " + (connection == null ? null : connection.getUri()));
|
log.info("Setting wallet daemon connection: " + (connection == null ? null : connection.getUri()));
|
||||||
if (wallet == null) maybeInitMainWallet();
|
if (wallet == null) maybeInitMainWallet();
|
||||||
else {
|
else {
|
||||||
|
@ -117,7 +117,7 @@ public class HavenoApp extends Application implements UncaughtExceptionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void startApplication(Runnable onApplicationStartedHandler) {
|
public void startApplication(Runnable onApplicationStartedHandler) {
|
||||||
log.info("Running startApplication...");
|
log.info("Starting application");
|
||||||
try {
|
try {
|
||||||
mainView = loadMainView(injector);
|
mainView = loadMainView(injector);
|
||||||
mainView.setOnApplicationStartedHandler(onApplicationStartedHandler);
|
mainView.setOnApplicationStartedHandler(onApplicationStartedHandler);
|
||||||
|
Loading…
Reference in New Issue
Block a user