Skip to content

Commit e304fe3

Browse files
committed
chore: enable community rekey loop
1 parent a38b34a commit e304fe3

File tree

5 files changed

+97
-136
lines changed

5 files changed

+97
-136
lines changed

protocol/communities/community.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,6 +1547,10 @@ func (o *Community) HasTokenPermissions() bool {
15471547
return len(o.tokenPermissions()) > 0
15481548
}
15491549

1550+
func (o *Community) ChannelEncrypted(channelID string) bool {
1551+
return o.ChannelHasTokenPermissions(o.IDString() + channelID)
1552+
}
1553+
15501554
func (o *Community) ChannelHasTokenPermissions(chatID string) bool {
15511555
o.mutex.Lock()
15521556
defer o.mutex.Unlock()

protocol/communities/manager.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3311,7 +3311,8 @@ func (m *Manager) IsChannelEncrypted(communityID string, chatID string) (bool, e
33113311
return false, err
33123312
}
33133313

3314-
return community.ChannelHasTokenPermissions(chatID), nil
3314+
channelID := strings.TrimPrefix(chatID, communityID)
3315+
return community.ChannelEncrypted(channelID), nil
33153316
}
33163317

33173318
func (m *Manager) ShouldHandleSyncCommunity(community *protobuf.SyncInstallationCommunity) (bool, error) {

protocol/communities_key_distributor.go

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212

1313
type CommunitiesKeyDistributor interface {
1414
Distribute(community *communities.Community, keyActions *communities.EncryptionKeyActions) error
15-
Rekey(community *communities.Community) error
1615
}
1716

1817
type CommunitiesKeyDistributorImpl struct {
@@ -41,32 +40,6 @@ func (ckd *CommunitiesKeyDistributorImpl) Distribute(community *communities.Comm
4140
return nil
4241
}
4342

44-
func (ckd *CommunitiesKeyDistributorImpl) Rekey(community *communities.Community) error {
45-
if !community.IsControlNode() {
46-
return communities.ErrNotControlNode
47-
}
48-
49-
err := ckd.distributeKey(community, community.ID(), &communities.EncryptionKeyAction{
50-
ActionType: communities.EncryptionKeyRekey,
51-
Members: community.Members(),
52-
})
53-
if err != nil {
54-
return err
55-
}
56-
57-
for channelID, channel := range community.Chats() {
58-
err := ckd.distributeKey(community, []byte(community.IDString()+channelID), &communities.EncryptionKeyAction{
59-
ActionType: communities.EncryptionKeyRekey,
60-
Members: channel.Members,
61-
})
62-
if err != nil {
63-
return err
64-
}
65-
}
66-
67-
return nil
68-
}
69-
7043
func (ckd *CommunitiesKeyDistributorImpl) distributeKey(community *communities.Community, hashRatchetGroupID []byte, keyAction *communities.EncryptionKeyAction) error {
7144
pubkeys := make([]*ecdsa.PublicKey, len(keyAction.Members))
7245
i := 0
@@ -77,15 +50,7 @@ func (ckd *CommunitiesKeyDistributorImpl) distributeKey(community *communities.C
7750

7851
switch keyAction.ActionType {
7952
case communities.EncryptionKeyAdd:
80-
_, err := ckd.encryptor.GenerateHashRatchetKey(hashRatchetGroupID)
81-
if err != nil {
82-
return err
83-
}
84-
85-
err = ckd.sendKeyExchangeMessage(community, hashRatchetGroupID, pubkeys, common.KeyExMsgReuse)
86-
if err != nil {
87-
return err
88-
}
53+
fallthrough
8954

9055
case communities.EncryptionKeyRekey:
9156
err := ckd.sendKeyExchangeMessage(community, hashRatchetGroupID, pubkeys, common.KeyExMsgRekey)

protocol/communities_messenger_test.go

Lines changed: 42 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ func (s *MessengerCommunitiesSuite) SetupTest() {
6363
s.bob = s.newMessenger()
6464
s.alice = s.newMessenger()
6565

66-
enableRekeyLoop = true
6766
s.owner.communitiesManager.RekeyInterval = 50 * time.Millisecond
6867

6968
_, err := s.owner.Start()
@@ -3352,28 +3351,12 @@ func (t *testPermissionChecker) CheckPermissions(permissions []*communities.Comm
33523351
}
33533352

33543353
func (s *MessengerCommunitiesSuite) TestStartCommunityRekeyLoop() {
3355-
// Create a new community
3356-
response, err := s.owner.CreateCommunity(
3357-
&requests.CreateCommunity{
3358-
Membership: protobuf.CommunityPermissions_AUTO_ACCEPT,
3359-
Name: "status",
3360-
Color: "#57a7e5",
3361-
Description: "status community description",
3362-
},
3363-
true,
3364-
)
3365-
s.Require().NoError(err)
3366-
s.Require().NotNil(response)
3367-
s.Require().Len(response.Communities(), 1)
3368-
3369-
// Check community is present in the DB and has default values we care about
3370-
c, err := s.owner.GetCommunityByID(response.Communities()[0].ID())
3371-
s.Require().NoError(err)
3372-
s.Require().False(c.Encrypted())
3373-
// TODO some check that there are no keys for the community. Alt for s.Require().Zero(c.RekeyedAt().Unix())
3354+
community, chat := s.createCommunity()
3355+
s.Require().False(community.Encrypted())
33743356

3375-
_, err = s.owner.CreateCommunityTokenPermission(&requests.CreateCommunityTokenPermission{
3376-
CommunityID: c.ID(),
3357+
// Add community permission
3358+
_, err := s.owner.CreateCommunityTokenPermission(&requests.CreateCommunityTokenPermission{
3359+
CommunityID: community.ID(),
33773360
Type: protobuf.CommunityTokenPermission_BECOME_MEMBER,
33783361
TokenCriteria: []*protobuf.TokenCriteria{{
33793362
ContractAddresses: map[uint64]string{3: "0x933"},
@@ -3386,37 +3369,57 @@ func (s *MessengerCommunitiesSuite) TestStartCommunityRekeyLoop() {
33863369
})
33873370
s.Require().NoError(err)
33883371

3389-
c, err = s.owner.GetCommunityByID(c.ID())
3372+
// Add channel permission
3373+
response, err := s.owner.CreateCommunityTokenPermission(&requests.CreateCommunityTokenPermission{
3374+
CommunityID: community.ID(),
3375+
Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL,
3376+
TokenCriteria: []*protobuf.TokenCriteria{
3377+
&protobuf.TokenCriteria{
3378+
ContractAddresses: map[uint64]string{3: "0x933"},
3379+
Type: protobuf.CommunityTokenType_ERC20,
3380+
Symbol: "STT",
3381+
Name: "Status Test Token",
3382+
Amount: "10",
3383+
Decimals: 18,
3384+
},
3385+
},
3386+
ChatIds: []string{chat.ID},
3387+
})
33903388
s.Require().NoError(err)
3391-
s.Require().True(c.Encrypted())
3392-
3393-
s.advertiseCommunityTo(c, s.owner, s.bob)
3394-
s.advertiseCommunityTo(c, s.owner, s.alice)
3389+
s.Require().Len(response.Communities(), 1)
3390+
community = response.Communities()[0]
3391+
s.Require().True(community.Encrypted())
3392+
s.Require().True(community.ChannelEncrypted(chat.CommunityChatID()))
33953393

33963394
s.owner.communitiesManager.PermissionChecker = &testPermissionChecker{}
33973395

3398-
s.joinCommunity(c, s.owner, s.bob)
3399-
s.joinCommunity(c, s.owner, s.alice)
3396+
s.advertiseCommunityTo(community, s.owner, s.bob)
3397+
s.advertiseCommunityTo(community, s.owner, s.alice)
3398+
s.joinCommunity(community, s.owner, s.bob)
3399+
s.joinCommunity(community, s.owner, s.alice)
34003400

3401-
// Check the Alice and Bob are members of the community
3402-
c, err = s.owner.GetCommunityByID(c.ID())
3401+
// Check keys in the database
3402+
communityKeys, err := s.owner.sender.GetKeysForGroup(community.ID())
34033403
s.Require().NoError(err)
3404-
s.Require().True(c.HasMember(&s.alice.identity.PublicKey))
3405-
s.Require().True(c.HasMember(&s.bob.identity.PublicKey))
3404+
communityKeyCount := len(communityKeys)
34063405

3407-
// Check the keys in the database
3408-
keys, err := s.owner.sender.GetKeysForGroup(c.ID())
3406+
channelKeys, err := s.owner.sender.GetKeysForGroup([]byte(chat.ID))
34093407
s.Require().NoError(err)
3410-
keyCount := len(keys)
3408+
channelKeyCount := len(channelKeys)
34113409

34123410
// Check that rekeying is occurring by counting the number of keyIDs in the encryptor's DB
34133411
// This test could be flaky, as the rekey function may not be finished before RekeyInterval * 2 has passed
34143412
for i := 0; i < 5; i++ {
34153413
time.Sleep(s.owner.communitiesManager.RekeyInterval * 2)
3416-
keys, err = s.owner.sender.GetKeysForGroup(c.ID())
3414+
communityKeys, err = s.owner.sender.GetKeysForGroup(community.ID())
3415+
s.Require().NoError(err)
3416+
s.Require().Greater(len(communityKeys), communityKeyCount)
3417+
communityKeyCount = len(communityKeys)
3418+
3419+
channelKeys, err = s.owner.sender.GetKeysForGroup([]byte(chat.ID))
34173420
s.Require().NoError(err)
3418-
s.Require().Greater(len(keys), keyCount)
3419-
keyCount = len(keys)
3421+
s.Require().Greater(len(channelKeys), channelKeyCount)
3422+
channelKeyCount = len(channelKeys)
34203423
}
34213424
}
34223425

protocol/messenger_communities.go

Lines changed: 48 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ import (
3737
"github.com/status-im/status-go/protocol/communities"
3838
"github.com/status-im/status-go/protocol/communities/token"
3939
"github.com/status-im/status-go/protocol/discord"
40-
"github.com/status-im/status-go/protocol/encryption"
4140
"github.com/status-im/status-go/protocol/protobuf"
4241
"github.com/status-im/status-go/protocol/requests"
4342
"github.com/status-im/status-go/protocol/transport"
@@ -511,6 +510,10 @@ func (m *Messenger) Communities() ([]*communities.Community, error) {
511510
return m.communitiesManager.All()
512511
}
513512

513+
func (m *Messenger) ControlledCommunities() ([]*communities.Community, error) {
514+
return m.communitiesManager.Controlled()
515+
}
516+
514517
func (m *Messenger) JoinedCommunities() ([]*communities.Community, error) {
515518
return m.communitiesManager.Joined()
516519
}
@@ -2302,9 +2305,6 @@ func (m *Messenger) ImportCommunity(ctx context.Context, key *ecdsa.PrivateKey)
23022305
return nil, err
23032306
}
23042307

2305-
// TODO Init hash ratchet for community
2306-
_, err = m.encryptor.GenerateHashRatchetKey(community.ID())
2307-
23082308
if err != nil {
23092309
return nil, err
23102310
}
@@ -5733,33 +5733,8 @@ func chunkAttachmentsByByteSize(slice []*protobuf.DiscordMessageAttachment, maxF
57335733
return chunks
57345734
}
57355735

5736-
// GetCurrentKeyForGroup returns the latest key timestampID belonging to a key group
5737-
func (m *Messenger) GetCurrentKeyForGroup(groupID []byte) (*encryption.HashRatchetKeyCompatibility, error) {
5738-
return m.sender.GetCurrentKeyForGroup(groupID)
5739-
}
5740-
5741-
// RekeyCommunity takes a communities.Community.config.ID and triggers a force rekey event for that community
5742-
func (m *Messenger) RekeyCommunity(cID types.HexBytes) error {
5743-
// Get the community as the member list could have changed
5744-
c, err := m.GetCommunityByID(cID)
5745-
if err != nil {
5746-
return err
5747-
}
5748-
5749-
// RekeyCommunity
5750-
return m.communitiesKeyDistributor.Rekey(c)
5751-
}
5752-
5753-
// NOTE: disabling rekey loop as it rekeys too aggressively
5754-
5755-
var enableRekeyLoop = false
5756-
57575736
// startCommunityRekeyLoop creates a 5-minute ticker and starts a routine that attempts to rekey every community every tick
57585737
func (m *Messenger) startCommunityRekeyLoop() {
5759-
if !enableRekeyLoop {
5760-
return
5761-
}
5762-
57635738
logger := m.logger.Named("CommunityRekeyLoop")
57645739
var d time.Duration
57655740
if m.communitiesManager.RekeyInterval != 0 {
@@ -5777,7 +5752,7 @@ func (m *Messenger) startCommunityRekeyLoop() {
57775752
for {
57785753
select {
57795754
case <-ticker.C:
5780-
m.rekeyAllCommunities(logger)
5755+
m.rekeyCommunities(logger)
57815756
case <-m.quit:
57825757
ticker.Stop()
57835758
logger.Debug("CommunityRekeyLoop stopped")
@@ -5787,47 +5762,60 @@ func (m *Messenger) startCommunityRekeyLoop() {
57875762
}()
57885763
}
57895764

5790-
// rekeyAllCommunities attempts to rekey every community in persistence.
5791-
// A community will be rekeyed if it meets all the following criteria:
5792-
// - Community.IsAdmin()
5793-
// - Community.Encrypted()
5794-
// - Community.RekeyedAt().Add(rki).Before(time.Now()) where rki is a defined rekey interval
5795-
func (m *Messenger) rekeyAllCommunities(logger *zap.Logger) {
5796-
// Determine the rekey interval, if the value is not set as a property of m.communitiesManager
5797-
// default to one hour
5765+
// rekeyCommunities loops over controlled communities and rekeys if rekey interval elapsed
5766+
func (m *Messenger) rekeyCommunities(logger *zap.Logger) {
57985767
// TODO in future have a community level rki rather than a global rki
5799-
/*
5800-
var rki time.Duration
5801-
if m.communitiesManager.RekeyInterval == 0 {
5802-
rki = time.Hour
5803-
} else {
5804-
rki = m.communitiesManager.RekeyInterval
5805-
}*/
5768+
var rekeyInterval time.Duration
5769+
if m.communitiesManager.RekeyInterval == 0 {
5770+
rekeyInterval = 48 * time.Hour
5771+
} else {
5772+
rekeyInterval = m.communitiesManager.RekeyInterval
5773+
}
58065774

5807-
// Get and loop over all communities in persistence
5808-
cs, err := m.Communities()
5775+
shouldRekey := func(hashRatchetGroupID []byte) bool {
5776+
key, err := m.sender.GetCurrentKeyForGroup(hashRatchetGroupID)
5777+
if err != nil {
5778+
logger.Error("failed to get current hash ratchet key", zap.Error(err))
5779+
return false
5780+
}
5781+
5782+
keyDistributedAt := time.UnixMilli(int64(key.Timestamp))
5783+
return time.Now().After(keyDistributedAt.Add(rekeyInterval))
5784+
}
5785+
5786+
controlledCommunities, err := m.ControlledCommunities()
58095787
if err != nil {
58105788
logger.Error("error getting communities", zap.Error(err))
58115789
return
58125790
}
5813-
for _, c := range cs {
5814-
if err != nil {
5815-
logger.Error("error getting current keyTimestampID for community", zap.Error(err), zap.Binary("community ID", c.ID()))
5816-
continue
5791+
5792+
for _, c := range controlledCommunities {
5793+
keyActions := &communities.EncryptionKeyActions{
5794+
CommunityKeyAction: communities.EncryptionKeyAction{},
5795+
ChannelKeysActions: map[string]communities.EncryptionKeyAction{},
58175796
}
58185797

5819-
// TODO add functionality to encryptor.go that compares the timestamps and returns a bool
5820-
// c.RekeyedAt().Add(rki).Before(time.Now())
5821-
// keyTimestampID + rki < time.Now()
5822-
// Just using the vars that will be used later
5798+
if c.Encrypted() && shouldRekey(c.ID()) {
5799+
keyActions.CommunityKeyAction = communities.EncryptionKeyAction{
5800+
ActionType: communities.EncryptionKeyRekey,
5801+
Members: c.Members(),
5802+
}
5803+
}
58235804

5824-
if c.IsControlNode() && c.Encrypted() { // && c.RekeyedAt().Add(rki).Before(time.Now())
5825-
err := m.RekeyCommunity(c.ID())
5826-
if err != nil {
5827-
logger.Error("error sending rekey message", zap.Error(err), zap.Binary("community ID", c.ID()))
5828-
continue
5805+
for channelID, channel := range c.Chats() {
5806+
if c.ChannelEncrypted(channelID) && shouldRekey([]byte(c.IDString()+channelID)) {
5807+
keyActions.ChannelKeysActions[channelID] = communities.EncryptionKeyAction{
5808+
ActionType: communities.EncryptionKeyRekey,
5809+
Members: channel.Members,
5810+
}
58295811
}
58305812
}
5813+
5814+
err = m.communitiesKeyDistributor.Distribute(c, keyActions)
5815+
if err != nil {
5816+
logger.Error("failed to rekey community", zap.Error(err), zap.String("community ID", c.IDString()))
5817+
continue
5818+
}
58315819
}
58325820
}
58335821

0 commit comments

Comments
 (0)