From 25f25e98533fe95eeaa9f0b9fefd1b19d625edee Mon Sep 17 00:00:00 2001 From: Patryk Osmaczko Date: Mon, 30 Oct 2023 19:34:21 +0100 Subject: [PATCH] chore: populate Community with PubsubTopicPrivateKey part of: status-im/status-desktop#12408 --- protocol/communities/community.go | 36 +++++++++++++++++++++----- protocol/communities/manager.go | 36 ++++++++++++++++++++------ protocol/messenger_communities.go | 43 +++++++++++++++---------------- protocol/messenger_response.go | 25 ------------------ services/chat/api.go | 6 +++++ 5 files changed, 84 insertions(+), 62 deletions(-) diff --git a/protocol/communities/community.go b/protocol/communities/community.go index c3b491e05..dab8bc2f0 100644 --- a/protocol/communities/community.go +++ b/protocol/communities/community.go @@ -12,6 +12,8 @@ import ( "github.com/golang/protobuf/proto" "go.uber.org/zap" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/images" @@ -45,6 +47,7 @@ type Config struct { SyncedAt uint64 EventsData *EventsData Shard *common.Shard + PubsubTopicPrivateKey *ecdsa.PrivateKey } type EventsData struct { @@ -142,15 +145,17 @@ func (o *Community) MarshalPublicAPIJSON() ([]byte, error) { CommunityTokensMetadata []*protobuf.CommunityTokenMetadata `json:"communityTokensMetadata"` ActiveMembersCount uint64 `json:"activeMembersCount"` PubsubTopic string `json:"pubsubTopic"` + PubsubTopicKey string `json:"pubsubTopicKey"` Shard *common.Shard `json:"shard"` }{ - ID: o.ID(), - Verified: o.config.Verified, - Chats: make(map[string]CommunityChat), - Categories: make(map[string]CommunityCategory), - Tags: o.Tags(), - PubsubTopic: o.PubsubTopic(), - Shard: o.Shard(), + ID: o.ID(), + Verified: o.config.Verified, + Chats: make(map[string]CommunityChat), + Categories: make(map[string]CommunityCategory), + Tags: o.Tags(), + PubsubTopic: o.PubsubTopic(), + PubsubTopicKey: o.PubsubTopicKey(), + Shard: o.Shard(), } if o.config.CommunityDescription != nil { @@ -258,6 +263,7 @@ func (o *Community) MarshalJSON() ([]byte, error) { CommunityTokensMetadata []*protobuf.CommunityTokenMetadata `json:"communityTokensMetadata"` ActiveMembersCount uint64 `json:"activeMembersCount"` PubsubTopic string `json:"pubsubTopic"` + PubsubTopicKey string `json:"pubsubTopicKey"` Shard *common.Shard `json:"shard"` }{ ID: o.ID(), @@ -279,6 +285,7 @@ func (o *Community) MarshalJSON() ([]byte, error) { Tags: o.Tags(), Encrypted: o.Encrypted(), PubsubTopic: o.PubsubTopic(), + PubsubTopicKey: o.PubsubTopicKey(), Shard: o.Shard(), } if o.config.CommunityDescription != nil { @@ -1308,6 +1315,21 @@ func (o *Community) PubsubTopic() string { return transport.GetPubsubTopic(o.Shard().TransportShard()) } +func (o *Community) PubsubTopicPrivateKey() *ecdsa.PrivateKey { + return o.config.PubsubTopicPrivateKey +} + +func (o *Community) SetPubsubTopicPrivateKey(privKey *ecdsa.PrivateKey) { + o.config.PubsubTopicPrivateKey = privKey +} + +func (o *Community) PubsubTopicKey() string { + if o.config.PubsubTopicPrivateKey == nil { + return "" + } + return hexutil.Encode(crypto.FromECDSAPub(&o.config.PubsubTopicPrivateKey.PublicKey)) +} + func (o *Community) DefaultFilters() []transport.FiltersToInitialize { cID := o.IDString() uncompressedPubKey := common.PubkeyToHex(o.config.ID)[2:] diff --git a/protocol/communities/manager.go b/protocol/communities/manager.go index 1e51560ce..154f93e5d 100644 --- a/protocol/communities/manager.go +++ b/protocol/communities/manager.go @@ -625,7 +625,7 @@ func (m *Manager) All() ([]*Community, error) { } for _, c := range communities { - err = initializeCommunity(c) + err = m.initializeCommunity(c) if err != nil { return nil, err } @@ -687,7 +687,7 @@ func (m *Manager) Joined() ([]*Community, error) { } for _, c := range communities { - err = initializeCommunity(c) + err = m.initializeCommunity(c) if err != nil { return nil, err } @@ -703,7 +703,7 @@ func (m *Manager) Spectated() ([]*Community, error) { } for _, c := range communities { - err = initializeCommunity(c) + err = m.initializeCommunity(c) if err != nil { return nil, err } @@ -719,7 +719,7 @@ func (m *Manager) JoinedAndPendingCommunitiesWithRequests() ([]*Community, error } for _, c := range communities { - err = initializeCommunity(c) + err = m.initializeCommunity(c) if err != nil { return nil, err } @@ -735,7 +735,7 @@ func (m *Manager) DeletedCommunities() ([]*Community, error) { } for _, c := range communities { - err = initializeCommunity(c) + err = m.initializeCommunity(c) if err != nil { return nil, err } @@ -754,7 +754,7 @@ func (m *Manager) Controlled() ([]*Community, error) { for _, c := range communities { if c.IsControlNode() { - err = initializeCommunity(c) + err = m.initializeCommunity(c) if err != nil { return nil, err } @@ -1116,6 +1116,18 @@ func (m *Manager) SetShard(communityID types.HexBytes, shard *common.Shard) (*Co return community, nil } +func (m *Manager) UpdatePubsubTopicPrivateKey(community *Community, privKey *ecdsa.PrivateKey) error { + community.SetPubsubTopicPrivateKey(privKey) + + if privKey != nil { + if err := m.transport.StorePubsubTopicKey(community.PubsubTopic(), privKey); err != nil { + return err + } + } + + return nil +} + // EditCommunity takes a description, updates the community with the description, // saves it and returns it func (m *Manager) EditCommunity(request *requests.EditCommunity) (*Community, error) { @@ -3188,12 +3200,20 @@ func (m *Manager) BanUserFromCommunity(request *requests.BanUserFromCommunity) ( } // Apply events to raw community -func initializeCommunity(community *Community) error { +func (m *Manager) initializeCommunity(community *Community) error { err := community.updateCommunityDescriptionByEvents() if err != nil { return err } + if m.transport != nil && m.transport.WakuVersion() == 2 { + privKey, err := m.transport.RetrievePubsubTopicKey(community.PubsubTopic()) + if err != nil { + return err + } + community.config.PubsubTopicPrivateKey = privKey + } + // Workaround for https://github.com/status-im/status-desktop/issues/12188 HydrateChannelsMembers(community.IDString(), community.config.CommunityDescription) @@ -3209,7 +3229,7 @@ func (m *Manager) GetByID(id []byte) (*Community, error) { return nil, nil } - err = initializeCommunity(community) + err = m.initializeCommunity(community) if err != nil { return nil, err } diff --git a/protocol/messenger_communities.go b/protocol/messenger_communities.go index 960d6be92..9b23a24f8 100644 --- a/protocol/messenger_communities.go +++ b/protocol/messenger_communities.go @@ -2084,7 +2084,12 @@ func (m *Messenger) SetCommunityShard(request *requests.SetCommunityShard) (*Mes return nil, err } - err = m.UpdateCommunityFilters(community, topicPrivKey) + err = m.communitiesManager.UpdatePubsubTopicPrivateKey(community, topicPrivKey) + if err != nil { + return nil, err + } + + err = m.UpdateCommunityFilters(community) if err != nil { return nil, err } @@ -2095,22 +2100,12 @@ func (m *Messenger) SetCommunityShard(request *requests.SetCommunityShard) (*Mes } response := &MessengerResponse{} - response.AddProtectedTopic(&ProtectedTopic{ - CommunityID: community.IDString(), - PubsubTopic: community.PubsubTopic(), - PublicKey: hexutil.Encode(crypto.FromECDSAPub(&topicPrivKey.PublicKey)), - }) + response.AddCommunity(community) return response, nil } -func (m *Messenger) UpdateCommunityFilters(community *communities.Community, privKey *ecdsa.PrivateKey) error { - if m.transport.WakuVersion() == 2 && privKey != nil { - if err := m.transport.StorePubsubTopicKey(community.PubsubTopic(), privKey); err != nil { - return err - } - } - +func (m *Messenger) UpdateCommunityFilters(community *communities.Community) error { publicFiltersToInit := make([]transport.FiltersToInitialize, 0, len(community.DefaultFilters())+len(community.Chats())) publicFiltersToInit = append(publicFiltersToInit, community.DefaultFilters()...) @@ -2499,11 +2494,7 @@ func (m *Messenger) SendCommunityShardKey(community *communities.Community, pubk return nil } - key, err := m.transport.RetrievePubsubTopicKey(community.PubsubTopic()) - if err != nil { - return err - } - + key := community.PubsubTopicPrivateKey() if key == nil { return nil // No community shard key available } @@ -3073,11 +3064,14 @@ func (m *Messenger) HandleCommunityShardKey(state *ReceivedMessageState, message return errors.New("signer can't be nil") } - if !community.IsMemberOwner(signer) { - return communities.ErrNotAuthorized + err = m.handleCommunityShardAndFiltersFromProto(community, common.ShardFromProtobuff(message.Shard), message.PrivateKey) + if err != nil { + return err } - return m.handleCommunityShardAndFiltersFromProto(community, common.ShardFromProtobuff(message.Shard), message.PrivateKey) + state.Response.AddCommunity(community) + + return nil } func (m *Messenger) handleCommunityShardAndFiltersFromProto(community *communities.Community, shard *common.Shard, privateKeyBytes []byte) error { @@ -3094,7 +3088,12 @@ func (m *Messenger) handleCommunityShardAndFiltersFromProto(community *communiti } } - err = m.UpdateCommunityFilters(community, privKey) + err = m.communitiesManager.UpdatePubsubTopicPrivateKey(community, privKey) + if err != nil { + return err + } + + err = m.UpdateCommunityFilters(community) if err != nil { return err } diff --git a/protocol/messenger_response.go b/protocol/messenger_response.go index 0972fce19..ecd6000f9 100644 --- a/protocol/messenger_response.go +++ b/protocol/messenger_response.go @@ -34,12 +34,6 @@ type ClearedHistory struct { ClearedAt uint64 `json:"clearedAt"` } -type ProtectedTopic struct { - CommunityID string `json:"communityID"` - PubsubTopic string `json:"pubsubTopic"` - PublicKey string `json:"publicKey"` -} - type MessengerResponse struct { Contacts []*Contact Installations []*multidevice.Installation @@ -68,7 +62,6 @@ type MessengerResponse struct { removedMessages map[string]*RemovedMessage communities map[string]*communities.Community communitiesSettings map[string]*communities.CommunitySettings - protectedTopics map[string]*ProtectedTopic activityCenterNotifications map[string]*ActivityCenterNotification activityCenterState *ActivityCenterState messages map[string]*common.Message @@ -110,7 +103,6 @@ func (r *MessengerResponse) MarshalJSON() ([]byte, error) { Notifications []*localnotifications.Notification `json:"notifications"` Communities []*communities.Community `json:"communities,omitempty"` CommunitiesSettings []*communities.CommunitySettings `json:"communitiesSettings,omitempty"` - ProtectedTopics []ProtectedTopic `json:"protectedTopics,omitempty"` ActivityCenterNotifications []*ActivityCenterNotification `json:"activityCenterNotifications,omitempty"` ActivityCenterState *ActivityCenterState `json:"activityCenterState,omitempty"` CurrentStatus *UserStatus `json:"currentStatus,omitempty"` @@ -152,7 +144,6 @@ func (r *MessengerResponse) MarshalJSON() ([]byte, error) { Chats: r.Chats(), Communities: r.Communities(), CommunitiesSettings: r.CommunitiesSettings(), - ProtectedTopics: r.ProtectedTopics(), RemovedChats: r.RemovedChats(), RemovedMessages: r.RemovedMessages(), ClearedHistories: r.ClearedHistories(), @@ -220,14 +211,6 @@ func (r *MessengerResponse) CommunitiesSettings() []*communities.CommunitySettin return settings } -func (r *MessengerResponse) ProtectedTopics() []ProtectedTopic { - protectedTopics := make([]ProtectedTopic, 0, len(r.protectedTopics)) - for _, pt := range r.protectedTopics { - protectedTopics = append(protectedTopics, *pt) - } - return protectedTopics -} - func (r *MessengerResponse) Notifications() []*localnotifications.Notification { var notifications []*localnotifications.Notification for _, n := range r.notifications { @@ -372,14 +355,6 @@ func (r *MessengerResponse) AddRequestsToJoinCommunity(requestsToJoin []*communi r.RequestsToJoinCommunity = append(r.RequestsToJoinCommunity, requestsToJoin...) } -func (r *MessengerResponse) AddProtectedTopic(pt *ProtectedTopic) { - if r.protectedTopics == nil { - r.protectedTopics = make(map[string]*ProtectedTopic) - } - - r.protectedTopics[pt.CommunityID] = pt -} - func (r *MessengerResponse) AddRequestToJoinCommunity(requestToJoin *communities.RequestToJoin) { r.RequestsToJoinCommunity = append(r.RequestsToJoinCommunity, requestToJoin) } diff --git a/services/chat/api.go b/services/chat/api.go index e0546918b..4b15b6476 100644 --- a/services/chat/api.go +++ b/services/chat/api.go @@ -104,6 +104,9 @@ type ChannelGroup struct { UnviewedMessagesCount int `json:"unviewedMessagesCount"` UnviewedMentionsCount int `json:"unviewedMentionsCount"` CheckChannelPermissionResponses map[string]*communities.CheckChannelPermissionsResponse `json:"checkChannelPermissionResponses"` + PubsubTopic string `json:"pubsubTopic"` + PubsubTopicKey string `json:"pubsubTopicKey"` + Shard *common.Shard `json:"shard"` } func NewAPI(service *Service) *API { @@ -234,6 +237,9 @@ func (api *API) getChannelGroups(ctx context.Context, channelGroupID string) (ma UnviewedMessagesCount: totalUnviewedMessageCount, UnviewedMentionsCount: totalUnviewedMentionsCount, CheckChannelPermissionResponses: make(map[string]*communities.CheckChannelPermissionsResponse), + PubsubTopic: community.PubsubTopic(), + PubsubTopicKey: community.PubsubTopicKey(), + Shard: community.Shard(), } for t, i := range community.Images() {