reinitialize main wallet on same thread as connection change

This commit is contained in:
woodser 2024-07-18 09:14:16 -04:00
parent cb132e727a
commit ebcadb7bed

View file

@ -1304,100 +1304,102 @@ public class XmrWalletService {
} }
private void maybeInitMainWallet(boolean sync, int numAttempts) { private void maybeInitMainWallet(boolean sync, int numAttempts) {
ThreadUtils.execute(() -> { ThreadUtils.execute(() -> doMaybeInitMainWallet(sync, numAttempts), THREAD_ID);
synchronized (WALLET_LOCK) { }
if (isShutDownStarted) return;
private void doMaybeInitMainWallet(boolean sync, int numAttempts) {
// open or create wallet main wallet synchronized (WALLET_LOCK) {
if (wallet == null) { if (isShutDownStarted) return;
MoneroDaemonRpc daemon = xmrConnectionService.getDaemon();
log.info("Initializing main wallet with monerod=" + (daemon == null ? "null" : daemon.getRpcConnection().getUri())); // open or create wallet main wallet
if (MoneroUtils.walletExists(xmrWalletFile.getPath())) { if (wallet == null) {
wallet = openWallet(MONERO_WALLET_NAME, rpcBindPort, isProxyApplied(wasWalletSynced)); MoneroDaemonRpc daemon = xmrConnectionService.getDaemon();
} else if (Boolean.TRUE.equals(xmrConnectionService.isConnected())) { log.info("Initializing main wallet with monerod=" + (daemon == null ? "null" : daemon.getRpcConnection().getUri()));
wallet = createWallet(MONERO_WALLET_NAME, rpcBindPort); if (MoneroUtils.walletExists(xmrWalletFile.getPath())) {
wallet = openWallet(MONERO_WALLET_NAME, rpcBindPort, isProxyApplied(wasWalletSynced));
// set wallet creation date to yesterday to guarantee complete restore } else if (Boolean.TRUE.equals(xmrConnectionService.isConnected())) {
LocalDateTime localDateTime = LocalDate.now().atStartOfDay().minusDays(1); wallet = createWallet(MONERO_WALLET_NAME, rpcBindPort);
long date = localDateTime.toEpochSecond(ZoneOffset.UTC);
user.setWalletCreationDate(date); // set wallet creation date to yesterday to guarantee complete restore
} LocalDateTime localDateTime = LocalDate.now().atStartOfDay().minusDays(1);
isClosingWallet = false; long date = localDateTime.toEpochSecond(ZoneOffset.UTC);
user.setWalletCreationDate(date);
} }
isClosingWallet = false;
// sync wallet and register listener }
if (wallet != null && !isShutDownStarted) {
log.info("Monero wallet path={}", wallet.getPath());
// sync main wallet if applicable
if (sync && numAttempts > 0) {
try {
// switch connection if disconnected // sync wallet and register listener
if (!wallet.isConnectedToDaemon()) { if (wallet != null && !isShutDownStarted) {
log.warn("Switching connection before syncing with progress because disconnected"); log.info("Monero wallet path={}", wallet.getPath());
if (requestSwitchToNextBestConnection()) return; // calls back to this method
}
// sync main wallet
log.info("Syncing main wallet");
long time = System.currentTimeMillis();
syncWithProgress(); // blocking
log.info("Done syncing main wallet in " + (System.currentTimeMillis() - time) + " ms");
// poll wallet // sync main wallet if applicable
doPollWallet(true); if (sync && numAttempts > 0) {
if (walletInitListener != null) xmrConnectionService.downloadPercentageProperty().removeListener(walletInitListener); try {
// log wallet balances // switch connection if disconnected
if (getMoneroNetworkType() != MoneroNetworkType.MAINNET) { if (!wallet.isConnectedToDaemon()) {
BigInteger balance = getBalance(); log.warn("Switching connection before syncing with progress because disconnected");
BigInteger unlockedBalance = getAvailableBalance(); if (requestSwitchToNextBestConnection()) return; // calls back to this method
log.info("Monero wallet unlocked balance={}, pending balance={}, total balance={}", unlockedBalance, balance.subtract(unlockedBalance), balance); }
}
// sync main wallet
// reapply connection after wallet synced (might reinitialize wallet on new thread) log.info("Syncing main wallet");
ThreadUtils.execute(() -> onConnectionChanged(xmrConnectionService.getConnection()), THREAD_ID); long time = System.currentTimeMillis();
syncWithProgress(); // blocking
// reset internal state if main wallet was swapped log.info("Done syncing main wallet in " + (System.currentTimeMillis() - time) + " ms");
resetIfWalletChanged();
// poll wallet
// signal that main wallet is synced doPollWallet(true);
doneDownload(); if (walletInitListener != null) xmrConnectionService.downloadPercentageProperty().removeListener(walletInitListener);
// notify setup that main wallet is initialized // log wallet balances
// TODO: app fully initializes after this is set to true, even though wallet might not be initialized if unconnected. wallet will be created when connection detected if (getMoneroNetworkType() != MoneroNetworkType.MAINNET) {
// refactor startup to call this and sync off main thread? but the calls to e.g. getBalance() fail with 'wallet and network is not yet initialized' BigInteger balance = getBalance();
BigInteger unlockedBalance = getAvailableBalance();
log.info("Monero wallet unlocked balance={}, pending balance={}, total balance={}", unlockedBalance, balance.subtract(unlockedBalance), balance);
}
// reapply connection after wallet synced (might reinitialize wallet on new thread)
ThreadUtils.execute(() -> onConnectionChanged(xmrConnectionService.getConnection()), THREAD_ID);
// reset internal state if main wallet was swapped
resetIfWalletChanged();
// signal that main wallet is synced
doneDownload();
// notify setup that main wallet is initialized
// TODO: app fully initializes after this is set to true, even though wallet might not be initialized if unconnected. wallet will be created when connection detected
// refactor startup to call this and sync off main thread? but the calls to e.g. getBalance() fail with 'wallet and network is not yet initialized'
HavenoUtils.havenoSetup.getWalletInitialized().set(true);
// save but skip backup on initialization
saveMainWallet(false);
} catch (Exception e) {
if (isClosingWallet || isShutDownStarted || HavenoUtils.havenoSetup.getWalletInitialized().get()) return; // ignore if wallet closing, shut down started, or app already initialized
log.warn("Error initially syncing main wallet: {}", e.getMessage());
if (numAttempts <= 1) {
log.warn("Failed to sync main wallet. Opening app without syncing", numAttempts);
HavenoUtils.havenoSetup.getWalletInitialized().set(true); HavenoUtils.havenoSetup.getWalletInitialized().set(true);
// save but skip backup on initialization
saveMainWallet(false); saveMainWallet(false);
} catch (Exception e) {
if (isClosingWallet || isShutDownStarted || HavenoUtils.havenoSetup.getWalletInitialized().get()) return; // ignore if wallet closing, shut down started, or app already initialized // reschedule to init main wallet
log.warn("Error initially syncing main wallet: {}", e.getMessage()); UserThread.runAfter(() -> {
if (numAttempts <= 1) { maybeInitMainWallet(true, MAX_SYNC_ATTEMPTS);
log.warn("Failed to sync main wallet. Opening app without syncing", numAttempts); }, xmrConnectionService.getRefreshPeriodMs() / 1000);
HavenoUtils.havenoSetup.getWalletInitialized().set(true); } else {
saveMainWallet(false); log.warn("Trying again in {} seconds", xmrConnectionService.getRefreshPeriodMs() / 1000);
UserThread.runAfter(() -> {
// reschedule to init main wallet maybeInitMainWallet(true, numAttempts - 1);
UserThread.runAfter(() -> { }, xmrConnectionService.getRefreshPeriodMs() / 1000);
maybeInitMainWallet(true, MAX_SYNC_ATTEMPTS);
}, xmrConnectionService.getRefreshPeriodMs() / 1000);
} else {
log.warn("Trying again in {} seconds", xmrConnectionService.getRefreshPeriodMs() / 1000);
UserThread.runAfter(() -> {
maybeInitMainWallet(true, numAttempts - 1);
}, xmrConnectionService.getRefreshPeriodMs() / 1000);
}
} }
} }
// start polling main wallet
startPolling();
} }
// start polling main wallet
startPolling();
} }
}, THREAD_ID); }
} }
private void resetIfWalletChanged() { private void resetIfWalletChanged() {
@ -1679,7 +1681,7 @@ public class XmrWalletService {
} else { } else {
log.info("Restarting main wallet because proxy URI has changed, old={}, new={}", oldProxyUri, newProxyUri); // TODO: set proxy without restarting wallet log.info("Restarting main wallet because proxy URI has changed, old={}, new={}", oldProxyUri, newProxyUri); // TODO: set proxy without restarting wallet
closeMainWallet(true); closeMainWallet(true);
maybeInitMainWallet(false); doMaybeInitMainWallet(false, MAX_SYNC_ATTEMPTS);
return; // wallet is re-initialized return; // wallet is re-initialized
} }
} else { } else {
@ -1846,7 +1848,6 @@ public class XmrWalletService {
synchronized (HavenoUtils.getDaemonLock()) { synchronized (HavenoUtils.getDaemonLock()) {
try { try {
cachedTxs = wallet.getTxs(new MoneroTxQuery().setIncludeOutputs(true)); cachedTxs = wallet.getTxs(new MoneroTxQuery().setIncludeOutputs(true));
lastLogPollErrorTimestamp = null;
} catch (Exception e) { // fetch from pool can fail } catch (Exception e) { // fetch from pool can fail
if (!isShutDownStarted) { if (!isShutDownStarted) {
if (lastLogPollErrorTimestamp == null || System.currentTimeMillis() - lastLogPollErrorTimestamp > HavenoUtils.LOG_POLL_ERROR_PERIOD_MS) { // limit error logging if (lastLogPollErrorTimestamp == null || System.currentTimeMillis() - lastLogPollErrorTimestamp > HavenoUtils.LOG_POLL_ERROR_PERIOD_MS) { // limit error logging