diff --git a/content/docs/rfcs/55/README.md b/content/docs/rfcs/55/README.md index add824e9..fb709dac 100644 --- a/content/docs/rfcs/55/README.md +++ b/content/docs/rfcs/55/README.md @@ -19,6 +19,15 @@ contributors: This specification describes how the Status 1-to-1 chat protocol is implemented on top of the Waku v2 protocol. This protocol can be used to send messages to a single recipient. +# Terminology + +- **Participant**: A participant is a user that is able to send and receive messages. +- **1-to-1 chat**: A chat between two participants. +- **Public chat**: A chat where any participant can join and read messages. +- **Private chat**: A chat where only invited participants can join and read messages. +- **Group chat**: A chat where multiple select participants can join and read messages. +- **Group admin**: A participant that is able to add/remove participants from a group chat. + # Background This document describes how 2 peers communicate with each other to send messages in a 1-to-1 chat, with privacy and authenticity guarantees. @@ -59,6 +68,136 @@ It is handled by the key-exchange protocol used. For example, 2. [35/WAKU2-NOISE](/spec/35/), the session management is described in [37/WAKU2-NOISE-SESSIONS](/spec/37/) +## Negotiation of a 1:1 chat amongst multiple participants (group chat) + +A small, private group chat can be constructed by having multiple participants negotiate a 1:1 chat amongst each other. +Each participant MUST maintain a session with all other participants in the group chat. +This allows for a group chat to be created with a small number of participants. + +However, this method does not scale as the number of participants increases, for the following reasons - +1. The number of messages sent over the network increases with the number of participants. +2. Handling the X3DH key exchange for each participant is computationally expensive. + +The above issues are addressed in [56/STATUS-COMMUNITIES](/spec/56/), with other trade-offs. + +### Flow + +The following flow describes how a group chat is created and maintained. + +#### Membership Update Flow + +Membership updates have the following wire format: + +```protobuf +message MembershipUpdateMessage { + // The chat id of the private group chat + // derived in the following way: + // chat_id = hex(chat_creator_public_key) + "-" + random_uuid + // This chat_id MUST be validated by all participants + string chat_id = 1; + // A list of events for this group chat, first 65 bytes are the signature, then is a + // protobuf encoded MembershipUpdateEvent + repeated bytes events = 2; + oneof chat_entity { + // An optional chat message + ChatMessage message = 3; + // An optional reaction to a message + EmojiReaction emoji_reaction = 4; + } +} +``` + +where `MembershipUpdateEvent` is defined as follows: + +```protobuf +message MembershipUpdateEvent { + // Lamport timestamp of the event + uint64 clock = 1; + // Optional list of public keys of the targets of the action + repeated string members = 2; + // Name of the chat for the CHAT_CREATED/NAME_CHANGED event types + string name = 3; + // The type of the event + EventType type = 4; + // Color of the chat for the CHAT_CREATED/COLOR_CHANGED event types + string color = 5; + // Chat image + bytes image = 6; + + enum EventType { + UNKNOWN = 0; + CHAT_CREATED = 1; // See [CHAT_CREATED](#chat-created) + NAME_CHANGED = 2; // See [NAME_CHANGED](#name-changed) + MEMBERS_ADDED = 3; // See [MEMBERS_ADDED](#members-added) + MEMBER_JOINED = 4; // See [MEMBER_JOINED](#member-joined) + MEMBER_REMOVED = 5; // See [MEMBER_REMOVED](#member-removed) + ADMINS_ADDED = 6; // See [ADMINS_ADDED](#admins-added) + ADMIN_REMOVED = 7; // See [ADMIN_REMOVED](#admin-removed) + COLOR_CHANGED = 8; // See [COLOR_CHANGED](#color-changed) + IMAGE_CHANGED = 9; // See [IMAGE_CHANGED](#image-changed) + } +} +``` + +Note that the definitions for `ChatMessage` and `EmojiReaction` can be found in [chat_message.proto](https://github.com/status-im/status-go/blob/5fd9e93e9c298ed087e6716d857a3951dbfb3c1e/protocol/protobuf/chat_message.proto#L1) and [emoji_reaction.proto](https://github.com/status-im/status-go/blob/5fd9e93e9c298ed087e6716d857a3951dbfb3c1e/protocol/protobuf/emoji_reaction.proto). + +##### Chat Created + +When creating a group chat, this is the first event that MUST be sent. +Any event with a clock value lower than this MUST be discarded. +Upon receiving this event a client MUST validate the `chat_id` provided with the update and create a chat with identified by `chat_id`. + +By default, the creator of the group chat is the only group admin. + +##### Name Changed + +To change the name of the group chat, group admins MUST use a `NAME_CHANGED` event. +Upon receiving this event a client MUST validate the `chat_id` provided with the updates and MUST ensure the author of the event is an admin of the chat, otherwise the event MUST be ignored. +If the event is valid the chat name SHOULD be changed according to the provided message. + +##### Members Added + +To add members to the chat, group admins MUST use a `MEMBERS_ADDED` event. +Upon receiving this event a participant MUST validate the `chat_id` provided with the updates and MUST ensure the author of the event is an admin of the chat, otherwise the event MUST be ignored. +If the event is valid, a participant MUST update the list of members of the chat who have not joined, adding the members received. + +##### Member Joined + +To signal the intent to start receiving messages from a given chat, new participants MUST use a `MEMBER_JOINED` event. +Upon receiving this event a participant MUST validate the `chat_id` provided with the updates. +If the event is valid a participant MUST add the new participant to the list of participants stored locally. +Any message sent to the group chat MUST now include the new participant. + +##### Member Removed + +There are two ways in which a member MAY be removed from a group chat: +- A member MAY leave the chat by sending a `MEMBER_REMOVED` event, with the `members` field containing their own public key. +- An admin MAY remove a member by sending a `MEMBER_REMOVED` event, with the `members` field containing the public key of the member to be removed. + +Each participant MUST validate the `chat_id` provided with the updates and MUST ensure the author of the event is an admin of the chat, otherwise the event MUST be ignored. +If the event is valid, a participant MUST update the local list of members accordingly. + +##### Admins Added + +To promote participants to group admin, group admins MUST use an `ADMINS_ADDED` event. +Upon receiving this event, a participant MUST validate the `chat_id` provided with the updates, MUST ensure the author of the event is an admin of the chat, otherwise the event MUST be ignored. +If the event is valid, a participant MUST update the list of admins of the chat accordingly. + +##### Admin Removed + +Group admins MUST NOT be able to remove other group admins. +An admin MAY remove themselves by sending an `ADMIN_REMOVED` event, with the `members` field containing their own public key. +Each participant MUST validate the `chat_id` provided with the updates and MUST ensure the author of the event is an admin of the chat, otherwise the event MUST be ignored. +If the event is valid, a participant MUST update the list of admins of the chat accordingly. + +##### Color Changed + +To change the text color of the group chat name, group admins MUST use a `COLOR_CHANGED` event. + +##### Image Changed + +To change the display image of the group chat, group admins MUST use an `IMAGE_CHANGED` event. + # Security Considerations 1. Inherits the security considerations of the key-exchange mechanism used, e.g., [53/WAKU2-X3DH](/spec/53/) or [35/WAKU2-NOISE](/spec/35/) @@ -72,4 +211,5 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public 1. [2/ACCOUNT](https://specs.status.im/spec/2) 2. [53/WAKU2-X3DH](/spec/53/) 3. [35/WAKU2-NOISE](/spec/35/) -4. [10/WAKU2](/spec/10/) \ No newline at end of file +4. [10/WAKU2](/spec/10/) +5. [7/GROUP-CHAT](https://specs.status.im/draft/7) \ No newline at end of file