mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-22 06:41:41 +01:00
Merge pull request #2674 from ManfredKarrer/add-more-info-to-dao-monitor
Handle dao state conflicts better
This commit is contained in:
commit
2945150e7e
13 changed files with 239 additions and 117 deletions
|
@ -162,16 +162,21 @@ public class FileManager<T extends PersistableEnvelope> {
|
|||
}
|
||||
}
|
||||
|
||||
public synchronized void removeAndBackupFile(String fileName) throws IOException {
|
||||
File corruptedBackupDir = new File(Paths.get(dir.getAbsolutePath(), "backup_of_corrupted_data").toString());
|
||||
public static void removeAndBackupFile(File dbDir, File storageFile, String fileName, String backupFolderName)
|
||||
throws IOException {
|
||||
File corruptedBackupDir = new File(Paths.get(dbDir.getAbsolutePath(), backupFolderName).toString());
|
||||
if (!corruptedBackupDir.exists())
|
||||
if (!corruptedBackupDir.mkdir())
|
||||
log.warn("make dir failed");
|
||||
|
||||
File corruptedFile = new File(Paths.get(dir.getAbsolutePath(), "backup_of_corrupted_data", fileName).toString());
|
||||
File corruptedFile = new File(Paths.get(dbDir.getAbsolutePath(), backupFolderName, fileName).toString());
|
||||
FileUtil.renameFile(storageFile, corruptedFile);
|
||||
}
|
||||
|
||||
public synchronized void removeAndBackupFile(String fileName) throws IOException {
|
||||
removeAndBackupFile(dir, storageFile, fileName, "backup_of_corrupted_data");
|
||||
}
|
||||
|
||||
public synchronized void backupFile(String fileName, int numMaxBackupFiles) {
|
||||
FileUtil.rollingBackup(dir, fileName, numMaxBackupFiles);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import bisq.core.dao.state.model.governance.DaoPhase;
|
|||
|
||||
import bisq.network.p2p.NodeAddress;
|
||||
import bisq.network.p2p.network.Connection;
|
||||
import bisq.network.p2p.seed.SeedNodeRepository;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.crypto.Hash;
|
||||
|
@ -49,6 +50,7 @@ import java.util.LinkedList;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -81,6 +83,7 @@ public class BlindVoteStateMonitoringService implements DaoSetupService, DaoStat
|
|||
private final GenesisTxInfo genesisTxInfo;
|
||||
private final PeriodService periodService;
|
||||
private final BlindVoteListService blindVoteListService;
|
||||
private final Set<String> seedNodeAddresses;
|
||||
|
||||
@Getter
|
||||
private final LinkedList<BlindVoteStateBlock> blindVoteStateBlockChain = new LinkedList<>();
|
||||
|
@ -88,7 +91,9 @@ public class BlindVoteStateMonitoringService implements DaoSetupService, DaoStat
|
|||
private final LinkedList<BlindVoteStateHash> blindVoteStateHashChain = new LinkedList<>();
|
||||
private final List<Listener> listeners = new CopyOnWriteArrayList<>();
|
||||
@Getter
|
||||
private boolean isInConflict;
|
||||
private boolean isInConflictWithNonSeedNode;
|
||||
@Getter
|
||||
private boolean isInConflictWithSeedNode;
|
||||
private boolean parseBlockChainComplete;
|
||||
|
||||
|
||||
|
@ -101,12 +106,16 @@ public class BlindVoteStateMonitoringService implements DaoSetupService, DaoStat
|
|||
BlindVoteStateNetworkService blindVoteStateNetworkService,
|
||||
GenesisTxInfo genesisTxInfo,
|
||||
PeriodService periodService,
|
||||
BlindVoteListService blindVoteListService) {
|
||||
BlindVoteListService blindVoteListService,
|
||||
SeedNodeRepository seedNodeRepository) {
|
||||
this.daoStateService = daoStateService;
|
||||
this.blindVoteStateNetworkService = blindVoteStateNetworkService;
|
||||
this.genesisTxInfo = genesisTxInfo;
|
||||
this.periodService = periodService;
|
||||
this.blindVoteListService = blindVoteListService;
|
||||
seedNodeAddresses = seedNodeRepository.getSeedNodeAddresses().stream()
|
||||
.map(NodeAddress::getFullAddress)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
|
||||
|
@ -276,7 +285,8 @@ public class BlindVoteStateMonitoringService implements DaoSetupService, DaoStat
|
|||
|
||||
private boolean processPeersBlindVoteStateHash(BlindVoteStateHash blindVoteStateHash, Optional<NodeAddress> peersNodeAddress, boolean notifyListeners) {
|
||||
AtomicBoolean changed = new AtomicBoolean(false);
|
||||
AtomicBoolean isInConflict = new AtomicBoolean(this.isInConflict);
|
||||
AtomicBoolean inConflictWithNonSeedNode = new AtomicBoolean(this.isInConflictWithNonSeedNode);
|
||||
AtomicBoolean inConflictWithSeedNode = new AtomicBoolean(this.isInConflictWithSeedNode);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
blindVoteStateBlockChain.stream()
|
||||
.filter(e -> e.getHeight() == blindVoteStateHash.getHeight()).findAny()
|
||||
|
@ -286,7 +296,12 @@ public class BlindVoteStateMonitoringService implements DaoSetupService, DaoStat
|
|||
daoStateBlock.putInPeersMap(peersNodeAddressAsString, blindVoteStateHash);
|
||||
if (!daoStateBlock.getMyStateHash().hasEqualHash(blindVoteStateHash)) {
|
||||
daoStateBlock.putInConflictMap(peersNodeAddressAsString, blindVoteStateHash);
|
||||
isInConflict.set(true);
|
||||
if (seedNodeAddresses.contains(peersNodeAddressAsString)) {
|
||||
inConflictWithSeedNode.set(true);
|
||||
} else {
|
||||
inConflictWithNonSeedNode.set(true);
|
||||
}
|
||||
|
||||
sb.append("We received a block hash from peer ")
|
||||
.append(peersNodeAddressAsString)
|
||||
.append(" which conflicts with our block hash.\n")
|
||||
|
@ -298,11 +313,15 @@ public class BlindVoteStateMonitoringService implements DaoSetupService, DaoStat
|
|||
changed.set(true);
|
||||
});
|
||||
|
||||
this.isInConflict = isInConflict.get();
|
||||
this.isInConflictWithNonSeedNode = inConflictWithNonSeedNode.get();
|
||||
this.isInConflictWithSeedNode = inConflictWithSeedNode.get();
|
||||
|
||||
String conflictMsg = sb.toString();
|
||||
if (this.isInConflict && !conflictMsg.isEmpty()) {
|
||||
log.warn(conflictMsg);
|
||||
if (!conflictMsg.isEmpty()) {
|
||||
if (this.isInConflictWithSeedNode)
|
||||
log.warn("Conflict with seed nodes: {}", conflictMsg);
|
||||
else if (this.isInConflictWithNonSeedNode)
|
||||
log.info("Conflict with non-seed nodes: {}", conflictMsg);
|
||||
}
|
||||
|
||||
if (notifyListeners && changed.get()) {
|
||||
|
|
|
@ -33,6 +33,7 @@ import bisq.core.dao.state.model.governance.IssuanceType;
|
|||
|
||||
import bisq.network.p2p.NodeAddress;
|
||||
import bisq.network.p2p.network.Connection;
|
||||
import bisq.network.p2p.seed.SeedNodeRepository;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.crypto.Hash;
|
||||
|
@ -48,6 +49,7 @@ import java.util.LinkedList;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -83,6 +85,8 @@ public class DaoStateMonitoringService implements DaoSetupService, DaoStateListe
|
|||
private final DaoStateService daoStateService;
|
||||
private final DaoStateNetworkService daoStateNetworkService;
|
||||
private final GenesisTxInfo genesisTxInfo;
|
||||
private final Set<String> seedNodeAddresses;
|
||||
|
||||
|
||||
@Getter
|
||||
private final LinkedList<DaoStateBlock> daoStateBlockChain = new LinkedList<>();
|
||||
|
@ -91,7 +95,9 @@ public class DaoStateMonitoringService implements DaoSetupService, DaoStateListe
|
|||
private final List<Listener> listeners = new CopyOnWriteArrayList<>();
|
||||
private boolean parseBlockChainComplete;
|
||||
@Getter
|
||||
private boolean isInConflict;
|
||||
private boolean isInConflictWithNonSeedNode;
|
||||
@Getter
|
||||
private boolean isInConflictWithSeedNode;
|
||||
@Getter
|
||||
private ObservableList<UtxoMismatch> utxoMismatches = FXCollections.observableArrayList();
|
||||
|
||||
|
@ -103,10 +109,14 @@ public class DaoStateMonitoringService implements DaoSetupService, DaoStateListe
|
|||
@Inject
|
||||
public DaoStateMonitoringService(DaoStateService daoStateService,
|
||||
DaoStateNetworkService daoStateNetworkService,
|
||||
GenesisTxInfo genesisTxInfo) {
|
||||
GenesisTxInfo genesisTxInfo,
|
||||
SeedNodeRepository seedNodeRepository) {
|
||||
this.daoStateService = daoStateService;
|
||||
this.daoStateNetworkService = daoStateNetworkService;
|
||||
this.genesisTxInfo = genesisTxInfo;
|
||||
seedNodeAddresses = seedNodeRepository.getSeedNodeAddresses().stream()
|
||||
.map(NodeAddress::getFullAddress)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
|
||||
|
@ -283,7 +293,8 @@ public class DaoStateMonitoringService implements DaoSetupService, DaoStateListe
|
|||
|
||||
private boolean processPeersDaoStateHash(DaoStateHash daoStateHash, Optional<NodeAddress> peersNodeAddress, boolean notifyListeners) {
|
||||
AtomicBoolean changed = new AtomicBoolean(false);
|
||||
AtomicBoolean isInConflict = new AtomicBoolean(this.isInConflict);
|
||||
AtomicBoolean inConflictWithNonSeedNode = new AtomicBoolean(this.isInConflictWithNonSeedNode);
|
||||
AtomicBoolean inConflictWithSeedNode = new AtomicBoolean(this.isInConflictWithSeedNode);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
daoStateBlockChain.stream()
|
||||
.filter(e -> e.getHeight() == daoStateHash.getHeight()).findAny()
|
||||
|
@ -293,7 +304,11 @@ public class DaoStateMonitoringService implements DaoSetupService, DaoStateListe
|
|||
daoStateBlock.putInPeersMap(peersNodeAddressAsString, daoStateHash);
|
||||
if (!daoStateBlock.getMyStateHash().hasEqualHash(daoStateHash)) {
|
||||
daoStateBlock.putInConflictMap(peersNodeAddressAsString, daoStateHash);
|
||||
isInConflict.set(true);
|
||||
if (seedNodeAddresses.contains(peersNodeAddressAsString)) {
|
||||
inConflictWithSeedNode.set(true);
|
||||
} else {
|
||||
inConflictWithNonSeedNode.set(true);
|
||||
}
|
||||
sb.append("We received a block hash from peer ")
|
||||
.append(peersNodeAddressAsString)
|
||||
.append(" which conflicts with our block hash.\n")
|
||||
|
@ -305,13 +320,18 @@ public class DaoStateMonitoringService implements DaoSetupService, DaoStateListe
|
|||
changed.set(true);
|
||||
});
|
||||
|
||||
this.isInConflict = isInConflict.get();
|
||||
this.isInConflictWithNonSeedNode = inConflictWithNonSeedNode.get();
|
||||
this.isInConflictWithSeedNode = inConflictWithSeedNode.get();
|
||||
|
||||
String conflictMsg = sb.toString();
|
||||
if (this.isInConflict && !conflictMsg.isEmpty()) {
|
||||
log.warn(conflictMsg);
|
||||
if (!conflictMsg.isEmpty()) {
|
||||
if (this.isInConflictWithSeedNode)
|
||||
log.warn("Conflict with seed nodes: {}", conflictMsg);
|
||||
else if (this.isInConflictWithNonSeedNode)
|
||||
log.info("Conflict with non-seed nodes: {}", conflictMsg);
|
||||
}
|
||||
|
||||
|
||||
if (notifyListeners && changed.get()) {
|
||||
listeners.forEach(Listener::onChangeAfterBatchProcessing);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import bisq.core.dao.state.model.governance.Proposal;
|
|||
|
||||
import bisq.network.p2p.NodeAddress;
|
||||
import bisq.network.p2p.network.Connection;
|
||||
import bisq.network.p2p.seed.SeedNodeRepository;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.crypto.Hash;
|
||||
|
@ -49,6 +50,7 @@ import java.util.LinkedList;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -81,6 +83,8 @@ public class ProposalStateMonitoringService implements DaoSetupService, DaoState
|
|||
private final GenesisTxInfo genesisTxInfo;
|
||||
private final PeriodService periodService;
|
||||
private final ProposalService proposalService;
|
||||
private final Set<String> seedNodeAddresses;
|
||||
|
||||
|
||||
@Getter
|
||||
private final LinkedList<ProposalStateBlock> proposalStateBlockChain = new LinkedList<>();
|
||||
|
@ -88,7 +92,9 @@ public class ProposalStateMonitoringService implements DaoSetupService, DaoState
|
|||
private final LinkedList<ProposalStateHash> proposalStateHashChain = new LinkedList<>();
|
||||
private final List<Listener> listeners = new CopyOnWriteArrayList<>();
|
||||
@Getter
|
||||
private boolean isInConflict;
|
||||
private boolean isInConflictWithNonSeedNode;
|
||||
@Getter
|
||||
private boolean isInConflictWithSeedNode;
|
||||
private boolean parseBlockChainComplete;
|
||||
|
||||
|
||||
|
@ -101,12 +107,16 @@ public class ProposalStateMonitoringService implements DaoSetupService, DaoState
|
|||
ProposalStateNetworkService proposalStateNetworkService,
|
||||
GenesisTxInfo genesisTxInfo,
|
||||
PeriodService periodService,
|
||||
ProposalService proposalService) {
|
||||
ProposalService proposalService,
|
||||
SeedNodeRepository seedNodeRepository) {
|
||||
this.daoStateService = daoStateService;
|
||||
this.proposalStateNetworkService = proposalStateNetworkService;
|
||||
this.genesisTxInfo = genesisTxInfo;
|
||||
this.periodService = periodService;
|
||||
this.proposalService = proposalService;
|
||||
seedNodeAddresses = seedNodeRepository.getSeedNodeAddresses().stream()
|
||||
.map(NodeAddress::getFullAddress)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
|
||||
|
@ -280,7 +290,8 @@ public class ProposalStateMonitoringService implements DaoSetupService, DaoState
|
|||
|
||||
private boolean processPeersProposalStateHash(ProposalStateHash proposalStateHash, Optional<NodeAddress> peersNodeAddress, boolean notifyListeners) {
|
||||
AtomicBoolean changed = new AtomicBoolean(false);
|
||||
AtomicBoolean isInConflict = new AtomicBoolean(this.isInConflict);
|
||||
AtomicBoolean inConflictWithNonSeedNode = new AtomicBoolean(this.isInConflictWithNonSeedNode);
|
||||
AtomicBoolean inConflictWithSeedNode = new AtomicBoolean(this.isInConflictWithSeedNode);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
proposalStateBlockChain.stream()
|
||||
.filter(e -> e.getHeight() == proposalStateHash.getHeight()).findAny()
|
||||
|
@ -290,7 +301,11 @@ public class ProposalStateMonitoringService implements DaoSetupService, DaoState
|
|||
daoStateBlock.putInPeersMap(peersNodeAddressAsString, proposalStateHash);
|
||||
if (!daoStateBlock.getMyStateHash().hasEqualHash(proposalStateHash)) {
|
||||
daoStateBlock.putInConflictMap(peersNodeAddressAsString, proposalStateHash);
|
||||
isInConflict.set(true);
|
||||
if (seedNodeAddresses.contains(peersNodeAddressAsString)) {
|
||||
inConflictWithSeedNode.set(true);
|
||||
} else {
|
||||
inConflictWithNonSeedNode.set(true);
|
||||
}
|
||||
sb.append("We received a block hash from peer ")
|
||||
.append(peersNodeAddressAsString)
|
||||
.append(" which conflicts with our block hash.\n")
|
||||
|
@ -302,11 +317,15 @@ public class ProposalStateMonitoringService implements DaoSetupService, DaoState
|
|||
changed.set(true);
|
||||
});
|
||||
|
||||
this.isInConflict = isInConflict.get();
|
||||
this.isInConflictWithNonSeedNode = inConflictWithNonSeedNode.get();
|
||||
this.isInConflictWithSeedNode = inConflictWithSeedNode.get();
|
||||
|
||||
String conflictMsg = sb.toString();
|
||||
if (this.isInConflict && !conflictMsg.isEmpty()) {
|
||||
log.warn(conflictMsg);
|
||||
if (!conflictMsg.isEmpty()) {
|
||||
if (this.isInConflictWithSeedNode)
|
||||
log.warn("Conflict with seed nodes: {}", conflictMsg);
|
||||
else if (this.isInConflictWithNonSeedNode)
|
||||
log.info("Conflict with non-seed nodes: {}", conflictMsg);
|
||||
}
|
||||
|
||||
if (notifyListeners && changed.get()) {
|
||||
|
|
|
@ -910,7 +910,8 @@ 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 BSQ consensus state will be rebuilt from the genesis transaction.
|
||||
setting.preferences.dao.resync.popup=After an application restart the P2P 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.isDaoFullNode=Run Bisq as DAO full node
|
||||
setting.preferences.dao.rpcUser=RPC username
|
||||
setting.preferences.dao.rpcPw=RPC password
|
||||
|
@ -1904,11 +1905,9 @@ dao.monitor.requestAlHashes=Request all hashes
|
|||
dao.monitor.resync=Resync DAO state
|
||||
dao.monitor.table.header.cycleBlockHeight=Cycle / block height
|
||||
dao.monitor.table.cycleBlockHeight=Cycle {0} / block {1}
|
||||
dao.monitor.table.seedPeers=Seed node: {0}
|
||||
|
||||
dao.monitor.daoState.headline=DAO state
|
||||
dao.monitor.daoState.daoStateInSync=Your local DAO state is in consensus with the network
|
||||
dao.monitor.daoState.daoStateNotInSync=Your local DAO state is not in consensus with the network. Please resync your \
|
||||
DAO state.
|
||||
dao.monitor.daoState.table.headline=Chain of DAO state hashes
|
||||
dao.monitor.daoState.table.blockHeight=Block height
|
||||
dao.monitor.daoState.table.hash=Hash of DAO state
|
||||
|
@ -1920,9 +1919,6 @@ dao.monitor.daoState.utxoConflicts.sumUtxo=Sum of all UTXO: {0} BSQ
|
|||
dao.monitor.daoState.utxoConflicts.sumBsq=Sum of all BSQ: {0} BSQ
|
||||
|
||||
dao.monitor.proposal.headline=Proposals state
|
||||
dao.monitor.proposal.daoStateInSync=Your local proposals state is in consensus with the network
|
||||
dao.monitor.proposal.daoStateNotInSync=Your local proposals state is not in consensus with the network. Please restart your \
|
||||
application.
|
||||
dao.monitor.proposal.table.headline=Chain of proposal state hashes
|
||||
dao.monitor.proposal.conflictTable.headline=Proposal state hashes from peers in conflict
|
||||
|
||||
|
@ -1930,11 +1926,13 @@ dao.monitor.proposal.table.hash=Hash of proposal state
|
|||
dao.monitor.proposal.table.prev=Previous hash
|
||||
dao.monitor.proposal.table.numProposals=No. proposals
|
||||
|
||||
dao.monitor.isInConflictWithSeedNode=Your local data is not in consensus with at least one seed node. \
|
||||
Please resync the DAO state.
|
||||
dao.monitor.isInConflictWithNonSeedNode=One of your peers is not in consensus with the network but your node \
|
||||
is in sync with the seed nodes.
|
||||
dao.monitor.daoStateInSync=Your local node is in consensus with the network
|
||||
|
||||
dao.monitor.blindVote.headline=Blind votes state
|
||||
dao.monitor.blindVote.daoStateInSync=Your local blind votes state is in consensus with the network
|
||||
dao.monitor.blindVote.daoStateNotInSync=Your local blind votes state is not in consensus with the network. Please restart your \
|
||||
application.
|
||||
dao.monitor.blindVote.table.headline=Chain of blind vote state hashes
|
||||
dao.monitor.blindVote.conflictTable.headline=Blind vote state hashes from peers in conflict
|
||||
dao.monitor.blindVote.table.hash=Hash of blind vote state
|
||||
|
|
|
@ -20,8 +20,12 @@ package bisq.desktop.main.dao.monitor;
|
|||
import bisq.core.dao.monitoring.model.StateHash;
|
||||
import bisq.core.locale.Res;
|
||||
|
||||
import bisq.network.p2p.NodeAddress;
|
||||
|
||||
import bisq.common.util.Utilities;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -36,10 +40,15 @@ public abstract class StateInConflictListItem<T extends StateHash> {
|
|||
private final String prevHash;
|
||||
private final T stateHash;
|
||||
|
||||
protected StateInConflictListItem(String peerAddress, T stateHash, int cycleIndex) {
|
||||
protected StateInConflictListItem(String peerAddress, T stateHash, int cycleIndex,
|
||||
Set<NodeAddress> seedNodeAddresses) {
|
||||
this.stateHash = stateHash;
|
||||
this.peerAddress = peerAddress;
|
||||
height = Res.get("dao.monitor.table.cycleBlockHeight", cycleIndex + 1, String.valueOf(stateHash.getHeight()));
|
||||
this.peerAddress = seedNodeAddresses.stream().anyMatch(e -> e.getFullAddress().equals(peerAddress)) ?
|
||||
Res.get("dao.monitor.table.seedPeers", peerAddress) :
|
||||
peerAddress;
|
||||
height = Res.get("dao.monitor.table.cycleBlockHeight",
|
||||
cycleIndex + 1,
|
||||
String.valueOf(stateHash.getHeight()));
|
||||
hash = Utilities.bytesAsHexString(stateHash.getHash());
|
||||
prevHash = stateHash.getPrevHash().length > 0 ?
|
||||
Utilities.bytesAsHexString(stateHash.getPrevHash()) : "-";
|
||||
|
|
|
@ -23,6 +23,7 @@ import bisq.desktop.components.AutoTooltipButton;
|
|||
import bisq.desktop.components.AutoTooltipLabel;
|
||||
import bisq.desktop.components.AutoTooltipTableColumn;
|
||||
import bisq.desktop.components.TableGroupHeadline;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
@ -36,7 +37,10 @@ import bisq.core.dao.state.DaoStateListener;
|
|||
import bisq.core.dao.state.DaoStateService;
|
||||
import bisq.core.locale.Res;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import bisq.network.p2p.NodeAddress;
|
||||
import bisq.network.p2p.seed.SeedNodeRepository;
|
||||
|
||||
import bisq.common.storage.FileManager;
|
||||
|
||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
|
||||
|
@ -64,8 +68,12 @@ import javafx.collections.transformation.SortedList;
|
|||
|
||||
import javafx.util.Callback;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@FxmlView
|
||||
|
@ -78,6 +86,8 @@ public abstract class StateMonitorView<StH extends StateHash,
|
|||
protected final DaoFacade daoFacade;
|
||||
protected final CycleService cycleService;
|
||||
protected final PeriodService periodService;
|
||||
protected final Set<NodeAddress> seedNodeAddresses;
|
||||
private final File storageDir;
|
||||
|
||||
protected TextField statusTextField;
|
||||
protected Button resyncButton;
|
||||
|
@ -91,22 +101,26 @@ public abstract class StateMonitorView<StH extends StateHash,
|
|||
|
||||
protected int gridRow = 0;
|
||||
private Subscription selectedItemSubscription;
|
||||
protected final BooleanProperty isInConflict = new SimpleBooleanProperty();
|
||||
protected final BooleanProperty isInConflictWithNonSeedNode = new SimpleBooleanProperty();
|
||||
protected final BooleanProperty isInConflictWithSeedNode = new SimpleBooleanProperty();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public StateMonitorView(DaoStateService daoStateService,
|
||||
DaoFacade daoFacade,
|
||||
CycleService cycleService,
|
||||
PeriodService periodService) {
|
||||
protected StateMonitorView(DaoStateService daoStateService,
|
||||
DaoFacade daoFacade,
|
||||
CycleService cycleService,
|
||||
PeriodService periodService,
|
||||
SeedNodeRepository seedNodeRepository,
|
||||
File storageDir) {
|
||||
this.daoStateService = daoStateService;
|
||||
this.daoFacade = daoFacade;
|
||||
this.cycleService = cycleService;
|
||||
this.periodService = periodService;
|
||||
this.seedNodeAddresses = new HashSet<>(seedNodeRepository.getSeedNodeAddresses());
|
||||
this.storageDir = storageDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -124,8 +138,36 @@ public abstract class StateMonitorView<StH extends StateHash,
|
|||
|
||||
daoStateService.addDaoStateListener(this);
|
||||
|
||||
resyncButton.visibleProperty().bind(isInConflict);
|
||||
resyncButton.managedProperty().bind(isInConflict);
|
||||
resyncButton.visibleProperty().bind(isInConflictWithSeedNode);
|
||||
resyncButton.managedProperty().bind(isInConflictWithSeedNode);
|
||||
|
||||
resyncButton.setOnAction(ev -> {
|
||||
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();
|
||||
}
|
||||
});
|
||||
|
||||
if (daoStateService.isParseBlockChainComplete()) {
|
||||
onDataUpdate();
|
||||
|
@ -250,6 +292,17 @@ public abstract class StateMonitorView<StH extends StateHash,
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected void onDataUpdate() {
|
||||
if (isInConflictWithSeedNode.get()) {
|
||||
statusTextField.setText(Res.get("dao.monitor.isInConflictWithSeedNode"));
|
||||
statusTextField.getStyleClass().add("dao-inConflict");
|
||||
} else if (isInConflictWithNonSeedNode.get()) {
|
||||
statusTextField.setText(Res.get("dao.monitor.isInConflictWithNonSeedNode"));
|
||||
statusTextField.getStyleClass().remove("dao-inConflict");
|
||||
} else {
|
||||
statusTextField.setText(Res.get("dao.monitor.daoStateInSync"));
|
||||
statusTextField.getStyleClass().remove("dao-inConflict");
|
||||
}
|
||||
|
||||
GUIUtil.setFitToRowsForTableView(tableView, 25, 28, 2, 5);
|
||||
}
|
||||
|
||||
|
@ -455,7 +508,7 @@ public abstract class StateMonitorView<StH extends StateHash,
|
|||
|
||||
|
||||
column = new AutoTooltipTableColumn<>(getPeersTableHeader());
|
||||
column.setMinWidth(80);
|
||||
column.setMinWidth(150);
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
|
@ -479,7 +532,7 @@ public abstract class StateMonitorView<StH extends StateHash,
|
|||
|
||||
|
||||
column = new AutoTooltipTableColumn<>(getHashTableHeader());
|
||||
column.setMinWidth(150);
|
||||
column.setMinWidth(120);
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
|
@ -503,7 +556,7 @@ public abstract class StateMonitorView<StH extends StateHash,
|
|||
|
||||
|
||||
column = new AutoTooltipTableColumn<>(getPrevHashTableHeader());
|
||||
column.setMinWidth(150);
|
||||
column.setMinWidth(120);
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
|
@ -527,7 +580,7 @@ public abstract class StateMonitorView<StH extends StateHash,
|
|||
|
||||
|
||||
column = new AutoTooltipTableColumn<>("");
|
||||
column.setMinWidth(100);
|
||||
column.setMinWidth(120);
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
|
|
|
@ -21,6 +21,10 @@ import bisq.desktop.main.dao.monitor.StateInConflictListItem;
|
|||
|
||||
import bisq.core.dao.monitoring.model.BlindVoteStateHash;
|
||||
|
||||
import bisq.network.p2p.NodeAddress;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Value;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -31,8 +35,9 @@ import lombok.extern.slf4j.Slf4j;
|
|||
class BlindVoteStateInConflictListItem extends StateInConflictListItem<BlindVoteStateHash> {
|
||||
private final String numBlindVotes;
|
||||
|
||||
BlindVoteStateInConflictListItem(String peerAddress, BlindVoteStateHash stateHash, int cycleIndex) {
|
||||
super(peerAddress, stateHash, cycleIndex);
|
||||
BlindVoteStateInConflictListItem(String peerAddress, BlindVoteStateHash stateHash, int cycleIndex,
|
||||
Set<NodeAddress> seedNodeAddresses) {
|
||||
super(peerAddress, stateHash, cycleIndex, seedNodeAddresses);
|
||||
|
||||
numBlindVotes = String.valueOf(stateHash.getNumBlindVotes());
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ package bisq.desktop.main.dao.monitor.blindvotes;
|
|||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.components.AutoTooltipTableColumn;
|
||||
import bisq.desktop.main.dao.monitor.StateMonitorView;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
|
@ -32,7 +31,12 @@ import bisq.core.dao.monitoring.model.BlindVoteStateHash;
|
|||
import bisq.core.dao.state.DaoStateService;
|
||||
import bisq.core.locale.Res;
|
||||
|
||||
import bisq.network.p2p.seed.SeedNodeRepository;
|
||||
|
||||
import bisq.common.storage.Storage;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import javafx.scene.control.TableCell;
|
||||
import javafx.scene.control.TableColumn;
|
||||
|
@ -41,6 +45,8 @@ import javafx.beans.property.ReadOnlyObjectWrapper;
|
|||
|
||||
import javafx.util.Callback;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -50,6 +56,7 @@ public class BlindVoteStateMonitorView extends StateMonitorView<BlindVoteStateHa
|
|||
implements BlindVoteStateMonitoringService.Listener {
|
||||
private final BlindVoteStateMonitoringService blindVoteStateMonitoringService;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -60,8 +67,10 @@ public class BlindVoteStateMonitorView extends StateMonitorView<BlindVoteStateHa
|
|||
DaoFacade daoFacade,
|
||||
BlindVoteStateMonitoringService blindVoteStateMonitoringService,
|
||||
CycleService cycleService,
|
||||
PeriodService periodService) {
|
||||
super(daoStateService, daoFacade, cycleService, periodService);
|
||||
PeriodService periodService,
|
||||
SeedNodeRepository seedNodeRepository,
|
||||
@Named(Storage.STORAGE_DIR) File storageDir) {
|
||||
super(daoStateService, daoFacade, cycleService, periodService, seedNodeRepository, storageDir);
|
||||
|
||||
this.blindVoteStateMonitoringService = blindVoteStateMonitoringService;
|
||||
}
|
||||
|
@ -80,14 +89,8 @@ public class BlindVoteStateMonitorView extends StateMonitorView<BlindVoteStateHa
|
|||
@Override
|
||||
protected void activate() {
|
||||
super.activate();
|
||||
blindVoteStateMonitoringService.addListener(this);
|
||||
|
||||
resyncButton.setOnAction(e -> daoFacade.resyncDao(() ->
|
||||
new Popup<>().attention(Res.get("setting.preferences.dao.resync.popup"))
|
||||
.useShutDownButton()
|
||||
.hideCloseButton()
|
||||
.show())
|
||||
);
|
||||
blindVoteStateMonitoringService.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -123,7 +126,7 @@ public class BlindVoteStateMonitorView extends StateMonitorView<BlindVoteStateHa
|
|||
protected BlindVoteStateInConflictListItem getStateInConflictListItem(Map.Entry<String, BlindVoteStateHash> mapEntry) {
|
||||
BlindVoteStateHash blindVoteStateHash = mapEntry.getValue();
|
||||
int cycleIndex = periodService.getCycle(blindVoteStateHash.getHeight()).map(cycleService::getCycleIndex).orElse(0);
|
||||
return new BlindVoteStateInConflictListItem(mapEntry.getKey(), mapEntry.getValue(), cycleIndex);
|
||||
return new BlindVoteStateInConflictListItem(mapEntry.getKey(), mapEntry.getValue(), cycleIndex, seedNodeAddresses);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -173,15 +176,8 @@ public class BlindVoteStateMonitorView extends StateMonitorView<BlindVoteStateHa
|
|||
|
||||
@Override
|
||||
protected void onDataUpdate() {
|
||||
isInConflict.set(blindVoteStateMonitoringService.isInConflict());
|
||||
|
||||
if (isInConflict.get()) {
|
||||
statusTextField.setText(Res.get("dao.monitor.blindVote.daoStateNotInSync"));
|
||||
statusTextField.getStyleClass().add("dao-inConflict");
|
||||
} else {
|
||||
statusTextField.setText(Res.get("dao.monitor.blindVote.daoStateInSync"));
|
||||
statusTextField.getStyleClass().remove("dao-inConflict");
|
||||
}
|
||||
isInConflictWithSeedNode.set(blindVoteStateMonitoringService.isInConflictWithSeedNode());
|
||||
isInConflictWithNonSeedNode.set(blindVoteStateMonitoringService.isInConflictWithNonSeedNode());
|
||||
|
||||
listItems.setAll(blindVoteStateMonitoringService.getBlindVoteStateBlockChain().stream()
|
||||
.map(this::getStateBlockListItem)
|
||||
|
@ -202,7 +198,7 @@ public class BlindVoteStateMonitorView extends StateMonitorView<BlindVoteStateHa
|
|||
TableColumn<BlindVoteStateBlockListItem, BlindVoteStateBlockListItem> column;
|
||||
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.monitor.blindVote.table.numBlindVotes"));
|
||||
column.setMinWidth(110);
|
||||
column.setMinWidth(90);
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
|
@ -232,7 +228,7 @@ public class BlindVoteStateMonitorView extends StateMonitorView<BlindVoteStateHa
|
|||
TableColumn<BlindVoteStateInConflictListItem, BlindVoteStateInConflictListItem> column;
|
||||
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.monitor.blindVote.table.numBlindVotes"));
|
||||
column.setMinWidth(110);
|
||||
column.setMinWidth(90);
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
|
|
|
@ -21,6 +21,10 @@ import bisq.desktop.main.dao.monitor.StateInConflictListItem;
|
|||
|
||||
import bisq.core.dao.monitoring.model.DaoStateHash;
|
||||
|
||||
import bisq.network.p2p.NodeAddress;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Value;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -29,7 +33,8 @@ import lombok.extern.slf4j.Slf4j;
|
|||
@Value
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
class DaoStateInConflictListItem extends StateInConflictListItem<DaoStateHash> {
|
||||
DaoStateInConflictListItem(String peerAddress, DaoStateHash stateHash, int cycleIndex) {
|
||||
super(peerAddress, stateHash, cycleIndex);
|
||||
DaoStateInConflictListItem(String peerAddress, DaoStateHash stateHash, int cycleIndex,
|
||||
Set<NodeAddress> seedNodeAddresses) {
|
||||
super(peerAddress, stateHash, cycleIndex, seedNodeAddresses);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,12 +33,18 @@ import bisq.core.dao.monitoring.model.UtxoMismatch;
|
|||
import bisq.core.dao.state.DaoStateService;
|
||||
import bisq.core.locale.Res;
|
||||
|
||||
import bisq.network.p2p.seed.SeedNodeRepository;
|
||||
|
||||
import bisq.common.storage.Storage;
|
||||
import bisq.common.util.Utilities;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import javafx.collections.ListChangeListener;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -60,8 +66,10 @@ public class DaoStateMonitorView extends StateMonitorView<DaoStateHash, DaoState
|
|||
DaoFacade daoFacade,
|
||||
DaoStateMonitoringService daoStateMonitoringService,
|
||||
CycleService cycleService,
|
||||
PeriodService periodService) {
|
||||
super(daoStateService, daoFacade, cycleService, periodService);
|
||||
PeriodService periodService,
|
||||
SeedNodeRepository seedNodeRepository,
|
||||
@Named(Storage.STORAGE_DIR) File storageDir) {
|
||||
super(daoStateService, daoFacade, cycleService, periodService, seedNodeRepository, storageDir);
|
||||
|
||||
this.daoStateMonitoringService = daoStateMonitoringService;
|
||||
}
|
||||
|
@ -87,13 +95,6 @@ public class DaoStateMonitorView extends StateMonitorView<DaoStateHash, DaoState
|
|||
daoStateMonitoringService.getUtxoMismatches().addListener(utxoMismatchListChangeListener);
|
||||
|
||||
updateUtxoMismatches();
|
||||
|
||||
resyncButton.setOnAction(e -> daoFacade.resyncDao(() ->
|
||||
new Popup<>().attention(Res.get("setting.preferences.dao.resync.popup"))
|
||||
.useShutDownButton()
|
||||
.hideCloseButton()
|
||||
.show())
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -131,7 +132,7 @@ public class DaoStateMonitorView extends StateMonitorView<DaoStateHash, DaoState
|
|||
protected DaoStateInConflictListItem getStateInConflictListItem(Map.Entry<String, DaoStateHash> mapEntry) {
|
||||
DaoStateHash daoStateHash = mapEntry.getValue();
|
||||
int cycleIndex = periodService.getCycle(daoStateHash.getHeight()).map(cycleService::getCycleIndex).orElse(0);
|
||||
return new DaoStateInConflictListItem(mapEntry.getKey(), daoStateHash, cycleIndex);
|
||||
return new DaoStateInConflictListItem(mapEntry.getKey(), daoStateHash, cycleIndex, seedNodeAddresses);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -181,15 +182,8 @@ public class DaoStateMonitorView extends StateMonitorView<DaoStateHash, DaoState
|
|||
|
||||
@Override
|
||||
protected void onDataUpdate() {
|
||||
isInConflict.set(daoStateMonitoringService.isInConflict());
|
||||
|
||||
if (isInConflict.get()) {
|
||||
statusTextField.setText(Res.get("dao.monitor.daoState.daoStateNotInSync"));
|
||||
statusTextField.getStyleClass().add("dao-inConflict");
|
||||
} else {
|
||||
statusTextField.setText(Res.get("dao.monitor.daoState.daoStateInSync"));
|
||||
statusTextField.getStyleClass().remove("dao-inConflict");
|
||||
}
|
||||
isInConflictWithSeedNode.set(daoStateMonitoringService.isInConflictWithSeedNode());
|
||||
isInConflictWithNonSeedNode.set(daoStateMonitoringService.isInConflictWithNonSeedNode());
|
||||
|
||||
listItems.setAll(daoStateMonitoringService.getDaoStateBlockChain().stream()
|
||||
.map(this::getStateBlockListItem)
|
||||
|
|
|
@ -21,6 +21,10 @@ import bisq.desktop.main.dao.monitor.StateInConflictListItem;
|
|||
|
||||
import bisq.core.dao.monitoring.model.ProposalStateHash;
|
||||
|
||||
import bisq.network.p2p.NodeAddress;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Value;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -31,8 +35,9 @@ import lombok.extern.slf4j.Slf4j;
|
|||
class ProposalStateInConflictListItem extends StateInConflictListItem<ProposalStateHash> {
|
||||
private final String numProposals;
|
||||
|
||||
ProposalStateInConflictListItem(String peerAddress, ProposalStateHash stateHash, int cycleIndex) {
|
||||
super(peerAddress, stateHash, cycleIndex);
|
||||
ProposalStateInConflictListItem(String peerAddress, ProposalStateHash stateHash, int cycleIndex,
|
||||
Set<NodeAddress> seedNodeAddresses) {
|
||||
super(peerAddress, stateHash, cycleIndex, seedNodeAddresses);
|
||||
|
||||
numProposals = String.valueOf(stateHash.getNumProposals());
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ package bisq.desktop.main.dao.monitor.proposals;
|
|||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.components.AutoTooltipTableColumn;
|
||||
import bisq.desktop.main.dao.monitor.StateMonitorView;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
|
@ -32,7 +31,12 @@ import bisq.core.dao.monitoring.model.ProposalStateHash;
|
|||
import bisq.core.dao.state.DaoStateService;
|
||||
import bisq.core.locale.Res;
|
||||
|
||||
import bisq.network.p2p.seed.SeedNodeRepository;
|
||||
|
||||
import bisq.common.storage.Storage;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import javafx.scene.control.TableCell;
|
||||
import javafx.scene.control.TableColumn;
|
||||
|
@ -41,6 +45,8 @@ import javafx.beans.property.ReadOnlyObjectWrapper;
|
|||
|
||||
import javafx.util.Callback;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -60,8 +66,10 @@ public class ProposalStateMonitorView extends StateMonitorView<ProposalStateHash
|
|||
DaoFacade daoFacade,
|
||||
ProposalStateMonitoringService proposalStateMonitoringService,
|
||||
CycleService cycleService,
|
||||
PeriodService periodService) {
|
||||
super(daoStateService, daoFacade, cycleService, periodService);
|
||||
PeriodService periodService,
|
||||
SeedNodeRepository seedNodeRepository,
|
||||
@Named(Storage.STORAGE_DIR) File storageDir) {
|
||||
super(daoStateService, daoFacade, cycleService, periodService, seedNodeRepository, storageDir);
|
||||
|
||||
this.proposalStateMonitoringService = proposalStateMonitoringService;
|
||||
}
|
||||
|
@ -81,13 +89,6 @@ public class ProposalStateMonitorView extends StateMonitorView<ProposalStateHash
|
|||
protected void activate() {
|
||||
super.activate();
|
||||
proposalStateMonitoringService.addListener(this);
|
||||
|
||||
resyncButton.setOnAction(e -> daoFacade.resyncDao(() ->
|
||||
new Popup<>().attention(Res.get("setting.preferences.dao.resync.popup"))
|
||||
.useShutDownButton()
|
||||
.hideCloseButton()
|
||||
.show())
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -123,7 +124,7 @@ public class ProposalStateMonitorView extends StateMonitorView<ProposalStateHash
|
|||
protected ProposalStateInConflictListItem getStateInConflictListItem(Map.Entry<String, ProposalStateHash> mapEntry) {
|
||||
ProposalStateHash proposalStateHash = mapEntry.getValue();
|
||||
int cycleIndex = periodService.getCycle(proposalStateHash.getHeight()).map(cycleService::getCycleIndex).orElse(0);
|
||||
return new ProposalStateInConflictListItem(mapEntry.getKey(), mapEntry.getValue(), cycleIndex);
|
||||
return new ProposalStateInConflictListItem(mapEntry.getKey(), mapEntry.getValue(), cycleIndex, seedNodeAddresses);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -173,15 +174,8 @@ public class ProposalStateMonitorView extends StateMonitorView<ProposalStateHash
|
|||
|
||||
@Override
|
||||
protected void onDataUpdate() {
|
||||
isInConflict.set(proposalStateMonitoringService.isInConflict());
|
||||
|
||||
if (isInConflict.get()) {
|
||||
statusTextField.setText(Res.get("dao.monitor.proposal.daoStateNotInSync"));
|
||||
statusTextField.getStyleClass().add("dao-inConflict");
|
||||
} else {
|
||||
statusTextField.setText(Res.get("dao.monitor.proposal.daoStateInSync"));
|
||||
statusTextField.getStyleClass().remove("dao-inConflict");
|
||||
}
|
||||
isInConflictWithSeedNode.set(proposalStateMonitoringService.isInConflictWithSeedNode());
|
||||
isInConflictWithNonSeedNode.set(proposalStateMonitoringService.isInConflictWithNonSeedNode());
|
||||
|
||||
listItems.setAll(proposalStateMonitoringService.getProposalStateBlockChain().stream()
|
||||
.map(this::getStateBlockListItem)
|
||||
|
|
Loading…
Add table
Reference in a new issue