- Instead of naively planning requests every two minutes into (potentially) the far future w/ mapAlreadyAskedFor, actively keep track of requests, and which nodes offer the requested items
- Better handles the case where nodes announce an inv and go away, or stop responding
- Maintains state separate from CNode, which makes it easier to review and understand separately from the rest, as well as localizes changes if extension of the logic is necessary
I also think it can serve as an example of how to ‘peel off’ a single concern from net/main.
Uses CTimeoutCondition from @ashleyholman (#4230).
Cases to test:
- Announce and don’t reply to getdata, make sure retry chooses different node after
REQUEST_TIMEOUT
- Node disconnects and was the current node requested from - should immediately try to get from different node
- Last node that had announced a certain transaction goes away - request should be discarded I’ve tested these cases using custom pynode clients, as well as by running this with full debugging on my node to see how it behaves,
- Premature flushing if more than 1000 getdatas queued to a node (this is a very unlikely path but it needs to be tested)
TODO:
- Slim down debug logging (this is initially useful for testing and checking, but too much in production)
- Make sure
FlushGetdata
’s handling of CNode locking is correct - Don’t request from nodes whose sendbuffer is full
Known issues:
Doesn’t currently group getdata requests (sends a getdata request per item instead of one getdata for many invs) - wouldn’t be too difficult to fit in but I’m not sure it is worth the complexity, as usually only one inv is sent at a time(done now)