From 47a34c2f54b67e61b26ffdb42b3ee6aac7dd5bdb Mon Sep 17 00:00:00 2001 From: CalDescent Date: Sun, 19 Sep 2021 17:33:04 +0100 Subject: [PATCH] Validate blocks in syncToPeerChain() before orphaning This prevents a valid block candidate being discarded in favour of an invalid one. We can't actually validate a block before orphaning (because it will fail due to various reasons such as already existing transactions, an existing block with the same height, etc) so we will instead just check the signature against the list of known invalid blocks. --- .../org/qortal/controller/Synchronizer.java | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/qortal/controller/Synchronizer.java b/src/main/java/org/qortal/controller/Synchronizer.java index 97d70027..f8ea0ec0 100644 --- a/src/main/java/org/qortal/controller/Synchronizer.java +++ b/src/main/java/org/qortal/controller/Synchronizer.java @@ -343,7 +343,7 @@ public class Synchronizer { } // Ignore this peer if it holds an invalid block - if (this.containsInvalidBlock(peer.getCommonBlockData().getBlockSummariesAfterCommonBlock())) { + if (this.containsInvalidBlockSummary(peer.getCommonBlockData().getBlockSummariesAfterCommonBlock())) { LOGGER.debug("Ignoring peer %s because it holds an invalid block", peer); peers.remove(peer); } @@ -503,7 +503,7 @@ public class Synchronizer { } invalidBlockSignatures.add(signature); } - private boolean containsInvalidBlock(List blockSummaries) { + private boolean containsInvalidBlockSummary(List blockSummaries) { if (blockSummaries == null || invalidBlockSignatures == null) { return false; } @@ -519,6 +519,21 @@ public class Synchronizer { } return false; } + private boolean containsInvalidBlockSignature(List blockSignatures) { + if (blockSignatures == null || invalidBlockSignatures == null) { + return false; + } + + // Loop through supplied block signatures and check each one against our known invalid blocks + for (byte[] signature : blockSignatures) { + for (byte[] invalidSignature : invalidBlockSignatures) { + if (Arrays.equals(signature, invalidSignature)) { + return true; + } + } + } + return false; + } /** @@ -920,6 +935,12 @@ public class Synchronizer { break; } + // Catch a block with an invalid signature before orphaning, so that we retain our existing valid candidate + if (this.containsInvalidBlockSignature(peerBlockSignatures)) { + LOGGER.info(String.format("Peer %s sent invalid block signature: %.8s", peer, Base58.encode(latestPeerSignature))); + return SynchronizationResult.INVALID_DATA; + } + byte[] nextPeerSignature = peerBlockSignatures.get(0); int nextHeight = height + 1;