IC WebSocket: Roadmap

Hello everyone,

The following is a proposal for providing WebSocket functionality to the Internet Computer. The goal is to start as a simple and standalone service - based on what has already been done by Dfinity - and further develop it based on the community’s requirements to eventually become an integral part of the IC, enabling clients to get live updates from the canisters.

Overview

The IC WebSocket will consist of two SDKs - a JavaScript one for the client and a Rust CDK for the backend canisters - and a Gateway which bridges the two.

The goal of the SDKs is to provide to the client and the canister the same interfaces of, respectively, the traditional WebSocket API and of a WS Server library.

The client uses the SDK to send and receive updates to the canister via a traditional WebSocket interface - wrapped into the IC WebSocket client SDK which handles the connection setup with the Gateway and the canister. The canister SDK manages the interaction with the WebSocket Gateway in order for the latter to get the messages that need to be sent to the clients. The Gateway bridges the two SDKs by connecting via a traditional WebSocket with the client SDK and polling the canister for updates. The Gateway remains hidden to the developers using the SDKs and they only have to implement the handlers for the different WebSocket events - both on the client and canister side - just like they would when using WebSocket on a Web2 infrastructure.

The client SDK provides the WS methods used to handle incoming updates from the canister and send messages to the canister. From a client using the SDK’s point of view, the client is connected via WebSocket directly to the canister.

The canister SDK provides the WS server methods which the developer has to expose via the candid interface. The Gateway calls these methods to manage a client’s connection and get messages for the clients. The SDK provides a structure where the canister can keep all the messages that have to be sent to the clients. Once the Gateway polls the canister, the new messages are sent to the Gateway, each of which is then relayed to the corresponding client.

Roadmap

Ideally, the WebSocket Gateway should be integrated into the boundary nodes and become part of the official IC specification as a new endpoint that clients connect to to get updates from a canister.

However, this is not on Dfinity’s short term roadmap and it is not possible for external developers to contribute to the boundary nodes. Still, the community’s interest for IC WebSocket seems to be high and therefore we should not wait for a full integration into the boundary nodes to start offering such a service to developers.

Therefore, initially, the WebSocket Gateway will be a standalone service - like the HTTP Gateway will be soon.

Our goal is to release a simple and “trusted” WS Gateway in order to get feedback from the community as soon as possible and then iterate to gradually turn it into a trustless component. Once it is mature enough, it could then be integrated first into the HTTP Gateway and then into the boundary node.

V1 - August 2023

In August 2023, we will release the first version of the IC WebSocket. This will consists of both SDKs and WS Gateway. The goal of this first version is to provide the WS interfaces that clients and backend canisters can use to interact with the WS Gateway. These interfaces will hide the inner-workings of the SDKs and the WS Gateway so that these can be upgraded without requiring any changes on the client and canister side.

This version will require the WS Gateway to be fully trusted and it will not be ready for production. However, IC WebSocket V1 will already provide the full WebSocket functionality so that developers can start using it. The trust assumption can be relaxed - at least on the developer’s side - by enabling developers to host the WS Gateway for their own canister themselves. For the others, we will provide a managed solution so that developers can embed WebSocket functionality into their dApps by simply using the IC WebSocket SDKs.

V2 - October 2023

Eventually, in order for the WS Gateway to be fully trustless, it needs to guarantee:

  • authentication:
    • the canister can verify that the message came from the client
    • the client can verify that the message came from the IC
  • privacy:
    • the gateway cannot read the messages coming from the client
    • the gateway cannot read the messages directed to the client

We consider authentication to have higher priority - as not even the IC guarantees privacy today - and therefore the second version of the WS Gateway will enable the messages to be authenticated in both directions. Detailed information on how to do this will follow but we plan to use certification to prove that messages are coming from the IC and traditional query/update calls - directly from the client - to ensure that the WS Gateway cannot impersonate clients. For this version, we will also focus on making the WS Gateway ready for production by adding SSL support and making sure that all errors are handled correctly so that the Gateway can stay up and running. At this stage, the worst thing the WS Gateway can do is to read or block the canister updates to clients - something which the boundary nodes can already do. We plan to have a production ready version of the WS gateway by October 2023.

Later versions - 2024

In the third version of the IC WebSocket, we will tackle privacy and here the idea is to rely on vetKD. Given the early stage of vetKD, we cannot provide a specific milestone for this.

Later versions of the IC WebSocket will focus on providing SLAs, load balancing across multiple WS Gateways, DDoS protection.

Conclusion

This is just an idea of what we plan to deliver. We would like to get feedback from the community as soon as possible so that we can develop a solution tailored to the needs of the developers. You can follow our progress here.
Looking forward to hear what you think :slight_smile:

28 Likes

Hi, thank you for your great work.

Regarding the “trust” part, every response to update call contains certification path, that can be transported via web socket back to client for verification purpose. This way you at least verify update calls responses right away.

