-
Notifications
You must be signed in to change notification settings - Fork 3
Chat Inboxes for receiving inbound invitations #72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
| - There is no assumption of exclusive usage, many clients can use the same inbox - though they will ignore messages addressed to others. | ||
| - There is no associated keypair, messages are encrypted to existing identities, using the defined encryption mechanism. | ||
| - There is no restriction on how many inboxes a client can have (cardinality unbounded). | ||
| - Developers/Contributors can determine which contacts learn of an inbox. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| - Developers/Contributors can determine which contacts learn of an inbox. | |
| - Developers/Users can determine which contacts learn of an inbox. |
Contributors are developers. But I assume a developer MAY let a user have some control.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Contributors are developers.
Contributors are developers who contribute and build novel conversationTypes.
Developers are consumers of the SDK.
The distinction here is that Both applications and conversation specifications can determine inbox visibility
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Contributors are developers who contribute and build novel conversationTypes.
Maybe worth defining this in the spec. Or are they spec implementers?
| ## Summary | ||
|
|
||
| ConversationId: `/convo/inbox/v1/<client_address>` | ||
| ContentTopic: `lower_hex(blake2s("/inbox/<inbox_address>"))` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not match the recommend content topic format: https://rfc.vac.dev/waku/informational/23/topics#content-topics
I assume this would be the content-topic-name. What do we think re application-name ? I assume we would want to set one for the chat sdk.
|
|
||
| The content topic that is used is defined by `lower_hex(blake2s("/inbox/<inbox_address>"))`. | ||
|
|
||
| The hash function does not provide privacy in this context as an observer can always enumerate inbox_addresses and unmask, because of this it's recommended that inbox_addresses be secret if recipient privacy is desired. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can they enumerate when an inbox_address can be any non-empty string?
standards/application/inbox.md
Outdated
| -> e, ee, es | ||
| ``` | ||
|
|
||
| In this case the responder provides both `s` and `e` out of band. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Who is the responder in this scenario? The recipient aka inbox client? So I assume that s, e and inbox_address should be provided to sender out-of-band, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Removed the noiseprotocol standard roles and replaced with the chat specific ..ones for clarity.]
Who is the responder in this scenario? The recipient
Yes.
I assume that s, e and inbox_address should be provided to sender out-of-band
At a high level Correct - or minimally the inbox_address needs to be deterministic. Strictly speaking the inbox_address is not relevant for encryption.
standards/application/inbox.md
Outdated
|
|
||
| The noise protocol name would then be `Noise_KNfallback_25519_ChaChaPoly_BLAKE2s` | ||
|
|
||
| This protocol opts for 32bit variants to optimize for mobile and resource constrained environments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do these still exist?
|
|
||
| ## Conversation Id | ||
|
|
||
| Messages sent to the inbox MUST use the conversation_id = `/convo/inbox/v1/<client_address>` where `client_address` is the defined address for the Identity you are trying to reach. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where is the conversation_id? in the payload? accessible before or after decryption?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its defined in the forth coming waku chat spec.
It's accessible before decryption, and is used to determine which encryption state to use for decryption.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^ #73
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Am I understanding this correctly?, this is the flow:
- I share out of band with Bob my inbox_id:
one, myeands, (also my conversation id?) - I subscribe to the content topic for my inbox_id:
lower_hex(blake2s("/inbox/one")) - Eventually Bob sends a message to the inbox's content topic (encrypted for me).
Nobody knows that Bob is the sender, people might know that its an inbox I'm using if I share it with others but others might be using the same inbox.
If that is the case I don't know what is the role of the conversation_id
jm-clius
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I've added a few comments below. LMK if you have any questions. :)
|
|
||
| ## Summary | ||
|
|
||
| ConversationId: `/convo/inbox/v1/<client_address>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the idea of the ConversationId to tie a single conversation state machine together in the app layer? If that is the case, perhaps it should not be mentioned in this spec (for now), as the current terms seems focused just on the strict interaction of the lower-layer action of initiating a conversation.
A more general point is that I think this spec perhaps makes more sense as a subsection for a more complete "conversations(?)" spec that explains interaction from beginning to end when Alice wants to speak to Bob, is explicit about our prior assumptions, and the message flow from setup to teardown of the conversation. You might already plan this, so not an urgent suggestion. It would be good to make sure that terms are defined either before or just after they're introduced. For example, I'm not sure what the client_address is in this context.
| To define an inbox, the following parameters must be set: | ||
| - **inbox_address:** a string value of length >=1. This value ought to be considered visible to observers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we rephrase this in the form of directives. As it reads I'm not sure where this inbox_address comes from.
For example:
To receive conversation invites,
a participant MUST define an `inbox_address`.
This MUST be any string value with a length of more than 1.
The `inbox_address` SHOULD be advertised to observers who may want to initiate a conversation to this participant.
The mechanism for advertising this address falls outside the scope of this spec.
This kind of directive usually follows in a "Protocol", "Syntax" or "Message Flow" section after the terms have been introduced, so may not belong under "Parameters".
Perhaps we need a separate section after Wire Protocol that is explicit about message flows and which actions are taken by which actors?
| ## Summary | ||
|
|
||
| ConversationId: `/convo/inbox/v1/<client_address>` | ||
| ContentTopic: `lower_hex(blake2s("/inbox/<inbox_address>"))` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this refer to a Waku ContentTopic? I don't think the INBOX spec should know about the filtering concepts in the routing layer. In any case, we would likely not want a separate content topic for each different inbox - this would be a massive load on filter nodes and clients. We likely want to define e.g. 8 content topics for all inbox addresses, with a modulo-hash of the inbox_address more or less randomly distributing inbox addresses to those content topics.
My preference here is usually to define inbox_address in this spec and separately define an implementation spec that is explicit about the entire conversation stack, including Waku usage. We could for example define our content topic preferences in some kind of Conversations Over Waku spec, by a phrasing such as:
...conversations (over Waku) MUST implement <INBOX-SPEC>. The `inbox_address` defined there MUST be used as input to modulo-hash function that selects between `n` content topics, of format...
In other words, someone can implement INBOX without requiring Waku or understanding Waku concepts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor comment, especially given my comment above, but why blake2 and not something simpler like a farm hash (especially if we're not all that concerned about collisions)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we would likely not want a separate content topic for each different inbox - this would be a massive load on filter nodes and clients.
This seems like a blocker that is worth diving into, as this not only applies to Inboxes but also future conversation types.
Does this refer to a Waku ContentTopic
Yes(ish) - I'm assuming Waku would need to prefix the ContentTopics to align with spec. So the content topics are a generalization which can then be transformed into the required format.
Content-based filtering using 12/FILTER helps reduce resource usage on clients. However, if filtering is limited to static “bins” of message traffic, it won’t effectively alleviate resource constraints for edge clients.
In the case of Inbox, your suggestion works nicely ( assuming one inbox per account), as the messages have a single destination.
However moving to a Conversation-based-addressing approach for private Conversations, this becomes problematic. As messages are addressed to Conversations rather than individual participants - a clients messages are not isolated to a single "bin".
flowchart TD
B0(Bin 0)
B1(Bin 1)
B2(Bin 2)
B3(Bin 3)
B4(Bin 4)
B0 --> CA("Convo A")
B2 --> CB("Convo B")
B3 --> CC("Convo C")
B3 --> CD("Convo D")
In the diagram above a participant of Conversations A,B,C,D would need to subscribe to 3/5 of the network traffic.
As interesting traffic in conversation-based-addressing approach cannot be isolated to a single "Bin"; all clients end up requiring most of the traffic which makes filtering moot.
What is the limiting factor on the number of subscriptions? Any ideas for how to get around this limitation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First suggestion that comes in mind is considering the Waku content topic as a delivery address (in-line with Delivery Service terminology).
I think in general it is fair to limit the number of delivery addresses an application need to listen to. If you swap Waku for something like Nostr, you could imagine a Nost relay server (+ maybe some inbox id) being a delivery address.
So now it means to send to an inbox, we need 2 piece of information:
- Inbox address
- Delivery address
We traditionally hashed (1) to end-up in a bucket for (2). Status protocol do:
-> secp private key -> secp public key -> hash + truncate -> topic code -> Waku content topic
The nice properties of that is randomness on the bucket you end up with (derived from the private key randomness), allowing fair distributions of users across the content topic buckets (and then shards via auto-sharding).
We purposely want to move away from secp keys defining your inbox and identity. Hence, I don't think we can copy the old system.
So instead, I would suggest:
- random generation of a delivery address for account: this should be mostly static, but can be rotated slowly. eg targeting a max of 5 in use for a given installation, and 1-2 for normal usage
- generation of inbox address as it is
A "full" inbox address then become delivery address + inbox address, where only delivery address is part of the Waku content topic
Based on this parameter, we can then bucket delivery addresses in a flexible manner. Where for example a v1 for chat SDK will bucket all delivery addresses to 10 possible one, and a v2, 100.
Thanks to the flexibility of inbox, upgrading can be easy as a user can listen to both version,until they have fully deprecated their old inboxes.
Finally, let's avoid re-using names that we have across the stack (eg waku content topic vs chat content topic). I think the "content topic" name was already a bad idea knowing underlying stack has "pubsub topic". Let's not repeat history.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the limiting factor on the number of subscriptions?
The number of subscriptions affect the efficiency of filter and store protocols.
Any ideas for how to get around this limitation?
I don't think one should try to get around it when you see it as a delivery address.
But what would be important is for core team to recommend the number of content topics (avg and max) a waku node should aim to subscribe to (relay/fitler/store) to help you decide on best approach. cc @jm-clius.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think in general it is fair to limit the number of delivery addresses an application need to listen to.
So instead, I would suggest:
random generation of a delivery address for account: this should be mostly static, but can be rotated slowly. eg targeting a max of 5 in use for a given installation, and 1-2 for normal usage
My concern is that this would mean that the entire networks messaging traffic would need to be sent to the same "delivery address" to stay within that limit. A client's access pattern cannot easily be isolated to single "delivery address", assuming Conversation-based-message-routing is used.
Dividing traffic is easy in Inbox-based-message-routing (the method used in Status), but its resource intensive on the network as messages are copied to each inbox via client-side fanout. Expensive copies of payloads is what makes querying efficient for clients.
There is a trade-off between network load and and client side resource management. If limited to ~2 subscriptions then approaches like MLS could use orders of magnitude more bandwidth that the existing status solution, even though there is a significant drop in overall message counts network wide.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is all outside of this specification - Although if conversation-based-routing is not feasible then Inboxes may not be the desired solution.
I'm going to pause(if not close) this PR and perform some testing to see what the exposure is before sinking more cycles.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
random generation of a delivery address for account: this should be mostly static, but can be rotated slowly. eg targeting a max of 5 in use for a given installation, and 1-2 for normal usage
My concern is that this would mean that the entire networks messaging traffic would need to be sent to the same "delivery address" to stay within that limit. A client's access pattern cannot easily be isolated to single "delivery address", assuming Conversation-based-message-routing is used.
Let's see what @jm-clius says here.
All I can say is that the usage of 100 content topics for Communities were problematic (cc @chaitanyaprem @plopezlpz ) for filter and store.
However, in the context of store, this was coupled with time range queries, and expectation of 30 days message access. Which we are moving away from with SDS.
In terms of filter, 100 content topics did mean slow time to setup the subscriptions and getting the "app ready".
But as @jm-clius's original comment, we still need to understand the expect usage of topics to comment here.
For example:
- content topic per active conversation (2 or more users).
- 5 baseline content topic for inbound inboxes
Maybe scalable enough? I can see in my chat app have hundreds of convo, but only maybe 10 are really "active"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think my main point is that this spec should exist on its own terms. It makes the assumptions:
- chat users exist that want to be notified of invitations to new conversations
- these chat users have access to a transport layer network (any one) that delivers them messages belonging to these inbox addresses
How we "divide up" inbox addresses, conversations, etc. into different filters (or even different routing shards) is an external concern - this spec only requires that the user has access to their messages.
As a rule of thumb, we currently suggest around 30 live content topic subscriptions per client. However, this is likely something that can be increased if we improve our implementation.
I think we could come up with various strategies here to have filter strategies that's compatible both with keeping bandwidth constrained and the filter cardinality reasonable.
It may even be possible to do a content topic per conversation as long as we keep the number of concurrent conversation subscriptions limited (stale conversations could e.g. require a notification to the user's inbox address to reactivate that as a "live" conversation subscription).
standards/application/inbox.md
Outdated
|
|
||
| The noise protocol name would then be `Noise_KNfallback_25519_ChaChaPoly_BLAKE2s` | ||
|
|
||
| This protocol opts for 32bit variants to optimize for mobile and resource constrained environments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would imagine that we don't want to go lower than 256 bits and afaik there are fast implementations, even in constrained environments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to help with clarity.
Also With %50+ of the mobile market using 64bit chips, its probably not worth maintaining optimized paths for 32 bit platforms and microcontrollers.
I'll update the primitives.
| ## Framing | ||
| ```mermaid | ||
| flowchart TD | ||
| WapEnvelopeV1 --> EncryptedPayload |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I understand what WapEnvelopeV1 is? Perhaps TBD in future version of this spec or referencing some other spec?
standards/application/inbox.md
Outdated
|
|
||
| ### EncryptedBytes | ||
|
|
||
| The EncryptedBytes message is a self-describing wrapper for all encrypted payloads. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this refer to the encrypted_bytes field in the EncryptedPayload's incorporated NoiseKN message?
If so, perhaps a good idea is to state the Wire Format, then explain what is included in each field?
standards/application/inbox.md
Outdated
| message EncryptedPayload { | ||
|
|
||
| oneof encryption { | ||
| NoiseKN noise_KN = 3; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps tag number should be 1 not 3?
I'm all for future proofing, but do we really imagine that we'll define more key exchange mechanisms in future? Perhaps simpler to just define the NoiseKN in this version of the spec?
| } | ||
|
|
||
| ``` | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think what will be great to see is a MessageFlow section that describes the protocol in a step-by-step manner, being explicit about the purpose of INBOX, the prior assumptions, the actors involved in each step, the messages they send and their direction.
| --- | ||
| # Abstract | ||
|
|
||
| An Inbox is a declaration of where a client is listening for messages, and the protocol for sending them. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After reading the spec, it seems like the purpose of Inbox may be more explicitly stated as the address where a client is waiting for an invite (only) to a conversation that allows it to setup a private conversation elsewhere (out of scope)?
This may indicate that this spec will make more sense as a subsection of a more complete Conversation protocol.

Overview
This specification outlines how clients can receive initial messages in the "ChatSDK" in order to establish other more secure conversation types.
It is intended to be used by other protocols to define where clients are expecting messages, while also defining an encryption method.
Design Decisions