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:
Node maintain a hostlist consisting of three parts, a whitelist, a
greylist and an anchorlist. Each hostlist entry is a tuple of two parts,
a URL address and a last_seen data field, which is 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 broadcast GetAddr
messages. Upon receiving a GetAddr message, peers reply with an Addr
message containing their whitelist. The requester inserts the received
peer data into its greylist.
Nodes update their hostlists 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.
On shutdown, whitelist entries are downgraded to greylist. This forces all whitelisted entries through the greylist refinery each time a node is started, further ensuring that whitelisted entries are active.
If a connection is established to a host, that host is promoted to anchorlist. If anchorlist or whitelist nodes disconnect or cannot be connected to, those hosts are downgraded to greylist.
Nodes can configure how many anchorlist connections or what percentage
of whitelist connections they would like to make, and this configuration
influences the connection behavior in OutboundSession. If there's
not enough anchorlist entries, the connection loop will select from
the whitelist. If there's not enough whitelist entries in the hostlist,
it will select from the greylist.
This design has been largely informed by the Monero p2p algo
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:
blacklist which allows us to reject hosts by addr.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.
To faciliate this future upgrade, we have made the peer discovery process a generic trait called PeerDiscoveryBase. Currently there is only one imeplementation, PeerDiscovery, which implements the peer discovery process in outbound sesssion. In the future PeerDiscoveryBase can be implemented to make new forms of peer discovery (i.e. subnets vs overlay peer discovery processes).
Connections should maintain a scoring system. Protocols can increment the score.
The score backs off exponentially. If the watermark is crossed then the connection is dropped.
Since the reader in messages.rs preallocs buffers, there should be a hard
limit here, and the raw reads also affects your score too.
In libp2p, resource usage is constrained by a Resource Manager that
defines resource usage limits. The Resource Manager checks whether
a given request is within a limit and returns an error if it exceeds
a limit.
Resources are deliminated by Resource Management Scopes. Each scope has a corresponding limit that resources cannot exceed.
Limits are calculated by measuring the following resources:
Memory
File descriptors
Connections (Inbound connections have stricter limits than outbound connections)
Streams: an object of interaction between nodes (~analogous to
Channel). Streams are not metered directly- rather they are constrained
within the protocol and service scope (defined below). Inbound streams
are more tightly controlled than outbound streams.
Resource Management Scopes are hierarchial and downstream resource usage is aggregated at higher levels.
System
+------------> Transient.............+................+
| . .
+------------> Service------------- . ----------+ .
| . | .
+-------------> Protocol----------- . ----------+ .
| . | .
+-------------->* Peer \/ | .
+------------> Connection | .
| \/ \/
+---------------------------> Stream
Session) scopes. Logical groupings of streams
that implement protocol flow and may additionally consume resources such
as memory.Channel) scopes. Begins when a stream is created
and ends when the stream is closed.There is also:
These are System and Transcient scopes for the allowlist, which is a
list of honest peer anagolous to our goldlist. Allowlist scopes can
continue to use (and meter) resources while the System scope has already
reached its limit (to protect against ellipse attack).
Limits have a default setting that can be configured. It's also possible to scale limits with a particular config that allows for scaling to different machines.