This fixes the download behavior to allow downloading blocks on a chain that is known only by inbound peers and not by outbound/preferred download peers, mentioned in issue #5138. @sipa I tried implementing your suggestion (on IRC) of just guarding the getdata code block with a (preferredpeer || rand() %100 == 0). I think this works for what we were discussing (where an inbound peer announces a tip more than 1 block ahead on a chain no one else knows about), but it doesn’t resolve @gavinandresen’s test case in issue #5138 because we still wouldn’t be sending getheaders when an inbound peer connects like we do for outbound peers. Instead, we’d have to wait for an inv that builds on the longer chain from the inbound peer before we send getheaders, and then with this code send the getdata.
One question: is it necessary to also check !pto->fOneShot()
with this change? I didn’t think it would be possible for us to have a one shot peer’s headers and therefore no blocks we’d ever try to download, so I left it out, but perhaps it’s preferable to include that check just to be safe…?
As an aside: I noticed that an additional way we could workaround the regtest issue @gavinandresen raised, besides connecting nodes to each other in both directions, would be to whitelist localhost.
I’ve tested this code on a modified version of the test, where after connecting a node with a longer chain and observing that the tips didn’t sync, I then generated one more block on that inbound peer and observed that the tips then did sync.
Finally, I believe that if we wanted to send an initial getheaders message to all inbound peers just as we do for outbound peers so that we could immediately download a longer chain known only by an inbound peer, we could do so with a similar small change to the code that sends the initial getheaders messages (while still preferring outbound peers for downloading blocks during initial block download), but it wasn’t clear to me whether such a behavior change would be desirable.