diff --git a/core/src/main/java/bisq/core/dao/node/full/FullNode.java b/core/src/main/java/bisq/core/dao/node/full/FullNode.java index 099fd0ad751..2493e437948 100644 --- a/core/src/main/java/bisq/core/dao/node/full/FullNode.java +++ b/core/src/main/java/bisq/core/dao/node/full/FullNode.java @@ -107,15 +107,17 @@ public void shutDown() { @Override protected void startParseBlocks() { - requestChainHeadHeightAndParseBlocks(getStartBlockHeight()); - } - - @Override - protected void startReOrgFromLastSnapshot() { - super.startReOrgFromLastSnapshot(); - int startBlockHeight = getStartBlockHeight(); - rpcService.requestChainHeadHeight(chainHeight -> parseBlocksOnHeadHeight(startBlockHeight, chainHeight), + + log.info("startParseBlocks: startBlockHeight={}", startBlockHeight); + rpcService.requestChainHeadHeight(chainHeight -> { + // If our persisted block is equal to the chain height we have startBlockHeight 1 block higher, + // so we do not call parseBlocksOnHeadHeight + log.info("startParseBlocks: chainHeight={}", chainHeight); + if (startBlockHeight <= chainHeight) { + parseBlocksOnHeadHeight(startBlockHeight, chainHeight); + } + }, this::handleError); } @@ -194,12 +196,6 @@ private void parseBlocksIfNewBlockAvailable(int chainHeight) { this::handleError); } - private void requestChainHeadHeightAndParseBlocks(int startBlockHeight) { - log.info("requestChainHeadHeightAndParseBlocks with startBlockHeight={}", startBlockHeight); - rpcService.requestChainHeadHeight(chainHeight -> parseBlocksOnHeadHeight(startBlockHeight, chainHeight), - this::handleError); - } - private void parseBlocksOnHeadHeight(int startBlockHeight, int chainHeight) { if (startBlockHeight <= chainHeight) { blocksToParseInBatch = chainHeight - startBlockHeight; @@ -221,7 +217,9 @@ private void parseBlocksOnHeadHeight(int startBlockHeight, int chainHeight) { log.warn("We are trying to start with a block which is above the chain height of Bitcoin Core. " + "We need probably wait longer until Bitcoin Core has fully synced. " + "We try again after a delay of 1 min."); - UserThread.runAfter(() -> requestChainHeadHeightAndParseBlocks(startBlockHeight), 60); + UserThread.runAfter(() -> rpcService.requestChainHeadHeight(chainHeight1 -> + parseBlocksOnHeadHeight(startBlockHeight, chainHeight1), + this::handleError), 60); } } diff --git a/core/src/main/java/bisq/core/dao/node/lite/LiteNode.java b/core/src/main/java/bisq/core/dao/node/lite/LiteNode.java index a7c6f0730e1..6466b675680 100644 --- a/core/src/main/java/bisq/core/dao/node/lite/LiteNode.java +++ b/core/src/main/java/bisq/core/dao/node/lite/LiteNode.java @@ -185,15 +185,6 @@ protected void startParseBlocks() { liteNodeNetworkService.requestBlocks(getStartBlockHeight()); } - @Override - protected void startReOrgFromLastSnapshot() { - super.startReOrgFromLastSnapshot(); - - int startBlockHeight = getStartBlockHeight(); - liteNodeNetworkService.reset(); - liteNodeNetworkService.requestBlocks(startBlockHeight); - } - /////////////////////////////////////////////////////////////////////////////////////////// // Private @@ -252,7 +243,7 @@ private void runDelayedBatchProcessing(List blocks, Runnable resultHan doParseBlock(block); runDelayedBatchProcessing(blocks, resultHandler); } catch (RequiredReorgFromSnapshotException e) { - resultHandler.run(); + log.warn("Interrupt batch processing because if a blockchain reorg. {}", e.toString()); } }); } diff --git a/seednode/src/main/java/bisq/seednode/SeedNodeMain.java b/seednode/src/main/java/bisq/seednode/SeedNodeMain.java index 080aff96d21..cea8390e84e 100644 --- a/seednode/src/main/java/bisq/seednode/SeedNodeMain.java +++ b/seednode/src/main/java/bisq/seednode/SeedNodeMain.java @@ -25,9 +25,11 @@ import bisq.core.user.CookieKey; import bisq.core.user.User; +import bisq.network.p2p.NodeAddress; import bisq.network.p2p.P2PService; import bisq.network.p2p.P2PServiceListener; import bisq.network.p2p.peers.PeerManager; +import bisq.network.p2p.seed.SeedNodeRepository; import bisq.common.Timer; import bisq.common.UserThread; @@ -42,6 +44,9 @@ import com.google.inject.Key; import com.google.inject.name.Names; +import java.util.ArrayList; +import java.util.List; + import lombok.extern.slf4j.Slf4j; @Slf4j @@ -108,9 +113,26 @@ protected void applyInjector() { seedNode.setInjector(injector); if (DevEnv.isDaoActivated()) { - injector.getInstance(DaoStateSnapshotService.class).setDaoRequiresRestartHandler(() -> gracefulShutDown(() -> { - })); + injector.getInstance(DaoStateSnapshotService.class).setDaoRequiresRestartHandler( + // We shut down with a deterministic delay per seed to avoid that all seeds shut down at the + // same time in case of a reorg. We use 30 sec. as distance delay between the seeds to be on the + // safe side. We have 12 seeds so that's 6 minutes. + () -> UserThread.runAfter(this::gracefulShutDown, 1 + (getMyIndex() * 30L)) + ); + } + } + + private int getMyIndex() { + P2PService p2PService = injector.getInstance(P2PService.class); + SeedNodeRepository seedNodeRepository = injector.getInstance(SeedNodeRepository.class); + List seedNodes = new ArrayList<>(seedNodeRepository.getSeedNodeAddresses()); + NodeAddress myAddress = p2PService.getAddress(); + for (int i = 0; i < seedNodes.size(); i++) { + if (seedNodes.get(i).equals(myAddress)) { + return i; + } } + return 0; } @Override @@ -197,6 +219,11 @@ private void setupConnectionLossCheck() { } + private void gracefulShutDown() { + gracefulShutDown(() -> { + }); + } + @Override public void gracefulShutDown(ResultHandler resultHandler) { seedNode.shutDown();