forked from Qortal/qortal
Keep track of invalid block signatures and avoid peers that return them
Until now, a high weight invalid block can cause other valid, lower weight alternatives to be discarded. The solution to this problem is to track invalid blocks and quickly avoid them once discovered. This gives other valid alternative blocks the opportunity to become part of a valid chain, where they would otherwise have been discarded. As with the block minter update, this will cause a fork when the highest weight block candidate is invalid. But it is likely that the fork would be short lived, assuming that the majority of nodes pick the valid chain.
This commit is contained in:
parent
54e5a65cf0
commit
44a90b4e12
@ -342,6 +342,12 @@ public class Synchronizer {
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore this peer if it holds an invalid block
|
||||
if (this.containsInvalidBlock(peer.getCommonBlockData().getBlockSummariesAfterCommonBlock())) {
|
||||
LOGGER.debug("Ignoring peer %s because it holds an invalid block", peer);
|
||||
peers.remove(peer);
|
||||
}
|
||||
|
||||
// Reduce minChainLength if needed. If we don't have any blocks, this peer will be excluded from chain weight comparisons later in the process, so we shouldn't update minChainLength
|
||||
List <BlockSummaryData> peerBlockSummaries = peer.getCommonBlockData().getBlockSummariesAfterCommonBlock();
|
||||
if (peerBlockSummaries != null && peerBlockSummaries.size() > 0)
|
||||
@ -485,6 +491,36 @@ public class Synchronizer {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Invalid block signature tracking */
|
||||
|
||||
private void addInvalidBlockSignature(byte[] signature) {
|
||||
for (byte[] invalidSignature : invalidBlockSignatures) {
|
||||
if (Arrays.equals(invalidSignature, signature)) {
|
||||
// Already present
|
||||
return;
|
||||
}
|
||||
}
|
||||
invalidBlockSignatures.add(signature);
|
||||
}
|
||||
private boolean containsInvalidBlock(List<BlockSummaryData> blockSummaries) {
|
||||
if (blockSummaries == null || invalidBlockSignatures == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Loop through supplied block summaries and check each one against our known invalid blocks
|
||||
for (BlockSummaryData blockSummary : blockSummaries) {
|
||||
byte[] signature = blockSummary.getSignature();
|
||||
for (byte[] invalidSignature : invalidBlockSignatures) {
|
||||
if (Arrays.equals(signature, invalidSignature)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attempt to synchronize blockchain with peer.
|
||||
* <p>
|
||||
@ -990,6 +1026,7 @@ public class Synchronizer {
|
||||
if (blockResult != ValidationResult.OK) {
|
||||
LOGGER.info(String.format("Peer %s sent invalid block for height %d, sig %.8s: %s", peer,
|
||||
newBlock.getBlockData().getHeight(), Base58.encode(newBlock.getSignature()), blockResult.name()));
|
||||
this.addInvalidBlockSignature(newBlock.getSignature());
|
||||
this.timeInvalidBlockLastReceived = NTP.getTime();
|
||||
return SynchronizationResult.INVALID_DATA;
|
||||
}
|
||||
@ -1082,6 +1119,7 @@ public class Synchronizer {
|
||||
if (blockResult != ValidationResult.OK) {
|
||||
LOGGER.info(String.format("Peer %s sent invalid block for height %d, sig %.8s: %s", peer,
|
||||
ourHeight, Base58.encode(latestPeerSignature), blockResult.name()));
|
||||
this.addInvalidBlockSignature(newBlock.getSignature());
|
||||
this.timeInvalidBlockLastReceived = NTP.getTime();
|
||||
return SynchronizationResult.INVALID_DATA;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user