From 895f02f17896c5ad78f7e8f26252d7530aae3a85 Mon Sep 17 00:00:00 2001 From: CalDescent Date: Sat, 16 Apr 2022 11:30:07 +0100 Subject: [PATCH] Remove peers with unknown height, lower height or same height and same block signature (unless we don't have their block signature) Adapted from code originally written by catbref from before genesis, and essentially prevents syncing backwards. This needs significant testing on testnet. --- .../org/qortal/controller/Controller.java | 23 +++++++++++++++++++ .../org/qortal/controller/Synchronizer.java | 3 +++ 2 files changed, 26 insertions(+) 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