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.
This commit is contained in:
CalDescent 2021-09-19 17:33:04 +01:00
parent 8a7446fb40
commit 47a34c2f54

View File

@ -343,7 +343,7 @@ public class Synchronizer {
} }
// Ignore this peer if it holds an invalid block // 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); LOGGER.debug("Ignoring peer %s because it holds an invalid block", peer);
peers.remove(peer); peers.remove(peer);
} }
@ -503,7 +503,7 @@ public class Synchronizer {
} }
invalidBlockSignatures.add(signature); invalidBlockSignatures.add(signature);
} }
private boolean containsInvalidBlock(List<BlockSummaryData> blockSummaries) { private boolean containsInvalidBlockSummary(List<BlockSummaryData> blockSummaries) {
if (blockSummaries == null || invalidBlockSignatures == null) { if (blockSummaries == null || invalidBlockSignatures == null) {
return false; return false;
} }
@ -519,6 +519,21 @@ public class Synchronizer {
} }
return false; return false;
} }
private boolean containsInvalidBlockSignature(List<byte[]> 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; 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); byte[] nextPeerSignature = peerBlockSignatures.get(0);
int nextHeight = height + 1; int nextHeight = height + 1;