Merge pull request #2117 from ManfredKarrer/fix-reorg-issues-with-phases

Fix reorg issues with phases
This commit is contained in:
Manfred Karrer 2018-12-12 14:24:51 +01:00 committed by GitHub
commit 445c643417
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 32 deletions

View file

@ -68,7 +68,7 @@ public class CycleService implements DaoStateListener, DaoSetupService {
@Override
public void start() {
daoStateService.getCycles().add(getFirstCycle());
addFirstCycle();
}
@ -96,6 +96,28 @@ public class CycleService implements DaoStateListener, DaoSetupService {
// API
///////////////////////////////////////////////////////////////////////////////////////////
public void addFirstCycle() {
daoStateService.getCycles().add(getFirstCycle());
}
public int getCycleIndex(Cycle cycle) {
return (cycle.getHeightOfFirstBlock() - genesisBlockHeight) / cycle.getDuration();
}
public boolean isTxInCycle(Cycle cycle, String txId) {
return daoStateService.getTx(txId).filter(tx -> isBlockHeightInCycle(tx.getBlockHeight(), cycle)).isPresent();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private boolean isBlockHeightInCycle(int blockHeight, Cycle cycle) {
return blockHeight >= cycle.getHeightOfFirstBlock() &&
blockHeight <= cycle.getHeightOfLastBlock();
}
private Optional<Cycle> maybeCreateNewCycle(int blockHeight, LinkedList<Cycle> cycles) {
// We want to set the correct phase and cycle before we start parsing a new block.
// For Genesis block we did it already in the start method.
@ -128,24 +150,6 @@ public class CycleService implements DaoStateListener, DaoSetupService {
return new Cycle(genesisBlockHeight, ImmutableList.copyOf(daoPhasesWithDefaultDuration));
}
public int getCycleIndex(Cycle cycle) {
return (cycle.getHeightOfFirstBlock() - genesisBlockHeight) / cycle.getDuration();
}
public boolean isTxInCycle(Cycle cycle, String txId) {
return daoStateService.getTx(txId).filter(tx -> isBlockHeightInCycle(tx.getBlockHeight(), cycle)).isPresent();
}
private boolean isBlockHeightInCycle(int blockHeight, Cycle cycle) {
return blockHeight >= cycle.getHeightOfFirstBlock() &&
blockHeight <= cycle.getHeightOfLastBlock();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private Cycle createNewCycle(int blockHeight, Cycle previousCycle) {
List<DaoPhase> daoPhaseList = previousCycle.getDaoPhaseList().stream()
.map(daoPhase -> {

View file

@ -17,6 +17,7 @@
package bisq.core.dao.state;
import bisq.core.dao.governance.period.CycleService;
import bisq.core.dao.state.model.DaoState;
import bisq.core.dao.state.model.blockchain.Block;
@ -41,6 +42,7 @@ public class DaoStateSnapshotService implements DaoStateListener {
private final DaoStateService daoStateService;
private final GenesisTxInfo genesisTxInfo;
private final CycleService cycleService;
private final DaoStateStorageService daoStateStorageService;
private DaoState snapshotCandidate;
@ -53,9 +55,11 @@ public class DaoStateSnapshotService implements DaoStateListener {
@Inject
public DaoStateSnapshotService(DaoStateService daoStateService,
GenesisTxInfo genesisTxInfo,
CycleService cycleService,
DaoStateStorageService daoStateStorageService) {
this.daoStateService = daoStateService;
this.genesisTxInfo = genesisTxInfo;
this.cycleService = cycleService;
this.daoStateStorageService = daoStateStorageService;
this.daoStateService.addBsqStateListener(this);
@ -128,19 +132,13 @@ public class DaoStateSnapshotService implements DaoStateListener {
log.warn("We applied already a snapshot with chainHeight {}. We will reset the daoState and " +
"start over from the genesis transaction again.", chainHeightOfLastApplySnapshot);
persisted = new DaoState();
int genesisBlockHeight = genesisTxInfo.getGenesisBlockHeight();
persisted.setChainHeight(genesisBlockHeight);
chainHeightOfLastApplySnapshot = genesisBlockHeight;
daoStateService.applySnapshot(persisted);
applyEmptySnapshot(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");
int genesisBlockHeight = genesisTxInfo.getGenesisBlockHeight();
persisted.setChainHeight(genesisBlockHeight);
chainHeightOfLastApplySnapshot = genesisBlockHeight;
daoStateService.applySnapshot(persisted);
applyEmptySnapshot(persisted);
}
} else {
log.info("Try to apply snapshot but no stored snapshot available. That is expected at first blocks.");
@ -152,6 +150,15 @@ public class DaoStateSnapshotService implements DaoStateListener {
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private void applyEmptySnapshot(DaoState persisted) {
int genesisBlockHeight = genesisTxInfo.getGenesisBlockHeight();
persisted.setChainHeight(genesisBlockHeight);
chainHeightOfLastApplySnapshot = genesisBlockHeight;
daoStateService.applySnapshot(persisted);
// In case we apply an empty snapshot we need to trigger the cycleService.addFirstCycle method
cycleService.addFirstCycle();
}
@VisibleForTesting
int getSnapshotHeight(int genesisHeight, int height, int grid) {
return Math.round(Math.max(genesisHeight + 3 * grid, height) / grid) * grid - grid;

View file

@ -1106,11 +1106,10 @@ account.seed.warn.noPw.msg=You have not setup a wallet password which would prot
Do you want to display the seed words?
account.seed.warn.noPw.yes=Yes, and don't ask me again
account.seed.enterPw=Enter password to view seed words
account.seed.restore.info=Please note that you cannot import a wallet from an old Bisq version (any version before 0.5.0), \
because the wallet format has changed!\n\n\
If you want to move the funds from the old version to the new Bisq application send it with a bitcoin transaction.\n\n\
Also be aware that wallet restore is only for emergency cases and might cause problems with the internal wallet database.\n\
It is not a way for applying a backup! Please use a backup from the application data directory for restoring a previous application state.
account.seed.restore.info=Please make a backup before applying restore from seed words. Be aware that wallet restore is \
only for emergency cases and might cause problems with the internal wallet database.\n\
It is not a way for applying a backup! Please use a backup from the application data directory for restoring a \
previous application state.
account.seed.restore.ok=Ok, I understand and want to restore