Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add checkpoint at block 586920 #2

Merged
merged 1 commit into from
Jul 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@

package bisq.core.dao.monitoring;

import bisq.core.app.AppOptionKeys;
import bisq.core.dao.DaoSetupService;
import bisq.core.dao.monitoring.model.DaoStateBlock;
import bisq.core.dao.monitoring.model.DaoStateHash;
import bisq.core.dao.monitoring.model.UtxoMismatch;
import bisq.core.dao.monitoring.network.Checkpoint;
import bisq.core.dao.monitoring.network.DaoStateNetworkService;
import bisq.core.dao.monitoring.network.messages.GetDaoStateHashesRequest;
import bisq.core.dao.monitoring.network.messages.NewDaoStateHashMessage;
Expand All @@ -37,14 +39,21 @@

import bisq.common.UserThread;
import bisq.common.crypto.Hash;
import bisq.common.storage.FileManager;
import bisq.common.storage.Storage;
import bisq.common.util.Utilities;

import javax.inject.Inject;
import javax.inject.Named;

import org.apache.commons.lang3.ArrayUtils;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

import java.io.File;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -80,6 +89,8 @@ public class DaoStateMonitoringService implements DaoSetupService, DaoStateListe

public interface Listener {
void onChangeAfterBatchProcessing();

void onCheckpointFail();
}

private final DaoStateService daoStateService;
Expand All @@ -101,6 +112,13 @@ public interface Listener {
@Getter
private ObservableList<UtxoMismatch> utxoMismatches = FXCollections.observableArrayList();

private List<Checkpoint> checkpoints = Arrays.asList(
new Checkpoint(586920, Utilities.decodeFromHex("523aaad4e760f6ac6196fec1b3ec9a2f42e5b272"))
);
private boolean checkpointFailed;
private boolean ignoreDevMsg;

private final File storageDir;

///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
Expand All @@ -110,10 +128,14 @@ public interface Listener {
public DaoStateMonitoringService(DaoStateService daoStateService,
DaoStateNetworkService daoStateNetworkService,
GenesisTxInfo genesisTxInfo,
SeedNodeRepository seedNodeRepository) {
SeedNodeRepository seedNodeRepository,
@Named(Storage.STORAGE_DIR) File storageDir,
@Named(AppOptionKeys.IGNORE_DEV_MSG_KEY) boolean ignoreDevMsg) {
this.daoStateService = daoStateService;
this.daoStateNetworkService = daoStateNetworkService;
this.genesisTxInfo = genesisTxInfo;
this.storageDir = storageDir;
this.ignoreDevMsg = ignoreDevMsg;
seedNodeAddresses = seedNodeRepository.getSeedNodeAddresses().stream()
.map(NodeAddress::getFullAddress)
.collect(Collectors.toSet());
Expand Down Expand Up @@ -150,6 +172,10 @@ public void onParseBlockChainComplete() {
// We wait for processing messages until we have completed batch processing
int fromHeight = daoStateService.getChainHeight() - 10;
daoStateNetworkService.requestHashesFromAllConnectedSeedNodes(fromHeight);

if (!ignoreDevMsg) {
verifyCheckpoints();
}
}

@Override
Expand All @@ -167,6 +193,7 @@ public void onDaoStateChanged(Block block) {
}
}


///////////////////////////////////////////////////////////////////////////////////////////
// StateNetworkService.Listener
///////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -291,7 +318,8 @@ private void updateHashChain(Block block) {
}
}

