mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 09:52:23 +01:00
Fix handling of reorgs
- apply snapshot in case of a reorg and if the snapshot is still empty. Set chain height to genesis height. - Handle case if cycles are empty - Add checks for getLast for linked lists
This commit is contained in:
parent
e1e9180291
commit
d4729751e8
@ -122,6 +122,7 @@ public class MyVoteListService implements PersistedDataHost {
|
||||
|
||||
public List<MyVote> getMyVoteListForCycle() {
|
||||
return myVoteList.getList().stream()
|
||||
.filter(e -> daoStateService.getCurrentCycle() != null)
|
||||
.filter(e -> daoStateService.getCurrentCycle().isInCycle(e.getHeight()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
@ -105,9 +105,9 @@ public class CycleService implements DaoStateListener, DaoSetupService {
|
||||
// applied the new cycle yet. But the first block of the old cycle will always be the same as the
|
||||
// first block of the new cycle.
|
||||
Cycle cycle = null;
|
||||
if (blockHeight != genesisBlockHeight && isFirstBlockAfterPreviousCycle(blockHeight, cycles)) {
|
||||
if (blockHeight != genesisBlockHeight && isFirstBlockAfterPreviousCycle(blockHeight, cycles) && !cycles.isEmpty()) {
|
||||
// We have the not update daoStateService.getCurrentCycle() so we grab here the previousCycle
|
||||
final Cycle previousCycle = cycles.getLast();
|
||||
Cycle previousCycle = cycles.getLast();
|
||||
// We create the new cycle as clone of the previous cycle and only if there have been change events we use
|
||||
// the new values from the change event.
|
||||
cycle = createNewCycle(blockHeight, previousCycle);
|
||||
|
@ -29,6 +29,8 @@ import java.util.Optional;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Slf4j
|
||||
public final class PeriodService {
|
||||
private final DaoStateService daoStateService;
|
||||
@ -52,6 +54,7 @@ public final class PeriodService {
|
||||
return daoStateService.getCycles();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Cycle getCurrentCycle() {
|
||||
return daoStateService.getCurrentCycle();
|
||||
}
|
||||
@ -65,7 +68,9 @@ public final class PeriodService {
|
||||
}
|
||||
|
||||
public DaoPhase.Phase getCurrentPhase() {
|
||||
return getCurrentCycle().getPhaseForHeight(this.getChainHeight()).get();
|
||||
return getCurrentCycle() != null ?
|
||||
getCurrentCycle().getPhaseForHeight(this.getChainHeight()).orElse(DaoPhase.Phase.UNDEFINED) :
|
||||
DaoPhase.Phase.UNDEFINED;
|
||||
}
|
||||
|
||||
public boolean isFirstBlockInCycle(int height) {
|
||||
|
@ -137,7 +137,7 @@ public abstract class BsqNode implements DaoSetupService {
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected void onInitialized() {
|
||||
applySnapshot();
|
||||
daoStateSnapshotService.applySnapshot(false);
|
||||
|
||||
if (p2PService.isBootstrapped()) {
|
||||
log.info("onAllServicesInitialized: isBootstrapped");
|
||||
@ -187,20 +187,11 @@ public abstract class BsqNode implements DaoSetupService {
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected void startReOrgFromLastSnapshot() {
|
||||
applySnapshot();
|
||||
daoStateSnapshotService.applySnapshot(true);
|
||||
startParseBlocks();
|
||||
}
|
||||
|
||||
protected boolean isBlockAlreadyAdded(RawBlock rawBlock) {
|
||||
return daoStateService.getBlockAtHeight(rawBlock.getHeight()).isPresent();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void applySnapshot() {
|
||||
daoStateSnapshotService.applySnapshot();
|
||||
}
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ public class BlockParser {
|
||||
|
||||
private void validateIfBlockIsConnecting(RawBlock rawBlock) throws BlockNotConnectingException {
|
||||
LinkedList<Block> blocks = daoStateService.getBlocks();
|
||||
if (!isBlockConnecting(rawBlock, blocks)) {
|
||||
if (!isBlockConnecting(rawBlock, blocks) && !blocks.isEmpty()) {
|
||||
Block last = blocks.getLast();
|
||||
log.warn("addBlock called with a not connecting block. New block:\n" +
|
||||
"height()={}, hash()={}, lastBlock.height()={}, lastBlock.hash()={}",
|
||||
|
@ -55,6 +55,8 @@ import java.util.stream.Stream;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
/**
|
||||
@ -99,6 +101,8 @@ public class DaoStateService implements DaoSetupService {
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void applySnapshot(DaoState snapshot) {
|
||||
log.info("Apply snapshot with chain height {}", snapshot.getChainHeight());
|
||||
|
||||
daoState.setChainHeight(snapshot.getChainHeight());
|
||||
|
||||
daoState.getBlocks().clear();
|
||||
@ -155,8 +159,9 @@ public class DaoStateService implements DaoSetupService {
|
||||
return daoState.getCycles();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Cycle getCurrentCycle() {
|
||||
return getCycles().getLast();
|
||||
return !getCycles().isEmpty() ? getCycles().getLast() : null;
|
||||
}
|
||||
|
||||
public Optional<Cycle> getCycle(int height) {
|
||||
|
@ -77,6 +77,7 @@ public class DaoStateSnapshotService implements DaoStateListener {
|
||||
// different to our current height.
|
||||
boolean noSnapshotCandidateOrDifferentHeight = snapshotCandidate == null || snapshotCandidate.getChainHeight() != chainHeight;
|
||||
if (isSnapshotHeight(chainHeight) &&
|
||||
!daoStateService.getBlocks().isEmpty() &&
|
||||
isValidHeight(daoStateService.getBlocks().getLast().getHeight()) &&
|
||||
noSnapshotCandidateOrDifferentHeight) {
|
||||
// At trigger event we store the latest snapshotCandidate to disc
|
||||
@ -108,7 +109,7 @@ public class DaoStateSnapshotService implements DaoStateListener {
|
||||
// API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void applySnapshot() {
|
||||
public void applySnapshot(boolean fromReorg) {
|
||||
DaoState persisted = daoStateStorageService.getPersistedBsqState();
|
||||
if (persisted != null) {
|
||||
LinkedList<Block> blocks = persisted.getBlocks();
|
||||
@ -117,6 +118,11 @@ public class DaoStateSnapshotService implements DaoStateListener {
|
||||
log.info("applySnapshot from persisted daoState with height of last block {}", heightOfLastBlock);
|
||||
if (isValidHeight(heightOfLastBlock))
|
||||
daoStateService.applySnapshot(persisted);
|
||||
} else if (fromReorg) {
|
||||
log.info("We got a reorg and we want to apply the snapshot but it is empty. That is expected in the first blocks until the " +
|
||||
"first snapshot has been created. We use our applySnapshot method and restart from the genesis tx");
|
||||
persisted.setChainHeight(genesisTxInfo.getGenesisBlockHeight());
|
||||
daoStateService.applySnapshot(persisted);
|
||||
}
|
||||
} else {
|
||||
log.info("Try to apply snapshot but no stored snapshot available. That is expected at first blocks.");
|
||||
|
Loading…
Reference in New Issue
Block a user