We are now implementing Libp2p for JVM. The first phase is targeted for using in Ethereum 2.0. The key protocol for Ethereum is gossip. Thus I have some questions regarding it:
Is it true that peers are added to fanout map when (and only when) your peer is publishing to some topic but not subscribed?
I.e. if every peer in the network is subscribed to a topic-1 then fanout maps of all peers are empty?
gossips are emitted to fanout and peers in a mesh only?
If the above is true (Iâm relaying on the Go implementation), then if we have a network where all peers a subscribed to a single topic then fanout and gossip features have no effect and the message propagation relies on meshes only?
@raul advised me to call for @vyzo to this topic as gossip author
Did I get it correctly, that pubsub communication between 2 peers is kind of âhalf-duplexâ in terms of streams? I.e. each peer opens a write-only stream and 2 -side communication requires 2 streams?
If this is correct then can you please explain the rationale behind this solution?
Gossipsub is designed as an âambientâ service. This means that as we connect to peers in the network, we interrogate if they support gossip by opening a stream. This approach has nice properties (including a level of randomness contributing to attack resistance), but it also means that each node needs to probe its peer by opening and owning a dedicated stream.
Alternatively, we could:
wait for identify to finish, but this wonât work well in future monoplexed scenarios.
run a role assignment heuristic (e.g. highest peer id wins and is in charge of opening the canonical full-duplex stream), but this introduces a timing dependency for the passive party.
consolidate both streams into a single one after the fact, but thatâs complex and has no benefit.
Really, keeping two half-duplex streams where each party owns one simplifies the design a lot.
@raul Thanks for detailed explanation!
Are there any other protocols which uses the same scheme?
I believe there are p2p protocols which uses a single full-duplex streams. How do they solve role-assignment then?
The stream architecture of a protocol is dependent on the requirements of the protocol itself. libp2p should be flexible enough to accommodate any style. Empirically speaking, there are (at least):
RPC-based protocols that rely on single-use streams (one per request).
Protocols that better suited to long-lived streams (e.g. overlay networks) where only one party has an active interest, and the one remains passive (e.g. unidirectional flows of data). The active peer may open multiple streams against the passive peer. An example is the circuit relay protocol.
Protocols that are inherently bi-directional, with both peers playing an active role. In this case, itâs common to have each peer own a stream.
The issue is that you donât know if the dialing peer is or not a gossipsub peer. Therefore, as the responder of the dial, gossipsub would need to park the candidate, introduce a timeout, deal with this transitory state in mesh maintenance, etc. Just like resolving the conflict based on peer ID, itâs a deterministic rule, but it leads to unnecessary complexity. And streams are cheap.