Is anybody planning on/currently working on adding support for addr messages and persisting a set of peers that have been seen on the network?
I see that there are todo's in the code for this, e.g.:
I'm playing around with building a peer crawler for the lulz, and I'm wondering if it is desirable to add support for addr messages directly in bitcoinj. All my peer crawler needs to do is connect to a few peers and listen for addr messages. Then it stores the peers that it learns about in a database. Super simple.
However, the interface for doing this is a bit ugly. The only way to be notified about addr messages is to subclass PeerSocketHandler directly, which means re-implementing the version exchange logic that is normally handled by the Peer class, and other protocol logic such as responding to pings. That also means you can't use the PeerGroup to manage multiple connections so I would have to reimplement that logic as well.
What do you guys think of adding a PeerStore interface? It will have methods like "addPeers", "removePeers", and "getAnyPeer". A first implementation would be called MemoryPeerStore, and would simply store an array of peers in memory. Other implementations could save the peers to a file, postgres, etc.
A PeerStore will be passed to the PeerGroup's constructor. When it wants to connect to a new peer, the PeerGroup first checks if its PeerStore has enough non-stale peers. If the so, then the PeerGroup tries to connect to one of those. If not, then it does PeerDiscovery like normal.
The PeerGroup will store the peers that it learned about from PeerDiscovery in the PeerStore.
To add peers to the PeerStore from addr messages, one option would be to pass the PeerStore to the Peer class's constructor. Then whenever the Peer receives an addr message it simply calls addPeers to update the PeerStore.
Alternatively, the Peer could notify its listeners with a list of peers when an addr message is received, and the listener (i.e. the PeerGroup) could update the PeerStore object.
I think I like the first option better, although then we have to be careful to make the PeerStore thread-safe.
Another question is how to verify that the peers in the PeerStore are actually reachable so they don't get stale. The simplest naive approach would be to just have the PeerGroup remove a peer from the PeerStore if it tries to connect and fails. The PeerStore implementation could also automatically remove peers older than a certain age.
The most heavy-weight approach would be to have something like a PeerTracker that actually opens a connection to each peer in the PeerStore periodically to check if it is still up, but that seems like a lot to ask of a smart phone, especially if there are >1000 peers.
What do you guys think? Then for my peer crawler, I could simply create a PeerGroup and pass my PeerStore to its constructor. That is much nicer than writing my own PeerSocketHandler implementation and managing multiple peer connections manually (since I couldn't use a PeerGroup).
This also has the benefit of reducing traffic to the seed peers, because clients could often connect to cached peers when they start up instead of doing dns discovery every time.