Skip to content
This repository has been archived by the owner on Jun 14, 2024. It is now read-only.

feat(56/STATUS-COMMUNITIES): initial draft #567

Merged
merged 25 commits into from
Feb 21, 2023
Merged
Changes from 3 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9a499c7
feat(55/WAKU2-ORGANIZATION-CHATS): initial draft
rymnc Jan 27, 2023
94b910e
fix(55/WAKU2-ORGANIZATION-CHATS): rename folder, omit cryptography
rymnc Jan 27, 2023
df9e554
fix(55/STATUS-COMMUNITIES): s/Organization/Communities
rymnc Jan 31, 2023
6352e9f
fix(55/STATUS-COMMUNITIES): address comments
rymnc Feb 1, 2023
048ba99
fix(55/STATUS-COMMUNITIES): move store to MUST use section
rymnc Feb 2, 2023
51f5ca1
fix: move to 56, add to index, copyright info
rymnc Feb 2, 2023
2edf657
fix: remove noise as a key-exchange candidate
rymnc Feb 2, 2023
d02ff45
fix(56/STATUS-COMMUNITIES): raw state, refs
rymnc Feb 3, 2023
068491d
feat(56/STATUS-COMMUNITIES): refer to backup mechanism
rymnc Feb 6, 2023
d63b975
fix(56/STATUS-COMMUNITIES): better wording
rymnc Feb 6, 2023
4d11e7a
fix(56/STATUS-COMMUNITIES): specific usage of content topics
rymnc Feb 7, 2023
bfd3e02
fix(56/STATUS-COMMUNITIES): hex-encoded hash, and formula for clarity
rymnc Feb 7, 2023
12c97a5
fix(56/STATUS-COMMUNITIES): address semantic changes
rymnc Feb 8, 2023
72b8553
fix(56/STATUS-COMMUNITIES): clearer background
rymnc Feb 8, 2023
64237af
fix(56/STATUS-COMMUNITIES): improved assumptions
rymnc Feb 8, 2023
30c465b
fix(56/STATUS-COMMUNITIES): definition of content topic
rymnc Feb 8, 2023
c0fc7cb
fix(56/STATUS-COMMUNITIES): clearer chat id
rymnc Feb 8, 2023
fccad2d
fix(56/STATUS-COMMUNITIES): add future work content topic usage for e…
rymnc Feb 8, 2023
6f7a44b
fix(56/STATUS-COMMUNITIES): usage of members where applicable
rymnc Feb 8, 2023
d64aeb2
fix(56/STATUS-COMMUNITIES): address semantic changes
rymnc Feb 14, 2023
609fd24
fix(56/STATUS-COMMUNITIES): topic usage
rymnc Feb 14, 2023
53a7692
fix(56/STATUS-COMMUNITIES): light node clarification
rymnc Feb 14, 2023
3690bab
fix(56/STATUS-COMMUNITIES): 1:1 chat for joining
rymnc Feb 14, 2023
b333c9c
fix(56/STATUS-COMMUNITIES): community ban flow update
rymnc Feb 20, 2023
b251b64
Merge branch 'master' into organization-spec
rymnc Feb 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
330 changes: 330 additions & 0 deletions content/docs/rfcs/55/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,330 @@
---
slug: 55
title: 55/STATUS-COMMUNITIES
name: Status Communities that run on Waku v2
status: raw
category: Standards Track
tags: waku-application
editor: Aaryamann Challani <[email protected]>
contributors:
---

# Abstract

This document describes the design of Status Communities for Waku v2, allowing for multiple users to communicate in a group chat.
This is a key feature for the Status messaging app.

# Background and Motivation

Large group chats enable communities to communicate.
This would require channels, which are subject-based.
The messages in a channel are broadcasted to all the users in the channel.

