We instantiate a p2p network and call start(). This will begin running a single
p2p network until stop() is called.
There are 3 session types:
InboundSession, concerned with incoming connectionsOutboundSession, concerned with outgoing connectionsSeedSession is a special session type which connects to seed nodes to populate
the hosts pool, then finishes once synced.Connections are made by either Acceptor or Connector for incoming or outgoing
respectively. They have multiple transport types; see src/net/transport/ for the
full list.
Connections are then wrapped in a Channel abstraction which allows
protocols to be attached. See src/net/protocol/ and run fd protocol for custom
application specific network protocols. Also see the follow tutorial:
The outbound session is responsible to ensure the hosts pool is populated, either through currently connected nodes or using the seed session. It performs this algorithm:
Then each slot performs this algorithm:
The main attacks are:
channel.ban() which immediately disconnects and blacklists the address.Core protocols should be modeled and analyzed with DoS protections added. Below are suggestions to start the investigation.
channel.ban().Apps should be able to configure:
TODO: research how this is handled on bittorrent. How do we lookup nodes in the swarm? Does the network maintain routing tables? Is this done through a DHT like Kademlia?
Swarming means more efficient downloading of data specific to a certain subset. A new p2p instance is spawned with a clean hosts table. This subnetwork is self contained.
An application is for example DarkIRC where everyday a new event graph is spawned. With swarming, you would connect to nodes maintaining this particular day's event graph.
The feature allows overlaying multiple different features in a single network such as tau, darkirc and so on. New networks require nodes to bootstrap, but with swarming, we reduce all these networks to a single bootstrap. The overlay network maintaining the routing tables is a kind of decentralized lilith which keeps track of all the swarms.
Possibly a post-mainnet feature depending on the scale of architectural changes or new code required in the net submodule.
In Monero, each node maintains a peer list consisting of two parts,
a whitelist and a greylist. White/ greylists contain a last_seen
data field, a timestamp of the last time the peer was interacted with.
The lists are ordered chronologically according to last_seen, with the
most recently seen peers at the top of the list. The whitelist max size
is 1000. The greylist max size is 5000. If the number of peers in these
lists reach this maximum, then the peers with the oldest last_seen
fields are removed from the list.
Each time a node receives info about a set of peers, the info is inserted
into its greylist. To discover peers, nodes exchange SYN messages
to their neighbors. Upon receiving a SYN message, peers reply with
a message with the top 250 peers from their whitelist. The requester
inserts the received peer data into its greylist.
Nodes update their whitelist and greylist through a mechanism called
"greylist housekeeping", which periodically pings randomly selected peers
from its greylist. If a peer is responsive, then it is promoted to the
whitelist with an updated last_seen field, otherwise it is removed
from the greylist.
To handle idle connections, nodes check connections through the
IDLE_HANDSHAKE protocol. Nodes iterate through their connections, send a
SYN message, and update the last seen fields of the connection if they
receive a response. Otherwise, they drop the associated connection and
select another peer from the whitelist. The disconnected peer stays on
the whitelist.
Nodes broadcast messages to connections choosen from their whitelist. If not enough peers from the whitelist are currently online, then a node will establish connections from its greylist. Nodes to which previous connections were established are classified as anchor nodes, and stored in the white list. Monero ensures that every node is connected to at least two anchor nodes.
Refactor src/hosts.rs to store two Vec<(Url, u64)> instead of single
Hashset<Url>, replacing the host list and its associated methods with
a whitelist and a greylist. [STATUS: COMPLETE/ TESTING]
Create a GreylistRefinery protocol in OutboundSession (renamed from
Monero's "greylist housekeeping" for succinctness) that periodically
selects random peers from its greylist and pings them. If a peer is
responsive, update the last_seen field and add it to the whitelist,
otherwise remove it from the greylist. [STATUS: COMPLETE/ TESTING]
lilith currently checks connections on the host list using a method
called periodic_purge that gets hosts from the host list, copies them to
a local ring buffer, and periodically handshakes the connections. If the
handshake fails, lilith removes the host from the hostlist. This protocol
has been replaced by a method called whitelist_cleansing. Like the
prior method, whitelist_cleansing pulls connections from the whitelist,
copies them to a ring buffer and handshakes them periodically. If they
respond, the last_seen is updated, otherwise nothing happens. This is
loosely based on Monero's IDLE_HANDSHAKE protocol. [STATUS: COMPLETE/
REEVALUATE/ TESTING]
ProtocolAddress: On receiving an address, append it to the greylist. On
receiving get_addr, fetch an address from the whitelist. [STATUS: COMPLETE/
TESTING].
SeedSyncSession: on receiving whitelisted peers, append them to
greylist. [STATUS: INCOMPLETE/ FIXME]
ProtocolSeed: Send our address to the seed node, and on receiving
addresses, append them to the whitelist. [STATUS: INCOMPLETE/ FIXME]
Create a new list in hosts.rs called anchorlist. OutboundSession
first tries to connect to address in the anchorlist on start(). [STATUS:
TODO]
Potentially create a new Protocol to send the top 250 nodes from the
whitelist (Monero SYN exchange). [STATUS: TODO/ EVALUATE]