From 431cbf01af5d52e5ff6a723bb6b1be87cf824b03 Mon Sep 17 00:00:00 2001 From: catbref Date: Thu, 16 Jun 2022 17:47:08 +0100 Subject: [PATCH] BlockMinter will discard block candidates that turn out to be invalid just prior to adding transactions, to be potentially reminted in the next pass --- .../org/qortal/controller/BlockMinter.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/qortal/controller/BlockMinter.java b/src/main/java/org/qortal/controller/BlockMinter.java index b8831464..c77bc579 100644 --- a/src/main/java/org/qortal/controller/BlockMinter.java +++ b/src/main/java/org/qortal/controller/BlockMinter.java @@ -284,7 +284,12 @@ public class BlockMinter extends Thread { continue; List goodBlocks = new ArrayList<>(); - for (Block testBlock : newBlocks) { + boolean wasInvalidBlockDiscarded = false; + Iterator newBlocksIterator = newBlocks.iterator(); + + while (newBlocksIterator.hasNext()) { + Block testBlock = newBlocksIterator.next(); + // Is new block's timestamp valid yet? // We do a separate check as some timestamp checks are skipped for testchains if (testBlock.isTimestampValid() != ValidationResult.OK) @@ -297,13 +302,21 @@ public class BlockMinter extends Thread { if (result != ValidationResult.OK) { moderatedLog(() -> LOGGER.error(String.format("To-be-minted block invalid '%s' before adding transactions?", result.name()))); - continue; + newBlocksIterator.remove(); + wasInvalidBlockDiscarded = true; + /* + * Bail out fast so that we loop around from the top again. + * This gives BlockMinter the possibility to remint this candidate block using another block from newBlocks, + * via the Blocks.remint() method, which avoids having to re-process Block ATs all over again. + * Particularly useful if some aspect of Blocks changes due a timestamp-based feature-trigger (see BlockChain class). + */ + break; } goodBlocks.add(testBlock); } - if (goodBlocks.isEmpty()) + if (wasInvalidBlockDiscarded || goodBlocks.isEmpty()) continue; // Pick best block