diff --git a/src/main/java/org/qortal/controller/Controller.java b/src/main/java/org/qortal/controller/Controller.java index d693f1fd..fcf6270f 100644 --- a/src/main/java/org/qortal/controller/Controller.java +++ b/src/main/java/org/qortal/controller/Controller.java @@ -655,6 +655,29 @@ public class Controller extends Thread { return lastMisbehaved != null && lastMisbehaved > NTP.getTime() - MISBEHAVIOUR_COOLOFF; }; + /** True if peer has unknown height, lower height or same height and same block signature (unless we don't have their block signature). */ + public static Predicate hasShorterBlockchain = peer -> { + BlockData highestBlockData = getInstance().getChainTip(); + int ourHeight = highestBlockData.getHeight(); + final PeerChainTipData peerChainTipData = peer.getChainTipData(); + + // Ensure we have chain tip data for this peer + if (peerChainTipData == null) + return true; + + // Remove if peer is at a lower height than us + Integer peerHeight = peerChainTipData.getLastHeight(); + if (peerHeight == null || peerHeight < ourHeight) + return true; + + // Don't remove if peer is on a greater height chain than us, or if we don't have their block signature + if (peerHeight > ourHeight || peerChainTipData.getLastBlockSignature() == null) + return false; + + // Remove if signatures match + return Arrays.equals(peerChainTipData.getLastBlockSignature(), highestBlockData.getSignature()); + }; + public static final Predicate hasNoRecentBlock = peer -> { final Long minLatestBlockTimestamp = getMinimumLatestBlockTimestamp(); final PeerChainTipData peerChainTipData = peer.getChainTipData(); diff --git a/src/main/java/org/qortal/controller/Synchronizer.java b/src/main/java/org/qortal/controller/Synchronizer.java index 63a48888..d574ef87 100644 --- a/src/main/java/org/qortal/controller/Synchronizer.java +++ b/src/main/java/org/qortal/controller/Synchronizer.java @@ -235,6 +235,9 @@ public class Synchronizer extends Thread { // Disregard peers that are on the same block as last sync attempt and we didn't like their chain peers.removeIf(Controller.hasInferiorChainTip); + // Remove peers with unknown height, lower height or same height and same block signature (unless we don't have their block signature) + peers.removeIf(Controller.hasShorterBlockchain); + final int peersBeforeComparison = peers.size(); // Request recent block summaries from the remaining peers, and locate our common block with each