mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 23:18:17 +01:00
Check if user has downgraded to an older version. If so require shutdown
and do not read or write persisted data. We had recently a case where a user downgraded from 1.4.2 to 1.3.9 and this caused failed trades and the wallet funds have been missing due to some complexities of the wallet wegwit upgrade. The fund could be recovered but it took quite some effort. As downgrade is never tested and can lead to all kind of weird bugs we should prevent that users accidentally can do it. If there is valid reason to downgrade they can remove the version file.
This commit is contained in:
parent
df9ef80edf
commit
9360e89ae8
5 changed files with 128 additions and 15 deletions
|
@ -68,6 +68,7 @@ public abstract class BisqExecutable implements GracefulShutDownHandler, BisqSet
|
|||
protected AppModule module;
|
||||
protected Config config;
|
||||
private boolean isShutdownInProgress;
|
||||
private boolean hasDowngraded;
|
||||
|
||||
public BisqExecutable(String fullName, String scriptName, String appName, String version) {
|
||||
this.fullName = fullName;
|
||||
|
@ -133,9 +134,17 @@ public abstract class BisqExecutable implements GracefulShutDownHandler, BisqSet
|
|||
CommonSetup.setupUncaughtExceptionHandler(this);
|
||||
setupGuice();
|
||||
setupAvoidStandbyMode();
|
||||
|
||||
hasDowngraded = BisqSetup.hasDowngraded();
|
||||
if (hasDowngraded) {
|
||||
// If user tried to downgrade we do not read the persisted data to avoid data corruption
|
||||
// We call startApplication to enable UI to show popup. We prevent in BisqSetup to go further
|
||||
// in the process and require a shut down.
|
||||
startApplication();
|
||||
} else {
|
||||
readAllPersisted(this::startApplication);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// We continue with a series of synchronous execution tasks
|
||||
|
@ -236,11 +245,16 @@ public abstract class BisqExecutable implements GracefulShutDownHandler, BisqSet
|
|||
injector.getInstance(P2PService.class).shutDown(() -> {
|
||||
log.info("P2PService shutdown completed");
|
||||
module.close(injector);
|
||||
if (!hasDowngraded) {
|
||||
// If user tried to downgrade we do not write the persistable data to avoid data corruption
|
||||
PersistenceManager.flushAllDataToDisk(() -> {
|
||||
log.info("Graceful shutdown completed. Exiting now.");
|
||||
resultHandler.handleResult();
|
||||
System.exit(EXIT_SUCCESS);
|
||||
});
|
||||
} else {
|
||||
System.exit(EXIT_SUCCESS);
|
||||
}
|
||||
});
|
||||
});
|
||||
walletsSetup.shutDown();
|
||||
|
@ -250,20 +264,31 @@ public abstract class BisqExecutable implements GracefulShutDownHandler, BisqSet
|
|||
// Wait max 20 sec.
|
||||
UserThread.runAfter(() -> {
|
||||
log.warn("Timeout triggered resultHandler");
|
||||
if (!hasDowngraded) {
|
||||
// If user tried to downgrade we do not write the persistable data to avoid data corruption
|
||||
PersistenceManager.flushAllDataToDisk(() -> {
|
||||
log.info("Graceful shutdown resulted in a timeout. Exiting now.");
|
||||
resultHandler.handleResult();
|
||||
System.exit(EXIT_SUCCESS);
|
||||
});
|
||||
} else {
|
||||
System.exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
}, 20);
|
||||
} catch (Throwable t) {
|
||||
log.error("App shutdown failed with exception {}", t.toString());
|
||||
t.printStackTrace();
|
||||
if (!hasDowngraded) {
|
||||
// If user tried to downgrade we do not write the persistable data to avoid data corruption
|
||||
PersistenceManager.flushAllDataToDisk(() -> {
|
||||
log.info("Graceful shutdown resulted in an error. Exiting now.");
|
||||
resultHandler.handleResult();
|
||||
System.exit(EXIT_FAILURE);
|
||||
});
|
||||
} else {
|
||||
System.exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ package bisq.core.app;
|
|||
import bisq.core.trade.TradeManager;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.app.Version;
|
||||
import bisq.common.file.CorruptedStorageFileHandler;
|
||||
import bisq.common.setup.GracefulShutDownHandler;
|
||||
|
||||
|
@ -94,6 +95,8 @@ public class BisqHeadlessApp implements HeadlessApp {
|
|||
bisqSetup.setRevolutAccountsUpdateHandler(revolutAccountList -> log.info("setRevolutAccountsUpdateHandler: revolutAccountList={}", revolutAccountList));
|
||||
bisqSetup.setOsxKeyLoggerWarningHandler(() -> log.info("setOsxKeyLoggerWarningHandler"));
|
||||
bisqSetup.setQubesOSInfoHandler(() -> log.info("setQubesOSInfoHandler"));
|
||||
bisqSetup.setDownGradePreventionHandler(lastVersion -> log.info("Downgrade from version {} to version {} is not supported",
|
||||
lastVersion, Version.VERSION));
|
||||
|
||||
corruptedStorageFileHandler.getFiles().ifPresent(files -> log.warn("getCorruptedDatabaseFiles. files={}", files));
|
||||
tradeManager.setTakeOfferRequestErrorMessageHandler(errorMessage -> log.error("onTakeOfferRequestErrorMessageHandler"));
|
||||
|
|
|
@ -48,6 +48,7 @@ import bisq.common.Timer;
|
|||
import bisq.common.UserThread;
|
||||
import bisq.common.app.DevEnv;
|
||||
import bisq.common.app.Log;
|
||||
import bisq.common.app.Version;
|
||||
import bisq.common.config.Config;
|
||||
import bisq.common.util.InvalidVersionException;
|
||||
import bisq.common.util.Utilities;
|
||||
|
@ -71,11 +72,15 @@ import javafx.collections.SetChangeListener;
|
|||
|
||||
import org.bouncycastle.crypto.params.KeyParameter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiConsumer;
|
||||
|
@ -92,6 +97,7 @@ import javax.annotation.Nullable;
|
|||
@Slf4j
|
||||
@Singleton
|
||||
public class BisqSetup {
|
||||
private static final String VERSION_FILE_NAME = "version";
|
||||
|
||||
public interface BisqSetupListener {
|
||||
default void onInitP2pNetwork() {
|
||||
|
@ -172,6 +178,9 @@ public class BisqSetup {
|
|||
@Setter
|
||||
@Nullable
|
||||
private Runnable qubesOSInfoHandler;
|
||||
@Setter
|
||||
@Nullable
|
||||
private Consumer<String> downGradePreventionHandler;
|
||||
|
||||
@Getter
|
||||
final BooleanProperty newVersionAvailableProperty = new SimpleBooleanProperty(false);
|
||||
|
@ -255,6 +264,12 @@ public class BisqSetup {
|
|||
}
|
||||
|
||||
public void start() {
|
||||
// If user tried to downgrade we require a shutdown
|
||||
if (hasDowngraded(downGradePreventionHandler)) {
|
||||
return;
|
||||
}
|
||||
|
||||
persistBisqVersion();
|
||||
maybeReSyncSPVChain();
|
||||
maybeShowTac(this::step2);
|
||||
}
|
||||
|
@ -487,6 +502,68 @@ public class BisqSetup {
|
|||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getLastBisqVersion() {
|
||||
File versionFile = getVersionFile();
|
||||
if (!versionFile.exists()) {
|
||||
return null;
|
||||
}
|
||||
try (Scanner scanner = new Scanner(versionFile)) {
|
||||
// We only expect 1 line
|
||||
if (scanner.hasNextLine()) {
|
||||
return scanner.nextLine();
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static File getVersionFile() {
|
||||
return new File(Config.appDataDir(), VERSION_FILE_NAME);
|
||||
}
|
||||
|
||||
public static boolean hasDowngraded() {
|
||||
return hasDowngraded(getLastBisqVersion());
|
||||
}
|
||||
|
||||
public static boolean hasDowngraded(String lastVersion) {
|
||||
return lastVersion != null && Version.isNewVersion(lastVersion, Version.VERSION);
|
||||
}
|
||||
|
||||
public static boolean hasDowngraded(@Nullable Consumer<String> downGradePreventionHandler) {
|
||||
String lastVersion = getLastBisqVersion();
|
||||
boolean hasDowngraded = hasDowngraded(lastVersion);
|
||||
if (hasDowngraded) {
|
||||
log.error("Downgrade from version {} to version {} is not supported", lastVersion, Version.VERSION);
|
||||
if (downGradePreventionHandler != null) {
|
||||
downGradePreventionHandler.accept(lastVersion);
|
||||
}
|
||||
}
|
||||
return hasDowngraded;
|
||||
}
|
||||
|
||||
public static void persistBisqVersion() {
|
||||
File versionFile = getVersionFile();
|
||||
if (!versionFile.exists()) {
|
||||
try {
|
||||
if (!versionFile.createNewFile()) {
|
||||
log.error("Version file could not be created");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error("Version file could not be created. {}", e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
try (FileWriter fileWriter = new FileWriter(versionFile, false)) {
|
||||
fileWriter.write(Version.VERSION);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error("Writing Version failed. {}", e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForCorrectOSArchitecture() {
|
||||
if (!Utilities.isCorrectOSArchitecture() && wrongOSArchitectureHandler != null) {
|
||||
String osArchitecture = Utilities.getOSArchitecture();
|
||||
|
|
|
@ -2819,6 +2819,7 @@ popup.info.shutDownWithOpenOffers=Bisq is being shut down, but there are open of
|
|||
(i.e., make sure it doesn't go into standby mode...monitor standby is not a problem).
|
||||
popup.info.qubesOSSetupInfo=It appears you are running Bisq on Qubes OS. \n\n\
|
||||
Please make sure your Bisq qube is setup according to our Setup Guide at [HYPERLINK:https://bisq.wiki/Running_Bisq_on_Qubes].
|
||||
popup.warn.downGradePrevention=Downgrade from version {0} to version {1} is not supported. Please use the latest Bisq version.
|
||||
|
||||
popup.privateNotification.headline=Important private notification!
|
||||
|
||||
|
|
|
@ -403,6 +403,13 @@ public class MainViewModel implements ViewModel, BisqSetup.BisqSetupListener {
|
|||
}
|
||||
});
|
||||
|
||||
bisqSetup.setDownGradePreventionHandler(lastVersion -> {
|
||||
new Popup().warning(Res.get("popup.warn.downGradePrevention", lastVersion, Version.VERSION))
|
||||
.useShutDownButton()
|
||||
.hideCloseButton()
|
||||
.show();
|
||||
});
|
||||
|
||||
corruptedStorageFileHandler.getFiles().ifPresent(files -> new Popup()
|
||||
.warning(Res.get("popup.warning.incompatibleDB", files.toString(), config.appDataDir))
|
||||
.useShutDownButton()
|
||||
|
|
Loading…
Add table
Reference in a new issue