From c4cbb64643e81c3d01bf51d59b73fa901bdba847 Mon Sep 17 00:00:00 2001 From: CalDescent Date: Sun, 9 May 2021 17:38:07 +0100 Subject: [PATCH 1/2] Added "minPeerVersion" setting, and avoid syncing with peers on lower versions. --- .../org/qortal/controller/Controller.java | 8 +++++ .../java/org/qortal/network/Handshake.java | 5 +-- src/main/java/org/qortal/network/Peer.java | 35 +++++++++++++++++++ .../java/org/qortal/settings/Settings.java | 4 +++ 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/qortal/controller/Controller.java b/src/main/java/org/qortal/controller/Controller.java index a7d028bc..c1386f53 100644 --- a/src/main/java/org/qortal/controller/Controller.java +++ b/src/main/java/org/qortal/controller/Controller.java @@ -623,6 +623,11 @@ public class Controller extends Thread { return peerChainTipData == null || peerChainTipData.getLastBlockSignature() == null || inferiorChainTips.contains(new ByteArray(peerChainTipData.getLastBlockSignature())); }; + public static final Predicate hasOldVersion = peer -> { + final String minPeerVersion = Settings.getInstance().getMinPeerVersion(); + return peer.isAtLeastVersion(minPeerVersion) == false; + }; + private void potentiallySynchronize() throws InterruptedException { // Already synchronizing via another thread? if (this.isSynchronizing) @@ -656,6 +661,9 @@ public class Controller extends Thread { // Disregard peers that are on the same block as last sync attempt and we didn't like their chain peers.removeIf(hasInferiorChainTip); + // Disregard peers that are on an old version + peers.removeIf(hasOldVersion); + final int peersBeforeComparison = peers.size(); // Request recent block summaries from the remaining peers, and locate our common block with each diff --git a/src/main/java/org/qortal/network/Handshake.java b/src/main/java/org/qortal/network/Handshake.java index 3c033e88..ed6d02db 100644 --- a/src/main/java/org/qortal/network/Handshake.java +++ b/src/main/java/org/qortal/network/Handshake.java @@ -4,7 +4,6 @@ import java.util.Arrays; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -51,7 +50,7 @@ public enum Handshake { String versionString = helloMessage.getVersionString(); - Matcher matcher = VERSION_PATTERN.matcher(versionString); + Matcher matcher = peer.VERSION_PATTERN.matcher(versionString); if (!matcher.lookingAt()) { LOGGER.debug(() -> String.format("Peer %s sent invalid HELLO version string '%s'", peer, versionString)); return null; @@ -244,8 +243,6 @@ public enum Handshake { /** Maximum allowed difference between peer's reported timestamp and when they connected, in milliseconds. */ private static final long MAX_TIMESTAMP_DELTA = 30 * 1000L; // ms - private static final Pattern VERSION_PATTERN = Pattern.compile(Controller.VERSION_PREFIX + "(\\d{1,3})\\.(\\d{1,5})\\.(\\d{1,5})"); - private static final long PEER_VERSION_131 = 0x0100030001L; private static final int POW_BUFFER_SIZE_PRE_131 = 8 * 1024 * 1024; // bytes diff --git a/src/main/java/org/qortal/network/Peer.java b/src/main/java/org/qortal/network/Peer.java index 08db0dd9..ffc90dc7 100644 --- a/src/main/java/org/qortal/network/Peer.java +++ b/src/main/java/org/qortal/network/Peer.java @@ -20,9 +20,12 @@ import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.qortal.controller.Controller; import org.qortal.data.block.CommonBlockData; import org.qortal.data.network.PeerChainTipData; import org.qortal.data.network.PeerData; @@ -87,6 +90,9 @@ public class Peer { byte[] ourChallenge; + // Versioning + public static final Pattern VERSION_PATTERN = Pattern.compile(Controller.VERSION_PREFIX + "(\\d{1,3})\\.(\\d{1,5})\\.(\\d{1,5})"); + // Peer info private final Object peerInfoLock = new Object(); @@ -634,6 +640,35 @@ public class Peer { } + // Minimum version + + public boolean isAtLeastVersion(String minVersionString) { + if (minVersionString == null) + return false; + + // Add the version prefix + minVersionString = Controller.VERSION_PREFIX + minVersionString; + + Matcher matcher = VERSION_PATTERN.matcher(minVersionString); + if (!matcher.lookingAt()) + return false; + + // We're expecting 3 positive shorts, so we can convert 1.2.3 into 0x0100020003 + long minVersion = 0; + for (int g = 1; g <= 3; ++g) { + long value = Long.parseLong(matcher.group(g)); + + if (value < 0 || value > Short.MAX_VALUE) + return false; + + minVersion <<= 16; + minVersion |= value; + } + + return this.getPeersVersion() >= minVersion; + } + + // Common block data public boolean canUseCachedCommonBlockData() { diff --git a/src/main/java/org/qortal/settings/Settings.java b/src/main/java/org/qortal/settings/Settings.java index ba9678f2..f94db927 100644 --- a/src/main/java/org/qortal/settings/Settings.java +++ b/src/main/java/org/qortal/settings/Settings.java @@ -124,6 +124,8 @@ public class Settings { private int networkPoWComputePoolSize = 2; /** Maximum number of retry attempts if a peer fails to respond with the requested data */ private int maxRetries = 2; + /** Minimum peer version number required in order to sync with them */ + private String minPeerVersion = "1.5.0"; // Which blockchains this node is running private String blockchainConfig = null; // use default from resources @@ -412,6 +414,8 @@ public class Settings { public int getMaxRetries() { return this.maxRetries; } + public String getMinPeerVersion() { return this.minPeerVersion; } + public String getBlockchainConfig() { return this.blockchainConfig; } From af9b536dd97a095b7c3c98cedbaf14af4ecc0f7a Mon Sep 17 00:00:00 2001 From: CalDescent Date: Sun, 9 May 2021 23:00:51 +0100 Subject: [PATCH 2/2] Moved version check above getMinBlockchainPeers() check, so that nodes with old versions aren't counted. --- src/main/java/org/qortal/controller/Controller.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/qortal/controller/Controller.java b/src/main/java/org/qortal/controller/Controller.java index c1386f53..9123a130 100644 --- a/src/main/java/org/qortal/controller/Controller.java +++ b/src/main/java/org/qortal/controller/Controller.java @@ -644,11 +644,15 @@ public class Controller extends Thread { // Disregard peers that don't have a recent block peers.removeIf(hasNoRecentBlock); + // Disregard peers that are on an old version + peers.removeIf(hasOldVersion); + checkRecoveryModeForPeers(peers); if (recoveryMode) { peers = Network.getInstance().getHandshakedPeers(); peers.removeIf(hasOnlyGenesisBlock); peers.removeIf(hasMisbehaved); + peers.removeIf(hasOldVersion); } // Check we have enough peers to potentially synchronize @@ -661,9 +665,6 @@ public class Controller extends Thread { // Disregard peers that are on the same block as last sync attempt and we didn't like their chain peers.removeIf(hasInferiorChainTip); - // Disregard peers that are on an old version - peers.removeIf(hasOldVersion); - final int peersBeforeComparison = peers.size(); // Request recent block summaries from the remaining peers, and locate our common block with each