6 Likes

Hi @massimoalbarello,

I’ve read the proposal and I think it’s a great idea. The plan to use a WebSocket Gateway to connect clients and canisters could really improve how we build apps on the IC.

I’m particularly interested in how this could be used to enhance B3Wallet. Implementing WebSocket functionality could allow for a smoother notification system, improving the user experience significantly.

I like that you’re starting with a standalone service. It seems like a smart way to get things going quickly. The roadmap looks good too, with clear steps to make the system better and more secure over time.

I do have a concern about needing to trust the WebSocket Gateway at first. I understand why it’s necessary, but I hope we can move to a trustless system soon. That’s really important for keeping the IC decentralized.

I’m also interested to see how you’ll add privacy features in the future. It’s good to see that you’re thinking about this.

Overall, I’m excited about this proposal and can’t wait to see how it develops. I think it could really help improve the apps we’re building on the IC.

Thanks for sharing this plan. I’ll be following along and I’m ready to help out where I can.

Behrad

5 Likes

Nice feature. What will the benefits be compared to multiple clients polling every second? Does the WS gateway poll only once from the canister each X for all users or it polls separately for each user?
I suppose if they are grouped up, that will reduce costs a lot and it will make sense to leave a client subscribed for long periods of time without much extra cost.

1 Like

Is there a reason that there is not a Motoko SDK mentioned? Perhaps it isn’t compatible with the model, but I thought I’d ask.

4 Likes

I think you will expose a function like the way http_request works.
Perhaps
ws_subscribe - store subscription_id
ws_request - return a list of messages for your subscription_ids
ws_unsubscribe - remove subscription_id

The main benefit is that the WS Gateway polls canister X for all the N clients that connected to the Gateway to get updates from canister X. The Gateway then sends each message to the corresponding client.
This should translate into a factor of N in the cycles cost once canisters have to pay also for query calls. Until then, the advantages are given by not overloading the subnet with N queries every few seconds and having a simple WebSocket API instead of re-implementing the polling on the client for every dApp.

2 Likes

You are absolutely right. We will provide a specification for the CDK and either implement the Motoko version ourselves or find someone else who takes care of it.
Would be great to know what other people think about this. If there is a lot of interest we could take care of the Motoko implementation relatively soon.

5 Likes

Yes exactly, the developer will have to expose some predefined methods on their canister’s candid interface. To have an idea, have a look at the lib.rs file in the example canister on our repo. In the example, the Rust sock module is what from v1 will become the CDK.

3 Likes

That will work.
Can’t we just call the canister methods thru WS gateway instead of having to pass them thru these functions

The WS Gateway is calling those methods exposed by the canister as, for example, you can see from the canister_methods:ws_open function in the Gateway. The sock methods are provided by us to make developers’ life easier, so that they don’t have to write the handlers manually.

Was it clearer? Or am I missing something from your question?

1 Like

I was wondering if the WS gateway can call actor methods directly. It seems currently it is passing messages to the ws_message method. But I guess linking it to actor methods has its disadvantages if doable at all. I would probably use the WS only to send messages to clients from the canister and use HTTP to send messages to the canister.

Thank you @massimoalbarello and @ilbert for picking up the torch and this write-up.

It’s great that this is getting built in public and there’s a chance that other developers chime in helping to build libraries or CDKs in Motoko, TypeScript, Python, and C++. As well as integrations of other protocols next to WebSockets eventually.

One interesting (research) question for the roadmap is to find a model of how we could incentivize many independent gateway providers. I think there are some case studies in the greater web3 ecosystem that could be studied.

9 Likes

Yes, the incentive mechanism is something that we always have in the back of our minds. Will definitely get into it after V2

3 Likes

Very important piece of ICP puzzle. We are planning to add support for WebSockets to our IC4J Java agent ASAP. I see many interesting use cases, especially in integration with external resources, like Apache Kafka topics.

4 Likes

Great news. Without a doubt, this functionality will be very useful. Congratulations, very good job

1 Like

IC4J Agent can provide direct access to WS Gateway, similar to JS Agent. IC4J Candid implementation has also implicit serialization/deserialization between Candid and popular Java types (JSON Jackson/Gson, XML DOM/JAXB, JDBC, React Native).

1 Like

Would be nice to also have Candid IDL description of WebSockets interface.

1 Like

I would probably use the WS only to send messages to clients from the canister and use HTTP to send messages to the canister.

That’s also what we are thinking about: you create an instance of IcWebsocket and whenever you call ws.send we use the canister actor you passed to the constructor to call the ws_message on the canister, skipping the gateway.

However, calling directly your methods on the canister (either from the gateway or the client as we said before) instead of the predefined ones is tricky and you would need to implement the CDK handlers inside your methods, by changing the logic.

1 Like

Yes that is something we have to provide in the documentation, because developers must implement the ws_* methods on their candid interfaces.

1 Like