chore(communities)_: reject outdated community descriptions

Prevent the inclusion of CommunityDescription with an outdated clock in
MessengerResponse to avoid false-positives in tests and reduce redundant
data exchange between status-go and clients.
This commit is contained in:
Patryk Osmaczko 2024-06-10 16:20:21 +02:00 committed by osmaczko
parent dbed69d155
commit 27934a4e1f
5 changed files with 71 additions and 6 deletions

View File

@ -1130,11 +1130,9 @@ func (o *Community) UpdateCommunityDescription(description *protobuf.CommunityDe
return nil, err
}
response := o.emptyCommunityChanges()
// Enables processing of identical clocks. Identical descriptions may be reprocessed upon subsequent receipt of the previously missing encryption key.
if description.Clock < o.config.CommunityDescription.Clock {
return response, nil
return nil, ErrInvalidCommunityDescriptionClockOutdated
}
originCommunity := o.CreateDeepCopy()
@ -1146,6 +1144,8 @@ func (o *Community) UpdateCommunityDescription(description *protobuf.CommunityDe
o.setControlNode(newControlNode)
}
response := o.emptyCommunityChanges()
// We only calculate changes if we joined/spectated the community or we requested access, otherwise not interested
if o.config.Joined || o.config.Spectated || o.config.RequestedToJoinAt > 0 {
response = EvaluateCommunityChanges(originCommunity, o)

View File

@ -567,8 +567,8 @@ func (s *CommunitySuite) TestHandleCommunityDescription() {
name: "updated version but lower clock",
description: s.oldCommunityDescription,
signer: signer,
changes: buildChanges,
err: nil,
changes: func(c *Community) *CommunityChanges { return nil },
err: ErrInvalidCommunityDescriptionClockOutdated,
},
{
name: "removed member from org",

View File

@ -12,6 +12,7 @@ var ErrChatAlreadyExists = errors.New("chat already exists")
var ErrCategoryAlreadyExists = errors.New("category already exists")
var ErrCantRequestAccess = errors.New("can't request access")
var ErrInvalidCommunityDescription = errors.New("invalid community description")
var ErrInvalidCommunityDescriptionClockOutdated = errors.New("invalid community description outdated clock")
var ErrInvalidCommunityDescriptionNoOrgPermissions = errors.New("invalid community description no org permissions")
var ErrInvalidCommunityDescriptionNoChatPermissions = errors.New("invalid community description no chat permissions")
var ErrInvalidCommunityDescriptionUnknownChatAccess = errors.New("invalid community description unknown chat access")

View File

@ -4554,3 +4554,66 @@ func (s *MessengerCommunitiesSuite) TestAliceDidNotProcessOutdatedCommunityReque
err = s.alice.HandleCommunityRequestToJoinResponse(state, requestToJoinResponse, nil)
s.Require().NoError(err)
}
func (s *MessengerCommunitiesSuite) TestIgnoreOutdatedCommunityDescription() {
community, _ := s.createCommunity()
wrappedDescription1, err := community.ToProtocolMessageBytes()
s.Require().NoError(err)
signer, description1, err := communities.UnwrapCommunityDescriptionMessage(wrappedDescription1)
s.Require().NoError(err)
_, err = community.AddMember(&s.alice.identity.PublicKey, []protobuf.CommunityMember_Roles{})
s.Require().NoError(err)
wrappedDescription2, err := community.ToProtocolMessageBytes()
s.Require().NoError(err)
_, description2, err := communities.UnwrapCommunityDescriptionMessage(wrappedDescription2)
s.Require().NoError(err)
_, err = community.AddMember(&s.bob.identity.PublicKey, []protobuf.CommunityMember_Roles{})
s.Require().NoError(err)
wrappedDescription3, err := community.ToProtocolMessageBytes()
s.Require().NoError(err)
_, description3, err := communities.UnwrapCommunityDescriptionMessage(wrappedDescription3)
s.Require().NoError(err)
s.Require().Less(description1.Clock, description2.Clock)
s.Require().Less(description2.Clock, description3.Clock)
// Handle first community description
{
messageState := s.bob.buildMessageState()
err = s.bob.handleCommunityDescription(messageState, signer, description1, wrappedDescription1, nil, nil)
s.Require().NoError(err)
s.Require().Len(messageState.Response.Communities(), 1)
s.Require().Equal(description1.Clock, messageState.Response.Communities()[0].Clock())
}
// Handle third community description
{
messageState := s.bob.buildMessageState()
err = s.bob.handleCommunityDescription(messageState, signer, description3, wrappedDescription3, nil, nil)
s.Require().NoError(err)
s.Require().Len(messageState.Response.Communities(), 1)
s.Require().Equal(description3.Clock, messageState.Response.Communities()[0].Clock())
communityFromDB, err := s.bob.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
s.Require().Equal(description3.Clock, communityFromDB.Clock())
s.Require().Len(communityFromDB.Members(), 3)
}
// Handle second (out of order) community description
// It should be ignored
{
messageState := s.bob.buildMessageState()
err = s.bob.handleCommunityDescription(messageState, signer, description2, wrappedDescription2, nil, nil)
s.Require().Len(messageState.Response.Communities(), 0)
s.Require().Len(messageState.Response.CommunityChanges, 0)
s.Require().ErrorIs(err, communities.ErrInvalidCommunityDescriptionClockOutdated)
communityFromDB, err := s.bob.communitiesManager.GetByID(community.ID())
s.Require().NoError(err)
s.Require().Equal(description3.Clock, communityFromDB.Clock())
s.Require().Len(communityFromDB.Members(), 3)
}
}

View File

@ -3693,7 +3693,8 @@ func (m *Messenger) handleSyncInstallationCommunity(messageState *ReceivedMessag
// TODO: handle shard
err = m.handleCommunityDescription(messageState, signer, &cd, syncCommunity.Description, signer, nil)
if err != nil {
// Even if the Description is outdated we should proceed in order to sync settings and joined state
if err != nil && err != communities.ErrInvalidCommunityDescriptionClockOutdated {
logger.Debug("m.handleCommunityDescription error", zap.Error(err))
return err
}