diff --git a/src/main/java/org/qortal/controller/Controller.java b/src/main/java/org/qortal/controller/Controller.java index cde965c1..7ce94b1e 100644 --- a/src/main/java/org/qortal/controller/Controller.java +++ b/src/main/java/org/qortal/controller/Controller.java @@ -722,6 +722,43 @@ public class Controller extends Thread { return lastMisbehaved != null && lastMisbehaved > NTP.getTime() - MISBEHAVIOUR_COOLOFF; }; + public static final Predicate hasInvalidBlock = peer -> { + final PeerChainTipData peerChainTipData = peer.getChainTipData(); + Map invalidBlockSignatures = Synchronizer.getInstance().getInvalidBlockSignatures(); + List peerSignatures = new ArrayList<>(); + + // Add peer's latest block signature + if (peerChainTipData != null) { + peerSignatures.add(peerChainTipData.getLastBlockSignature()); + } + + // Add peer's blocks since common block + if (peer.getCommonBlockData() == null) { + List peerSummaries = peer.getCommonBlockData().getBlockSummariesAfterCommonBlock(); + if (peerSummaries != null) { + for (BlockSummaryData blockSummaryData : peerSummaries) { + peerSignatures.add(blockSummaryData.getSignature()); + } + } + } + + // Shortcut if no data + if (peerSignatures.isEmpty() || invalidBlockSignatures == null || invalidBlockSignatures.isEmpty()) { + return false; + } + + // Loop through our known invalid blocks and check each one against supplied block summaries + for (String invalidSignature58 : invalidBlockSignatures.keySet()) { + byte[] invalidSignature = Base58.decode(invalidSignature58); + for (byte[] peerSignature : peerSignatures) { + if (Arrays.equals(peerSignature, invalidSignature)) { + return true; + } + } + } + return false; + }; + 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 597752d2..e1f248dd 100644 --- a/src/main/java/org/qortal/controller/Synchronizer.java +++ b/src/main/java/org/qortal/controller/Synchronizer.java @@ -241,6 +241,10 @@ public class Synchronizer extends Thread { // Compare the peers against each other, and against our chain, which will return an updated list excluding those without common blocks peers = Synchronizer.getInstance().comparePeers(peers); + // Disregard peers that hold invalid blocks + // Make sure this is after findCommonBlocksWithPeers() so that peers' summaries can be updated + peers.removeIf(Controller.hasInvalidBlock); + // We may have added more inferior chain tips when comparing peers, so remove any peers that are currently on those chains peers.removeIf(Controller.hasInferiorChainTip); @@ -840,6 +844,10 @@ public class Synchronizer extends Thread { /* Invalid block signature tracking */ + public Map getInvalidBlockSignatures() { + return this.invalidBlockSignatures; + } + private void addInvalidBlockSignature(byte[] signature) { Long now = NTP.getTime(); if (now == null) {