Virtual offsite recommendations: Target API and architecture

TL;DR

  • Layer separation for public facing vs low level: Waku Core, Waku API, App API(s)
  • Public mentioning only for public facing API’s: give one option, e.g. Chat API
  • Target platform presence is a MUST: Go, Rust, JS (Node & Browser)
  • Manage expectations and be clear: rate limiting in the network, local-first approach, privacy, bandwidth consumption, limited scalability

Problem statement

Adoption is low and used primarily by Status, Railgun and The Graph. We conclude that this is partially related to the problems that project developers face while integrating Waku into their code bases. Most commonly seen are: lack of understanding of consequences of using P2P stack instead of centralized client-server architecture; limited understanding of development patterns in P2P way, e.g local-first approach; high entry point with integrating Waku into project’s code base due to different limitations of present protocol APIs (no retry in LightPush out of the box, no recovery of Filter subscriptions, Store protocol limitations in a public network).

Recommendations

  1. Layer separation for public facing vs low level: Waku Core, Waku API, App API(s)

It is critical to distinguish between what is publicly available for external consumers and what is not. For that we recommend the following layers of Waku APIs: Waku Core, Waku API, App API(s).

Waku Core: private, meant to be used for core development of the Waku protocol layer and have implementations close to RFCs and specs.

Waku API: public, set of API that addresses general problematic points for outside consumers such as Send and Receive functionality with retries, connection and peer management that addresses availability in the network.

App API(s): public, higher order functionality that is meant to be used by projects and addresses their specific needs, can include: identity management, encryption, chat abstractions.

  1. Public mentioning only for public API’s: give one option, e.g. Chat API.

To mitigate confusion we MUST limit our proposition to only APIs that are ready to be consumed by projects from the start and those are Waku API and App API(s). The option we propose is only to communicate about one that is suitable for consumption, though may vary by use case.

  1. Target platform presence is a MUST: Go, Rust, JS (Node & Browser)

We must ensure presence on projects’ main target platforms and smooth experience there. For that we derive different points such as: simple dependency management and package distribution, ease for building right from the start.

Simple dependency management and distribution depends on the language. We must ensure presence on crates, npm. We want it to be something like:

