Browse Source

Update PROTOCOL.rst and PEER_DISCOVERY.rst

master
Neil Booth 8 years ago
parent
commit
31755e1dac
  1. 56
      docs/PEER_DISCOVERY.rst
  2. 61
      docs/PROTOCOL.rst

56
docs/PEER_DISCOVERY.rst

@ -72,11 +72,12 @@ 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 either the TCP or
SSL port. On connecting it should issue **server.peers.subscribe**
and **server.features** RPC calls to collect information about the
server and its peers, and if it is the first time connecting to this
peer, a **server.add_peer** call to advertise itself. Once this is
done and replies received it should terminate the connection.
SSL port. On connecting it should issue **server.peers.subscribe**,
**blockchain.headers.subscribe**, and **server.features** RPC calls to
collect information about the server and its peers. If the peer seems
to not know of you, you can issue a **server.add_peer** call to
advertise yourself. Once this is done and replies received it should
terminate the connection.
The peer database should view information obtained from an outgoing
connection as authoritative, and prefer it to information obtained
@ -84,13 +85,12 @@ from any other source.
On connecting, a server should confirm the peer is serving the same
network, ideally via the genesis block hash of the **server.features**
RPC call below. If the peer does not implement that call, perhaps
instead check the **blockchain.headers.subscribe** RPC call returns a
peer block height within a small number of the expected value. If a
peer is on the wrong network it should never be advertised to clients
or other peers. Such invalid peers should perhaps be remembered for a
short time to prevent redundant revalidation if other peers persist in
advertising them, and later forgotten.
RPC call below. Also the height reported by the peer should be within
a small number of the expected value. If a peer is on the wrong
network it should never be advertised to clients or other peers. Such
invalid peers should perhaps be remembered for a short time to prevent
redundant revalidation if other peers persist in advertising them, and
later forgotten.
If a connection attempt fails, subsequent reconnection attempts should
follow some kind of exponential backoff.
@ -200,3 +200,35 @@ the hard-coded peer list used to seed this process should suffice.
Any peer on IRC will report other peers on IRC, and so if any one of
them is known to any single peer implementing this protocol, they will
all become known to all peers quite rapidly.
Notes to Implementators
-----------------------
* it is very important to only accept peers that appear to be on the
same network. At a minimum the genesis hash should be compared (if
the peer supports the *server.features* RPC call), and also that the
peer's reported height is within a few blocks of your own server's
height.
* care should be taken with the *add_peer* call. Consider only
accepting it once per connection. Clearnet peer requests should
check the peer resolves to the requesting IP address, to prevent
attackers from being able to trigger arbitrary outgoing connections
from your server. This doesn't work for onion peers so they should
be rate-limited.
* it should be possible for a peer to change their port assignments -
presumably connecting to the old ports to perform checks will not
work.
* peer host names should be checked for validity before accepting
them; and *localhost* should probably be rejected. If it is an IP
address it should be a normal public one (not private, multicast or
unspecified).
* you should limit the number of new peers accepted from any single
source to at most a handful, to limit the effectiveness of malicious
peers wanting to trigger arbitrary outgoing connections or fill your
peer tables with junk data.
* in the response to *server.peers.subscribe* calls, consider limiting
the number of peers on similar IP subnets to protect against sybil
attacks, and in the case of onion servers the total returned.
* you should not advertise a peer's IP address if it also advertises a
hostname (avoiding duplicates).

61
docs/PROTOCOL.rst

@ -703,37 +703,62 @@ Get a list of features and services supported by the server.
The following features MUST be reported by the server. Additional
key-value pairs may be returned.
* **hosts**
* **hosts**
A dictionary of host names the server can be reached at. Each
value is a dictionary with keys "ssl_port" and "tcp_port" at which
the given host can be reached. If there is no open port for a
transport, its value should be *null*.
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).
* **server_version**
The value for a host is itself a dictionary, with the following
optional keys:
The same identifying string as returned in response to *server.version*.
* **ssl_port**
* **protocol_version**
An integer. Omit or set to *null* if SSL connectivity is not
provided.
A pair [`protocol_min`, `protocol_max`] of the protocols supported
by the server, each of which is itself a [major_version,
minor_version] pair.
* **tcp_port**
* **pruning**
An integer. Omit or set to *null* if TCP connectivity is not
provided.
The history pruning limit of the server as an integer. If the
server does not prune return *null*.
A server should ignore information provided about any host other
than the one it connected to.
* **genesis_hash**
The hash of the genesis block. This is used to detect if a peer is
connected to one serving a different network.
* **server_version**
A string that identifies the server software. Should be the same as
the response to **server.version** RPC call.
* **protocol_max**
* **protocol_min**
Strings that are the minimum and maximum Electrum protcol versions
this server speaks. The maximum value should be the same as what
would suffix the letter **v** in the IRC real name. Example: "1.1".
* **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.
**Example Response**
::
{
"server_version": "ElectrumX 0.10.14",
"protocol_version": [[1, 0], [1, 1]],
"hosts": {"14.3.140.101": {"ssl_port": 50002, "tcp_port": 50001}},
"pruning": null
"genesis_hash": "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943",
"hosts": {"14.3.140.101": {"tcp_port": 51001, "ssl_port": 51002}},
"protocol_max": "1.0",
"protocol_min": "1.0",
"pruning": null,
"server_version": "ElectrumX 1.0.1"
}
.. _JSON RPC 1.0: http://json-rpc.org/wiki/specification

Loading…
Cancel
Save