diff --git a/docs/PEER_DISCOVERY.rst b/docs/PEER_DISCOVERY.rst new file mode 100644 index 0000000..14c3a6b --- /dev/null +++ b/docs/PEER_DISCOVERY.rst @@ -0,0 +1,165 @@ +Peer Discovery +============== + +This is a suggestion of a peer discovery prtocol as a way to gradually +move off depending on IRC. + +It will be implemented in ElectrumX from version 0.11.0 +onwards. + + +Peer Database +------------- + +A persistent store of peers with at least the following information +about a peer so that state persists across server restarts. This +information is required for a response to the *server.peers.subscribe* +RPC call: + +* host name +* ip address +* TCP and SSL port numbers +* protocol version +* pruning limit, if any + +At present ElectrumX uses a flat file for this DB in the main database +directory. It retains additional per-peer metadata including: + +* time of last successful connection +* time of last connection attempt +* count of unsuccessful attempts since last successful one +* source of the information stored about this peer + + +Default Peers +------------- + +This is a list of hard-coded, well-known peers to seed the peer +discovery process if the peer database is empty or corrupt. If the +peer database is available it is not used. Ideally it should hold up +to 10 servers that have shown commitment to reliable service. + +In ElectrumX this is a per-coin property in `lib/coins.py`. + + +Response to "server.peers.subscribe" RPC call +--------------------------------------------- + +This RPC call is used by Electrum clients to get a list of peer +servers, in preference to a hard-coded list of peer servers in the +client, which it will fall back to if necessary. + +The response should only include peers it has successfully connected +to recently. If Tor routing is not available to the server, so it +cannot connect to them, it should return a random limited number of +onion peers it is aware of. + +In ElectrumX, "recently" is taken to be the last 24 hours, and it will +serve up to 3 onion peers if onion routing is not available. + + +Maintaining the Peer Database +----------------------------- + +In order to keep its peer database up-to-date and fresh, if some time +has passed since the last successful connection to a peer, an Electrum +server should make an attempt to connect, choosing the TCP or SSL port +at random if both are available. On connecting it should issue +**server.peers.subscribe** and **server.features** RPC calls to +collect information about the server and its peers, and issue a +**server.add_peer** call to advertise itself. Once this is done and +replies received it should terminate the connection. + +The peer database should prefer information obtained from the peer +itself over information obtained from any other source. + +If a connection attempt fails, reconnection should follow some kind of +exponential backoff. If a long period of time has elapsed since the +successful connection attempt, the peer entry should be removed from +the database. + +ElectrumX will choose the SSL port most of the time if both ports are +available. It tries to reconnect to each peer once every 24 hours and +drops peers if two weeks have passed since a successful connection. + + +"server.features" RPC call +-------------------------- + +This is a new RPC call that a server can use to advertise what +services and features it offers. It is intended for use by Electrum +clients as well as peer servers. In the case of servers it is useful +in order to have database peer information sourced from the peer +itself. + +The call takes no arguments and returns a dictionary keyed by feature +name whose value gives details about the feature where appropriate. +If a key is missing the feature is presumed not to be offered. + +Currently ElectrumX understands and returns the following keys: + +* **hosts** + + An dictionary, keyed by host name, that this server can be reached + at. Normally this will only have a single entry; other entries can + be used in case there are other connection routes (e.g. ToR). + + The value for a host is itself a dictionary, with the following + optional keys: + + * **ssl_port** + + An integer. Omit or set to *null* if SSL connectivity is not + provided. + + * **tcp_port** + + An integer. Omit or set to *null* if TCP connectivity is not + provided. + + A server should ignore information provided about any host other + than the one it connected to. + +* **server_version** + + A string that identifies the server software. Should be the same as + the response to 'server.version' RPC call. Defaults to "unknown". + +* **protocol_version** + + A string that is the Electrum protcol version. Should be the same + as what would suffix the letter 'v' in the IRC real name. + +* **pruning** + + An integer, the pruning limit. Omit or set to *null* if there is no + pruning limit. Should be the same as what would suffix the letter + 'p' in the IRC real name. + + +"server.add_peer" RPC call +-------------------------- + +This call is intended for a new server to get itself in the connected +set. + +It takes a single parameter (named **features** if JSON RPCv2 named +parameters are being used) which contains the same information as the +*server.features* RPC call would return. + +A server receiving a **server.add_peer** call should not replace +existing information about the host(s) given, but instead schedule a +separate connection to verify the information for itself. + +To prevent abuse a server may want to ignore excessive calls to this +function. + + +IRC +--- + +Other server implementations may not have implemented the peer +discovery protocol yet. Whilst we transition away from IRC, in order +to keep these servers in the connected peer set, software implementing +this protocol should provide a way to occasionally connect to IRC to +pick up stragglers only advertising themselves there.