From c6456669e2a0daf65542295362e418e469c0eb49 Mon Sep 17 00:00:00 2001 From: CalDescent Date: Sun, 21 May 2023 12:33:37 +0100 Subject: [PATCH] Don't allow core to start if transaction sequences haven't been rebuilt yet. --- .../java/org/qortal/controller/Controller.java | 12 ++++++++++++ .../qortal/repository/RepositoryManager.java | 17 ++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/qortal/controller/Controller.java b/src/main/java/org/qortal/controller/Controller.java index 7e8fea5e..94ad885f 100644 --- a/src/main/java/org/qortal/controller/Controller.java +++ b/src/main/java/org/qortal/controller/Controller.java @@ -440,6 +440,18 @@ public class Controller extends Thread { } } + try (Repository repository = RepositoryManager.getRepository()) { + if (RepositoryManager.needsTransactionSequenceRebuild(repository)) { + // Don't allow the node to start if transaction sequences haven't been built yet + // This is needed to handle a case when bootstrapping + Gui.getInstance().fatalError("Database upgrade needed", "Please start the core again to complete the process."); + return; + } + } catch (DataException e) { + LOGGER.error("Error checking transaction sequences in repository", e); + return; + } + // Import current trade bot states and minting accounts if they exist Controller.importRepositoryData(); diff --git a/src/main/java/org/qortal/repository/RepositoryManager.java b/src/main/java/org/qortal/repository/RepositoryManager.java index 92936278..03147662 100644 --- a/src/main/java/org/qortal/repository/RepositoryManager.java +++ b/src/main/java/org/qortal/repository/RepositoryManager.java @@ -69,6 +69,19 @@ public abstract class RepositoryManager { // Backup is best-effort so don't complain } } + + public static boolean needsTransactionSequenceRebuild(Repository repository) throws DataException { + // Check if we have any unpopulated block_sequence values for the first 1000 blocks + List testSignatures = repository.getTransactionRepository().getSignaturesMatchingCustomCriteria( + null, Arrays.asList("block_height < 1000 AND block_sequence IS NULL"), new ArrayList<>()); + if (testSignatures.isEmpty()) { + // block_sequence already populated for the first 1000 blocks, so assume complete. + return false; + } + + return true; + } + public static boolean rebuildTransactionSequences(Repository repository) throws DataException { if (Settings.getInstance().isLite()) { // Lite nodes have no blockchain @@ -81,9 +94,7 @@ public abstract class RepositoryManager { try { // Check if we have any unpopulated block_sequence values for the first 1000 blocks - List testSignatures = repository.getTransactionRepository().getSignaturesMatchingCustomCriteria( - null, Arrays.asList("block_height < 1000 AND block_sequence IS NULL"), new ArrayList<>()); - if (testSignatures.isEmpty()) { + if (!needsTransactionSequenceRebuild(repository)) { // block_sequence already populated for the first 1000 blocks, so assume complete. // We avoid checkpointing and prevent the node from starting up in the case of a rebuild failure, so // we shouldn't ever be left in a partially rebuilt state.