go get [github.com/waku-org/chatsdk](http://github.com/waku-org/chatsdk)
npm i @waku/sdk

Ease for building must be ensured with minimal configuration and opinionated defaults and requested API that has needed functionality embedded: sending and receiving with reliability, encryption tools, ambient connection management:

w := waku.New({
  ...
})

if err := w.Start(); err != nil {
  panic("failed to start waku", err)
}

defer w.Stop()

w.Send("0xabc...", "hello")

go w.OnReceive(func(msg WakuMessage) {

fmt.Printf(msg)
  ...
})

Since Nim is the language of choice for IFT, we agree that implementations should be provided in both Nim and TypeScript. Support for other languages should be enabled through bindings to the Nim implementation.

  1. Manage expectations and be clear.

As mentioned in the Problem statement - many developers are not aware of tradeoffs that are coming with P2P infrastructure and SDKs. It is our duty to articulate what is possible and what not with providing clear documentation, simple yet useful examples and main benchmarks with limitations.

This includes: being clear on limitations of RLN and its time consumption (sync node, generate proof, need of RPC endpoint); public network’s Store availability limitations and need for local-first approach with its requirements; if superior privacy is needed - its burden on time to initiate message exchange etc; requirements on bandwidth; time to bootstrap a node for application to function. For TWN we need to be clear what benefits and drawbacks there are for projects: cost of TWN vs their network setup.

Links

  • presentation - link
  • notion page with notes - link
3 Likes

If I understand from this image:

The intent is to cut that “Waku API/SDK” only contains p2p reliability.

We then move SDS, encryption, etc to App/Chat SDK

I think it makes sense. Especially that I am often reminded that SDS needs to live within a secure session.

I do see some immediate actions here:

  • Encryption matter (AES, ECIES), should be move to App/Chat layer
    • we can finally get rid of version on Waku Message (it can remain unused until we have a useful version 3 that is a routing only matter)
  • Encryption choices are a Chat SDK matter
    • Choice of AES vs ECIES vs NEW STUFF
    • AES/ECIES → need to understand if there are really any specific usage that would not be covered by NEW STUFF, and potentially deprecate
    • in all cases, SDS is included out of the box.
    • there is no “no-encryption” option, no version of SDS used without encryption. If encryption does not matter for the app, we/they can just use AES, deriving a key from content topic for example (this could be done under the hood).
  • I am not convinced ECIES is of any use if we have the NEW STUFF in place.
  • SDS involves a concept of “channel” we assume a developer would set. I wonder if that can easily be abstracted by just using a content topic as a channel, aka, by default, SDS is applied per content topic

I do have some questions:

  • We do need a name for the App / Chat SDK. This could even become the messaging SDK (because after, status call the boundary the “messaging API”).
    • what is the best name here?
  • Where does RLN API fit? I am not convinced it fits within Waku Core, because we want to make it pluggable. I would see RLN SDK potentially at the same level as Waku SDK, and App SDK may abstract RLN if feasible.

My proposal:

  • Post Chat SDK, we schedule an item which is to provide AES + SDS as part of chat SDK. This can be a blanket approach when encryption is not needed, where AES key and SDS channels are deduced from content topic. An easy interface to use AES is also available when developer what to use some basic encryption. Both for JS and native languages.
  • for ECIES, I assume we should move towards deprecation but some people may use it JS. So in JS we could move ECIES to a js chat sdk as a first step, and then based on demand, roll out new chat SDK in JS to deprecate ECIES.
    Deprecate ECIES in native in favour of chat sdk, unless users ask for it.
2 Likes

(Maybe I’m wrong here):

RLN

RLN applies per waku node per shard, that means if the waku node is subscribed to two shards, 32 and 64 it would require two RLN registrations.

There are three main functions that a waku node needs to perform when relaying in a RLN-protected shard: register, generate proof (on publishing), validate proof (on receiving).

From my point of view this sits on the routing layer (in Waku Core layer, not even Waku API, I mean it looks like a core protocol: rln-relay, it is not related to a higher level functionality like: send, send could use relay, lightpush or rln-relay under the hood)

Having said that there is one action required from the end user: the registration, apart from that all other RLN functions can be performed in Waku Core level. But this registration seems like something you need to do with a wallet and then you can pass the result to your waku node, it looks like a .env configuration property:

rln-relay:

For registration, a peer MUST create a transaction to invoke the registration function on the contract, which registers its pk in the RLN group

Point of contention

So the registration could be somehow included in ChatSDK layer to call your wallet with the right data for signing and passing the result to the Waku Core configuration. It is a problem of how to get the registration done, from a website? from my app with an exposed endpoint in ChatSDK such as registerRLN(identity)?

In my mind RLN is like a mode of operation: edge, relay or rln-relay. Considering modes of operation on a shard basis, I can be relay on shard 32, edge on 64 and rln-relay on 128.

Encryption

Agree with you, at ChatSDK level all needs to be encrypted.

Regarding Waku Core level: do you mean that relay between node A and node B should no further encrypt? it might be beneficial to a certain extent if you were not participating at time t and then you end up catching a message from node A to node B at time t + 1_month if plaintext then you can read it, if encrypted you cannot. But it is true that you can just run a node connected to a shard and you will be able to see everything anyway, encrypted or not (at this level).

Naming

I like “Message SDK” (for what we currently call ChatSDK)

I think RLN extraction needs to follow a kind of dependency injection schema.
This needs to be supported from Waku AppSDK - WakuSDK and down to WakuCore during the init process.
And we can rely on the mentioned interface as a generic one.
The fact that it involves the inner message structure we use in Waku might need some generalization though.

@fryorcraken

SDS involves a concept of “channel” we assume a developer would set. I wonder if that can easily be abstracted by just using a content topic as a channel, aka, by default, SDS is applied per content topic

Mmm, there may be some issues with this approach. Firstly, it will increase the importance of apps having very well-designed content topic cardinality (i.e. we would now require "content topic" == "definition of participants in a conversation"). I’ll be concerned that a content topic explosion might now be a much more expensive mistake than just affecting e.g. filter and query performance.

More importantly, though, it ties the encryption layer to the messaging layer filtering concept of a content topic. Not all participants on the same content topic might be able to decrypt all messages on that topic (e.g. Status 1:1 chats are only visible to the participants, but they share a few content topics - participants simply discard messages they can’t decrypt). The SDS channel is determined by the participants of an encryption group, which may or may not map to unique content topic.

I haven’t thought about this very much, but an alternative default could just be a single channel ID of, say, 0. This would mean that default behaviour is for all app participants to participate in ensuring a single reliability scheme that applies to the entire body of that app’s messages. This assumes default behaviour is for all messages in an app to be visible to all participants, but at least is an encryption and not messaging/filter layer assumption.

I’m not quite convinced on either direction and we’ll probably need to look at a few example use cases to come up with a good scheme.

Where does RLN API fit?

  • RLN Membership functions should probably be an API that works at the Chat/App SDK level: creating a new app-level identity should trigger the functions that allow someone to receive an RLN membership that gets “passed down” to the Core layer for publishing.
  • RLN proof generation and validation seem to me core functions. We simply extract relay validation to an API. Proof generation can probably use the same API, but add generated proofs to your own messages before validating them and publishing.

@pablo

RLN applies per waku node per shard

No, RLN can be applied over multiple shards. We should only need a single RLN membership to allow publishing across the entire app feature, no matter how many shards are used. If we believe that some nodes will not be subscribed to a specific app feature (e.g. Communities), we will indeed require a separate membership for that feature. Most likely, for a start we’ll have two memberships: one for 1:1 and group chats, and a separate for those participating in Communities.

this registration seems like something you need to do with a wallet

I’d imagine our first version would simply allow users to interact with semi-centralised RLN “membership providers” that performs the transaction on behalf of the user and then distribute the membership. I think this interaction (of requesting and receiving a membership from a peer) could be specced as a protocol and included in the ChatSDK layer.

2 Likes

Nowadays the RLN registration is performed globally, i.e., to all clusters and shards.
Now that you mention it Pablo, IMO, I think it would make more sense to apply RLN
registration per cluster-id and not per shard.

I agree with Franck that the RLN library should be a pluggable component and it seems
natural that should to be at the same level as Waku-SDK and libSDS because the Chat-SDK will take care of
identities and RLN is some kind of hidden identity.

IMO, RLN should always be enabled.

Let’s just be more deliberate here:

A NetworkConfig as I am defining it in the Waku API should ultimately be:

  • a cluster id
  • a sharding strategy (default auto sharding)
  • a total number of shards (for auto sharding)
  • a message validation mechanism
  • a set of bootstrap nodes

RLN is one potential message validation mechanism, and one instance of RLN for a network can be defined as

  • a smart contract address
  • a chain id on which the smart contract is deployed
1 Like

After spending time writing Improving Content Topics: A Coordinate-Based Approach for Better Privacy, Distribution and Dev Ex I agree with you.

My initial proposal was the wrong way around. SDS channel is higher level so that it what should be exposed to the developer, instead, we may look into abstracting the content topic. For example, asking the developer to set a SDS id, and the content topic being derived (in a bucket) from the SDS id.