libp2p / specs

Technical specifications for the libp2p networking stack
https://libp2p.io
1.56k stars 273 forks source link

Agent v. Protocol Version #352

Closed Stebalien closed 3 years ago

Stebalien commented 3 years ago

We currently have two versions:

  1. Agent Version
  2. Protocol Version

The agent version is like a browser's "user agent" and is usually specific to the application.

The protocol version indicates the libp2p protocol version. Historically (and by spec) peers with mismatched protocol versions would automatically disconnect. However:

  1. The historical "protocol" version for libp2p is ipfs/0.1.0. Neither go-ipfs nor go-libp2p enforce a protocol version match, so we can change this here without breaking either. However, it's unclear what other libp2p users this might break.
  2. The protocol version isn't always sufficient to determine if two peers should speak to each other. For example, Filecoin compares genesis blocks with a dedicated "hello" protocol.
  3. By the time we receive the libp2p protocol version, we've already bootstrapped a connection. So it's a bit late to make any libp2p protocol decisions.
  4. It's an interoperability hazard.

Personally, 4 is my biggest concern. I want to be able to build a single libp2p application that can connect Ethereum 2.0 to interact with a smart contract, the IPFS network to transfer files, and the Filecoin network to store files. This p2p interoperability is, IMO, one of the major selling points of libp2p.

So, I guess the question is, what to do about the agent version.

  1. Leaving it as ipfs/0.1.0 by default makes little sense.
  2. We can't easily change the default then start enforcing the spec's "disconnect if they don't match" requirement without a long deprecation period.

Thoughts/ideas?

aschmahmann commented 3 years ago

I'm not really sure what a "Protocol Version" is supposed to mean when any given application supports many protocols with different versions (the different flavors of Identify, different kademlia networks, relays, pubsub, etc.).

So what would somebody use this for? If it's just that people want to throw some extra information into the identify protocol instead of using a different protocol then it seems like either we should lean into it and let people pass a map of arbitrary key-value pairs, or just say no and deprecate the "Protocol Version".

My inclination is to deprecate "Protocol Version" and keep the identify protocol, and the messages it sends, smaller.

vyzo commented 3 years ago

The way I see it, the protocol/libp2p version is only useful for debugging and statistics.

If you want to feature test, you really shouldn't rely on it. All protocols of interest will be mounted, so that they can be feature tested with identify. And if you need an actual protocol-level check, this should be performed with a side protocol handshake, just like lotus does.

vyzo commented 3 years ago

I think we should adjust the spec and drop the requirement of dropping the connetion if they don't match. Really, ipfs/0.1.0 says nothing at this point, libp2p has evolved radically since then.

marten-seemann commented 3 years ago

I agree with @vyzo and @aschmahmann, let's change the spec. Depending on how current implementations (other than the Go implementation) handle a different / missing value, we can either stop sending it right away, or we'll have to live with a transition period.

mxinden commented 3 years ago

I still see value in the identify Protocol Version field, namely:

With that in mind, and also given the fact that it is already optional in the Protocol Buffer schema, I suggest:

I suggest changing the specification along the lines of:

 ### protocolVersion

-The protocol version identifies the family of protocols used by the peer.
-The current protocol version is `ipfs/0.1.0`; if the protocol major or minor
-version does not match the protocol used by the initiating peer, then the connection
-is considered unusable and the peer must close the connection.
+The protocol version identifies the family of protocols used by the peer. The
+field is optional but recommended for debugging and statistic
+purposes.
+
+Previous versions of this specification required connections to be closed on
+version mismatch. This requirement is revoked to allow interoperability between
+protocol families / networks.
+
+Example value: `/my-network/0.1.0`.

However, it's unclear what other libp2p users this might break.

It is e.g. used in Substrate to allow validator nodes to filter connections for their network only.

The historical "protocol" version for libp2p is ipfs/0.1.0.

I would suggest go-libp2p itself not to set the Protocol Version field at all. Go IPFS can still set it, but maybe either update the 0.1.0 or drop the suffix.

Stebalien commented 3 years ago

Fair enough. Applications can choose to "name" their family of protocols "ipfs", "filecoin", etc. but libp2p won't do anything based on this.