A regular group chat between two or more peers reduces to a 1:1 chat between each peer and the other peers.
One mechanism for 1:1 chats is described in [53/WAKU2-X3DH](https://rfc.vac.dev/spec/53/).
However, this method does not scale as the number of peers increases, for the following reasons -
1. The number of messages sent over the network increases as the number of peers increases.
2. Handling the X3DH key exchange for each peer is computationally expensive.

Having multicast channels reduces the overhead of a regular group chat.
Additionally, if all the peers have a shared key, then the number of messages sent over the network is reduced to one per message.

# Design Requirements

Due to the nature of communities, the following requirements are necessary for the design of communities -

1. The Community owner is trusted.
2. The Community owner can add or remove peers from the Community.
3. The Community owner can add or remove channels.
4. The peers in the Community can send/receive messages to the channels which they have access to.
5. Communitys may be encrypted or unencrypted (public).
6. A Community is uniquely identified by a public key.
7. The public key of the Community is shared out of band.
8. The metadata of the Community can be found by listening on a content topic derived from the public key of the Community.
9. Peers part of a Community run their own infrastructure.

# Design

## Cryptographic Primitives

The following cryptographic primitives are used in the design -

- X3DH
- Single Ratchet
- The single ratchet is used to encrypt the messages sent to the Community.
- The single ratchet is re-keyed when a peer is added/removed from the Community.

## Wire format

<!--
The wire format is described first to give an overview of the protocol.
It is referenced in the flow of community creation and community management.
More or less an intersection of https://github.com/status-im/specs/blob/403b5ce316a270565023fc6a1f8dec138819f4b0/docs/raw/organisation-channels.md and https://github.com/status-im/status-go/blob/6072bd17ab1e5d9fc42cf844fcb8ad18aa07760c/protocol/protobuf/communities.proto,

-->

```protobuf
syntax = "proto3";

message IdentityImage {
// payload is a context based payload for the profile image data,
// context is determined by the `source_type`
bytes payload = 1;
// source_type signals the image payload source
SourceType source_type = 2;
// image_type signals the image type and method of parsing the payload
ImageType image_type = 3;
// encryption_keys is a list of encrypted keys that can be used to decrypt an encrypted payload
repeated bytes encryption_keys = 4;
// encrypted signals the encryption state of the payload, default is false.
bool encrypted = 5;
// SourceType are the predefined types of image source allowed
enum SourceType {
UNKNOWN_SOURCE_TYPE = 0;

// RAW_PAYLOAD image byte data
RAW_PAYLOAD = 1;

// ENS_AVATAR uses the ENS record's resolver get-text-data.avatar data
// The `payload` field will be ignored if ENS_AVATAR is selected
// The application will read and parse the ENS avatar data as image payload data, URLs will be ignored
// The parent `ChatMessageIdentity` must have a valid `ens_name` set
ENS_AVATAR = 2;
}
}

// SocialLinks represents social link assosiated with given chat identity (personal/community)
message SocialLink {
// Type of the social link
string text = 1;
// URL of the social link
string url = 2;
}
// ChatIdentity represents identity of a community/chat
message ChatIdentity {
// Lamport timestamp of the message
uint64 clock = 1;
// ens_name is the valid ENS name associated with the chat key
string ens_name = 2;
// images is a string indexed mapping of images associated with an identity
map<string, IdentityImage> images = 3;
// display name is the user set identity
string display_name = 4;
// description is the user set description
string description = 5;
string color = 6;
string emoji = 7;
repeated SocialLink social_links = 8;
// first known message timestamp in seconds (valid only for community chats for now)
// 0 - unknown
// 1 - no messages
uint32 first_message_timestamp = 9;
}

message Grant {
// Community ID (The public key of the community)
bytes community_id = 1;
// The member ID (The public key of the member)
bytes member_id = 2;
// The chat for which the grant is given
string chat_id = 3;
// The Lamport timestamp of the grant
uint64 clock = 4;
}

message CommunityMember {
// The roles a community member MAY have
enum Roles {
UNKNOWN_ROLE = 0;
ROLE_ALL = 1;
ROLE_MANAGE_USERS = 2;
ROLE_MODERATE_CONTENT = 3;
}
repeated Roles roles = 1;
}

message CommunityPermissions {
// The type of access a community MAY have
enum Access {
UNKNOWN_ACCESS = 0;
NO_MEMBERSHIP = 1;
INVITATION_ONLY = 2;
ON_REQUEST = 3;
}

// If the community should be available only to ens users
bool ens_only = 1;
// If the community is private
bool private = 2;
Access access = 3;
}

message CommunityAdminSettings {
// If the Community admin may pin messages
bool pin_message_all_members_enabled = 1;
}

message CommunityChat {
// A map of members in the community to their roles in a chat
map<string,CommunityMember> members = 1;
// The permissions of the chat
CommunityPermissions permissions = 2;
// The metadata of the chat
ChatIdentity identity = 3;
// The category of the chat
string category_id = 4;
// The position of chat in the display
int32 position = 5;
}

message CommunityCategory {
// The category id
string category_id = 1;
// The name of the category
string name = 2;
// The position of the category in the display
int32 position = 3;
}

message CommunityInvitation {
// Encrypted/unencrypted community description
bytes community_description = 1;
// The grant offered by the community
bytes grant = 2;
// The chat id requested to join
string chat_id = 3;
// The public key of the community
bytes public_key = 4;
}

message CommunityRequestToJoin {
// The Lamport timestamp of the request
uint64 clock = 1;
// The ENS name of the requester
string ens_name = 2;
// The chat id requested to join
string chat_id = 3;
// The public key of the community
bytes community_id = 4;
// The display name of the requester
string display_name = 5;
}

message CommunityCancelRequestToJoin {
// The Lamport timestamp of the request
uint64 clock = 1;
// The ENS name of the requester
string ens_name = 2;
// The chat id requested to join
string chat_id = 3;
// The public key of the community
bytes community_id = 4;
// The display name of the requester
string display_name = 5;
// Magnet uri for community history protocol
string magnet_uri = 6;
}

message CommunityRequestToJoinResponse {
// The Lamport timestamp of the request
uint64 clock = 1;
// The community description
CommunityDescription community = 2;
// If the request was accepted
bool accepted = 3;
// The grant offered by the community
bytes grant = 4;
// The community public key
bytes community_id = 5;
}

message CommunityRequestToLeave {
// The Lamport timestamp of the request
uint64 clock = 1;
// The community public key
bytes community_id = 2;
}

message CommunityDescription {
// The Lamport timestamp of the message
uint64 clock = 1;
// A mapping of members in the community to their roles
map<string,CommunityMember> members = 2;
// The permissions of the Community
CommunityPermissions permissions = 3;
// The metadata of the Community
ChatIdentity identity = 5;
// A mapping of chats to their details
map<string,CommunityChat> chats = 6;
// A list of banned members
repeated string ban_list = 7;
// A mapping of categories to their details
map<string,CommunityCategory> categories = 8;
// The admin settings of the Community
CommunityAdminSettings admin_settings = 10;
// If the community is encrypted
bool encrypted = 13;
// The list of tags
repeated string tags = 14;
}
rymnc marked this conversation as resolved.
Show resolved Hide resolved
```

## Community Management

The flows for Community management are as described below.

### Community Creation Flow

1. The Community owner generates a public/private key pair.
2. The Community owner configures the Community metadata, according to the wire format "CommunityDescription".
3. The Community owner publishes the Community metadata on a content topic derived from the public key of the Community.
he Community metadata SHOULD be encrypted with the public key of the Community. <!-- TODO: Verify this-->
The Community metadata MAY be sent during fixed intervals, to ensure that the Community metadata is available to peers.
The Community metadata SHOULD be sent every time the Community metadata is updated.
4. The Community owner MAY advertise the Community out of band, by sharing the public key of the Community on other mediums of communication.

### Community Join Flow (peer requests to join a Community)

1. A peer generates a public/private key pair.
2. The peer requests to join a Community by sending a "CommunityRequestToJoin" message to the Community.
At this point, the peer MAY send a "CommunityCancelRequestToJoin" message to cancel the request.
3. The Community owner MAY accept or reject the request.
4. If the request is accepted, the Community owner sends a "CommunityRequestToJoinResponse" message to the peer.
5. The Community owner then adds the member to the Community metadata, and publishes the updated Community metadata.

### Community Join Flow (peer is invited to join a Community)

1. The peer is invited to join a Community by the Community owner, by sending a "CommunityInvitation" message.
2. A peer generates a public/private key pair.
3. The peer decrypts the "CommunityInvitation" message, and verifies the signature.
4. The peer requests to join a Community by sending a "CommunityRequestToJoin" message to the Community.
5. The Community owner MAY accept or reject the request.
6. If the request is accepted, the Community owner sends a "CommunityRequestToJoinResponse" message to the peer.
7. The Community owner then adds the member to the Community metadata, and publishes the updated Community metadata.

### Community Leave Flow

1. A peer requests to leave a Community by sending a "CommunityRequestToLeave" message to the Community.
2. The Community owner MAY accept or reject the request.
3. If the request is accepted, the Community owner removes the member from the Community metadata, and publishes the updated Community metadata.

### Community Ban Flow

1. The Community owner adds a member to the ban list, revokes their grants, and publishes the updated Community metadata.


## Security Considerations

1. The Community owner is a single point of failure. If the Community owner is compromised, the Community is compromised.

2. Follows the same security considerations as the [53/WAKU2-X3DH](https://rfc.vac.dev/spec/53/) protocol.

## Future work

1. To scale and optimize the Community management, the Community metadata should be stored on a decentralized storage system, and only the references to the Community metadata should be broadcasted. The following document describes this method in more detail - [Optimizing the `CommunityDescription` dissemination](https://hackmd.io/rD1OfIbJQieDe3GQdyCRTw)

## References

- [53/WAKU2-X3DH](https://rfc.vac.dev/spec/53/)
- https://github.com/status-im/status-go/blob/6072bd17ab1e5d9fc42cf844fcb8ad18aa07760c/protocol/communities/community.go
- https://github.com/status-im/specs/blob/403b5ce316a270565023fc6a1f8dec138819f4b0/docs/raw/organisation-channels.md