Skip to content

Lazy negotiation is unsound #20

@Stebalien

Description

@Stebalien

Setup:

  • Peer A supports protocol protocolA.
  • Peer B supports protocol protocolB.

Using the lazy handshake protocol, peer A can send:

<len>/multistream/1.0.0
<len>/protocolA/1.0.0

Then, as the first message (without waiting for a response), it can send:

<len>/protocolB/1.0.0
other data

Unfortunately, if peer B supports protocolB but not protocolA, it will respond with:

<len>/multistream/1.0.0
<len>na
<len>/protocolB/1.0.0

And then think it's speaking protocolB. It will then intrpret other data in the context of protocolB.


Unfortunately, there are perfectly valid uses for multistream where this can happen. For example, switching. Let's say that peer A wants to talk to a sub-identity C hosted on peer B. One might reasonably support this using the multistream muxer by registering peer IDs with the muxer (treating them as "services"). One could then end up with the following conversation:

<len>/multistream/1.0.0
<len>/p2p/peerC
<len>/multistream/1.0.0
<len>/protocol/1.0.0

If peer B doesn't have a peerC registered, it would respond as follows:

<len>/multistream/1.0.0
<len>na
<len>na
<len>/protocol/1.0.0

At this point, peer A will be talking the protocol with peer B instead of with the sub identity C.


Unfortunately, I don't know of a good fix that won't break everything (without upping the version and adding a mandatory round trip).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions