forked from Qortal/qortal
Activate checkpoints
This commit is contained in:
parent
e4134a769b
commit
708a978de0
@ -806,18 +806,17 @@ public class BlockChain {
|
||||
* @throws SQLException
|
||||
*/
|
||||
public static void validate() throws DataException {
|
||||
|
||||
boolean isTopOnly = Settings.getInstance().isTopOnly();
|
||||
boolean archiveEnabled = Settings.getInstance().isArchiveEnabled();
|
||||
boolean isLite = Settings.getInstance().isLite();
|
||||
boolean canBootstrap = Settings.getInstance().getBootstrap();
|
||||
boolean needsArchiveRebuild = false;
|
||||
int checkHeight = 0;
|
||||
BlockData chainTip;
|
||||
boolean checkPointFailed = false;
|
||||
int currentChainHeight = 0;
|
||||
int checkPointHeight = 0;
|
||||
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
chainTip = repository.getBlockRepository().getLastBlock();
|
||||
checkHeight = repository.getBlockRepository().getBlockchainHeight();
|
||||
currentChainHeight = repository.getBlockRepository().getBlockchainHeight();
|
||||
|
||||
// Ensure archive is (at least partially) intact, and force a bootstrap if it isn't
|
||||
if (!isTopOnly && archiveEnabled && canBootstrap) {
|
||||
@ -833,23 +832,30 @@ public class BlockChain {
|
||||
}
|
||||
}
|
||||
|
||||
// Validate bootstrap
|
||||
if (!canBootstrap) {
|
||||
if (checkHeight > 2) {
|
||||
if (currentChainHeight > 2) {
|
||||
LOGGER.info("Retrieved block 2 from archive. Syncing from genesis block resumed!");
|
||||
} else {
|
||||
needsArchiveRebuild = (repository.getBlockArchiveRepository().fromHeight(2) == null);
|
||||
if (needsArchiveRebuild) {
|
||||
LOGGER.info("Couldn't retrieve block 2 from archive. Bootstrapping is disabled. Syncing from genesis block!");
|
||||
|
||||
// If there are minting accounts, make sure to back them up
|
||||
// Don't backup if there are no minting accounts, as this can cause problems
|
||||
if (!repository.getAccountRepository().getMintingAccounts().isEmpty()) {
|
||||
Controller.getInstance().exportRepositoryData();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate checkpoints
|
||||
// Limited to topOnly nodes for now, in order to reduce risk, and to solve a real-world problem with divergent topOnly nodes
|
||||
// TODO: remove the isTopOnly conditional below once this feature has had more testing time
|
||||
if (isTopOnly && !isLite) {
|
||||
if (!isTopOnly && !isLite) {
|
||||
List<Checkpoint> checkpoints = BlockChain.getInstance().getCheckpoints();
|
||||
for (Checkpoint checkpoint : checkpoints) {
|
||||
checkPointHeight = checkpoint.height;
|
||||
if (currentChainHeight > checkPointHeight) {
|
||||
BlockData blockData = repository.getBlockRepository().fromHeight(checkpoint.height);
|
||||
if (blockData == null) {
|
||||
// Try the archive
|
||||
@ -864,19 +870,19 @@ public class BlockChain {
|
||||
|
||||
byte[] signature = Base58.decode(checkpoint.signature);
|
||||
if (!Arrays.equals(signature, blockData.getSignature())) {
|
||||
LOGGER.info("Error: block at height {} with signature {} doesn't match checkpoint sig: {}. Bootstrapping...", checkpoint.height, Base58.encode(blockData.getSignature()), checkpoint.signature);
|
||||
needsArchiveRebuild = true;
|
||||
LOGGER.info("Error: block at height {} with sig: {} doesn't match checkpoint sig: {}. Bootstrapping / Resync...", checkpoint.height, Base58.encode(blockData.getSignature()), checkpoint.signature);
|
||||
checkPointFailed = true;
|
||||
break;
|
||||
}
|
||||
LOGGER.info("Block at height {} matches checkpoint signature", blockData.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Check first block is Genesis Block
|
||||
if (!isGenesisBlockValid() || needsArchiveRebuild) {
|
||||
if (checkHeight < 3) {
|
||||
if (!canBootstrap && currentChainHeight < 3) {
|
||||
try {
|
||||
rebuildBlockchain();
|
||||
} catch (InterruptedException e) {
|
||||
@ -885,6 +891,20 @@ public class BlockChain {
|
||||
}
|
||||
}
|
||||
|
||||
// If checkpoint failed resync or bootstrap
|
||||
if (checkPointFailed) {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
// If there are minting accounts, make sure to back them up
|
||||
// Don't backup if there are no minting accounts, as this can cause problems
|
||||
if (!repository.getAccountRepository().getMintingAccounts().isEmpty()) {
|
||||
Controller.getInstance().exportRepositoryData();
|
||||
}
|
||||
rebuildBlockchain();
|
||||
} catch (InterruptedException e) {
|
||||
throw new DataException(String.format("Interrupted when trying to rebuild blockchain: %s", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
// We need to create a new connection, as the previous repository and its connections may be been
|
||||
// closed by rebuildBlockchain() if a bootstrap was applied
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user