libp2p / libp2p/specs

Proposal: 1-RTT Handshakes (incl. Identify)

Open
#498 9 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
No language data
Stars
1.8k
Forks
320
Avg merge
11d 15h
Merged PRs (30d)
1

Description

A (libp2p) QUIC handshake takes 1 RTT, a libp2p TCP handshake incl. takes 4 RTTs (3 RTTs when using the inlined muxer negotiation). That's not the whole story however. After the handshake, implementations might wait for Identify to finish before actually making the connection available to the application. Since Identify is a request-response protocol (peer A opens a /ipfs/id/1.0.0 stream, and then waits for the response), this consumes another round-trip.

The 0.5-RTT optimization

TLS 1.3 allows the server to send application data right after receiving the client's first flight (which is 0.5 RTTs after the client started the handshake, hence the name). At this point, the server possesses the keys to encrypt application data packets, however, as it hasn't received the client's certificate yet, it doesn't know who it's sending the data. For the client, data sent in 0.5 RTT is indistinguishable from data sent after handshake completion (unless looking at packet timing), so there's no changes needed on the client side to accept 0.5-RTT data.

The Go standard library doesn't expose an API to use 0.5-RTT data, but quic-go will do, starting with the next release: https://github.com/lucas-clemente/quic-go/issues/3634.

Identify: Request vs Push

Unfortunately, this doesn't allow us to get the handshake down to 1 RTT, since Identify itself is request-response. There is a push variant, Identify Push (/ipfs/id/push/1.0.0), which allows peers to push their Identify message instead of waiting for the incoming identify stream. If the server used that variant in 0.5-RTT data, the client would finish the handshake (incl. Identify) within just a single round trip.

Legacy clients will continue using the regular Identify protocol, and we don't necessarily want to send them our Identify data twice.
Legacy servers won't send the Identify push message, and clients need to decide if they want to start the regular Identify request or not.

We can solve this problem by distinguishing between the current Identify mode and the push mode suggested here. QUIC currently uses the "libp2p" ALPN. By minting a new ALPN identifier, e.g. "libp2p+idpush", peers could negotiate the new behavior (or fall back to the old behavior) in an unambiguous way.

Required Spec Changes

  • specify the new ALPN for libp2p+QUIC, link the Identify and the QUIC (or TLS) document

cc @MarcoPolo @mxinden @thomaseizinger @elenaf9 @p-shahi @achingbrain @Stebalien @Menduist

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the existing libp2p QUIC and Identify specifications referenced by the issue, then trace how the current "libp2p" ALPN is defined. Specify the new ALPN and document negotiation and fallback behavior for Identify Push versus regular Identify.

Written by the indexing model from the issue text.

Assessment

Domain
networking
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.