interledger / rfcs

Specifications for Interledger and related protocols
https://interledger.org
Other
453 stars 111 forks source link

[BTP]: Indicate protocol version at connection establishment #294

Closed dappelt closed 6 years ago

dappelt commented 7 years ago

To distinguish the current CLP protocol version from future CLP versions, we should include a CLP version number at connection establishment. We could use the subprotocol mechanism of the websocket protocol for the client and server to agree on the CLP protocol version.

When establishing the websocket connection, the client indicates which CLP version he supports. He does this by setting the HTTP header Sec-WebSocket-Protocol to a comma-separated list of CLP versions he supports, e.g.: Sec-WebSocket-Protocol: CLP-1.1, CLP-1.0. The server selects a version from the list and sets the same HTTP header in the response to the selected version, e.g.: Sec-WebSocket-Protocol: CLP-1.1.

dappelt commented 7 years ago

There is a nice explanation on how to use WebSocket sub-protocols on MDN: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#Subprotocols

dappelt commented 7 years ago

Evan asked me to have a look if WebSocket libraries for popular languages support the subprotocol mechanism. This is what I found:

Feel free to leave feedback if your favorite lib supports WebSocket subprotocols or not.

emschwartz commented 7 years ago

To me the main question is whether this kind of protocol negotiation should happen in this protocol or before the connection is established.

These are the main things that need to be versioned and negotiated:

Will peers know which of these they're going to be using before they connect?

michielbdejong commented 7 years ago

I think we should distinguish between two problems, the language problem, and the list-of-services problem, they are two different things. If I go to a shop and try to buy "een appel", the answer might be "ja" or "nee", depending on whether that shop sells apples or not. Or it might be "I don't understand" if the shopkeeper doesn't speak Dutch. Those are two different problems. Stating that a peer speaks 'BTP-2' is orthogonal to stating that that peer offers, for instance, a quoting service. BTP-1 includes a registry of named services, this list can only grow, and each service can only grow. BTP-2 includes a new registry, where sub-protocols can be changed (e.g. switch 'balance' from UInt64 to Int64).

From the context of who you're connecting to, you probably know that e.g. a frog for red.ilpdemo.org only supports ILQP if you specify the to: 'us.usd.red.connie' side-protocol. That's the 'list-of-services' problem.

I used to think, we might as well use /api/v1 and /api/v2 so the client can choose, but @dappelt made me realize that that's not ideal. Suppose there is a network where software updates each 6 months. One node in the network updates its software right away, from supporting version 3 and 4, to supporting versions 4 and 5. The rest of the network still supports versions 3 and 4, and only version 4 is still used. Now, a second node updates, and next time those two nodes connect, they will automatically start using version 5. It's worth automating this, because otherwise you either need a deterministic URL scheme, and connection will take longer (trying /api/v5 first, and falling back to /api/v4 if that first attempt times out), or the sysadmin of a node with n peers needs to update their server config n+1 times instead of just once per six months.

dappelt commented 7 years ago

It cannot hurt if BTP implementations are explicit about the BTP version they speak.

These are the main things that need to be versioned and negotiated:

  • BTP version
  • Required subprotocols (for example, if you're using BTP for a payment channel with claims)
  • Optional subprotocols (to, from, balance, info, etc)

This proposal addresses the first bullet point. It is not suitable for a choose-M-out-of-N scenario like we have it with BTP sub-protocols.

In the case of asymmetric trustlines I'm not sure. Would you have one Websocket URI you would connect to with different clients, each of which might support different features?

Yes, absolutely. For example, an ILP Service Provider has users Alice and Bob. Alice connects with her BitTorrent client that uses version BTP/1.0 and Bob connects with ILP-Jeopardy that uses BTP/2.0. You could compare this ILP Service Provider with a web server serving HTTP/1.1 and HTTP/2.0 requests. Having a web server that serves only HTTP/2.0 would lock out many clients.

dappelt commented 7 years ago

As just discussed, we decided that we don't need a version number for BTP. We expect the sub-protocol mechanism of BTP flexible enough to implement new features.

michielbdejong commented 6 years ago

This issue has become relevant again, since https://github.com/interledger/rfcs/pull/413 currently relies on BTP/2.0 and it would be nice to be able to just use a wss+btp:// URL instead of a wss+btp2:// URL.

OTOH, @adrianhopebailie would prefer to also allow loopback servers to speak languages that are not even BTP, so then we might need a language selection mechanism outside the wss+btp:// URLs anyway, and then we had better use that one mechanism for both the choice to use BTP and the choice to specifically use BTP/2.0

adrianhopebailie commented 6 years ago

I would also like us to use the Sec-WebSocket-Protocol standard as this makes implementing BTP on top of other WS stacks easier.

Many WS stacks (e.g. Jetty) allow for custom handlers that are invoked by the core stack based on the value of this header. Implementing BTP is a lot easier (and less tightly coupled to the specific stack) if we use sub-protocols.

So a big +1 from me for @dappelt 's original request

stale[bot] commented 6 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. \n\n If this issue is important, please feel free to bring it up on the next Interledger Community Group Call or in the Gitter chat.