private boolean processPeersDaoStateHash(DaoStateHash daoStateHash, Optional<NodeAddress> peersNodeAddress, boolean notifyListeners) {
private boolean processPeersDaoStateHash(DaoStateHash daoStateHash, Optional<NodeAddress> peersNodeAddress,
boolean notifyListeners) {
AtomicBoolean changed = new AtomicBoolean(false);
AtomicBoolean inConflictWithNonSeedNode = new AtomicBoolean(this.isInConflictWithNonSeedNode);
AtomicBoolean inConflictWithSeedNode = new AtomicBoolean(this.isInConflictWithSeedNode);
Expand Down Expand Up @@ -338,4 +366,49 @@ else if (this.isInConflictWithNonSeedNode)

return changed.get();
}

private void verifyCheckpoints() {
// Checkpoint
checkpoints.forEach(checkpoint -> daoStateHashChain.stream()
.filter(daoStateHash -> daoStateHash.getHeight() == checkpoint.getHeight())
.findAny()
.ifPresent(daoStateHash -> {
if (Arrays.equals(daoStateHash.getHash(), checkpoint.getHash())) {
log.info("Passed checkpoint {}", checkpoint.toString());
} else {
if (checkpointFailed) {
return;
}
checkpointFailed = true;
try {
// Delete state and stop
removeFile("DaoStateStore");
removeFile("BlindVoteStore");
removeFile("ProposalStore");
removeFile("TempProposalStore");

listeners.forEach(Listener::onCheckpointFail);
log.error("Failed checkpoint {}", checkpoint.toString());
} catch (Throwable t) {
t.printStackTrace();
log.error(t.toString());
}
}
}));
}

private void removeFile(String storeName) {
long currentTime = System.currentTimeMillis();
String newFileName = storeName + "_" + currentTime;
String backupDirName = "out_of_sync_dao_data";
File corrupted = new File(storageDir, storeName);
try {
if (corrupted.exists()) {
FileManager.removeAndBackupFile(storageDir, corrupted, newFileName, backupDirName);
}
} catch (Throwable t) {
t.printStackTrace();
log.error(t.toString());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* This file is part of Bisq.
*
* Bisq is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bisq is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/

package bisq.core.dao.monitoring.network;

import bisq.common.util.Utilities;

import lombok.Getter;
import lombok.Setter;

@Getter
public class Checkpoint {
final int height;
final byte[] hash;
@Setter
boolean passed;

public Checkpoint(int height, byte[] hash) {
this.height = height;
this.hash = hash;
}

@Override
public String toString() {
return "Checkpoint {" +
"\n height=" + height +
",\n hash=" + Utilities.bytesAsHexString(hash) +
"\n}";
}

}
2 changes: 2 additions & 0 deletions core/src/main/resources/i18n/displayStrings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1971,6 +1971,8 @@ dao.monitor.daoState.utxoConflicts=UTXO conflicts
dao.monitor.daoState.utxoConflicts.blockHeight=Block height: {0}
dao.monitor.daoState.utxoConflicts.sumUtxo=Sum of all UTXO: {0} BSQ
dao.monitor.daoState.utxoConflicts.sumBsq=Sum of all BSQ: {0} BSQ
dao.monitor.daoState.checkpoint.popup=DAO state is not in sync with the network. \
After restart the DAO state will resync.

dao.monitor.proposal.headline=Proposals state
dao.monitor.proposal.table.headline=Chain of proposal state hashes
Expand Down
32 changes: 30 additions & 2 deletions desktop/src/main/java/bisq/desktop/main/MainView.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import bisq.desktop.main.settings.SettingsView;
import bisq.desktop.util.Transitions;

import bisq.core.dao.monitoring.DaoStateMonitoringService;
import bisq.core.exceptions.BisqException;
import bisq.core.locale.GlobalSettings;
import bisq.core.locale.Res;
Expand Down Expand Up @@ -104,7 +105,8 @@

@FxmlView
@Slf4j
public class MainView extends InitializableView<StackPane, MainViewModel> {
public class MainView extends InitializableView<StackPane, MainViewModel>
implements DaoStateMonitoringService.Listener {
// If after 30 sec we have not got connected we show "open network settings" button
private final static int SHOW_TOR_SETTINGS_DELAY_SEC = 90;
private Label versionLabel;
Expand Down Expand Up @@ -150,18 +152,21 @@ public static void removeEffect() {
private ProgressBar btcSyncIndicator, p2pNetworkProgressBar;
private Label btcSplashInfo;
private Popup<?> p2PNetworkWarnMsgPopup, btcNetworkWarnMsgPopup;
private final DaoStateMonitoringService daoStateMonitoringService;

@Inject
public MainView(MainViewModel model,
CachingViewLoader viewLoader,
Navigation navigation,
Transitions transitions,
BSFormatter formatter) {
BSFormatter formatter,
DaoStateMonitoringService daoStateMonitoringService) {
super(model);
this.viewLoader = viewLoader;
this.navigation = navigation;
this.formatter = formatter;
MainView.transitions = transitions;
this.daoStateMonitoringService = daoStateMonitoringService;
}

@Override
Expand Down Expand Up @@ -387,10 +392,33 @@ protected Tooltip computeValue() {
}
});

daoStateMonitoringService.addListener(this);

// Delay a bit to give time for rendering the splash screen
UserThread.execute(() -> onUiReadyHandler.run());
}

///////////////////////////////////////////////////////////////////////////////////////////
// DaoStateMonitoringService.Listener
///////////////////////////////////////////////////////////////////////////////////////////

@Override
public void onChangeAfterBatchProcessing() {
}

@Override
public void onCheckpointFail() {
new Popup<>().attention(Res.get("dao.monitor.daoState.checkpoint.popup"))
.useShutDownButton()
.hideCloseButton()
.show();
}


///////////////////////////////////////////////////////////////////////////////////////////
// Helpers
///////////////////////////////////////////////////////////////////////////////////////////

@NotNull
private Separator getNavigationSeparator() {
final Separator separator = new Separator(Orientation.VERTICAL);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ public void onChangeAfterBatchProcessing() {
}
}

@Override
public void onCheckpointFail() {
}

///////////////////////////////////////////////////////////////////////////////////////////
// Implementation abstract methods
Expand Down