-
Notifications
You must be signed in to change notification settings - Fork 312
Fixed peer that were stuck #3296
Changes from all commits
248ceb1
375120b
e546121
2d1bfa5
865bc0c
3311bf1
03bd3b0
f1e9499
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -257,6 +257,12 @@ public ConnectNewHeadersResult HeadersPresented(INetworkPeer peer, List<BlockHea | |
|
||
connectNewHeadersResult = this.chainedHeaderTree.ConnectNewHeaders(peerId, headers); | ||
|
||
if (!this.peersByPeerId.ContainsKey(peerId)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The position in the locked code segment that this is placed seems a bit arbitrary (both doing it last and moving it higher up). What was the reasoning behind putting it after There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @dangershony didn't wanted to put it before because in case Probably it's right because we may incur in a deadlock if we put it before ConnectNewHeaders because it causes peer to disconnect. Anyway there are more things to investigate about peersByPeerId because it seems this gets populated only for peers supporting PH (after last checkpoint) and this may cause problems There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @dangershony @MithrilMan I'm also sketchy on why this has been moved up? Care to elaborate? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Its a bit long but here goes: The bellow code is valid scenarios of the flow From CM.HeadersPresented method
If both the above conditions are true this means insufficient info to validate a proven header. If
But this issue is actually reflected later in the method
That method will trigger when consensus tip changed and should notify the peer to send the next batch of headers (or actually its proven headers) that are waiting in cache to be processed (because we could not connect them earlier due to missing UTXOs). but the peer was never added to this list So the bug that this change fixes (because the fix to CHT will fix the scenario where any of the headers had insufficient info) is that if we connected to a peer and the first headers it presents could not be connected the peer would be stuck because we would not notify the peer's behaviour to try presenting those headers again when consensus advances. |
||
{ | ||
this.peersByPeerId.Add(peerId, peer); | ||
this.logger.LogTrace("New peer with ID {0} was added.", peerId); | ||
} | ||
|
||
if (connectNewHeadersResult == null) | ||
{ | ||
this.logger.LogTrace("(-)[NO_HEADERS_CONNECTED]:null"); | ||
|
@@ -272,12 +278,6 @@ public ConnectNewHeadersResult HeadersPresented(INetworkPeer peer, List<BlockHea | |
this.chainState.IsAtBestChainTip = this.IsConsensusConsideredToBeSyncedLocked(); | ||
|
||
this.blockPuller.NewPeerTipClaimed(peer, connectNewHeadersResult.Consumed); | ||
|
||
if (!this.peersByPeerId.ContainsKey(peerId)) | ||
{ | ||
this.peersByPeerId.Add(peerId, peer); | ||
this.logger.LogTrace("New peer with ID {0} was added.", peerId); | ||
} | ||
} | ||
|
||
if (triggerDownload && (connectNewHeadersResult.DownloadTo != null)) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -112,7 +112,8 @@ public async Task<ConnectNewHeadersResult> ConsensusTipChangedAsync() | |
this.BestReceivedTip = result.Consumed; | ||
this.UpdateBestSentHeader(this.BestReceivedTip); | ||
|
||
int consumedCount = this.cachedHeaders.IndexOf(result.Consumed.Header) + 1; | ||
int consumedCount = this.GetConsumedHeadersCount(this.cachedHeaders, result.Consumed.Header); | ||
|
||
this.cachedHeaders.RemoveRange(0, consumedCount); | ||
int cacheSize = this.cachedHeaders.Count; | ||
|
||
|
@@ -379,7 +380,7 @@ protected virtual async Task ProcessHeadersAsync(INetworkPeer peer, List<BlockHe | |
if (result.Consumed.HashBlock != headers.Last().GetHash()) | ||
{ | ||
// Some headers were not consumed, add to cache. | ||
int consumedCount = headers.IndexOf(result.Consumed.Header) + 1; | ||
int consumedCount = this.GetConsumedHeadersCount(headers, result.Consumed.Header); | ||
this.cachedHeaders.AddRange(headers.Skip(consumedCount)); | ||
|
||
this.logger.LogDebug("{0} out of {1} items were not consumed and added to cache.", headers.Count - consumedCount, headers.Count); | ||
|
@@ -659,5 +660,32 @@ public override object Clone() | |
{ | ||
return new ConsensusManagerBehavior(this.chain, this.initialBlockDownloadState, this.consensusManager, this.peerBanning, this.loggerFactory); | ||
} | ||
|
||
internal int GetCachedItemsCount() | ||
{ | ||
return this.cachedHeaders.Count; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm what about a lock? Maybe for taking the count it snot a big deal. |
||
} | ||
|
||
/// <summary> | ||
/// Gets the count of consumed headers in a <paramref name="headers"/> list, giving a <paramref name="consumedHeader"/> reference. | ||
/// All items up to <paramref name="consumedHeader"/> are considered consumed. | ||
/// </summary> | ||
/// <param name="headers">List of headers to use to get the consumed count.</param> | ||
/// <param name="consumedHeader">The consumed header reference.</param> | ||
/// <returns>The number of consumed cached items.</returns> | ||
private int GetConsumedHeadersCount(List<BlockHeader> headers, BlockHeader consumedHeader) | ||
{ | ||
uint256 consumedHeaderHash = consumedHeader.GetHash(); | ||
|
||
for (int i = 0; i < headers.Count; i++) | ||
{ | ||
if (headers[i].GetHash() == consumedHeaderHash) | ||
{ | ||
return i + 1; | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks correct, gj
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thats the main fix indeed.