diff --git a/protocol/communities_messenger_test.go b/protocol/communities_messenger_test.go index cc081b646..cf7ce53b8 100644 --- a/protocol/communities_messenger_test.go +++ b/protocol/communities_messenger_test.go @@ -48,7 +48,8 @@ const alicePassword = "qwerty" const bobPassword = "bob123" const adminAddress = "0x0100000000000000000000000000000000000000" -const aliceAddress = "0x0200000000000000000000000000000000000000" +const aliceAddress1 = "0x0200000000000000000000000000000000000000" +const aliceAddress2 = "0x0210000000000000000000000000000000000000" const bobAddress = "0x0300000000000000000000000000000000000000" type AccountManagerMock struct { @@ -110,9 +111,9 @@ func (s *MessengerCommunitiesSuite) SetupTest() { s.shh = gethbridge.NewGethWakuWrapper(shh) s.Require().NoError(shh.Start()) - s.admin = s.newMessengerWithWallet(adminPassword, adminAddress) - s.bob = s.newMessengerWithWallet(bobPassword, bobAddress) - s.alice = s.newMessengerWithWallet(alicePassword, aliceAddress) + s.admin = s.newMessengerWithWallet(adminPassword, []string{adminAddress}) + s.bob = s.newMessengerWithWallet(bobPassword, []string{bobAddress}) + s.alice = s.newMessengerWithWallet(alicePassword, []string{aliceAddress1, aliceAddress2}) _, err := s.admin.Start() s.Require().NoError(err) _, err = s.bob.Start() @@ -204,29 +205,35 @@ func (s *MessengerCommunitiesSuite) newMessenger(accountsManager account.Manager return s.newMessengerWithKey(s.shh, privateKey, accountsManager) } -func (s *MessengerCommunitiesSuite) newMessengerWithWallet(password string, walletAddress string) *Messenger { +func (s *MessengerCommunitiesSuite) newMessengerWithWallet(password string, walletAddresses []string) *Messenger { accountsManager := &AccountManagerMock{} accountsManager.AccountsMap = make(map[string]string) - accountsManager.AccountsMap[walletAddress] = types.EncodeHex(crypto.Keccak256([]byte(password))) + for _, walletAddress := range walletAddresses { + accountsManager.AccountsMap[walletAddress] = types.EncodeHex(crypto.Keccak256([]byte(password))) + } messenger := s.newMessenger(accountsManager) // add wallet account with keypair - kp := accounts.GetProfileKeypairForTest(false, true, false) - kp.Accounts[0].Address = types.HexToAddress(walletAddress) - err := messenger.settings.SaveOrUpdateKeypair(kp) - s.Require().NoError(err) + for _, walletAddress := range walletAddresses { + kp := accounts.GetProfileKeypairForTest(false, true, false) + kp.Accounts[0].Address = types.HexToAddress(walletAddress) + err := messenger.settings.SaveOrUpdateKeypair(kp) + s.Require().NoError(err) + } walletAccounts, err := messenger.settings.GetAccounts() s.Require().NoError(err) - s.Require().Len(walletAccounts, 1) - s.Require().Equal(walletAccounts[0].Type, accounts.AccountTypeGenerated) + s.Require().Len(walletAccounts, len(walletAddresses)) + for i := range walletAddresses { + s.Require().Equal(walletAccounts[i].Type, accounts.AccountTypeGenerated) + } return messenger } -func (s *MessengerCommunitiesSuite) requestToJoinCommunity(user *Messenger, communityID types.HexBytes, password string) (*MessengerResponse, error) { +func (s *MessengerCommunitiesSuite) requestToJoinCommunity(user *Messenger, communityID types.HexBytes, password string, addresses []string) (*MessengerResponse, error) { passwdHash := types.EncodeHex(crypto.Keccak256([]byte(password))) - request := &requests.RequestToJoinCommunity{CommunityID: communityID, Password: passwdHash} + request := &requests.RequestToJoinCommunity{CommunityID: communityID, Password: passwdHash, AddressesToReveal: addresses} return user.RequestToJoinCommunity(request) } @@ -262,7 +269,7 @@ func (s *MessengerCommunitiesSuite) TestCreateCommunity_WithoutDefaultChannel() } func (s *MessengerCommunitiesSuite) TestRetrieveCommunity() { - alice := s.newMessengerWithWallet(alicePassword, aliceAddress) + alice := s.newMessengerWithWallet(alicePassword, []string{aliceAddress1}) description := &requests.CreateCommunity{ Membership: protobuf.CommunityPermissions_NO_MEMBERSHIP, @@ -577,9 +584,9 @@ func (s *MessengerCommunitiesSuite) advertiseCommunityTo(community *communities. s.Require().NoError(err) } -func (s *MessengerCommunitiesSuite) joinCommunity(community *communities.Community, user *Messenger, password string) { +func (s *MessengerCommunitiesSuite) joinCommunityWithAddresses(community *communities.Community, user *Messenger, password string, addresses []string) { // Request to join the community - response, err := s.requestToJoinCommunity(user, community.ID(), password) + response, err := s.requestToJoinCommunity(user, community.ID(), password, addresses) s.Require().NoError(err) s.Require().NotNil(response) @@ -625,6 +632,10 @@ func (s *MessengerCommunitiesSuite) joinCommunity(community *communities.Communi s.Require().NoError(err) } +func (s *MessengerCommunitiesSuite) joinCommunity(community *communities.Community, user *Messenger, password string) { + s.joinCommunityWithAddresses(community, user, password, []string{}) +} + func (s *MessengerCommunitiesSuite) TestCommunityContactCodeAdvertisement() { // add bob's profile keypair bobProfileKp := accounts.GetProfileKeypairForTest(true, false, false) @@ -3709,12 +3720,14 @@ func (s *MessengerCommunitiesSuite) TestJoinedCommunityMembersSharedAddress() { for pubKey, member := range community.Members() { if pubKey != common.PubkeyToHex(&s.admin.identity.PublicKey) { - s.Require().Len(member.RevealedAccounts, 1) switch pubKey { case common.PubkeyToHex(&s.alice.identity.PublicKey): - s.Require().Equal(member.RevealedAccounts[0].Address, aliceAddress) + s.Require().Len(member.RevealedAccounts, 2) + s.Require().Equal(member.RevealedAccounts[0].Address, aliceAddress1) + s.Require().Equal(member.RevealedAccounts[1].Address, aliceAddress2) case common.PubkeyToHex(&s.bob.identity.PublicKey): + s.Require().Len(member.RevealedAccounts, 1) s.Require().Equal(member.RevealedAccounts[0].Address, bobAddress) default: s.Require().Fail("pubKey does not match expected keys") @@ -3722,3 +3735,28 @@ func (s *MessengerCommunitiesSuite) TestJoinedCommunityMembersSharedAddress() { } } } + +func (s *MessengerCommunitiesSuite) TestJoinedCommunityMembersSelectedSharedAddress() { + community := s.createCommunity() + s.advertiseCommunityTo(community, s.alice) + + s.joinCommunityWithAddresses(community, s.alice, alicePassword, []string{aliceAddress2}) + + community, err := s.admin.GetCommunityByID(community.ID()) + s.Require().NoError(err) + + s.Require().Equal(2, community.MembersCount()) + + for pubKey, member := range community.Members() { + if pubKey != common.PubkeyToHex(&s.admin.identity.PublicKey) { + s.Require().Len(member.RevealedAccounts, 1) + + switch pubKey { + case common.PubkeyToHex(&s.alice.identity.PublicKey): + s.Require().Equal(member.RevealedAccounts[0].Address, aliceAddress2) + default: + s.Require().Fail("pubKey does not match expected keys") + } + } + } +} diff --git a/protocol/messenger_communities.go b/protocol/messenger_communities.go index 0b6e59c5a..1d02e05d2 100644 --- a/protocol/messenger_communities.go +++ b/protocol/messenger_communities.go @@ -704,8 +704,22 @@ func (m *Messenger) RequestToJoinCommunity(request *requests.RequestToJoinCommun revealedAccounts := make(map[gethcommon.Address]*protobuf.RevealedAccount) revealedAddresses := make([]gethcommon.Address, 0) + containsAddress := func(addresses []string, targetAddress string) bool { + for _, address := range addresses { + if address == targetAddress { + return true + } + } + return false + } + for _, walletAccount := range walletAccounts { if !walletAccount.Chat && walletAccount.Type != accounts.AccountTypeWatch { + + if len(request.AddressesToReveal) > 0 && !containsAddress(request.AddressesToReveal, walletAccount.Address.Hex()) { + continue + } + verifiedAccount, err := m.accountsManager.GetVerifiedWalletAccount(m.settings, walletAccount.Address.Hex(), request.Password) if err != nil { return nil, err diff --git a/protocol/requests/request_to_join_community.go b/protocol/requests/request_to_join_community.go index 6fb4bacd4..2016540d2 100644 --- a/protocol/requests/request_to_join_community.go +++ b/protocol/requests/request_to_join_community.go @@ -7,17 +7,22 @@ import ( ) var ErrRequestToJoinCommunityInvalidCommunityID = errors.New("request-to-join-community: invalid community id") +var ErrRequestToJoinCommunityMissingPassword = errors.New("request-to-join-community: password is necessary when sending a list of addresses") type RequestToJoinCommunity struct { - CommunityID types.HexBytes `json:"communityId"` - ENSName string `json:"ensName"` - Password string `json:"password"` + CommunityID types.HexBytes `json:"communityId"` + ENSName string `json:"ensName"` + Password string `json:"password"` + AddressesToReveal []string `json:"addressesToReveal"` } func (j *RequestToJoinCommunity) Validate() error { if len(j.CommunityID) == 0 { return ErrRequestToJoinCommunityInvalidCommunityID } + if len(j.AddressesToReveal) > 0 && j.Password == "" { + return ErrRequestToJoinCommunityMissingPassword + } return nil }