From f7dfef253ad2f944fb619de21eefea018d7bdd4d Mon Sep 17 00:00:00 2001 From: chimp1984 Date: Tue, 28 Apr 2020 15:18:11 -0500 Subject: [PATCH] Add resync from resources button We add a second button (displayed as first) to the preferences UI for resync from latest resources. We add a warning to the resync from genesis as it takes very long time and causes heavy network load for seeds. The resync button at the stateMonitor does now a resync from resources, not from genesis. We add handling of the UnconfirmedBsqChangeOutputList file as well. In Filemanager we add a check if file exists. --- .../java/bisq/common/storage/FileManager.java | 4 +- .../main/java/bisq/core/dao/DaoFacade.java | 14 ++++-- .../dao/state/DaoStateStorageService.java | 26 +++++++++- .../resources/i18n/displayStrings.properties | 11 +++-- .../main/dao/monitor/StateMonitorView.java | 49 +++++++------------ .../settings/preferences/PreferencesView.java | 46 +++++++++++++---- 6 files changed, 101 insertions(+), 49 deletions(-) diff --git a/common/src/main/java/bisq/common/storage/FileManager.java b/common/src/main/java/bisq/common/storage/FileManager.java index 06ae86b869..c0eed50821 100644 --- a/common/src/main/java/bisq/common/storage/FileManager.java +++ b/common/src/main/java/bisq/common/storage/FileManager.java @@ -165,7 +165,9 @@ public class FileManager { log.warn("make dir failed"); File corruptedFile = new File(Paths.get(dbDir.getAbsolutePath(), backupFolderName, fileName).toString()); - FileUtil.renameFile(storageFile, corruptedFile); + if (storageFile.exists()) { + FileUtil.renameFile(storageFile, corruptedFile); + } } synchronized void removeAndBackupFile(String fileName) throws IOException { diff --git a/core/src/main/java/bisq/core/dao/DaoFacade.java b/core/src/main/java/bisq/core/dao/DaoFacade.java index 15712f5ab7..1485ae2546 100644 --- a/core/src/main/java/bisq/core/dao/DaoFacade.java +++ b/core/src/main/java/bisq/core/dao/DaoFacade.java @@ -91,6 +91,7 @@ import javafx.beans.property.SimpleObjectProperty; import javafx.collections.ObservableList; import javafx.collections.transformation.FilteredList; +import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -517,7 +518,10 @@ public class DaoFacade implements DaoSetupService { lockupTxService.publishLockupTx(lockupAmount, lockTime, lockupReason, hash, resultHandler, exceptionHandler); } - public Tuple2 getLockupTxMiningFeeAndTxSize(Coin lockupAmount, int lockTime, LockupReason lockupReason, byte[] hash) + public Tuple2 getLockupTxMiningFeeAndTxSize(Coin lockupAmount, + int lockTime, + LockupReason lockupReason, + byte[] hash) throws InsufficientMoneyException, IOException, TransactionVerificationException, WalletException { return lockupTxService.getMiningFeeAndTxSize(lockupAmount, lockTime, lockupReason, hash); } @@ -700,8 +704,12 @@ public class DaoFacade implements DaoSetupService { return daoStateService.getParamValue(param, blockHeight); } - public void resyncDao(Runnable resultHandler) { - daoStateStorageService.resetDaoState(resultHandler); + public void resyncDaoStateFromGenesis(Runnable resultHandler) { + daoStateStorageService.resyncDaoStateFromGenesis(resultHandler); + } + + public void resyncDaoStateFromResources(File storageDir) throws IOException { + daoStateStorageService.resyncDaoStateFromResources(storageDir); } public boolean isMyRole(Role role) { diff --git a/core/src/main/java/bisq/core/dao/state/DaoStateStorageService.java b/core/src/main/java/bisq/core/dao/state/DaoStateStorageService.java index 2e1e9abd1d..8571eb2b12 100644 --- a/core/src/main/java/bisq/core/dao/state/DaoStateStorageService.java +++ b/core/src/main/java/bisq/core/dao/state/DaoStateStorageService.java @@ -26,12 +26,14 @@ import bisq.network.p2p.storage.persistence.StoreService; import bisq.common.UserThread; import bisq.common.config.Config; +import bisq.common.storage.FileManager; import bisq.common.storage.Storage; import javax.inject.Inject; import javax.inject.Named; import java.io.File; +import java.io.IOException; import java.util.LinkedList; import java.util.concurrent.TimeUnit; @@ -101,11 +103,33 @@ public class DaoStateStorageService extends StoreService { return store.getDaoStateHashChain(); } - public void resetDaoState(Runnable resultHandler) { + public void resyncDaoStateFromGenesis(Runnable resultHandler) { persist(new DaoState(), new LinkedList<>(), 1); UserThread.runAfter(resultHandler, 300, TimeUnit.MILLISECONDS); } + public void resyncDaoStateFromResources(File storageDir) throws IOException { + // We delete all DAO consensus payload data and remove the daoState so it will rebuild from latest + // resource files. + long currentTime = System.currentTimeMillis(); + String backupDirName = "out_of_sync_dao_data"; + String newFileName = "BlindVoteStore_" + currentTime; + FileManager.removeAndBackupFile(storageDir, new File(storageDir, "BlindVoteStore"), newFileName, backupDirName); + + newFileName = "ProposalStore_" + currentTime; + FileManager.removeAndBackupFile(storageDir, new File(storageDir, "ProposalStore"), newFileName, backupDirName); + + // We also need to remove ballot list as it contains the proposals as well. It will be recreated at resync + newFileName = "BallotList_" + currentTime; + FileManager.removeAndBackupFile(storageDir, new File(storageDir, "BallotList"), newFileName, backupDirName); + + newFileName = "UnconfirmedBsqChangeOutputList_" + currentTime; + FileManager.removeAndBackupFile(storageDir, new File(storageDir, "UnconfirmedBsqChangeOutputList"), newFileName, backupDirName); + + newFileName = "DaoStateStore_" + currentTime; + FileManager.removeAndBackupFile(storageDir, new File(storageDir, "DaoStateStore"), newFileName, backupDirName); + } + /////////////////////////////////////////////////////////////////////////////////////////// // Protected diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index e477ce6e9a..ed7e335087 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -1074,10 +1074,15 @@ settings.preferences.languageChange=To apply the language change to all screens settings.preferences.supportLanguageWarning=In case of a dispute, please note that mediation is handled in {0} and arbitration in {1}. settings.preferences.selectCurrencyNetwork=Select network setting.preferences.daoOptions=DAO options -setting.preferences.dao.resync.label=Rebuild DAO state from genesis tx -setting.preferences.dao.resync.button=Resync -setting.preferences.dao.resync.popup=After an application restart the Bisq network governance data will be reloaded from \ +setting.preferences.dao.resyncFromGenesis.label=Rebuild DAO state from genesis tx +setting.preferences.dao.resyncFromResources.label=Rebuild DAO state from resources +setting.preferences.dao.resyncFromResources.popup=After an application restart the Bisq network governance data will be reloaded from \ + the seed nodes and the BSQ consensus state will be rebuilt from the latest resource files. +setting.preferences.dao.resyncFromGenesis.popup=A resync from genesis transaction can take considerable time and CPU \ + resources. Are you sure you want to do that? Mostly a resync from latest resource files is sufficient and much faster.\n\n\ + If you proceed, after an application restart the Bisq network governance data will be reloaded from \ the seed nodes and the BSQ consensus state will be rebuilt from the genesis transaction. +setting.preferences.dao.resyncFromGenesis.resync=Resync from genesis and shutdown setting.preferences.dao.isDaoFullNode=Run Bisq as DAO full node setting.preferences.dao.rpcUser=RPC username setting.preferences.dao.rpcPw=RPC password diff --git a/desktop/src/main/java/bisq/desktop/main/dao/monitor/StateMonitorView.java b/desktop/src/main/java/bisq/desktop/main/dao/monitor/StateMonitorView.java index f815e6e0c9..962ca6eaf2 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/monitor/StateMonitorView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/monitor/StateMonitorView.java @@ -18,7 +18,6 @@ package bisq.desktop.main.dao.monitor; import bisq.desktop.common.view.ActivatableView; -import bisq.desktop.common.view.FxmlView; import bisq.desktop.components.AutoTooltipButton; import bisq.desktop.components.AutoTooltipLabel; import bisq.desktop.components.AutoTooltipTableColumn; @@ -40,8 +39,6 @@ import bisq.core.locale.Res; import bisq.network.p2p.NodeAddress; import bisq.network.p2p.seed.SeedNodeRepository; -import bisq.common.storage.FileManager; - import de.jensd.fx.fontawesome.AwesomeIcon; import javafx.scene.control.Button; @@ -140,33 +137,7 @@ public abstract class StateMonitorView { - try { - // We delete all consensus payload data and reset the daoState so it will rebuild from genesis. - // Deleting the daoState would cause to read the file from the resources and we would not rebuild from - // genesis if a snapshot exist! - long currentTime = System.currentTimeMillis(); - String backupDirName = "out_of_sync_dao_data"; - String newFileName = "BlindVoteStore_" + currentTime; - FileManager.removeAndBackupFile(storageDir, new File(storageDir, "BlindVoteStore"), newFileName, backupDirName); - - newFileName = "ProposalStore_" + currentTime; - FileManager.removeAndBackupFile(storageDir, new File(storageDir, "ProposalStore"), newFileName, backupDirName); - - // We also need to remove ballot list as it contains the proposals as well. It will be recreated at resync - newFileName = "BallotList_" + currentTime; - FileManager.removeAndBackupFile(storageDir, new File(storageDir, "BallotList"), newFileName, backupDirName); - - daoFacade.resyncDao(() -> new Popup().attention(Res.get("setting.preferences.dao.resync.popup")) - .useShutDownButton() - .hideCloseButton() - .show()); - } catch (Throwable t) { - t.printStackTrace(); - log.error(t.toString()); - new Popup().error(t.toString()).show(); - } - }); + resyncButton.setOnAction(ev -> resyncDaoState()); if (daoStateService.isParseBlockChainComplete()) { onDataUpdate(); @@ -294,7 +265,9 @@ public abstract class StateMonitorView fiatCurrenciesListView; private ComboBox fiatCurrenciesComboBox; private ListView cryptoCurrenciesListView; private ComboBox cryptoCurrenciesComboBox; - private Button resetDontShowAgainButton, resyncDaoButton; + private Button resetDontShowAgainButton, resyncDaoFromGenesisButton, resyncDaoFromResourcesButton; // private ListChangeListener displayCurrenciesListChangeListener; private ObservableList blockExplorers; private ObservableList bsqBlockChainExplorers; @@ -162,13 +166,15 @@ public class PreferencesView extends ActivatableViewAndModel 0 ? String.valueOf(blockNotifyPort) : ""); updateDaoFields(); - resyncDaoButton.setOnAction(e -> daoFacade.resyncDao(() -> - new Popup().attention(Res.get("setting.preferences.dao.resync.popup")) + resyncDaoFromResourcesButton.setOnAction(e -> { + try { + daoFacade.resyncDaoStateFromResources(storageDir); + new Popup().attention(Res.get("setting.preferences.dao.resyncFromResources.popup")) .useShutDownButton() .hideCloseButton() - .show())); + .show(); + } catch (Throwable t) { + t.printStackTrace(); + log.error(t.toString()); + new Popup().error(t.toString()).show(); + } + }); + + resyncDaoFromGenesisButton.setOnAction(e -> + new Popup().attention(Res.get("setting.preferences.dao.resyncFromGenesis.popup")) + .actionButtonText(Res.get("setting.preferences.dao.resyncFromGenesis.resync")) + .onAction(() -> daoFacade.resyncDaoStateFromGenesis(() -> BisqApp.getShutDownHandler().run())) + .closeButtonText(Res.get("shared.cancel")) + .show()); isDaoFullNodeToggleButton.setOnAction(e -> { String key = "daoFullModeInfoShown"; @@ -973,7 +998,8 @@ public class PreferencesView extends ActivatableViewAndModel