From 475036e9f20b20f6a4342c4f17b41aac001e5de7 Mon Sep 17 00:00:00 2001 From: Patryk Osmaczko Date: Mon, 25 Sep 2023 13:26:17 +0200 Subject: [PATCH] fix: stop sending channels members over the wire fixes: status-im/status-desktop#12114 --- protocol/communities/community.go | 39 ++++++++++ protocol/communities/manager.go | 118 ++++++++++++++++++++++++++---- 2 files changed, 142 insertions(+), 15 deletions(-) diff --git a/protocol/communities/community.go b/protocol/communities/community.go index 0db76269d..c772dbf24 100644 --- a/protocol/communities/community.go +++ b/protocol/communities/community.go @@ -1290,9 +1290,48 @@ func (o *Community) toProtocolMessageBytes() ([]byte, error) { func (o *Community) ToProtocolMessageBytes() ([]byte, error) { o.mutex.Lock() defer o.mutex.Unlock() + + // This is only workaround to lower the size of the message that goes over the wire, + // see https://github.com/status-im/status-desktop/issues/12188 + if o.IsControlNode() { + clone := o.CreateDeepCopy() + clone.DehydrateChannelsMembers() + return clone.toProtocolMessageBytes() + } + return o.toProtocolMessageBytes() } +func (o *Community) DehydrateChannelsMembers() { + // To save space, we don't attach members for channels without permissions, + // otherwise the message will hit waku msg size limit. + for channelID, channel := range o.chats() { + if !o.ChannelHasTokenPermissions(o.IDString() + channelID) { + channel.Members = map[string]*protobuf.CommunityMember{} // clean members + } + } +} + +func HydrateChannelsMembers(communityID string, description *protobuf.CommunityDescription) { + channelHasTokenPermissions := func(channelID string) bool { + for _, tokenPermission := range description.TokenPermissions { + if includes(tokenPermission.ChatIds, communityID+channelID) { + return true + } + } + return false + } + + for channelID, channel := range description.Chats { + if !channelHasTokenPermissions(channelID) { + channel.Members = make(map[string]*protobuf.CommunityMember) + for pubKey, member := range description.Members { + channel.Members[pubKey] = member + } + } + } +} + func (o *Community) Chats() map[string]*protobuf.CommunityChat { // Why are we checking here for nil, it should be the responsibility of the caller if o == nil { diff --git a/protocol/communities/manager.go b/protocol/communities/manager.go index 38cf89751..f78af2a2e 100644 --- a/protocol/communities/manager.go +++ b/protocol/communities/manager.go @@ -489,7 +489,19 @@ func (m *Manager) publish(subscription *Subscription) { } func (m *Manager) All() ([]*Community, error) { - return m.persistence.AllCommunities(&m.identity.PublicKey) + communities, err := m.persistence.AllCommunities(&m.identity.PublicKey) + if err != nil { + return nil, err + } + + for _, c := range communities { + err = initializeCommunity(c) + if err != nil { + return nil, err + } + } + + return communities, nil } type KnownCommunitiesResponse struct { @@ -525,23 +537,83 @@ func (m *Manager) GetStoredDescriptionForCommunities(communityIDs []types.HexByt } func (m *Manager) Joined() ([]*Community, error) { - return m.persistence.JoinedCommunities(&m.identity.PublicKey) + communities, err := m.persistence.JoinedCommunities(&m.identity.PublicKey) + if err != nil { + return nil, err + } + + for _, c := range communities { + err = initializeCommunity(c) + if err != nil { + return nil, err + } + } + + return communities, nil } func (m *Manager) Spectated() ([]*Community, error) { - return m.persistence.SpectatedCommunities(&m.identity.PublicKey) + communities, err := m.persistence.SpectatedCommunities(&m.identity.PublicKey) + if err != nil { + return nil, err + } + + for _, c := range communities { + err = initializeCommunity(c) + if err != nil { + return nil, err + } + } + + return communities, nil } func (m *Manager) JoinedAndPendingCommunitiesWithRequests() ([]*Community, error) { - return m.persistence.JoinedAndPendingCommunitiesWithRequests(&m.identity.PublicKey) + communities, err := m.persistence.JoinedAndPendingCommunitiesWithRequests(&m.identity.PublicKey) + if err != nil { + return nil, err + } + + for _, c := range communities { + err = initializeCommunity(c) + if err != nil { + return nil, err + } + } + + return communities, nil } func (m *Manager) DeletedCommunities() ([]*Community, error) { - return m.persistence.DeletedCommunities(&m.identity.PublicKey) + communities, err := m.persistence.DeletedCommunities(&m.identity.PublicKey) + if err != nil { + return nil, err + } + + for _, c := range communities { + err = initializeCommunity(c) + if err != nil { + return nil, err + } + } + + return communities, nil } func (m *Manager) ControlledCommunities() ([]*Community, error) { - return m.persistence.CommunitiesWithPrivateKey(&m.identity.PublicKey) + communities, err := m.persistence.CommunitiesWithPrivateKey(&m.identity.PublicKey) + if err != nil { + return nil, err + } + + for _, c := range communities { + err = initializeCommunity(c) + if err != nil { + return nil, err + } + } + + return communities, nil } // CreateCommunity takes a description, generates an ID for it, saves it and return it @@ -953,7 +1025,7 @@ func (m *Manager) ExportCommunity(id types.HexBytes) (*ecdsa.PrivateKey, error) func (m *Manager) ImportCommunity(key *ecdsa.PrivateKey) (*Community, error) { communityID := crypto.CompressPubkey(&key.PublicKey) - community, err := m.persistence.GetByID(&m.identity.PublicKey, communityID) + community, err := m.GetByID(communityID) if err != nil { return nil, err } @@ -1238,11 +1310,14 @@ func (m *Manager) HandleCommunityDescriptionMessage(signer *ecdsa.PublicKey, des id := crypto.CompressPubkey(signer) - community, err := m.persistence.GetByID(&m.identity.PublicKey, id) + community, err := m.GetByID(id) if err != nil { return nil, err } + // Workaround for https://github.com/status-im/status-desktop/issues/12188 + HydrateChannelsMembers(types.EncodeHex(id), description) + if community == nil { config := Config{ CommunityDescription: description, @@ -1405,7 +1480,7 @@ func (m *Manager) HandleCommunityEventsMessage(signer *ecdsa.PublicKey, message return nil, err } - community, err := m.persistence.GetByID(&m.identity.PublicKey, eventsMessage.CommunityID) + community, err := m.GetByID(eventsMessage.CommunityID) if err != nil { return nil, err } @@ -1481,7 +1556,7 @@ func (m *Manager) HandleCommunityEventsMessageRejected(signer *ecdsa.PublicKey, } id := crypto.CompressPubkey(signer) - community, err := m.persistence.GetByID(&m.identity.PublicKey, id) + community, err := m.GetByID(id) if err != nil { return nil, err } @@ -2025,7 +2100,7 @@ func (m *Manager) isUserRejectedFromCommunity(signer *ecdsa.PublicKey, community } func (m *Manager) HandleCommunityCancelRequestToJoin(signer *ecdsa.PublicKey, request *protobuf.CommunityCancelRequestToJoin) (*RequestToJoin, error) { - community, err := m.persistence.GetByID(&m.identity.PublicKey, request.CommunityId) + community, err := m.GetByID(request.CommunityId) if err != nil { return nil, err } @@ -2201,7 +2276,7 @@ func (m *Manager) HandleCommunityRequestToJoin(signer *ecdsa.PublicKey, receiver } func (m *Manager) HandleCommunityEditSharedAddresses(signer *ecdsa.PublicKey, request *protobuf.CommunityEditSharedAddresses) error { - community, err := m.persistence.GetByID(&m.identity.PublicKey, request.CommunityId) + community, err := m.GetByID(request.CommunityId) if err != nil { return err } @@ -2752,7 +2827,7 @@ type CheckAllChannelsPermissionsResponse struct { func (m *Manager) HandleCommunityRequestToJoinResponse(signer *ecdsa.PublicKey, request *protobuf.CommunityRequestToJoinResponse) (*RequestToJoin, error) { pkString := common.PubkeyToHex(&m.identity.PublicKey) - community, err := m.persistence.GetByID(&m.identity.PublicKey, request.CommunityId) + community, err := m.GetByID(request.CommunityId) if err != nil { return nil, err } @@ -3113,6 +3188,19 @@ func (m *Manager) BanUserFromCommunity(request *requests.BanUserFromCommunity) ( return community, nil } +// Apply events to raw community +func initializeCommunity(community *Community) error { + err := community.updateCommunityDescriptionByEvents() + if err != nil { + return err + } + + // Workaround for https://github.com/status-im/status-desktop/issues/12188 + HydrateChannelsMembers(community.IDString(), community.config.CommunityDescription) + + return nil +} + func (m *Manager) GetByID(id []byte) (*Community, error) { community, err := m.persistence.GetByID(&m.identity.PublicKey, id) if err != nil { @@ -3122,7 +3210,7 @@ func (m *Manager) GetByID(id []byte) (*Community, error) { return nil, nil } - err = community.updateCommunityDescriptionByEvents() + err = initializeCommunity(community) if err != nil { return nil, err } @@ -3162,7 +3250,7 @@ func (m *Manager) SaveRequestToJoinAndCommunity(requestToJoin *RequestToJoin, co } func (m *Manager) CreateRequestToJoin(requester *ecdsa.PublicKey, request *requests.RequestToJoinCommunity) (*Community, *RequestToJoin, error) { - community, err := m.persistence.GetByID(&m.identity.PublicKey, request.CommunityID) + community, err := m.GetByID(request.CommunityID) if err != nil { return nil, nil, err }