Skip to content

Commit 6612ac4

Browse files
committed
prompt to fall back on startup error with custom node
1 parent dc8d854 commit 6612ac4

File tree

7 files changed

+70
-10
lines changed

7 files changed

+70
-10
lines changed

core/src/main/java/haveno/core/api/XmrConnectionService.java

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,15 @@
4343

4444
import org.apache.commons.lang3.exception.ExceptionUtils;
4545

46+
import javafx.beans.property.BooleanProperty;
4647
import javafx.beans.property.IntegerProperty;
4748
import javafx.beans.property.LongProperty;
4849
import javafx.beans.property.ObjectProperty;
4950
import javafx.beans.property.ReadOnlyDoubleProperty;
5051
import javafx.beans.property.ReadOnlyIntegerProperty;
5152
import javafx.beans.property.ReadOnlyLongProperty;
5253
import javafx.beans.property.ReadOnlyObjectProperty;
54+
import javafx.beans.property.SimpleBooleanProperty;
5355
import javafx.beans.property.SimpleIntegerProperty;
5456
import javafx.beans.property.SimpleLongProperty;
5557
import javafx.beans.property.SimpleObjectProperty;
@@ -89,6 +91,8 @@ public final class XmrConnectionService {
8991
private final LongProperty chainHeight = new SimpleLongProperty(0);
9092
private final DownloadListener downloadListener = new DownloadListener();
9193
@Getter
94+
private final BooleanProperty connectionServiceFallbackProperty = new SimpleBooleanProperty();
95+
@Getter
9296
private final StringProperty connectionServiceErrorMsg = new SimpleStringProperty();
9397
private final LongProperty numUpdates = new SimpleLongProperty(0);
9498
private Socks5ProxyProvider socks5ProxyProvider;
@@ -99,6 +103,7 @@ public final class XmrConnectionService {
99103
private Boolean isConnected = false;
100104
@Getter
101105
private MoneroDaemonInfo lastInfo;
106+
private Long lastFallbackInvocation;
102107
private Long lastLogPollErrorTimestamp;
103108
private long lastLogDaemonNotSyncedTimestamp;
104109
private Long syncStartHeight;
@@ -115,6 +120,7 @@ public final class XmrConnectionService {
115120
private int numRequestsLastMinute;
116121
private long lastSwitchTimestamp;
117122
private Set<MoneroRpcConnection> excludedConnections = new HashSet<>();
123+
private static final long FALLBACK_INVOCATION_PERIOD_MS = 1000 * 60 * 1; // offer to fallback up to once every minute
118124

119125
@Inject
120126
public XmrConnectionService(P2PService p2PService,
@@ -424,6 +430,18 @@ public ReadOnlyLongProperty numUpdatesProperty() {
424430
return numUpdates;
425431
}
426432

433+
public void fallbackToBestConnection() {
434+
if (isShutDownStarted) return;
435+
if (xmrNodes.getProvidedXmrNodes().isEmpty()) {
436+
log.warn("Falling back to public nodes");
437+
preferences.setMoneroNodesOptionOrdinal(XmrNodes.MoneroNodesOption.PUBLIC.ordinal());
438+
} else {
439+
log.warn("Falling back to provided nodes");
440+
preferences.setMoneroNodesOptionOrdinal(XmrNodes.MoneroNodesOption.PROVIDED.ordinal());
441+
}
442+
initializeConnections();
443+
}
444+
427445
// ------------------------------- HELPERS --------------------------------
428446

429447
private void doneDownload() {
@@ -716,16 +734,13 @@ private void doPollDaemon() {
716734
// skip handling if shutting down
717735
if (isShutDownStarted) return;
718736

719-
// fallback to provided or public nodes if custom connection fails on startup
720-
if (lastInfo == null && "".equals(config.xmrNode) && preferences.getMoneroNodesOption() == XmrNodes.MoneroNodesOption.CUSTOM) {
721-
if (xmrNodes.getProvidedXmrNodes().isEmpty()) {
722-
log.warn("Failed to fetch daemon info from custom node on startup, falling back to public nodes: " + e.getMessage());
723-
preferences.setMoneroNodesOptionOrdinal(XmrNodes.MoneroNodesOption.PUBLIC.ordinal());
724-
} else {
725-
log.warn("Failed to fetch daemon info from custom node on startup, falling back to provided nodes: " + e.getMessage());
726-
preferences.setMoneroNodesOptionOrdinal(XmrNodes.MoneroNodesOption.PROVIDED.ordinal());
737+
// handle error fetching daemon info on startup with fixed connection
738+
if (lastInfo == null && isFixedConnection()) {
739+
if (!connectionServiceFallbackProperty.get() && (lastFallbackInvocation == null || System.currentTimeMillis() - lastFallbackInvocation > FALLBACK_INVOCATION_PERIOD_MS)) {
740+
log.warn("Failed to fetch daemon info from fixed connection on startup: " + e.getMessage());
741+
lastFallbackInvocation = System.currentTimeMillis();
742+
connectionServiceFallbackProperty.set(true);
727743
}
728-
initializeConnections();
729744
return;
730745
}
731746

core/src/main/java/haveno/core/app/HavenoHeadlessApp.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ protected void setupHandlers() {
7575
log.info("onDisplayTacHandler: We accept the tacs automatically in headless mode");
7676
acceptedHandler.run();
7777
});
78+
havenoSetup.setDisplayMoneroConnectionFallbackHandler(show -> log.info("onDisplayMoneroConnectionFallbackHandler: show={}", show));
7879
havenoSetup.setDisplayTorNetworkSettingsHandler(show -> log.info("onDisplayTorNetworkSettingsHandler: show={}", show));
7980
havenoSetup.setChainFileLockedExceptionHandler(msg -> log.error("onChainFileLockedExceptionHandler: msg={}", msg));
8081
tradeManager.setLockedUpFundsHandler(msg -> log.info("onLockedUpFundsHandler: msg={}", msg));

core/src/main/java/haveno/core/app/HavenoSetup.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ public class HavenoSetup {
158158
rejectedTxErrorMessageHandler;
159159
@Setter
160160
@Nullable
161+
private Consumer<Boolean> displayMoneroConnectionFallbackHandler;
162+
@Setter
163+
@Nullable
161164
private Consumer<Boolean> displayTorNetworkSettingsHandler;
162165
@Setter
163166
@Nullable
@@ -426,6 +429,12 @@ private void startP2pNetworkAndWallet(Runnable nextStep) {
426429
getXmrDaemonSyncProgress().addListener((observable, oldValue, newValue) -> resetStartupTimeout());
427430
getXmrWalletSyncProgress().addListener((observable, oldValue, newValue) -> resetStartupTimeout());
428431

432+
// listen for fallback handling
433+
getConnectionServiceFallbackProperty().addListener((observable, oldValue, newValue) -> {
434+
if (displayMoneroConnectionFallbackHandler == null) return;
435+
displayMoneroConnectionFallbackHandler.accept(newValue);
436+
});
437+
429438
log.info("Init P2P network");
430439
havenoSetupListeners.forEach(HavenoSetupListener::onInitP2pNetwork);
431440
p2pNetworkReady = p2PNetworkSetup.init(this::initWallet, displayTorNetworkSettingsHandler);
@@ -725,6 +734,10 @@ public StringProperty getConnectionServiceErrorMsg() {
725734
return xmrConnectionService.getConnectionServiceErrorMsg();
726735
}
727736

737+
public BooleanProperty getConnectionServiceFallbackProperty() {
738+
return xmrConnectionService.getConnectionServiceFallbackProperty();
739+
}
740+
728741
public StringProperty getTopErrorMsg() {
729742
return topErrorMsg;
730743
}

core/src/main/java/haveno/core/app/WalletAppSetup.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ void init(@Nullable Consumer<String> chainFileLockedExceptionHandler,
120120
@Nullable Runnable showPopupIfInvalidBtcConfigHandler,
121121
Runnable downloadCompleteHandler,
122122
Runnable walletInitializedHandler) {
123-
log.info("Initialize WalletAppSetup with monero-java version {}", MoneroUtils.getVersion());
123+
log.info("Initialize WalletAppSetup with monero-java v{}", MoneroUtils.getVersion());
124124

125125
ObjectProperty<Throwable> walletServiceException = new SimpleObjectProperty<>();
126126
xmrInfoBinding = EasyBind.combine(

core/src/main/resources/i18n/displayStrings.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2044,6 +2044,9 @@ closedTradesSummaryWindow.totalTradeFeeInXmr.title=Sum of all trade fees paid in
20442044
closedTradesSummaryWindow.totalTradeFeeInXmr.value={0} ({1} of total trade amount)
20452045
walletPasswordWindow.headline=Enter password to unlock
20462046

2047+
connectionFallback.headline=Connection error
2048+
connectionFallback.msg=Error connecting to your custom Monero node(s).\n\nDo you want to try the next best available Monero node?
2049+
20472050
torNetworkSettingWindow.header=Tor networks settings
20482051
torNetworkSettingWindow.noBridges=Don't use bridges
20492052
torNetworkSettingWindow.providedBridges=Connect with provided bridges

desktop/src/main/java/haveno/desktop/main/MainView.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,7 @@ private AnchorPane createFooter() {
674674
}
675675
} else {
676676
xmrInfoLabel.setId("footer-pane");
677+
xmrInfoLabel.getStyleClass().remove("error-text");
677678
if (xmrNetworkWarnMsgPopup != null)
678679
xmrNetworkWarnMsgPopup.hide();
679680
}

desktop/src/main/java/haveno/desktop/main/MainViewModel.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ public class MainViewModel implements ViewModel, HavenoSetup.HavenoSetupListener
140140
@SuppressWarnings("FieldCanBeLocal")
141141
private MonadicBinding<Boolean> tradesAndUIReady;
142142
private final Queue<Overlay<?>> popupQueue = new PriorityQueue<>(Comparator.comparing(Overlay::getDisplayOrderPriority));
143+
private Popup moneroConnectionFallbackPopup;
143144

144145

145146
///////////////////////////////////////////////////////////////////////////////////////////
@@ -334,9 +335,35 @@ private void setupHandlers() {
334335
tacWindow.onAction(acceptedHandler::run).show();
335336
}, 1));
336337

338+
havenoSetup.setDisplayMoneroConnectionFallbackHandler(show -> {
339+
if (moneroConnectionFallbackPopup == null) {
340+
moneroConnectionFallbackPopup = new Popup()
341+
.headLine(Res.get("connectionFallback.headline"))
342+
.warning(Res.get("connectionFallback.msg"))
343+
.closeButtonText(Res.get("shared.no"))
344+
.actionButtonText(Res.get("shared.yes"))
345+
.onAction(() -> new Thread(() -> HavenoUtils.xmrConnectionService.fallbackToBestConnection()).start())
346+
.onClose(() -> {
347+
log.warn("User has declined to fallback to the next best available Monero node.");
348+
havenoSetup.getConnectionServiceFallbackProperty().set(false);
349+
});
350+
}
351+
if (show) {
352+
moneroConnectionFallbackPopup.show();
353+
} else if (moneroConnectionFallbackPopup.isDisplayed()) {
354+
moneroConnectionFallbackPopup.hide();
355+
}
356+
});
357+
337358
havenoSetup.setDisplayTorNetworkSettingsHandler(show -> {
338359
if (show) {
339360
torNetworkSettingsWindow.show();
361+
362+
// bring connection fallback popup to front if displayed
363+
if (moneroConnectionFallbackPopup != null && moneroConnectionFallbackPopup.isDisplayed()) {
364+
moneroConnectionFallbackPopup.hide();
365+
moneroConnectionFallbackPopup.show();
366+
}
340367
} else if (torNetworkSettingsWindow.isDisplayed()) {
341368
torNetworkSettingsWindow.hide();
342369
}

0 commit comments

Comments
 (0)