From 38443583804ef992ffa17a515dd214169a3e19f1 Mon Sep 17 00:00:00 2001 From: CalDescent Date: Fri, 14 Oct 2022 16:38:05 +0100 Subject: [PATCH] Mark a peer as misbehaved if it fails to respond with a usable block 3 times in a row. This should help to workaround deserialization and missing response issues. --- .../org/qortal/controller/Synchronizer.java | 17 ++++++++++++++++- .../java/org/qortal/data/network/PeerData.java | 15 +++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/qortal/controller/Synchronizer.java b/src/main/java/org/qortal/controller/Synchronizer.java index 0fe9a56b..a7dd38ff 100644 --- a/src/main/java/org/qortal/controller/Synchronizer.java +++ b/src/main/java/org/qortal/controller/Synchronizer.java @@ -53,6 +53,9 @@ public class Synchronizer extends Thread { /** Maximum number of block signatures we ask from peer in one go */ private static final int MAXIMUM_REQUEST_SIZE = 200; // XXX move to Settings? + /** Maximum number of consecutive failed sync attempts before marking peer as misbehaved */ + private static final int MAX_CONSECUTIVE_FAILED_SYNC_ATTEMPTS = 3; + private static final long RECOVERY_MODE_TIMEOUT = 10 * 60 * 1000L; // ms @@ -1591,8 +1594,20 @@ public class Synchronizer extends Thread { Message getBlockMessage = new GetBlockMessage(signature); Message message = peer.getResponse(getBlockMessage); - if (message == null) + if (message == null) { + peer.getPeerData().incrementFailedSyncCount(); + if (peer.getPeerData().getFailedSyncCount() >= MAX_CONSECUTIVE_FAILED_SYNC_ATTEMPTS) { + // Several failed attempts, so mark peer as misbehaved + LOGGER.info("Marking peer {} as misbehaved due to {} failed sync attempts", peer, peer.getPeerData().getFailedSyncCount()); + Network.getInstance().peerMisbehaved(peer); + } return null; + } + + // Reset failed sync count now that we have a block response + // FUTURE: we could move this to the end of the sync process, but to reduce risk this can be done + // at a later stage. For now we are only defending against serialization errors or no responses. + peer.getPeerData().setFailedSyncCount(0); switch (message.getType()) { case BLOCK: { diff --git a/src/main/java/org/qortal/data/network/PeerData.java b/src/main/java/org/qortal/data/network/PeerData.java index 09982c00..471685dd 100644 --- a/src/main/java/org/qortal/data/network/PeerData.java +++ b/src/main/java/org/qortal/data/network/PeerData.java @@ -28,6 +28,9 @@ public class PeerData { private Long addedWhen; private String addedBy; + /** The number of consecutive times we failed to sync with this peer */ + private int failedSyncCount = 0; + // Constructors // necessary for JAXB serialization @@ -92,6 +95,18 @@ public class PeerData { return this.addedBy; } + public int getFailedSyncCount() { + return this.failedSyncCount; + } + + public void setFailedSyncCount(int failedSyncCount) { + this.failedSyncCount = failedSyncCount; + } + + public void incrementFailedSyncCount() { + this.failedSyncCount++; + } + // Pretty peerAddress getter for JAXB @XmlElement(name = "address") protected String getPrettyAddress() {