From 58a9557c58c1b2408664b9b9459649bfd6773bdd Mon Sep 17 00:00:00 2001 From: Mykhailo Prakhov Date: Wed, 7 Aug 2024 17:57:02 +0200 Subject: [PATCH] fix: reject handling requests to join without revealed accounts (#5549) * fix(requestToJoin)_: request to join must have revealed addresses with signature * fix(tests)_: fix tests * chore(tests)_: increase tests timeout --- _assets/scripts/run_unit_tests.sh | 2 +- api/messenger_raw_message_resend_test.go | 472 ------------------ protocol/communities/community.go | 7 +- protocol/communities/community_test.go | 33 +- protocol/communities/manager.go | 21 +- protocol/communities/persistence.go | 15 +- ...nities_events_eventual_consistency_test.go | 41 +- ...events_owner_without_community_key_test.go | 114 +---- .../communities_events_token_master_test.go | 116 +---- protocol/communities_events_utils_test.go | 267 ++++------ protocol/communities_messenger_admin_test.go | 120 ++--- .../communities_messenger_helpers_test.go | 92 +++- ...es_messenger_shared_member_address_test.go | 324 +++++------- .../communities_messenger_signers_test.go | 125 +---- protocol/communities_messenger_test.go | 133 ++--- ...munities_messenger_test_suite_base_test.go | 140 ++++++ ...nities_messenger_token_permissions_test.go | 77 +-- protocol/messenger_activity_center_test.go | 38 +- protocol/messenger_communities.go | 2 +- .../messenger_communities_sharding_test.go | 29 +- ...senger_delete_message_for_everyone_test.go | 47 +- protocol/messenger_delete_messages_test.go | 69 +-- protocol/messenger_handler.go | 13 +- protocol/messenger_offline_test.go | 30 +- protocol/messenger_peersyncing_test.go | 22 +- protocol/messenger_profile_showcase_test.go | 103 ++-- protocol/messenger_raw_message_resend_test.go | 200 ++++++++ protocol/messenger_send_images_album_test.go | 55 +- protocol/messenger_storenode_comunity_test.go | 3 +- .../messenger_sync_activity_center_test.go | 61 ++- protocol/push_notification_test.go | 4 +- .../requests/request_to_join_community.go | 12 +- 32 files changed, 1137 insertions(+), 1650 deletions(-) delete mode 100644 api/messenger_raw_message_resend_test.go create mode 100644 protocol/communities_messenger_test_suite_base_test.go create mode 100644 protocol/messenger_raw_message_resend_test.go diff --git a/_assets/scripts/run_unit_tests.sh b/_assets/scripts/run_unit_tests.sh index d4d2296f9..5360a8a87 100755 --- a/_assets/scripts/run_unit_tests.sh +++ b/_assets/scripts/run_unit_tests.sh @@ -24,7 +24,7 @@ if [[ -z "${UNIT_TEST_COUNT}" ]]; then fi UNIT_TEST_PACKAGE_TIMEOUT="3m" -UNIT_TEST_PACKAGE_TIMEOUT_EXTENDED="36m" +UNIT_TEST_PACKAGE_TIMEOUT_EXTENDED="45m" redirect_stdout() { output_file=$1 diff --git a/api/messenger_raw_message_resend_test.go b/api/messenger_raw_message_resend_test.go deleted file mode 100644 index b0c07b4dd..000000000 --- a/api/messenger_raw_message_resend_test.go +++ /dev/null @@ -1,472 +0,0 @@ -package api - -import ( - "context" - "errors" - "path/filepath" - "testing" - "time" - - "github.com/cenkalti/backoff/v3" - "github.com/golang/protobuf/proto" - "go.uber.org/zap" - - "github.com/status-im/status-go/eth-node/types" - m_common "github.com/status-im/status-go/multiaccounts/common" - "github.com/status-im/status-go/params" - "github.com/status-im/status-go/protocol" - "github.com/status-im/status-go/protocol/common" - "github.com/status-im/status-go/protocol/common/shard" - "github.com/status-im/status-go/protocol/communities" - "github.com/status-im/status-go/protocol/protobuf" - "github.com/status-im/status-go/protocol/requests" - "github.com/status-im/status-go/protocol/tt" - "github.com/status-im/status-go/services/utils" - "github.com/status-im/status-go/signal" - tutils "github.com/status-im/status-go/t/utils" - "github.com/status-im/status-go/wakuv2" - - "github.com/stretchr/testify/suite" -) - -type MessengerRawMessageResendTest struct { - suite.Suite - logger *zap.Logger - aliceBackend *GethStatusBackend - bobBackend *GethStatusBackend - aliceMessenger *protocol.Messenger - bobMessenger *protocol.Messenger - // add exchangeBootNode to ensure alice and bob can find each other. - // If relying on in the fleet, the test will likely be flaky - exchangeBootNode *wakuv2.Waku -} - -func TestMessengerRawMessageResendTestSuite(t *testing.T) { - suite.Run(t, new(MessengerRawMessageResendTest)) -} - -func (s *MessengerRawMessageResendTest) SetupTest() { - tutils.Init() - - var err error - s.logger, err = zap.NewDevelopment() - s.Require().NoError(err) - - signal.SetMobileSignalHandler(nil) - - exchangeNodeConfig := &wakuv2.Config{ - Port: 0, - EnableDiscV5: true, - EnablePeerExchangeServer: true, - ClusterID: 16, - DefaultShardPubsubTopic: shard.DefaultShardPubsubTopic(), - EnableStoreConfirmationForMessagesSent: false, - } - s.exchangeBootNode, err = wakuv2.New(nil, "", exchangeNodeConfig, s.logger.Named("pxServerNode"), nil, nil, nil, nil) - s.Require().NoError(err) - s.Require().NoError(s.exchangeBootNode.Start()) - - s.createAliceBobBackendAndLogin() - community := s.createTestCommunity(s.aliceMessenger, protobuf.CommunityPermissions_MANUAL_ACCEPT) - s.addMutualContact() - advertiseCommunityToUserOldWay(&s.Suite, community, s.aliceMessenger, s.bobMessenger) - requestBob := &requests.RequestToJoinCommunity{ - CommunityID: community.ID(), - } - joinOnRequestCommunity(&s.Suite, community, s.aliceMessenger, s.bobMessenger, requestBob) -} - -func (s *MessengerRawMessageResendTest) TearDownTest() { - // Initialize a map to keep track of the operation status. - operationStatus := map[string]bool{ - "Alice Logout": false, - "Bob Logout": false, - "Boot Node Stop": false, - } - - done := make(chan string, 3) // Buffered channel to receive the names of the completed operations - errs := make(chan error, 3) // Channel to receive errs from operations - - // Asynchronously perform operations and report completion or errs. - go func() { - err := s.aliceBackend.Logout() - if err != nil { - errs <- err - } - done <- "Alice Logout" - }() - - go func() { - err := s.bobBackend.Logout() - if err != nil { - errs <- err - } - done <- "Bob Logout" - }() - - go func() { - err := s.exchangeBootNode.Stop() - if err != nil { - errs <- err - } - done <- "Boot Node Stop" - }() - - timeout := time.After(30 * time.Second) - operationsCompleted := 0 - - for operationsCompleted < 3 { - select { - case opName := <-done: - s.T().Logf("%s completed successfully.", opName) - operationStatus[opName] = true - operationsCompleted++ - case err := <-errs: - s.Require().NoError(err) - case <-timeout: - // If a timeout occurs, check which operations have not reported completion. - s.T().Errorf("Timeout occurred, the following operations did not complete in time:") - for opName, completed := range operationStatus { - if !completed { - s.T().Errorf("%s is still pending.", opName) - } - } - s.T().FailNow() - } - } -} - -func (s *MessengerRawMessageResendTest) createAliceBobBackendAndLogin() { - pxServerNodeENR, err := s.exchangeBootNode.GetNodeENRString() - s.Require().NoError(err) - // we don't support multiple logger instances, so just share the log dir - shareLogDir := filepath.Join(s.T().TempDir(), "logs") - s.T().Logf("shareLogDir: %s", shareLogDir) - s.createBackendAndLogin(&s.aliceBackend, &s.aliceMessenger, "alice66", pxServerNodeENR, shareLogDir) - s.createBackendAndLogin(&s.bobBackend, &s.bobMessenger, "bob66", pxServerNodeENR, shareLogDir) - - aliceWaku := s.aliceBackend.StatusNode().WakuV2Service() - bobWaku := s.bobBackend.StatusNode().WakuV2Service() - // NOTE: default MaxInterval is 10s, which is too short for the test - // TODO(frank) figure out why it takes so long for the peers to know each other - err = tt.RetryWithBackOff(func() error { - if len(aliceWaku.Peerstore().Addrs(bobWaku.PeerID())) > 0 { - return nil - } - s.T().Logf("alice don't know bob's addresses") - return errors.New("alice don't know bob's addresses") - }, func(b *backoff.ExponentialBackOff) { b.MaxInterval = 20 * time.Second }) - s.Require().NoError(err) - err = tt.RetryWithBackOff(func() error { - if len(bobWaku.Peerstore().Addrs(aliceWaku.PeerID())) > 0 { - return nil - } - s.T().Logf("bob don't know alice's addresses") - return errors.New("bob don't know alice's addresses") - }, func(b *backoff.ExponentialBackOff) { b.MaxInterval = 20 * time.Second }) - s.Require().NoError(err) -} - -func (s *MessengerRawMessageResendTest) createBackendAndLogin(backend **GethStatusBackend, messenger **protocol.Messenger, displayName, pxServerNodeENR, shareLogDir string) { - *backend = NewGethStatusBackend() - rootDir := filepath.Join(s.T().TempDir()) - s.T().Logf("%s rootDir: %s", displayName, rootDir) - createAccountRequest := s.setCreateAccountRequest(displayName, rootDir, shareLogDir) - _, err := (*backend).CreateAccountAndLogin(createAccountRequest, - params.WithDiscV5BootstrapNodes([]string{pxServerNodeENR}), - // override fleet nodes - params.WithWakuNodes([]string{})) - s.Require().NoError(err) - *messenger = (*backend).Messenger() - s.Require().NotNil(messenger) - _, err = (*messenger).Start() - s.Require().NoError(err) -} - -func (s *MessengerRawMessageResendTest) setCreateAccountRequest(displayName, rootDataDir, logFilePath string) *requests.CreateAccount { - nameServer := "1.1.1.1" - verifyENSContractAddress := "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e" - verifyTransactionChainID := int64(1) - verifyURL := "https://eth-archival.rpc.grove.city/v1/3ef2018191814b7e1009b8d9" - logLevel := "DEBUG" - networkID := uint64(1) - password := "qwerty" - return &requests.CreateAccount{ - UpstreamConfig: verifyURL, - WakuV2Nameserver: &nameServer, - VerifyENSContractAddress: &verifyENSContractAddress, - RootDataDir: rootDataDir, - Password: password, - DisplayName: displayName, - LogEnabled: true, - VerifyTransactionChainID: &verifyTransactionChainID, - VerifyTransactionURL: &verifyURL, - VerifyENSURL: &verifyURL, - LogLevel: &logLevel, - LogFilePath: logFilePath, - NetworkID: &networkID, - CustomizationColor: string(m_common.CustomizationColorPrimary), - } -} - -func (s *MessengerRawMessageResendTest) waitForMessageSent(messageID string) { - err := tt.RetryWithBackOff(func() error { - rawMessage, err := s.bobMessenger.RawMessageByID(messageID) - s.Require().NoError(err) - s.Require().NotNil(rawMessage) - if rawMessage.SendCount > 0 { - return nil - } - return errors.New("raw message should be sent finally") - }) - s.Require().NoError(err) -} - -// TestMessageSent tests if ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN is in state `sent` without resending -func (s *MessengerRawMessageResendTest) TestMessageSent() { - ids, err := s.bobMessenger.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN) - s.Require().NoError(err) - s.Require().Len(ids, 1) - - s.waitForMessageSent(ids[0]) -} - -// TestMessageResend tests if ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN is resent -func (s *MessengerRawMessageResendTest) TestMessageResend() { - ids, err := s.bobMessenger.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN) - s.Require().NoError(err) - s.Require().Len(ids, 1) - // wait for Sent status for already sent message to make sure that sent message was delivered - // before testing resend - s.waitForMessageSent(ids[0]) - - rawMessage, err := s.bobMessenger.RawMessageByID(ids[0]) - s.Require().NoError(err) - s.Require().NotNil(rawMessage) - - s.Require().NoError(s.bobMessenger.UpdateRawMessageSent(rawMessage.ID, false)) - s.Require().NoError(s.bobMessenger.UpdateRawMessageLastSent(rawMessage.ID, 0)) - - err = tt.RetryWithBackOff(func() error { - rawMessage, err := s.bobMessenger.RawMessageByID(ids[0]) - s.Require().NoError(err) - s.Require().NotNil(rawMessage) - if rawMessage.SendCount < 2 { - return errors.New("message ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN was not resent yet") - } - return nil - }) - s.Require().NoError(err) - - waitOnMessengerResponse(&s.Suite, func(r *protocol.MessengerResponse) error { - if len(r.RequestsToJoinCommunity()) > 0 { - return nil - } - return errors.New("community request to join not received") - }, s.aliceMessenger) -} - -func (s *MessengerRawMessageResendTest) TestInvalidRawMessageToWatchDoesNotProduceResendLoop() { - ids, err := s.bobMessenger.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN) - s.Require().NoError(err) - s.Require().Len(ids, 1) - - s.waitForMessageSent(ids[0]) - - rawMessage, err := s.bobMessenger.RawMessageByID(ids[0]) - s.Require().NoError(err) - - requestToJoinProto := &protobuf.CommunityRequestToJoin{} - err = proto.Unmarshal(rawMessage.Payload, requestToJoinProto) - s.Require().NoError(err) - - requestToJoinProto.DisplayName = "invalid_ID" - payload, err := proto.Marshal(requestToJoinProto) - s.Require().NoError(err) - rawMessage.Payload = payload - - _, err = s.bobMessenger.AddRawMessageToWatch(rawMessage) - s.Require().Error(err, common.ErrModifiedRawMessage) - - // simulate storing msg with modified payload, but old message ID - _, err = s.bobMessenger.UpsertRawMessageToWatch(rawMessage) - s.Require().NoError(err) - s.Require().NoError(s.bobMessenger.UpdateRawMessageSent(rawMessage.ID, false)) - s.Require().NoError(s.bobMessenger.UpdateRawMessageLastSent(rawMessage.ID, 0)) - - // check counter increased for invalid message to escape the loop - err = tt.RetryWithBackOff(func() error { - rawMessage, err := s.bobMessenger.RawMessageByID(ids[0]) - s.Require().NoError(err) - s.Require().NotNil(rawMessage) - if rawMessage.SendCount < 2 { - return errors.New("message ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN was not resent yet") - } - return nil - }) - s.Require().NoError(err) -} - -// To be removed in https://github.com/status-im/status-go/issues/4437 -func advertiseCommunityToUserOldWay(s *suite.Suite, community *communities.Community, alice *protocol.Messenger, bob *protocol.Messenger) { - chat := protocol.CreateOneToOneChat(bob.IdentityPublicKeyString(), bob.IdentityPublicKey(), bob.GetTransport()) - - inputMessage := common.NewMessage() - inputMessage.ChatId = chat.ID - inputMessage.Text = "some text" - inputMessage.CommunityID = community.IDString() - - err := alice.SaveChat(chat) - s.Require().NoError(err) - _, err = alice.SendChatMessage(context.Background(), inputMessage) - s.Require().NoError(err) - - // Ensure community is received - response, err := protocol.WaitOnMessengerResponse( - bob, - func(r *protocol.MessengerResponse) bool { - return len(r.Communities()) > 0 - }, - "bob did not receive community request to join", - ) - s.Require().NoError(err) - communityInResponse := response.Communities()[0] - s.Require().Equal(community.ID(), communityInResponse.ID()) -} - -func (s *MessengerRawMessageResendTest) addMutualContact() { - bobPubkey := s.bobMessenger.IdentityPublicKeyCompressed() - bobZQ3ID, err := utils.SerializePublicKey(bobPubkey) - s.Require().NoError(err) - mr, err := s.aliceMessenger.AddContact(context.Background(), &requests.AddContact{ - ID: bobZQ3ID, - DisplayName: "bob666", - }) - s.Require().NoError(err) - s.Require().Len(mr.Messages(), 2) - - var contactRequest *common.Message - waitOnMessengerResponse(&s.Suite, func(r *protocol.MessengerResponse) error { - for _, m := range r.Messages() { - if m.GetContentType() == protobuf.ChatMessage_CONTACT_REQUEST { - contactRequest = m - return nil - } - } - return errors.New("contact request not received") - }, s.bobMessenger) - - mr, err = s.bobMessenger.AcceptContactRequest(context.Background(), &requests.AcceptContactRequest{ - ID: types.FromHex(contactRequest.ID), - }) - s.Require().NoError(err) - s.Require().Len(mr.Contacts, 1) - - waitOnMessengerResponse(&s.Suite, func(r *protocol.MessengerResponse) error { - if len(r.Contacts) > 0 { - return nil - } - return errors.New("contact accepted not received") - }, s.aliceMessenger) -} - -type MessageResponseValidator func(*protocol.MessengerResponse) error - -func waitOnMessengerResponse(s *suite.Suite, fnWait MessageResponseValidator, user *protocol.Messenger) { - _, err := protocol.WaitOnMessengerResponse( - user, - func(r *protocol.MessengerResponse) bool { - err := fnWait(r) - if err != nil { - s.T().Logf("response error: %s", err.Error()) - } - return err == nil - }, - "MessengerResponse data not received", - ) - s.Require().NoError(err) -} - -func requestToJoinCommunity(s *suite.Suite, controlNode *protocol.Messenger, user *protocol.Messenger, request *requests.RequestToJoinCommunity) types.HexBytes { - response, err := user.RequestToJoinCommunity(request) - s.Require().NoError(err) - s.Require().NotNil(response) - s.Require().Len(response.RequestsToJoinCommunity(), 1) - - requestToJoin := response.RequestsToJoinCommunity()[0] - s.Require().Equal(requestToJoin.PublicKey, user.IdentityPublicKeyString()) - - _, err = protocol.WaitOnMessengerResponse( - controlNode, - func(r *protocol.MessengerResponse) bool { - if len(r.RequestsToJoinCommunity()) == 0 { - return false - } - - for _, resultRequest := range r.RequestsToJoinCommunity() { - if resultRequest.PublicKey == user.IdentityPublicKeyString() { - return true - } - } - return false - }, - "control node did not receive community request to join", - ) - s.Require().NoError(err) - - return requestToJoin.ID -} - -func joinOnRequestCommunity(s *suite.Suite, community *communities.Community, controlNode *protocol.Messenger, user *protocol.Messenger, request *requests.RequestToJoinCommunity) { - // Request to join the community - requestToJoinID := requestToJoinCommunity(s, controlNode, user, request) - - // accept join request - acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: requestToJoinID} - response, err := controlNode.AcceptRequestToJoinCommunity(acceptRequestToJoin) - s.Require().NoError(err) - s.Require().NotNil(response) - - updatedCommunity := response.Communities()[0] - s.Require().NotNil(updatedCommunity) - s.Require().True(updatedCommunity.HasMember(user.IdentityPublicKey())) - - // receive request to join response - _, err = protocol.WaitOnMessengerResponse( - user, - func(r *protocol.MessengerResponse) bool { - return len(r.Communities()) > 0 && r.Communities()[0].HasMember(user.IdentityPublicKey()) - }, - "user did not receive request to join response", - ) - s.Require().NoError(err) - - userCommunity, err := user.GetCommunityByID(community.ID()) - s.Require().NoError(err) - s.Require().True(userCommunity.HasMember(user.IdentityPublicKey())) - - _, err = protocol.WaitOnMessengerResponse( - controlNode, - func(r *protocol.MessengerResponse) bool { - return len(r.Communities()) > 0 && r.Communities()[0].HasMember(user.IdentityPublicKey()) - }, - "control node did not receive request to join response", - ) - s.Require().NoError(err) -} - -func (s *MessengerRawMessageResendTest) createTestCommunity(controlNode *protocol.Messenger, membershipType protobuf.CommunityPermissions_Access) *communities.Community { - description := &requests.CreateCommunity{ - Membership: membershipType, - Name: "status", - Color: "#ffffff", - Description: "status community description", - PinMessageAllMembersEnabled: false, - } - response, err := controlNode.CreateCommunity(description, true) - s.Require().NoError(err) - s.Require().NotNil(response) - s.Require().Len(response.Communities(), 1) - s.Require().Len(response.Chats(), 1) - return response.Communities()[0] -} diff --git a/protocol/communities/community.go b/protocol/communities/community.go index 50dd6e76e..f0f5dd2e5 100644 --- a/protocol/communities/community.go +++ b/protocol/communities/community.go @@ -1273,10 +1273,9 @@ func (o *Community) ValidateRequestToJoin(signer *ecdsa.PublicKey, request *prot defer o.mutex.Unlock() if o.IsControlNode() { - // TODO: Enable this once mobile supports revealed addresses. - // if len(request.RevealedAccounts) == 0 { - // return errors.New("no addresses revealed") - // } + if len(request.RevealedAccounts) == 0 { + return errors.New("no addresses revealed") + } } else if o.HasPermissionToSendCommunityEvents() { if o.AutoAccept() { return errors.New("auto-accept community requests can only be processed by the control node") diff --git a/protocol/communities/community_test.go b/protocol/communities/community_test.go index 3581fd9ef..5037e67e1 100644 --- a/protocol/communities/community_test.go +++ b/protocol/communities/community_test.go @@ -339,28 +339,37 @@ func (s *CommunitySuite) TestValidateRequestToJoin() { signer := &key.PublicKey + revealedAccounts := []*protobuf.RevealedAccount{ + &protobuf.RevealedAccount{ + Address: "0x0100000000000000000000000000000000000000"}, + } + request := &protobuf.CommunityRequestToJoin{ - EnsName: "donvanvliet.stateofus.eth", - CommunityId: s.communityID, - Clock: uint64(time.Now().Unix()), + EnsName: "donvanvliet.stateofus.eth", + CommunityId: s.communityID, + Clock: uint64(time.Now().Unix()), + RevealedAccounts: revealedAccounts, } requestWithChatID := &protobuf.CommunityRequestToJoin{ - EnsName: "donvanvliet.stateofus.eth", - CommunityId: s.communityID, - ChatId: testChatID1, - Clock: uint64(time.Now().Unix()), + EnsName: "donvanvliet.stateofus.eth", + CommunityId: s.communityID, + ChatId: testChatID1, + Clock: uint64(time.Now().Unix()), + RevealedAccounts: revealedAccounts, } requestWithoutENS := &protobuf.CommunityRequestToJoin{ - CommunityId: s.communityID, - Clock: uint64(time.Now().Unix()), + CommunityId: s.communityID, + Clock: uint64(time.Now().Unix()), + RevealedAccounts: revealedAccounts, } requestWithChatWithoutENS := &protobuf.CommunityRequestToJoin{ - CommunityId: s.communityID, - ChatId: testChatID1, - Clock: uint64(time.Now().Unix()), + CommunityId: s.communityID, + ChatId: testChatID1, + Clock: uint64(time.Now().Unix()), + RevealedAccounts: revealedAccounts, } // MATRIX diff --git a/protocol/communities/manager.go b/protocol/communities/manager.go index 2f63c0b1f..86f2bc6fb 100644 --- a/protocol/communities/manager.go +++ b/protocol/communities/manager.go @@ -2665,9 +2665,11 @@ func (m *Manager) DeletePendingRequestToJoin(request *RequestToJoin) error { return err } - err = m.saveAndPublish(community) - if err != nil { - return err + if community.IsControlNode() { + err = m.saveAndPublish(community) + if err != nil { + return err + } } return nil @@ -3646,10 +3648,6 @@ func (m *Manager) GetMagnetlinkMessageClock(communityID types.HexBytes) (uint64, return m.persistence.GetMagnetlinkMessageClock(communityID) } -func (m *Manager) GetRequestToJoinIDByPkAndCommunityID(pk *ecdsa.PublicKey, communityID []byte) ([]byte, error) { - return m.persistence.GetRequestToJoinIDByPkAndCommunityID(common.PubkeyToHex(pk), communityID) -} - func (m *Manager) GetCommunityRequestToJoinClock(pk *ecdsa.PublicKey, communityID string) (uint64, error) { communityIDBytes, err := types.DecodeHex(communityID) if err != nil { @@ -4836,6 +4834,10 @@ func (m *Manager) handleCommunityEvents(community *Community) error { } func (m *Manager) ShareRequestsToJoinWithPrivilegedMembers(community *Community, privilegedMembers map[protobuf.CommunityMember_Roles][]*ecdsa.PublicKey) error { + if len(privilegedMembers) == 0 { + return nil + } + requestsToJoin, err := m.GetCommunityRequestsToJoinWithRevealedAddresses(community.ID()) if err != nil { return err @@ -4844,6 +4846,11 @@ func (m *Manager) ShareRequestsToJoinWithPrivilegedMembers(community *Community, var syncRequestsWithoutRevealedAccounts []*protobuf.SyncCommunityRequestsToJoin var syncRequestsWithRevealedAccounts []*protobuf.SyncCommunityRequestsToJoin for _, request := range requestsToJoin { + // if shared request to join is not approved by control node - do not send revealed accounts. + // revealed accounts will be sent as soon as control node accepts request to join + if request.State != RequestToJoinStateAccepted { + request.RevealedAccounts = []*protobuf.RevealedAccount{} + } syncRequestsWithRevealedAccounts = append(syncRequestsWithRevealedAccounts, request.ToSyncProtobuf()) requestProtoWithoutAccounts := request.ToSyncProtobuf() requestProtoWithoutAccounts.RevealedAccounts = []*protobuf.RevealedAccount{} diff --git a/protocol/communities/persistence.go b/protocol/communities/persistence.go index 745a32dad..84e20645e 100644 --- a/protocol/communities/persistence.go +++ b/protocol/communities/persistence.go @@ -799,6 +799,11 @@ func (p *Persistence) SetRequestToJoinState(pk string, communityID []byte, state func (p *Persistence) DeletePendingRequestToJoin(id []byte) error { _, err := p.db.Exec(`DELETE FROM communities_requests_to_join WHERE id = ?`, id) + if err != nil { + return err + } + _, err = p.db.Exec(`DELETE FROM communities_requests_to_join_revealed_addresses WHERE request_id = ?`, id) + return err } @@ -858,16 +863,6 @@ func (p *Persistence) GetRequestToJoinByPkAndCommunityID(pk string, communityID return request, nil } -func (p *Persistence) GetRequestToJoinIDByPkAndCommunityID(pk string, communityID []byte) ([]byte, error) { - var id []byte - err := p.db.QueryRow(`SELECT id FROM communities_requests_to_join WHERE community_id = ? AND public_key = ?`, communityID, pk).Scan(&id) - if err != nil && err != sql.ErrNoRows { - return nil, err - } - - return id, nil -} - func (p *Persistence) GetRequestToJoinByPk(pk string, communityID []byte, state RequestToJoinState) (*RequestToJoin, error) { request := &RequestToJoin{} err := p.db.QueryRow(`SELECT id,public_key,clock,ens_name,customization_color,chat_id,community_id,state, share_future_addresses FROM communities_requests_to_join WHERE public_key = ? AND community_id = ? AND state = ?`, pk, communityID, state).Scan(&request.ID, &request.PublicKey, &request.Clock, &request.ENSName, &request.CustomizationColor, &request.ChatID, &request.CommunityID, &request.State, &request.ShareFutureAddresses) diff --git a/protocol/communities_events_eventual_consistency_test.go b/protocol/communities_events_eventual_consistency_test.go index a98674300..e6576285e 100644 --- a/protocol/communities_events_eventual_consistency_test.go +++ b/protocol/communities_events_eventual_consistency_test.go @@ -18,7 +18,7 @@ func TestCommunityEventsEventualConsistencySuite(t *testing.T) { } type CommunityEventsEventualConsistencySuite struct { - AdminCommunityEventsSuiteBase + EventSenderCommunityEventsSuiteBase messagesOrderController *MessagesOrderController } @@ -26,7 +26,8 @@ type CommunityEventsEventualConsistencySuite struct { func (s *CommunityEventsEventualConsistencySuite) SetupTest() { s.logger = tt.MustCreateTestLogger() s.collectiblesServiceMock = &CollectiblesServiceMock{} - + s.accountsTestData = make(map[string][]string) + s.accountsPasswords = make(map[string]string) s.mockedBalances = createMockedWalletBalance(&s.Suite) config := waku.DefaultConfig @@ -41,24 +42,19 @@ func (s *CommunityEventsEventualConsistencySuite) SetupTest() { s.messagesOrderController.Start(wakuWrapper.SubscribePostEvents()) s.owner = s.newMessenger("", []string{}) - s.admin = s.newMessenger(accountPassword, []string{eventsSenderAccountAddress}) + s.eventSender = s.newMessenger(accountPassword, []string{eventsSenderAccountAddress}) s.alice = s.newMessenger(accountPassword, []string{aliceAccountAddress}) _, err = s.owner.Start() s.Require().NoError(err) - _, err = s.admin.Start() + _, err = s.eventSender.Start() s.Require().NoError(err) _, err = s.alice.Start() s.Require().NoError(err) } -func (s *CommunityEventsEventualConsistencySuite) TearDownTest() { - s.AdminCommunityEventsSuiteBase.TearDownTest() - s.messagesOrderController.Stop() -} - func (s *CommunityEventsEventualConsistencySuite) newMessenger(password string, walletAddresses []string) *Messenger { - return newTestCommunitiesMessenger(&s.Suite, s.shh, testCommunitiesMessengerConfig{ + messenger := newTestCommunitiesMessenger(&s.Suite, s.shh, testCommunitiesMessengerConfig{ testMessengerConfig: testMessengerConfig{ logger: s.logger, messagesOrderController: s.messagesOrderController, @@ -68,6 +64,16 @@ func (s *CommunityEventsEventualConsistencySuite) newMessenger(password string, mockedBalances: &s.mockedBalances, collectiblesService: s.collectiblesServiceMock, }) + + publicKey := messenger.IdentityPublicKeyString() + s.accountsTestData[publicKey] = walletAddresses + s.accountsPasswords[publicKey] = password + return messenger +} + +func (s *CommunityEventsEventualConsistencySuite) TearDownTest() { + s.EventSenderCommunityEventsSuiteBase.TearDownTest() + s.messagesOrderController.Stop() } type requestToJoinActionType int @@ -82,13 +88,18 @@ func (s *CommunityEventsEventualConsistencySuite) testRequestsToJoin(actions []r s.Require().True(community.IsControlNode()) // set up additional user that will send request to join - user := s.newMessenger("", []string{}) + user := s.newMessenger("somePassword", []string{"0x0123400000000000000000000000000000000000"}) s.SetupAdditionalMessengers([]*Messenger{user}) advertiseCommunityToUserOldWay(&s.Suite, community, s.owner, user) // user sends request to join - requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID(), ENSName: "testName"} + userPPk := user.IdentityPublicKeyString() + userPassword, exists := s.accountsPasswords[userPPk] + s.Require().True(exists) + userAccounts, exists := s.accountsTestData[userPPk] + s.Require().True(exists) + requestToJoin := createRequestToJoinCommunity(&s.Suite, community.ID(), user, userPassword, userAccounts) response, err := user.RequestToJoinCommunity(requestToJoin) s.Require().NoError(err) s.Require().NotNil(response) @@ -107,7 +118,7 @@ func (s *CommunityEventsEventualConsistencySuite) testRequestsToJoin(actions []r // admin receives request to join response, err = WaitOnMessengerResponse( - s.admin, + s.eventSender, checkRequestToJoin, "event sender did not receive community request to join", ) @@ -118,12 +129,12 @@ func (s *CommunityEventsEventualConsistencySuite) testRequestsToJoin(actions []r switch action { case requestToJoinAccept: acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: sentRequest.ID} - _, err = s.admin.AcceptRequestToJoinCommunity(acceptRequestToJoin) + _, err = s.eventSender.AcceptRequestToJoinCommunity(acceptRequestToJoin) s.Require().NoError(err) case requestToJoinReject: rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: sentRequest.ID} - _, err = s.admin.DeclineRequestToJoinCommunity(rejectRequestToJoin) + _, err = s.eventSender.DeclineRequestToJoinCommunity(rejectRequestToJoin) s.Require().NoError(err) } } diff --git a/protocol/communities_events_owner_without_community_key_test.go b/protocol/communities_events_owner_without_community_key_test.go index 4113d766a..9c956bcb8 100644 --- a/protocol/communities_events_owner_without_community_key_test.go +++ b/protocol/communities_events_owner_without_community_key_test.go @@ -4,18 +4,10 @@ import ( "testing" "github.com/stretchr/testify/suite" - "go.uber.org/zap" - gethcommon "github.com/ethereum/go-ethereum/common" - hexutil "github.com/ethereum/go-ethereum/common/hexutil" - - gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" - "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/protocol/common" "github.com/status-im/status-go/protocol/communities/token" "github.com/status-im/status-go/protocol/protobuf" - "github.com/status-im/status-go/protocol/tt" - "github.com/status-im/status-go/waku" ) func TestOwnerWithoutCommunityKeyCommunityEventsSuite(t *testing.T) { @@ -23,94 +15,7 @@ func TestOwnerWithoutCommunityKeyCommunityEventsSuite(t *testing.T) { } type OwnerWithoutCommunityKeyCommunityEventsSuite struct { - suite.Suite - controlNode *Messenger - ownerWithoutCommunityKey *Messenger - alice *Messenger - // If one wants to send messages between different instances of Messenger, - // a single Waku service should be shared. - shh types.Waku - logger *zap.Logger - mockedBalances map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big // chainID, account, token, balance - collectiblesServiceMock *CollectiblesServiceMock - - additionalEventSenders []*Messenger -} - -func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) GetControlNode() *Messenger { - return s.controlNode -} - -func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) GetEventSender() *Messenger { - return s.ownerWithoutCommunityKey -} - -func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) GetMember() *Messenger { - return s.alice -} - -func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) GetSuite() *suite.Suite { - return &s.Suite -} - -func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) GetCollectiblesServiceMock() *CollectiblesServiceMock { - return s.collectiblesServiceMock -} - -func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) SetupTest() { - s.logger = tt.MustCreateTestLogger() - s.collectiblesServiceMock = &CollectiblesServiceMock{} - - s.mockedBalances = createMockedWalletBalance(&s.Suite) - - config := waku.DefaultConfig - config.MinimumAcceptedPoW = 0 - shh := waku.New(&config, s.logger) - s.shh = gethbridge.NewGethWakuWrapper(shh) - s.Require().NoError(shh.Start()) - - s.controlNode = s.newMessenger("", []string{}) - s.ownerWithoutCommunityKey = s.newMessenger("qwerty", []string{eventsSenderAccountAddress}) - s.alice = s.newMessenger("", []string{}) - _, err := s.controlNode.Start() - s.Require().NoError(err) - _, err = s.ownerWithoutCommunityKey.Start() - s.Require().NoError(err) - _, err = s.alice.Start() - s.Require().NoError(err) -} - -func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TearDownTest() { - TearDownMessenger(&s.Suite, s.controlNode) - TearDownMessenger(&s.Suite, s.ownerWithoutCommunityKey) - TearDownMessenger(&s.Suite, s.alice) - - for _, m := range s.additionalEventSenders { - TearDownMessenger(&s.Suite, m) - } - s.additionalEventSenders = nil - - _ = s.logger.Sync() -} - -func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) SetupAdditionalMessengers(messengers []*Messenger) { - for _, m := range messengers { - s.additionalEventSenders = append(s.additionalEventSenders, m) - _, err := m.Start() - s.Require().NoError(err) - } -} - -func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) newMessenger(password string, walletAddresses []string) *Messenger { - return newTestCommunitiesMessenger(&s.Suite, s.shh, testCommunitiesMessengerConfig{ - testMessengerConfig: testMessengerConfig{ - logger: s.logger, - }, - password: password, - walletAddresses: walletAddresses, - mockedBalances: &s.mockedBalances, - collectiblesService: s.collectiblesServiceMock, - }) + EventSenderCommunityEventsSuiteBase } func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerEditCommunityDescription() { @@ -140,11 +45,11 @@ func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerCreateEditDelete } func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders() { - additionalOwner := s.newMessenger("", []string{}) + additionalOwner := s.newMessenger(accountPassword, []string{eventsSenderAccountAddress}) community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER, []*Messenger{additionalOwner}) // set up additional user that will send request to join - user := s.newMessenger("", []string{}) + user := s.newMessenger("somePassword", []string{"0x0123400000000000000000000000000000000000"}) s.SetupAdditionalMessengers([]*Messenger{user}) testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders(s, community, user, additionalOwner) @@ -154,18 +59,18 @@ func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerAcceptMemberRequ community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER, []*Messenger{}) // set up additional user that will send request to join - user := s.newMessenger("", []string{}) + user := s.newMessenger("somePassword", []string{"0x0123400000000000000000000000000000000000"}) s.SetupAdditionalMessengers([]*Messenger{user}) testAcceptMemberRequestToJoin(s, community, user) } func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerRejectMemberRequestToJoinResponseSharedWithOtherEventSenders() { - additionalOwner := s.newMessenger("", []string{}) + additionalOwner := s.newMessenger(accountPassword, []string{eventsSenderAccountAddress}) community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER, []*Messenger{additionalOwner}) // set up additional user that will send request to join - user := s.newMessenger("", []string{}) + user := s.newMessenger("somePassword", []string{"0x0123400000000000000000000000000000000000"}) s.SetupAdditionalMessengers([]*Messenger{user}) testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders(s, community, user, additionalOwner) @@ -175,20 +80,21 @@ func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerRejectMemberRequ community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER, []*Messenger{}) // set up additional user that will send request to join - user := s.newMessenger("", []string{}) + user := s.newMessenger("somePassword", []string{"0x0123400000000000000000000000000000000000"}) s.SetupAdditionalMessengers([]*Messenger{user}) testRejectMemberRequestToJoin(s, community, user) } func (s *OwnerWithoutCommunityKeyCommunityEventsSuite) TestOwnerControlNodeHandlesMultipleEventSenderRequestToJoinDecisions() { + // TODO: test fixed, need to fix the code as it contains error s.T().Skip("flaky test") - additionalOwner := s.newMessenger("", []string{}) + additionalOwner := s.newMessenger(accountPassword, []string{eventsSenderAccountAddress}) community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_OWNER, []*Messenger{additionalOwner}) // set up additional user that will send request to join - user := s.newMessenger("", []string{}) + user := s.newMessenger("somePassword", []string{"0x0123400000000000000000000000000000000000"}) testControlNodeHandlesMultipleEventSenderRequestToJoinDecisions(s, community, user, additionalOwner) } diff --git a/protocol/communities_events_token_master_test.go b/protocol/communities_events_token_master_test.go index 21a1b73d2..d6c9355f6 100644 --- a/protocol/communities_events_token_master_test.go +++ b/protocol/communities_events_token_master_test.go @@ -4,18 +4,10 @@ import ( "testing" "github.com/stretchr/testify/suite" - "go.uber.org/zap" - gethcommon "github.com/ethereum/go-ethereum/common" - hexutil "github.com/ethereum/go-ethereum/common/hexutil" - - gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" - "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/protocol/common" "github.com/status-im/status-go/protocol/communities/token" "github.com/status-im/status-go/protocol/protobuf" - "github.com/status-im/status-go/protocol/tt" - "github.com/status-im/status-go/waku" ) func TestTokenMasterCommunityEventsSuite(t *testing.T) { @@ -23,95 +15,7 @@ func TestTokenMasterCommunityEventsSuite(t *testing.T) { } type TokenMasterCommunityEventsSuite struct { - suite.Suite - controlNode *Messenger - tokenMaster *Messenger - alice *Messenger - // If one wants to send messages between different instances of Messenger, - // a single Waku service should be shared. - shh types.Waku - logger *zap.Logger - mockedBalances map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big // chainID, account, token, balance - collectiblesServiceMock *CollectiblesServiceMock - - additionalEventSenders []*Messenger -} - -func (s *TokenMasterCommunityEventsSuite) GetControlNode() *Messenger { - return s.controlNode -} - -func (s *TokenMasterCommunityEventsSuite) GetEventSender() *Messenger { - return s.tokenMaster -} - -func (s *TokenMasterCommunityEventsSuite) GetMember() *Messenger { - return s.alice -} - -func (s *TokenMasterCommunityEventsSuite) GetSuite() *suite.Suite { - return &s.Suite -} - -func (s *TokenMasterCommunityEventsSuite) GetCollectiblesServiceMock() *CollectiblesServiceMock { - return s.collectiblesServiceMock -} - -func (s *TokenMasterCommunityEventsSuite) SetupTest() { - s.logger = tt.MustCreateTestLogger() - s.collectiblesServiceMock = &CollectiblesServiceMock{} - - s.mockedBalances = createMockedWalletBalance(&s.Suite) - - config := waku.DefaultConfig - config.MinimumAcceptedPoW = 0 - shh := waku.New(&config, s.logger) - s.shh = gethbridge.NewGethWakuWrapper(shh) - s.Require().NoError(shh.Start()) - - s.controlNode = s.newMessenger("", []string{}) - s.tokenMaster = s.newMessenger(accountPassword, []string{eventsSenderAccountAddress}) - s.alice = s.newMessenger(accountPassword, []string{aliceAccountAddress}) - _, err := s.controlNode.Start() - s.Require().NoError(err) - _, err = s.tokenMaster.Start() - s.Require().NoError(err) - _, err = s.alice.Start() - s.Require().NoError(err) - -} - -func (s *TokenMasterCommunityEventsSuite) TearDownTest() { - TearDownMessenger(&s.Suite, s.controlNode) - TearDownMessenger(&s.Suite, s.tokenMaster) - TearDownMessenger(&s.Suite, s.alice) - - for _, m := range s.additionalEventSenders { - TearDownMessenger(&s.Suite, m) - } - s.additionalEventSenders = nil - - _ = s.logger.Sync() -} - -func (s *TokenMasterCommunityEventsSuite) SetupAdditionalMessengers(messengers []*Messenger) { - for _, m := range messengers { - s.additionalEventSenders = append(s.additionalEventSenders, m) - _, err := m.Start() - s.Require().NoError(err) - } -} - -func (s *TokenMasterCommunityEventsSuite) newMessenger(password string, walletAddresses []string) *Messenger { - return newTestCommunitiesMessenger(&s.Suite, s.shh, testCommunitiesMessengerConfig{ - testMessengerConfig: testMessengerConfig{ - logger: s.logger, - }, - password: password, - walletAddresses: walletAddresses, - mockedBalances: &s.mockedBalances, - collectiblesService: s.collectiblesServiceMock, - }) + EventSenderCommunityEventsSuiteBase } func (s *TokenMasterCommunityEventsSuite) TestTokenMasterEditCommunityDescription() { @@ -166,7 +70,7 @@ func (s *TokenMasterCommunityEventsSuite) TestTokenMasterCannotDeleteBecomeToken func (s *TokenMasterCommunityEventsSuite) TestTokenMasterAcceptMemberRequestToJoin() { community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{}) // set up additional user that will send request to join - user := s.newMessenger("", []string{}) + user := s.newMessenger("somePassword", []string{"0x0123400000000000000000000000000000000000"}) s.SetupAdditionalMessengers([]*Messenger{user}) testAcceptMemberRequestToJoin(s, community, user) @@ -177,7 +81,7 @@ func (s *TokenMasterCommunityEventsSuite) TestTokenMasterAcceptMemberRequestToJo community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{additionalTokenMaster}) // set up additional user that will send request to join - user := s.newMessenger("", []string{}) + user := s.newMessenger("somePassword", []string{"0x0123400000000000000000000000000000000000"}) s.SetupAdditionalMessengers([]*Messenger{user}) testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders(s, community, user, additionalTokenMaster) @@ -187,7 +91,7 @@ func (s *TokenMasterCommunityEventsSuite) TestTokenMasterRejectMemberRequestToJo additionalTokenMaster := s.newMessenger("qwerty", []string{eventsSenderAccountAddress}) community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{additionalTokenMaster}) // set up additional user that will send request to join - user := s.newMessenger("", []string{}) + user := s.newMessenger("somePassword", []string{"0x0123400000000000000000000000000000000000"}) s.SetupAdditionalMessengers([]*Messenger{user}) testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders(s, community, user, additionalTokenMaster) @@ -196,7 +100,7 @@ func (s *TokenMasterCommunityEventsSuite) TestTokenMasterRejectMemberRequestToJo func (s *TokenMasterCommunityEventsSuite) TestTokenMasterRejectMemberRequestToJoin() { community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{}) // set up additional user that will send request to join - user := s.newMessenger("", []string{}) + user := s.newMessenger("somePassword", []string{"0x0123400000000000000000000000000000000000"}) s.SetupAdditionalMessengers([]*Messenger{user}) testRejectMemberRequestToJoin(s, community, user) @@ -209,7 +113,7 @@ func (s *TokenMasterCommunityEventsSuite) TestTokenMasterControlNodeHandlesMulti community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{additionalTokenMaster}) // set up additional user that will send request to join - user := s.newMessenger("", []string{}) + user := s.newMessenger("somePassword", []string{"0x0123400000000000000000000000000000000000"}) testControlNodeHandlesMultipleEventSenderRequestToJoinDecisions(s, community, user, additionalTokenMaster) } @@ -294,8 +198,8 @@ func (s *TokenMasterCommunityEventsSuite) TestMemberReceiveTokenMasterEventsWhen } func (s *TokenMasterCommunityEventsSuite) TestJoinedTokenMasterReceiveRequestsToJoinWithRevealedAccounts() { - s.T().Skip("flaky test") - community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{}) + // event sender will receive privileged role during permission creation + community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_NONE, []*Messenger{}) // set up additional user (bob) that will send request to join bob := s.newMessenger(accountPassword, []string{bobAccountAddress}) @@ -304,12 +208,10 @@ func (s *TokenMasterCommunityEventsSuite) TestJoinedTokenMasterReceiveRequestsTo newPrivilegedUser := s.newMessenger(accountPassword, []string{eventsSenderAccountAddress}) s.SetupAdditionalMessengers([]*Messenger{bob, newPrivilegedUser}) - testJoinedPrivilegedMemberReceiveRequestsToJoin(s, community, bob, newPrivilegedUser, protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER) } func (s *TokenMasterCommunityEventsSuite) TestReceiveRequestsToJoinWithRevealedAccountsAfterGettingTokenMasterRole() { - s.T().Skip("flaky test") // set up additional user (bob) that will send request to join bob := s.newMessenger(accountPassword, []string{bobAccountAddress}) s.SetupAdditionalMessengers([]*Messenger{bob}) @@ -320,7 +222,7 @@ func (s *TokenMasterCommunityEventsSuite) TestTokenMasterAcceptsRequestToJoinAft community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_TOKEN_MASTER, []*Messenger{}) // set up additional user that will send request to join - user := s.newMessenger("", []string{}) + user := s.newMessenger("somePassword", []string{"0x0123400000000000000000000000000000000000"}) s.SetupAdditionalMessengers([]*Messenger{user}) testPrivilegedMemberAcceptsRequestToJoinAfterMemberLeave(s, community, user) } diff --git a/protocol/communities_events_utils_test.go b/protocol/communities_events_utils_test.go index c25ed2f69..31f1f02b6 100644 --- a/protocol/communities_events_utils_test.go +++ b/protocol/communities_events_utils_test.go @@ -28,14 +28,16 @@ type CommunityEventsTestsInterface interface { GetSuite() *suite.Suite GetCollectiblesServiceMock() *CollectiblesServiceMock SetupAdditionalMessengers([]*Messenger) + GetAccountsTestData() map[string][]string + GetAccountsPasswords() map[string]string } const communitiesEventsTestTokenAddress = "0x0400000000000000000000000000000000000000" const aliceAccountAddress = "0x0777100000000000000000000000000000000000" const bobAccountAddress = "0x0330000000000000000000000000000000000000" -const communitiesEventsTestChainID = 1 const eventsSenderAccountAddress = "0x0200000000000000000000000000000000000000" const accountPassword = "qwerty" +const commonAccountAddress = "0x0890000000000000000000000000000000000000" type MessageResponseValidator func(*MessengerResponse) error @@ -106,7 +108,7 @@ func createMockedWalletBalance(s *suite.Suite) map[uint64]map[gethcommon.Address decimalsFactor := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(18)), nil) balance.Mul(balance, decimalsFactor) - mockedBalances[communitiesEventsTestChainID][eventSenderAddress][contractAddress] = (*hexutil.Big)(balance) + mockedBalances[testChainID1][eventSenderAddress][contractAddress] = (*hexutil.Big)(balance) return mockedBalances } @@ -124,20 +126,10 @@ func setUpCommunityAndRoles(base CommunityEventsTestsInterface, role protobuf.Co advertiseCommunityToUserOldWay(suite, community, base.GetControlNode(), base.GetEventSender()) advertiseCommunityToUserOldWay(suite, community, base.GetControlNode(), base.GetMember()) - request := &requests.RequestToJoinCommunity{ - CommunityID: community.ID(), - AddressesToReveal: []string{eventsSenderAccountAddress}, - AirdropAddress: eventsSenderAccountAddress, - } - joinCommunity(suite, community, base.GetControlNode(), base.GetEventSender(), request, accountPassword) + joinCommunity(suite, community.ID(), base.GetControlNode(), base.GetEventSender(), accountPassword, []string{eventsSenderAccountAddress}) refreshMessengerResponses(base) - request = &requests.RequestToJoinCommunity{ - CommunityID: community.ID(), - AddressesToReveal: []string{aliceAccountAddress}, - AirdropAddress: aliceAccountAddress, - } - joinCommunity(suite, community, base.GetControlNode(), base.GetMember(), request, accountPassword) + joinCommunity(suite, community.ID(), base.GetControlNode(), base.GetMember(), accountPassword, []string{aliceAccountAddress}) refreshMessengerResponses(base) // grant permissions to the event sender @@ -270,7 +262,7 @@ func createTestPermissionRequest(community *communities.Community, pType protobu TokenCriteria: []*protobuf.TokenCriteria{ { Type: protobuf.CommunityTokenType_ERC20, - ContractAddresses: map[uint64]string{uint64(communitiesEventsTestChainID): communitiesEventsTestTokenAddress}, + ContractAddresses: map[uint64]string{uint64(testChainID1): communitiesEventsTestTokenAddress}, Symbol: "TEST", AmountInWei: "100000000000000000000", Decimals: uint64(18), @@ -426,23 +418,17 @@ func setUpOnRequestCommunityAndRoles(base CommunityEventsTestsInterface, role pr advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), base.GetEventSender()) advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), base.GetMember()) + accountsTestData := base.GetAccountsTestData() + accounts := accountsTestData[base.GetEventSender().IdentityPublicKeyString()] + accountsPasswords := base.GetAccountsPasswords() + password := accountsPasswords[base.GetEventSender().IdentityPublicKeyString()] - requestEventSender := &requests.RequestToJoinCommunity{ - CommunityID: community.ID(), - AddressesToReveal: []string{eventsSenderAccountAddress}, - ENSName: "eventSender", - AirdropAddress: eventsSenderAccountAddress, - } + joinOnRequestCommunity(s, community.ID(), base.GetControlNode(), base.GetEventSender(), password, accounts) - joinOnRequestCommunity(s, community, base.GetControlNode(), base.GetEventSender(), requestEventSender) + accounts = accountsTestData[base.GetEventSender().IdentityPublicKeyString()] + password = accountsPasswords[base.GetEventSender().IdentityPublicKeyString()] - requestMember := &requests.RequestToJoinCommunity{ - CommunityID: community.ID(), - AddressesToReveal: []string{aliceAccountAddress}, - ENSName: "alice", - AirdropAddress: aliceAccountAddress, - } - joinOnRequestCommunity(s, community, base.GetControlNode(), base.GetMember(), requestMember) + joinOnRequestCommunity(s, community.ID(), base.GetControlNode(), base.GetMember(), password, accounts) checkMemberJoined := func(response *MessengerResponse) error { return checkMemberJoinedToTheCommunity(response, base.GetMember().IdentityPublicKey()) @@ -451,22 +437,27 @@ func setUpOnRequestCommunityAndRoles(base CommunityEventsTestsInterface, role pr waitOnMessengerResponse(s, checkMemberJoined, base.GetEventSender()) // grant permissions to event sender - grantPermission(s, community, base.GetControlNode(), base.GetEventSender(), role) checkPermissionGranted := func(response *MessengerResponse) error { return checkRolePermissionInResponse(response, base.GetEventSender().IdentityPublicKey(), role) } - waitOnMessengerResponse(s, checkPermissionGranted, base.GetMember()) + if role != protobuf.CommunityMember_ROLE_NONE { + grantPermission(s, community, base.GetControlNode(), base.GetEventSender(), role) + waitOnMessengerResponse(s, checkPermissionGranted, base.GetMember()) + } for _, eventSender := range additionalEventSenders { advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), eventSender) - joinOnRequestCommunity(s, community, base.GetControlNode(), eventSender, requestEventSender) - grantPermission(s, community, base.GetControlNode(), eventSender, role) - checkPermissionGranted = func(response *MessengerResponse) error { - return checkRolePermissionInResponse(response, eventSender.IdentityPublicKey(), role) + accounts = accountsTestData[base.GetEventSender().IdentityPublicKeyString()] + password = accountsPasswords[base.GetEventSender().IdentityPublicKeyString()] + + joinOnRequestCommunity(s, community.ID(), base.GetControlNode(), eventSender, password, accounts) + + if role != protobuf.CommunityMember_ROLE_NONE { + grantPermission(s, community, base.GetControlNode(), eventSender, role) + waitOnMessengerResponse(s, checkPermissionGranted, base.GetMember()) + waitOnMessengerResponse(s, checkPermissionGranted, base.GetEventSender()) } - waitOnMessengerResponse(s, checkPermissionGranted, base.GetMember()) - waitOnMessengerResponse(s, checkPermissionGranted, base.GetEventSender()) } return community @@ -996,6 +987,7 @@ func controlNodeCreatesCommunityPermission(base CommunityEventsTestsInterface, c }, "event sender did not receive community token permission", ) + s.Require().NoError(err) s.Require().NotNil(resp) eventSenderCommunity, err := base.GetEventSender().communitiesManager.GetByID(community.ID()) @@ -1085,27 +1077,21 @@ func testAcceptMemberRequestToJoin(base CommunityEventsTestsInterface, community advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), user) // user sends request to join - requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID(), ENSName: "testName"} - response, err := user.RequestToJoinCommunity(requestToJoin) - s.Require().NoError(err) - s.Require().NotNil(response) - s.Require().Len(response.RequestsToJoinCommunity(), 1) - - sentRequest := response.RequestsToJoinCommunity()[0] + requestID := testSendRequestToJoin(base, user, community.ID()) checkRequestToJoin := func(r *MessengerResponse) bool { if len(r.RequestsToJoinCommunity()) == 0 { return false } for _, request := range r.RequestsToJoinCommunity() { - if request.ENSName == requestToJoin.ENSName { + if request.PublicKey == user.IdentityPublicKeyString() { return true } } return false } // event sender receives request to join - response, err = WaitOnMessengerResponse( + response, err := WaitOnMessengerResponse( base.GetEventSender(), checkRequestToJoin, "event sender did not receive community request to join", @@ -1113,20 +1099,12 @@ func testAcceptMemberRequestToJoin(base CommunityEventsTestsInterface, community s.Require().NoError(err) s.Require().Len(response.RequestsToJoinCommunity(), 1) - // control node receives request to join - _, err = WaitOnMessengerResponse( - base.GetControlNode(), - checkRequestToJoin, - "event sender did not receive community request to join", - ) - s.Require().NoError(err) - // event sender has not accepted request yet eventSenderCommunity, err := base.GetEventSender().GetCommunityByID(community.ID()) s.Require().NoError(err) s.Require().False(eventSenderCommunity.HasMember(&user.identity.PublicKey)) - acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: sentRequest.ID} + acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: requestID} response, err = base.GetEventSender().AcceptRequestToJoinCommunity(acceptRequestToJoin) s.Require().NoError(err) s.Require().NotNil(response) @@ -1201,16 +1179,9 @@ func testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders(base Commu advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), user) // user sends request to join - requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - response, err := user.RequestToJoinCommunity(requestToJoin) - s.Require().NoError(err) - s.Require().NotNil(response) - s.Require().Len(response.RequestsToJoinCommunity(), 1) - - sentRequest := response.RequestsToJoinCommunity()[0] - + requestID := testSendRequestToJoin(base, user, community.ID()) // event sender receives request to join - _, err = WaitOnMessengerResponse( + _, err := WaitOnMessengerResponse( base.GetEventSender(), func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity()) > 0 }, "event sender did not receive community request to join", @@ -1226,8 +1197,8 @@ func testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders(base Commu s.Require().NoError(err) // event sender 1 accepts request - acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: sentRequest.ID} - response, err = base.GetEventSender().AcceptRequestToJoinCommunity(acceptRequestToJoin) + acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: requestID} + response, err := base.GetEventSender().AcceptRequestToJoinCommunity(acceptRequestToJoin) s.Require().NoError(err) s.Require().NotNil(response) s.Require().Len(response.Communities(), 1) @@ -1247,7 +1218,7 @@ func testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders(base Commu s.Require().Equal(acceptedPendingRequests[0].PublicKey, common.PubkeyToHex(&user.identity.PublicKey)) // event sender 1 changes its mind and rejects the request - rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: sentRequest.ID} + rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: requestID} response, err = base.GetEventSender().DeclineRequestToJoinCommunity(rejectRequestToJoin) s.Require().NoError(err) s.Require().NotNil(response) @@ -1273,16 +1244,10 @@ func testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders(base Commu advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), user) // user sends request to join - requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - response, err := user.RequestToJoinCommunity(requestToJoin) - s.Require().NoError(err) - s.Require().NotNil(response) - s.Require().Len(response.RequestsToJoinCommunity(), 1) - - sentRequest := response.RequestsToJoinCommunity()[0] + requestID := testSendRequestToJoin(base, user, community.ID()) // event sender receives request to join - response, err = WaitOnMessengerResponse( + response, err := WaitOnMessengerResponse( base.GetEventSender(), func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity()) > 0 }, "event sender did not receive community request to join", @@ -1299,7 +1264,7 @@ func testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders(base Commu s.Require().NoError(err) s.Require().Len(response.RequestsToJoinCommunity(), 1) - rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: sentRequest.ID} + rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: requestID} response, err = base.GetEventSender().DeclineRequestToJoinCommunity(rejectRequestToJoin) s.Require().NoError(err) s.Require().NotNil(response) @@ -1319,7 +1284,7 @@ func testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders(base Commu s.Require().Equal(rejectedPendingRequests[0].PublicKey, common.PubkeyToHex(&user.identity.PublicKey)) // event sender 1 changes its mind and accepts the request - acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: sentRequest.ID} + acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: requestID} response, err = base.GetEventSender().AcceptRequestToJoinCommunity(acceptRequestToJoin) s.Require().NoError(err) s.Require().NotNil(response) @@ -1346,16 +1311,10 @@ func testRejectMemberRequestToJoin(base CommunityEventsTestsInterface, community advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), user) // user sends request to join - requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - response, err := user.RequestToJoinCommunity(requestToJoin) - s.Require().NoError(err) - s.Require().NotNil(response) - s.Require().Len(response.RequestsToJoinCommunity(), 1) - - sentRequest := response.RequestsToJoinCommunity()[0] + requestID := testSendRequestToJoin(base, user, community.ID()) // event sender receives request to join - response, err = WaitOnMessengerResponse( + response, err := WaitOnMessengerResponse( base.GetEventSender(), func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity()) > 0 }, "event sender did not receive community request to join", @@ -1363,22 +1322,13 @@ func testRejectMemberRequestToJoin(base CommunityEventsTestsInterface, community s.Require().NoError(err) s.Require().Len(response.RequestsToJoinCommunity(), 1) - // control node receives request to join - response, err = WaitOnMessengerResponse( - base.GetControlNode(), - func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity()) > 0 }, - "control node did not receive community request to join", - ) - s.Require().NoError(err) - s.Require().Len(response.RequestsToJoinCommunity(), 1) - // event sender has not accepted request yet eventSenderCommunity, err := base.GetEventSender().GetCommunityByID(community.ID()) s.Require().NoError(err) s.Require().False(eventSenderCommunity.HasMember(&user.identity.PublicKey)) // event sender rejects request to join - rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: sentRequest.ID} + rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: requestID} _, err = base.GetEventSender().DeclineRequestToJoinCommunity(rejectRequestToJoin) s.Require().NoError(err) @@ -1396,7 +1346,7 @@ func testRejectMemberRequestToJoin(base CommunityEventsTestsInterface, community func(r *MessengerResponse) bool { requests, err := base.GetControlNode().DeclinedRequestsToJoinForCommunity(community.ID()) s.Require().NoError(err) - return len(response.Communities()) == 1 && len(requests) == 1 + return len(requests) == 1 && requests[0].State == communities.RequestToJoinStateDeclined }, "control node did not receive community request to join update from event sender", ) @@ -1411,7 +1361,8 @@ func testRejectMemberRequestToJoin(base CommunityEventsTestsInterface, community _, err = WaitOnMessengerResponse( base.GetEventSender(), func(r *MessengerResponse) bool { - return len(r.Communities()) > 0 && !r.Communities()[0].HasMember(&user.identity.PublicKey) + return len(r.Communities()) > 0 && !r.Communities()[0].HasMember(&user.identity.PublicKey) && + checkRequestToJoinInResponse(r, user, communities.RequestToJoinStateDeclined, 0) }, "event sender did not receive community update", ) @@ -1444,18 +1395,14 @@ func testControlNodeHandlesMultipleEventSenderRequestToJoinDecisions(base Commun advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), user) // user sends request to join - requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - response, err := user.RequestToJoinCommunity(requestToJoin) - s.Require().NoError(err) - s.Require().NotNil(response) - s.Require().Len(response.RequestsToJoinCommunity(), 1) - - sentRequest := response.RequestsToJoinCommunity()[0] + requestID := testSendRequestToJoin(base, user, community.ID()) // event sender receives request to join _, err = WaitOnMessengerResponse( base.GetEventSender(), - func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity()) > 0 }, + func(r *MessengerResponse) bool { + return checkRequestToJoinInResponse(r, user, communities.RequestToJoinStatePending, 0) + }, "event sender did not receive community request to join", ) s.Require().NoError(err) @@ -1463,21 +1410,15 @@ func testControlNodeHandlesMultipleEventSenderRequestToJoinDecisions(base Commun // event sender 2 receives request to join _, err = WaitOnMessengerResponse( additionalEventSender, - func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity()) > 0 }, - "event sender did not receive community request to join", - ) - s.Require().NoError(err) - - // control node receives request to join - _, err = WaitOnMessengerResponse( - base.GetControlNode(), - func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity()) > 0 }, - "event sender did not receive community request to join", + func(r *MessengerResponse) bool { + return checkRequestToJoinInResponse(r, user, communities.RequestToJoinStatePending, 0) + }, + "event sender 2 did not receive community request to join", ) s.Require().NoError(err) // event sender 1 rejects request to join - rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: sentRequest.ID} + rejectRequestToJoin := &requests.DeclineRequestToJoinCommunity{ID: requestID} _, err = base.GetEventSender().DeclineRequestToJoinCommunity(rejectRequestToJoin) s.Require().NoError(err) // request to join is now marked as rejected pending for event sender 1 @@ -1489,7 +1430,9 @@ func testControlNodeHandlesMultipleEventSenderRequestToJoinDecisions(base Commun // control node receives event sender 1's and 2's decision _, err = WaitOnMessengerResponse( base.GetControlNode(), - func(r *MessengerResponse) bool { return len(r.RequestsToJoinCommunity()) > 0 }, + func(r *MessengerResponse) bool { + return checkRequestToJoinInResponse(r, user, communities.RequestToJoinStateDeclinedPending, 0) + }, "control node did not receive event senders decision", ) s.Require().NoError(err) @@ -1500,16 +1443,21 @@ func testControlNodeHandlesMultipleEventSenderRequestToJoinDecisions(base Commun if err != nil { return err } + if len(rejectedRequests) != 1 { return errors.New("rejected requests should be 1") } + if rejectedRequests[0].PublicKey != common.PubkeyToHex(&user.identity.PublicKey) { + return errors.New("public key of rejected request not matching") + } + return nil }) s.Require().NoError(err) // event sender 2 accepts request to join - acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: sentRequest.ID} + acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: requestID} _, err = additionalEventSender.AcceptRequestToJoinCommunity(acceptRequestToJoin) s.Require().NoError(err) @@ -2074,26 +2022,18 @@ func addCommunityTokenToCommunityTokensService(base CommunityEventsTestsInterfac func testJoinedPrivilegedMemberReceiveRequestsToJoin(base CommunityEventsTestsInterface, community *communities.Community, bob *Messenger, newPrivilegedUser *Messenger, tokenPermissionType protobuf.CommunityTokenPermission_Type) { + s := base.GetSuite() // create community permission rolePermission := createTestPermissionRequest(community, tokenPermissionType) controlNodeCreatesCommunityPermission(base, community, rolePermission) - s := base.GetSuite() - advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), bob) advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), newPrivilegedUser) - requestNewPrivilegedUser := &requests.RequestToJoinCommunity{ - CommunityID: community.ID(), - AddressesToReveal: []string{eventsSenderAccountAddress}, - ENSName: "newPrivilegedUser", - AirdropAddress: eventsSenderAccountAddress, - } - - requestToJoinID := requestToJoinCommunity(s, base.GetControlNode(), newPrivilegedUser, requestNewPrivilegedUser) + requestID := testSendRequestToJoin(base, newPrivilegedUser, community.ID()) // accept join request - acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: requestToJoinID} + acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: requestID} response, err := base.GetControlNode().AcceptRequestToJoinCommunity(acceptRequestToJoin) s.Require().NoError(err) s.Require().NotNil(response) @@ -2102,16 +2042,16 @@ func testJoinedPrivilegedMemberReceiveRequestsToJoin(base CommunityEventsTestsIn s.Require().NotNil(updatedCommunity) s.Require().True(updatedCommunity.HasMember(&newPrivilegedUser.identity.PublicKey)) + s.Require().NoError(err) + _, err = WaitOnMessengerResponse( - base.GetEventSender(), + newPrivilegedUser, func(r *MessengerResponse) bool { return len(r.Communities()) > 0 && - len(r.Communities()[0].TokenPermissionsByType(tokenPermissionType)) > 0 && r.Communities()[0].HasPermissionToSendCommunityEvents() }, "newPrivilegedUser did not receive privileged role", ) - s.Require().NoError(err) expectedLength := 3 @@ -2119,17 +2059,10 @@ func testJoinedPrivilegedMemberReceiveRequestsToJoin(base CommunityEventsTestsIn waitAndCheckRequestsToJoin(s, newPrivilegedUser, expectedLength, community.ID(), tokenPermissionType == protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER) // bob joins the community - requestMember := &requests.RequestToJoinCommunity{ - CommunityID: community.ID(), - AddressesToReveal: []string{bobAccountAddress}, - ENSName: "bob", - AirdropAddress: bobAccountAddress, - } - - bobRequestToJoinID := requestToJoinCommunity(s, base.GetControlNode(), bob, requestMember) + requestID = testSendRequestToJoin(base, bob, community.ID()) // accept join request - acceptRequestToJoin = &requests.AcceptRequestToJoinCommunity{ID: bobRequestToJoinID} + acceptRequestToJoin = &requests.AcceptRequestToJoinCommunity{ID: requestID} _, err = base.GetControlNode().AcceptRequestToJoinCommunity(acceptRequestToJoin) s.Require().NoError(err) @@ -2150,33 +2083,15 @@ func testMemberReceiveRequestsToJoinAfterGettingNewRole(base CommunityEventsTest advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), base.GetMember()) advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), bob) - requestAlice := &requests.RequestToJoinCommunity{ - CommunityID: community.ID(), - AddressesToReveal: []string{aliceAccountAddress}, - ENSName: "alice", - AirdropAddress: aliceAccountAddress, - } + _ = testSendRequestToJoin(base, base.GetMember(), community.ID()) - requestToJoinCommunity(s, base.GetControlNode(), base.GetMember(), requestAlice) + _ = testSendRequestToJoin(base, bob, community.ID()) - requestBob := &requests.RequestToJoinCommunity{ - CommunityID: community.ID(), - AddressesToReveal: []string{bobAccountAddress}, - ENSName: "bob", - AirdropAddress: bobAccountAddress, - } - - requestToJoinCommunity(s, base.GetControlNode(), bob, requestBob) - - requestEventSender := &requests.RequestToJoinCommunity{ - CommunityID: community.ID(), - AddressesToReveal: []string{eventsSenderAccountAddress}, - ENSName: "eventSender", - AirdropAddress: eventsSenderAccountAddress, - } + accounts := base.GetAccountsTestData()[base.GetEventSender().IdentityPublicKeyString()] + password := base.GetAccountsPasswords()[base.GetEventSender().IdentityPublicKeyString()] // event sender joins as simple user - joinOnRequestCommunity(s, community, base.GetControlNode(), base.GetEventSender(), requestEventSender) + joinOnRequestCommunity(s, community.ID(), base.GetControlNode(), base.GetEventSender(), password, accounts) // create community permission rolePermission := createTestPermissionRequest(community, tokenPermissionType) @@ -2207,7 +2122,8 @@ func testMemberReceiveRequestsToJoinAfterGettingNewRole(base CommunityEventsTest s.Require().NoError(err) expectedLength := 3 - waitAndCheckRequestsToJoin(s, base.GetEventSender(), expectedLength, community.ID(), tokenPermissionType == protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER) + // if request to join state pending - privileged members should not receive revealed addresses + waitAndCheckRequestsToJoin(s, base.GetEventSender(), expectedLength, community.ID(), false) } func waitAndCheckRequestsToJoin(s *suite.Suite, user *Messenger, expectedLength int, communityID types.HexBytes, checkRevealedAddresses bool) { @@ -2229,7 +2145,7 @@ func waitAndCheckRequestsToJoin(s *suite.Suite, user *Messenger, expectedLength s.T().Log("our own requests to join must always have accounts revealed") return false } - } else if checkRevealedAddresses { + } else if checkRevealedAddresses && request.State != communities.RequestToJoinStatePending { if len(request.RevealedAccounts) != 1 { s.T().Log("no accounts revealed") return false @@ -2253,8 +2169,10 @@ func testPrivilegedMemberAcceptsRequestToJoinAfterMemberLeave(base CommunityEven advertiseCommunityToUserOldWay(s, community, base.GetControlNode(), user) - // user sends request to join - requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID(), ENSName: "testName"} + userPk := user.IdentityPublicKeyString() + userPassword := base.GetAccountsPasswords()[userPk] + userAccounts := base.GetAccountsTestData()[userPk] + requestToJoin := createRequestToJoinCommunity(s, community.ID(), user, userPassword, userAccounts) response, err := user.RequestToJoinCommunity(requestToJoin) s.Require().NoError(err) s.Require().NotNil(response) @@ -2267,7 +2185,7 @@ func testPrivilegedMemberAcceptsRequestToJoinAfterMemberLeave(base CommunityEven return false } for _, request := range r.RequestsToJoinCommunity() { - if request.ENSName == requestToJoin.ENSName { + if request.PublicKey == sentRequest.PublicKey { return true } } @@ -2286,7 +2204,7 @@ func testPrivilegedMemberAcceptsRequestToJoinAfterMemberLeave(base CommunityEven _, err = WaitOnMessengerResponse( base.GetControlNode(), checkRequestToJoin, - "event sender did not receive community request to join", + "control node did not receive community request to join", ) s.Require().NoError(err) @@ -2524,3 +2442,12 @@ func testBanMemberWithDeletingAllMessages(base CommunityEventsTestsInterface, co banMember(base, banRequest) } + +func testSendRequestToJoin(base CommunityEventsTestsInterface, user *Messenger, communityID types.HexBytes) types.HexBytes { + s := base.GetSuite() + userPk := user.IdentityPublicKeyString() + userPassword := base.GetAccountsPasswords()[userPk] + userAccounts := base.GetAccountsTestData()[userPk] + requestToJoin := createRequestToJoinCommunity(s, communityID, user, userPassword, userAccounts) + return requestToJoinCommunity(s, base.GetControlNode(), user, requestToJoin) +} diff --git a/protocol/communities_messenger_admin_test.go b/protocol/communities_messenger_admin_test.go index 46ee8d2b0..9d5aa2d3f 100644 --- a/protocol/communities_messenger_admin_test.go +++ b/protocol/communities_messenger_admin_test.go @@ -5,90 +5,93 @@ import ( "testing" "github.com/stretchr/testify/suite" - "go.uber.org/zap" - gethcommon "github.com/ethereum/go-ethereum/common" - hexutil "github.com/ethereum/go-ethereum/common/hexutil" - - gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" - "github.com/status-im/status-go/eth-node/types" + "github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/protocol/common" + "github.com/status-im/status-go/protocol/communities" "github.com/status-im/status-go/protocol/communities/token" "github.com/status-im/status-go/protocol/protobuf" - "github.com/status-im/status-go/protocol/tt" "github.com/status-im/status-go/services/wallet/bigint" - "github.com/status-im/status-go/waku" ) func TestAdminCommunityEventsSuite(t *testing.T) { suite.Run(t, new(AdminCommunityEventsSuite)) } -type AdminCommunityEventsSuiteBase struct { - suite.Suite - owner *Messenger - admin *Messenger - alice *Messenger - // If one wants to send messages between different instances of Messenger, - // a single Waku service should be shared. - shh types.Waku - logger *zap.Logger - mockedBalances map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big // chainID, account, token, balance - collectiblesServiceMock *CollectiblesServiceMock +type EventSenderCommunityEventsSuiteBase struct { + CommunitiesMessengerTestSuiteBase + owner *Messenger + eventSender *Messenger + alice *Messenger additionalEventSenders []*Messenger } type AdminCommunityEventsSuite struct { - AdminCommunityEventsSuiteBase + EventSenderCommunityEventsSuiteBase } -func (s *AdminCommunityEventsSuiteBase) GetControlNode() *Messenger { +func (s *EventSenderCommunityEventsSuiteBase) GetControlNode() *Messenger { return s.owner } -func (s *AdminCommunityEventsSuiteBase) GetEventSender() *Messenger { - return s.admin +func (s *EventSenderCommunityEventsSuiteBase) GetEventSender() *Messenger { + return s.eventSender } -func (s *AdminCommunityEventsSuiteBase) GetMember() *Messenger { +func (s *EventSenderCommunityEventsSuiteBase) GetMember() *Messenger { return s.alice } -func (s *AdminCommunityEventsSuiteBase) GetSuite() *suite.Suite { +func (s *EventSenderCommunityEventsSuiteBase) GetSuite() *suite.Suite { return &s.Suite } -func (s *AdminCommunityEventsSuiteBase) GetCollectiblesServiceMock() *CollectiblesServiceMock { +func (s *EventSenderCommunityEventsSuiteBase) GetCollectiblesServiceMock() *CollectiblesServiceMock { return s.collectiblesServiceMock } -func (s *AdminCommunityEventsSuiteBase) SetupTest() { - s.logger = tt.MustCreateTestLogger() - s.collectiblesServiceMock = &CollectiblesServiceMock{} +func (s *EventSenderCommunityEventsSuiteBase) GetAccountsTestData() map[string][]string { + return s.accountsTestData +} +func (s *EventSenderCommunityEventsSuiteBase) GetAccountsPasswords() map[string]string { + return s.accountsPasswords +} + +func (s *EventSenderCommunityEventsSuiteBase) SetupTest() { + s.CommunitiesMessengerTestSuiteBase.SetupTest() s.mockedBalances = createMockedWalletBalance(&s.Suite) - config := waku.DefaultConfig - config.MinimumAcceptedPoW = 0 - shh := waku.New(&config, s.logger) - s.shh = gethbridge.NewGethWakuWrapper(shh) - s.Require().NoError(shh.Start()) - s.owner = s.newMessenger("", []string{}) - s.admin = s.newMessenger(accountPassword, []string{eventsSenderAccountAddress}) + s.eventSender = s.newMessenger(accountPassword, []string{eventsSenderAccountAddress}) s.alice = s.newMessenger(accountPassword, []string{aliceAccountAddress}) _, err := s.owner.Start() s.Require().NoError(err) - _, err = s.admin.Start() + _, err = s.eventSender.Start() s.Require().NoError(err) _, err = s.alice.Start() s.Require().NoError(err) } -func (s *AdminCommunityEventsSuiteBase) TearDownTest() { +func (s *EventSenderCommunityEventsSuiteBase) newMessenger(password string, walletAddresses []string) *Messenger { + privateKey, err := crypto.GenerateKey() + s.Require().NoError(err) + + communityManagerOptions := []communities.ManagerOption{ + communities.WithAllowForcingCommunityMembersReevaluation(true), + } + + return s.newMessengerWithConfig(testMessengerConfig{ + logger: s.logger, + privateKey: privateKey, + extraOptions: []Option{WithCommunityManagerOptions(communityManagerOptions)}, + }, password, walletAddresses) +} + +func (s *EventSenderCommunityEventsSuiteBase) TearDownTest() { TearDownMessenger(&s.Suite, s.owner) - TearDownMessenger(&s.Suite, s.admin) + TearDownMessenger(&s.Suite, s.eventSender) TearDownMessenger(&s.Suite, s.alice) for _, m := range s.additionalEventSenders { @@ -96,10 +99,10 @@ func (s *AdminCommunityEventsSuiteBase) TearDownTest() { } s.additionalEventSenders = nil - _ = s.logger.Sync() + s.CommunitiesMessengerTestSuiteBase.TearDownTest() } -func (s *AdminCommunityEventsSuiteBase) SetupAdditionalMessengers(messengers []*Messenger) { +func (s *EventSenderCommunityEventsSuiteBase) SetupAdditionalMessengers(messengers []*Messenger) { for _, m := range messengers { s.additionalEventSenders = append(s.additionalEventSenders, m) _, err := m.Start() @@ -107,19 +110,6 @@ func (s *AdminCommunityEventsSuiteBase) SetupAdditionalMessengers(messengers []* } } -func (s *AdminCommunityEventsSuiteBase) newMessenger(password string, walletAddresses []string) *Messenger { - return newTestCommunitiesMessenger(&s.Suite, s.shh, testCommunitiesMessengerConfig{ - testMessengerConfig: testMessengerConfig{ - logger: s.logger, - }, - password: password, - walletAddresses: walletAddresses, - mockedBalances: &s.mockedBalances, - collectiblesService: s.collectiblesServiceMock, - }) - -} - func (s *AdminCommunityEventsSuite) TestAdminEditCommunityDescription() { // TODO admin test: update to include edit tags, logo, banner, request to join required setting, pin setting, etc... community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN) @@ -175,7 +165,7 @@ func (s *AdminCommunityEventsSuite) TestAdminAcceptMemberRequestToJoinResponseSh community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{additionalAdmin}) // set up additional user that will send request to join - user := s.newMessenger("", []string{}) + user := s.newMessenger("somePassword", []string{"0x0123400000000000000000000000000000000000"}) s.SetupAdditionalMessengers([]*Messenger{user}) testAcceptMemberRequestToJoinResponseSharedWithOtherEventSenders(s, community, user, additionalAdmin) @@ -185,7 +175,7 @@ func (s *AdminCommunityEventsSuite) TestAdminAcceptMemberRequestToJoin() { community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{}) // set up additional user that will send request to join - user := s.newMessenger("", []string{}) + user := s.newMessenger("somePassword", []string{"0x0123400000000000000000000000000000000000"}) s.SetupAdditionalMessengers([]*Messenger{user}) testAcceptMemberRequestToJoin(s, community, user) @@ -195,7 +185,7 @@ func (s *AdminCommunityEventsSuite) TestAdminRejectMemberRequestToJoinResponseSh additionalAdmin := s.newMessenger("qwerty", []string{eventsSenderAccountAddress}) community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{additionalAdmin}) // set up additional user that will send request to join - user := s.newMessenger("", []string{}) + user := s.newMessenger("somePassword", []string{"0x0123400000000000000000000000000000000000"}) s.SetupAdditionalMessengers([]*Messenger{user}) testRejectMemberRequestToJoinResponseSharedWithOtherEventSenders(s, community, user, additionalAdmin) @@ -205,7 +195,7 @@ func (s *AdminCommunityEventsSuite) TestAdminRejectMemberRequestToJoin() { community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{}) // set up additional user that will send request to join - user := s.newMessenger("", []string{}) + user := s.newMessenger("somePassword", []string{"0x0123400000000000000000000000000000000000"}) s.SetupAdditionalMessengers([]*Messenger{user}) testRejectMemberRequestToJoin(s, community, user) @@ -218,7 +208,7 @@ func (s *AdminCommunityEventsSuite) TestAdminControlNodeHandlesMultipleEventSend community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{additionalAdmin}) // set up additional user that will send request to join - user := s.newMessenger("", []string{}) + user := s.newMessenger("somePassword", []string{"0x0123400000000000000000000000000000000000"}) testControlNodeHandlesMultipleEventSenderRequestToJoinDecisions(s, community, user, additionalAdmin) } @@ -291,10 +281,10 @@ func (s *AdminCommunityEventsSuite) TestAdminAddCommunityToken() { Base64Image: "ABCD", } - _, err := s.admin.SaveCommunityToken(tokenERC721, nil) + _, err := s.eventSender.SaveCommunityToken(tokenERC721, nil) s.Require().NoError(err) - err = s.admin.AddCommunityToken(tokenERC721.CommunityID, tokenERC721.ChainID, tokenERC721.Address) + err = s.eventSender.AddCommunityToken(tokenERC721.CommunityID, tokenERC721.ChainID, tokenERC721.Address) s.Require().Error(err) } @@ -305,9 +295,7 @@ func (s *AdminCommunityEventsSuite) TestAdminAddTokenMasterAndOwnerToken() { func (s *AdminCommunityEventsSuite) TestAdminReceiveOwnerTokenFromControlNode() { community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN) - testAddAndSyncOwnerTokenFromControlNode(s, community, token.OwnerLevel) - } func (s *AdminCommunityEventsSuite) TestAdminReceiveTokenMasterTokenFromControlNode() { @@ -326,8 +314,8 @@ func (s *AdminCommunityEventsSuite) TestMemberReceiveOwnerEventsWhenControlNodeO } func (s *AdminCommunityEventsSuite) TestJoinedAdminReceiveRequestsToJoinWithoutRevealedAccounts() { - s.T().Skip("flaky test") - community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{}) + // event sender will receive privileged role during permission creation + community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_NONE, []*Messenger{}) // set up additional user (bob) that will send request to join bob := s.newMessenger(accountPassword, []string{bobAccountAddress}) @@ -351,7 +339,7 @@ func (s *AdminCommunityEventsSuite) TestAdminAcceptsRequestToJoinAfterMemberLeav community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{}) // set up additional user that will send request to join - user := s.newMessenger("", []string{}) + user := s.newMessenger("somePassword", []string{"0x0123400000000000000000000000000000000000"}) s.SetupAdditionalMessengers([]*Messenger{user}) testPrivilegedMemberAcceptsRequestToJoinAfterMemberLeave(s, community, user) } diff --git a/protocol/communities_messenger_helpers_test.go b/protocol/communities_messenger_helpers_test.go index 674acc031..ba1adf181 100644 --- a/protocol/communities_messenger_helpers_test.go +++ b/protocol/communities_messenger_helpers_test.go @@ -48,7 +48,11 @@ func (m *AccountManagerMock) CanRecover(rpcParams account.RecoverParams, reveale } func (m *AccountManagerMock) Sign(rpcParams account.SignParams, verifiedAccount *account.SelectedExtKey) (result types.HexBytes, err error) { - return types.HexBytes{}, nil + // mock signature + bytesArray := []byte(rpcParams.Address) + bytesArray = append(bytesArray, []byte(rpcParams.Password)...) + bytesArray = common.Shake256(bytesArray) + return append([]byte{0}, bytesArray...), nil } func (m *AccountManagerMock) DeleteAccount(address types.Address) error { @@ -69,7 +73,6 @@ func (m *TokenManagerMock) GetAllChainIDs() ([]uint64, error) { func (m *TokenManagerMock) getBalanceBasedOnParams(accounts, tokenAddresses []gethcommon.Address, chainIDs []uint64) map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big { retBalances := make(map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big) - retBalances[testChainID1] = make(map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big) for _, chainId := range chainIDs { if _, exists := retBalances[chainId]; !exists { @@ -275,8 +278,8 @@ type testCommunitiesMessengerConfig struct { password string walletAddresses []string mockedBalances *communities.BalancesByChain - mockedCollectibles *communities.CollectiblesByChain collectiblesService communities.CommunityTokensServiceInterface + collectiblesManager communities.CollectiblesManager } func (tcmc *testCommunitiesMessengerConfig) complete() error { @@ -301,7 +304,6 @@ func defaultTestCommunitiesMessengerNodeConfig() *params.NodeConfig { DataDir: "test", } } - func defaultTestCommunitiesMessengerSettings() *settings.Settings { networks := json.RawMessage("{}") return &settings.Settings{ @@ -341,14 +343,10 @@ func newTestCommunitiesMessenger(s *suite.Suite, waku types.Waku, config testCom Balances: config.mockedBalances, } - collectiblesManagerMock := &CollectiblesManagerMock{ - Collectibles: config.mockedCollectibles, - } - options := []Option{ WithAccountManager(accountsManagerMock), WithTokenManager(tokenManagerMock), - WithCollectiblesManager(collectiblesManagerMock), + WithCollectiblesManager(config.collectiblesManager), WithCommunityTokensService(config.collectiblesService), WithAppSettings(*config.appSettings, *config.nodeConfig), } @@ -478,9 +476,19 @@ func advertiseCommunityTo(s *suite.Suite, community *communities.Community, owne s.Require().NoError(err) } -func joinCommunity(s *suite.Suite, community *communities.Community, owner *Messenger, user *Messenger, request *requests.RequestToJoinCommunity, password string) { +func createRequestToJoinCommunity(s *suite.Suite, communityID types.HexBytes, user *Messenger, password string, addresses []string) *requests.RequestToJoinCommunity { + airdropAddress := "" + if len(addresses) > 0 { + airdropAddress = addresses[0] + } + + request := &requests.RequestToJoinCommunity{ + CommunityID: communityID, + AddressesToReveal: addresses, + AirdropAddress: airdropAddress} + if password != "" { - signingParams, err := user.GenerateJoiningCommunityRequestsForSigning(common.PubkeyToHex(&user.identity.PublicKey), community.ID(), request.AddressesToReveal) + signingParams, err := user.GenerateJoiningCommunityRequestsForSigning(common.PubkeyToHex(&user.identity.PublicKey), communityID, request.AddressesToReveal) s.Require().NoError(err) for i := range signingParams { @@ -502,7 +510,12 @@ func joinCommunity(s *suite.Suite, community *communities.Community, owner *Mess } } - response, err := user.RequestToJoinCommunity(request) + return request +} + +func joinCommunity(s *suite.Suite, communityID types.HexBytes, controlNode *Messenger, user *Messenger, password string, addresses []string) { + requestToJoin := createRequestToJoinCommunity(s, communityID, user, password, addresses) + response, err := user.RequestToJoinCommunity(requestToJoin) s.Require().NoError(err) s.Require().NotNil(response) s.Require().Len(response.RequestsToJoinCommunity(), 1) @@ -514,14 +527,16 @@ func joinCommunity(s *suite.Suite, community *communities.Community, owner *Mess s.Require().Equal(notification.MembershipStatus, ActivityCenterMembershipStatusPending) // Retrieve and accept join request - _, err = WaitOnMessengerResponse(owner, func(r *MessengerResponse) bool { + _, err = WaitOnMessengerResponse(controlNode, func(r *MessengerResponse) bool { return len(r.Communities()) > 0 && r.Communities()[0].HasMember(&user.identity.PublicKey) - }, "user not accepted") + }, "control node did accept user request to join") s.Require().NoError(err) // Retrieve join request response _, err = WaitOnMessengerResponse(user, func(r *MessengerResponse) bool { - return len(r.Communities()) > 0 && r.Communities()[0].HasMember(&user.identity.PublicKey) + return len(r.Communities()) > 0 && r.Communities()[0].HasMember(&user.identity.PublicKey) && + // Note: 'handleCommunityRequestToJoinResponse' does not return RequestToJoin with revealed addresses + checkRequestToJoinInResponse(r, user, communities.RequestToJoinStateAccepted, 0) }, "user not accepted") s.Require().NoError(err) } @@ -538,16 +553,7 @@ func requestToJoinCommunity(s *suite.Suite, controlNode *Messenger, user *Messen _, err = WaitOnMessengerResponse( controlNode, func(r *MessengerResponse) bool { - if len(r.RequestsToJoinCommunity()) == 0 { - return false - } - - for _, resultRequest := range r.RequestsToJoinCommunity() { - if resultRequest.PublicKey == common.PubkeyToHex(&user.identity.PublicKey) { - return true - } - } - return false + return checkRequestToJoinInResponse(r, user, communities.RequestToJoinStatePending, 1) }, "control node did not receive community request to join", ) @@ -556,7 +562,11 @@ func requestToJoinCommunity(s *suite.Suite, controlNode *Messenger, user *Messen return requestToJoin.ID } -func joinOnRequestCommunity(s *suite.Suite, community *communities.Community, controlNode *Messenger, user *Messenger, request *requests.RequestToJoinCommunity) { +func joinOnRequestCommunity(s *suite.Suite, communityID types.HexBytes, controlNode *Messenger, user *Messenger, password string, addresses []string) { + s.Require().NotEmpty(password) + s.Require().NotEmpty(addresses) + s.Require().NotEmpty(communityID) + request := createRequestToJoinCommunity(s, communityID, user, password, addresses) // Request to join the community requestToJoinID := requestToJoinCommunity(s, controlNode, user, request) @@ -580,7 +590,7 @@ func joinOnRequestCommunity(s *suite.Suite, community *communities.Community, co ) s.Require().NoError(err) - userCommunity, err := user.GetCommunityByID(community.ID()) + userCommunity, err := user.GetCommunityByID(communityID) s.Require().NoError(err) s.Require().True(userCommunity.HasMember(&user.identity.PublicKey)) @@ -701,11 +711,20 @@ func makeAddressSatisfyTheCriteria(s *suite.Suite, mockedBalances communities.Ba walletAddress := gethcommon.HexToAddress(address) contractAddress := gethcommon.HexToAddress(criteria.ContractAddresses[chainID]) + switch criteria.Type { case protobuf.CommunityTokenType_ERC20: balance, ok := new(big.Int).SetString(criteria.AmountInWei, 10) s.Require().True(ok) + if _, exists := mockedBalances[chainID]; !exists { + mockedBalances[chainID] = make(map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big) + } + + if _, exists := mockedBalances[chainID][walletAddress]; !exists { + mockedBalances[chainID][walletAddress] = make(map[gethcommon.Address]*hexutil.Big) + } + mockedBalances[chainID][walletAddress][contractAddress] = (*hexutil.Big)(balance) case protobuf.CommunityTokenType_ERC721: @@ -724,9 +743,28 @@ func makeAddressSatisfyTheCriteria(s *suite.Suite, mockedBalances communities.Ba }) } + if _, exists := mockedCollectibles[chainID]; !exists { + mockedCollectibles[chainID] = make(map[gethcommon.Address]thirdparty.TokenBalancesPerContractAddress) + } + + if _, exists := mockedCollectibles[chainID][walletAddress]; !exists { + mockedCollectibles[chainID][walletAddress] = make(thirdparty.TokenBalancesPerContractAddress) + } + mockedCollectibles[chainID][walletAddress][contractAddress] = balances case protobuf.CommunityTokenType_ENS: // not implemented } } + +func checkRequestToJoinInResponse(r *MessengerResponse, member *Messenger, state communities.RequestToJoinState, accountsCount int) bool { + for _, request := range r.RequestsToJoinCommunity() { + if request.PublicKey == member.IdentityPublicKeyString() && + request.State == state && + accountsCount == len(request.RevealedAccounts) { + return true + } + } + return false +} diff --git a/protocol/communities_messenger_shared_member_address_test.go b/protocol/communities_messenger_shared_member_address_test.go index 08f5844b6..493e07319 100644 --- a/protocol/communities_messenger_shared_member_address_test.go +++ b/protocol/communities_messenger_shared_member_address_test.go @@ -1,7 +1,6 @@ package protocol import ( - "math/big" "testing" "time" @@ -39,6 +38,8 @@ type MessengerCommunitiesSharedMemberAddressSuite struct { mockedBalances map[uint64]map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big // chainID, account, token, balance collectiblesServiceMock *CollectiblesServiceMock + mockedCollectibles communities.CollectiblesByChain + collectiblesManagerMock CollectiblesManagerMock } func (s *MessengerCommunitiesSharedMemberAddressSuite) SetupTest() { @@ -52,6 +53,10 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) SetupTest() { communities.SetValidateInterval(300 * time.Millisecond) s.collectiblesServiceMock = &CollectiblesServiceMock{} + s.mockedCollectibles = communities.CollectiblesByChain{} + s.collectiblesManagerMock = CollectiblesManagerMock{ + Collectibles: &s.mockedCollectibles, + } s.resetMockedBalances() @@ -108,21 +113,12 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) newMessenger(password str walletAddresses: walletAddresses, mockedBalances: &s.mockedBalances, collectiblesService: s.collectiblesServiceMock, + collectiblesManager: &s.collectiblesManagerMock, }) } func (s *MessengerCommunitiesSharedMemberAddressSuite) joinCommunity(community *communities.Community, user *Messenger, password string, addresses []string) { - s.joinCommunityWithAirdropAddress(community, user, password, addresses, "") -} - -func (s *MessengerCommunitiesSharedMemberAddressSuite) joinCommunityWithAirdropAddress(community *communities.Community, user *Messenger, password string, addresses []string, airdropAddress string) { - passwdHash := types.EncodeHex(crypto.Keccak256([]byte(password))) - if airdropAddress == "" && len(addresses) > 0 { - airdropAddress = addresses[0] - } - - request := &requests.RequestToJoinCommunity{CommunityID: community.ID(), AddressesToReveal: addresses, AirdropAddress: airdropAddress} - joinCommunity(&s.Suite, community, s.owner, user, request, passwdHash) + joinCommunity(&s.Suite, community.ID(), s.owner, user, password, addresses) } func (s *MessengerCommunitiesSharedMemberAddressSuite) checkRevealedAccounts(communityID types.HexBytes, user *Messenger, expectedAccounts []*protobuf.RevealedAccount) { @@ -132,12 +128,7 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) checkRevealedAccounts(com } func (s *MessengerCommunitiesSharedMemberAddressSuite) makeAddressSatisfyTheCriteria(chainID uint64, address string, criteria *protobuf.TokenCriteria) { - walletAddress := gethcommon.HexToAddress(address) - contractAddress := gethcommon.HexToAddress(criteria.ContractAddresses[chainID]) - balance, ok := new(big.Int).SetString(criteria.AmountInWei, 10) - s.Require().True(ok) - - s.mockedBalances[chainID][walletAddress][contractAddress] = (*hexutil.Big)(balance) + makeAddressSatisfyTheCriteria(&s.Suite, s.mockedBalances, s.mockedCollectibles, chainID, address, criteria) } func (s *MessengerCommunitiesSharedMemberAddressSuite) resetMockedBalances() { @@ -187,6 +178,59 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) createEditSharedAddresses return request } +func (s *MessengerCommunitiesSharedMemberAddressSuite) joinOnRequestCommunityAsTokenMaster(community *communities.Community) { + bobRequest := createRequestToJoinCommunity(&s.Suite, community.ID(), s.bob, bobPassword, []string{bobAddress}) + requestToJoinID := requestToJoinCommunity(&s.Suite, s.owner, s.bob, bobRequest) + // accept join request + acceptRequestToJoin := &requests.AcceptRequestToJoinCommunity{ID: requestToJoinID} + response, err := s.owner.AcceptRequestToJoinCommunity(acceptRequestToJoin) + s.Require().NoError(err) + s.Require().NotNil(response) + + updatedCommunity := response.Communities()[0] + s.Require().NotNil(updatedCommunity) + s.Require().True(updatedCommunity.HasMember(&s.bob.identity.PublicKey)) + s.Require().True(updatedCommunity.IsMemberTokenMaster(&s.bob.identity.PublicKey)) + + // receive request to join response + _, err = WaitOnMessengerResponse( + s.bob, + func(r *MessengerResponse) bool { + return len(r.Communities()) > 0 && + r.Communities()[0].HasMember(&s.bob.identity.PublicKey) && + r.Communities()[0].IsMemberTokenMaster(&s.bob.identity.PublicKey) + }, + "user did not receive request to join response", + ) + s.Require().NoError(err) + + userCommunity, err := s.bob.GetCommunityByID(community.ID()) + s.Require().NoError(err) + s.Require().True(userCommunity.HasMember(&s.bob.identity.PublicKey)) + s.Require().True(userCommunity.IsTokenMaster()) +} + +func (s *MessengerCommunitiesSharedMemberAddressSuite) waitForRevealedAddresses(receiver *Messenger, communityID types.HexBytes, expectedAccounts []*protobuf.RevealedAccount) { + _, err := WaitOnMessengerResponse(receiver, func(r *MessengerResponse) bool { + revealedAccounts, err := receiver.communitiesManager.GetRevealedAddresses(communityID, s.alice.IdentityPublicKeyString()) + if err != nil { + return false + } + if len(expectedAccounts) != len(revealedAccounts) { + return false + } + + for index := range revealedAccounts { + if revealedAccounts[index].Address != expectedAccounts[index].Address { + return false + } + } + + return true + }, "client did not receive alice shared address") + s.Require().NoError(err) +} + func (s *MessengerCommunitiesSharedMemberAddressSuite) TestJoinedCommunityMembersSharedAddress() { community, _ := createCommunity(&s.Suite, s.owner) advertiseCommunityTo(&s.Suite, community, s.owner, s.alice) @@ -265,7 +309,7 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestJoinedCommunityMember community, _ := createCommunity(&s.Suite, s.owner) advertiseCommunityTo(&s.Suite, community, s.owner, s.alice) - s.joinCommunityWithAirdropAddress(community, s.alice, alicePassword, []string{aliceAddress1, aliceAddress2}, aliceAddress2) + s.joinCommunity(community, s.alice, alicePassword, []string{aliceAddress1, aliceAddress2}) community, err := s.owner.GetCommunityByID(community.ID()) s.Require().NoError(err) @@ -280,7 +324,7 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestJoinedCommunityMember s.Require().Len(revealedAccountsInAlicesDB, 2) s.Require().Equal(revealedAccountsInAlicesDB[0].Address, aliceAddress1) s.Require().Equal(revealedAccountsInAlicesDB[1].Address, aliceAddress2) - s.Require().Equal(true, revealedAccountsInAlicesDB[1].IsAirdropAddress) + s.Require().Equal(true, revealedAccountsInAlicesDB[0].IsAirdropAddress) // Check owner's DB for revealed accounts s.checkRevealedAccounts(community.ID(), s.owner, revealedAccountsInAlicesDB) @@ -318,16 +362,7 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestEditSharedAddresses() s.Require().Equal(true, aliceExpectedRevealedAccounts[0].IsAirdropAddress) // check that owner received revealed address - _, err = WaitOnMessengerResponse(s.owner, func(r *MessengerResponse) bool { - revealedAccounts, err := s.owner.communitiesManager.GetRevealedAddresses(community.ID(), s.alice.IdentityPublicKeyString()) - s.Require().NoError(err) - s.Require().Len(revealedAccounts, 1) - return revealedAccounts[0].Address == aliceAddress2 - - }, "owned did not receive alice shared address") - s.Require().NoError(err) - - s.checkRevealedAccounts(community.ID(), s.owner, aliceExpectedRevealedAccounts) + s.waitForRevealedAddresses(s.owner, community.ID(), aliceExpectedRevealedAccounts) // check that we filter out outdated edit shared addresses events community, err = s.owner.GetCommunityByID(community.ID()) @@ -383,42 +418,30 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestTokenMasterReceivesEd s.Require().NoError(err) checkRoleBasedOnThePermissionType(protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER, &s.bob.identity.PublicKey, community) - aliceRevealedAccounts, err := s.bob.GetRevealedAccounts(community.ID(), alicePubkey) s.Require().NoError(err) - s.Require().Len(aliceRevealedAccounts, 1) + + expectedAliceRevealedAccounts, err := s.alice.communitiesManager.GetRevealedAddresses(community.ID(), s.alice.IdentityPublicKeyString()) + s.Require().NoError(err) + s.Require().Len(expectedAliceRevealedAccounts, 1) + + s.waitForRevealedAddresses(s.bob, community.ID(), expectedAliceRevealedAccounts) request := s.createEditSharedAddressesRequest(community.ID()) response, err := s.alice.EditSharedAddressesForCommunity(request) s.Require().NoError(err) s.Require().NotNil(response) - expectedAliceRevealedAccounts, err := s.alice.communitiesManager.GetRevealedAddresses(community.ID(), alicePubkey) + expectedAliceRevealedAccounts, err = s.alice.communitiesManager.GetRevealedAddresses(community.ID(), alicePubkey) s.Require().NoError(err) s.Require().Len(expectedAliceRevealedAccounts, 1) s.Require().Equal(expectedAliceRevealedAccounts[0].Address, aliceAddress2) s.Require().Equal(true, expectedAliceRevealedAccounts[0].IsAirdropAddress) - // check that owner received revealed address - _, err = WaitOnMessengerResponse(s.owner, func(r *MessengerResponse) bool { - revealedAccounts, err := s.owner.communitiesManager.GetRevealedAddresses(community.ID(), s.alice.IdentityPublicKeyString()) - s.Require().NoError(err) - s.Require().Len(revealedAccounts, 1) - return revealedAccounts[0].Address == aliceAddress2 + s.waitForRevealedAddresses(s.owner, community.ID(), expectedAliceRevealedAccounts) - }, "owned did not receive alice shared address") s.Require().NoError(err) - s.checkRevealedAccounts(community.ID(), s.owner, expectedAliceRevealedAccounts) - - // check that bob as a token master received revealed address - _, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool { - revealedAccounts, err := s.bob.communitiesManager.GetRevealedAddresses(community.ID(), s.alice.IdentityPublicKeyString()) - s.Require().NoError(err) - s.Require().Len(revealedAccounts, 1) - return revealedAccounts[0].Address == aliceAddress2 - }, "user not accepted") - s.Require().NoError(err) - s.checkRevealedAccounts(community.ID(), s.bob, expectedAliceRevealedAccounts) + s.waitForRevealedAddresses(s.bob, community.ID(), expectedAliceRevealedAccounts) } func (s *MessengerCommunitiesSharedMemberAddressSuite) TestSharedAddressesReturnsRevealedAccount() { @@ -552,17 +575,21 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestTokenMasterReceivesMe advertiseCommunityTo(&s.Suite, community, s.owner, s.bob) s.joinCommunity(community, s.bob, bobPassword, []string{bobAddress}) + s.Require().NoError(err) // check bob has TM role community, err = s.bob.communitiesManager.GetByID(community.ID()) s.Require().NoError(err) checkRoleBasedOnThePermissionType(protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER, &s.bob.identity.PublicKey, community) - s.checkRevealedAccounts(community.ID(), s.bob, expectedAliceRevealedAccounts) + s.waitForRevealedAddresses(s.bob, community.ID(), expectedAliceRevealedAccounts) // remove alice revealed addresses - aliceRequestID := communities.CalculateRequestID(s.alice.IdentityPublicKeyString(), community.ID()) - err = s.bob.communitiesManager.RemoveRequestToJoinRevealedAddresses(aliceRequestID) + requestToDelete, err := s.bob.communitiesManager.GetRequestToJoinByPkAndCommunityID(s.alice.IdentityPublicKey(), community.ID()) + s.Require().NoError(err) + err = s.bob.communitiesManager.RemoveRequestToJoinRevealedAddresses(requestToDelete.ID) + s.Require().NoError(err) + err = s.bob.communitiesManager.DeletePendingRequestToJoin(requestToDelete) s.Require().NoError(err) emptySharedAddresses, err := s.bob.GetRevealedAccounts(community.ID(), s.alice.IdentityPublicKeyString()) @@ -589,23 +616,13 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestTokenMasterReceivesMe s.bob, func(r *MessengerResponse) bool { _, _ = s.owner.RetrieveAll() - if len(r.requestsToJoinCommunity) == 0 { - return false - } - - for _, requestToJoin := range r.requestsToJoinCommunity { - if requestToJoin.PublicKey == s.alice.IdentityPublicKeyString() { - return true - } - } - - return false + aliceAccounts, err := s.bob.communitiesManager.GetRevealedAddresses(community.ID(), s.alice.IdentityPublicKeyString()) + s.Require().NoError(err) + return len(aliceAccounts) > 0 && aliceAccounts[0].Address == aliceAddress1 }, "alice request to join with revealed addresses not received", ) s.Require().NoError(err) - - s.checkRevealedAccounts(community.ID(), s.bob, expectedAliceRevealedAccounts) } func (s *MessengerCommunitiesSharedMemberAddressSuite) TestTokenMasterReceivedRevealedAddressesFromJoinedMember() { @@ -641,18 +658,18 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestTokenMasterReceivedRe advertiseCommunityTo(&s.Suite, community, s.owner, s.alice) s.joinCommunity(community, s.alice, alicePassword, []string{aliceAddress1}) - // check that bob received revealed address - _, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool { - return len(r.RequestsToJoinCommunity()) == 1 && r.RequestsToJoinCommunity()[0].PublicKey == s.alice.IdentityPublicKeyString() - }, "user not accepted") - s.Require().NoError(err) - expectedAliceRevealedAccounts, err := s.alice.communitiesManager.GetRevealedAddresses(community.ID(), s.alice.IdentityPublicKeyString()) s.Require().NoError(err) s.Require().Len(expectedAliceRevealedAccounts, 1) s.Require().Equal(expectedAliceRevealedAccounts[0].Address, aliceAddress1) s.Require().Equal(true, expectedAliceRevealedAccounts[0].IsAirdropAddress) + // check that bob received revealed address + _, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool { + return checkRequestToJoinInResponse(r, s.alice, communities.RequestToJoinStateAccepted, len(expectedAliceRevealedAccounts)) + }, "user not accepted") + s.Require().NoError(err) + s.checkRevealedAccounts(community.ID(), s.bob, expectedAliceRevealedAccounts) } @@ -682,6 +699,7 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestTokenMasterJoinedToCo s.makeAddressSatisfyTheCriteria(testChainID1, bobAddress, tokenCriteria) advertiseCommunityTo(&s.Suite, community, s.owner, s.bob) + s.joinCommunity(community, s.bob, bobPassword, []string{bobAddress}) community, err = s.bob.communitiesManager.GetByID(community.ID()) @@ -694,7 +712,7 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestTokenMasterJoinedToCo s.Require().Equal(expectedAliceRevealedAccounts[0].Address, aliceAddress1) s.Require().Equal(true, expectedAliceRevealedAccounts[0].IsAirdropAddress) - s.checkRevealedAccounts(community.ID(), s.bob, expectedAliceRevealedAccounts) + s.waitForRevealedAddresses(s.bob, community.ID(), expectedAliceRevealedAccounts) } func (s *MessengerCommunitiesSharedMemberAddressSuite) TestMemberReceivedSharedAddressOnGettingTokenMasterRole() { @@ -733,18 +751,18 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestMemberReceivedSharedA err = <-waitOnOwnerSendSyncMessage s.Require().NoError(err) - _, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool { - return len(r.Communities()) == 1 && r.Communities()[0].IsTokenMaster() - }, "bob didn't receive token master role") - s.Require().NoError(err) - expectedAliceRevealedAccounts, err := s.alice.communitiesManager.GetRevealedAddresses(community.ID(), s.alice.IdentityPublicKeyString()) s.Require().NoError(err) s.Require().Len(expectedAliceRevealedAccounts, 1) s.Require().Equal(expectedAliceRevealedAccounts[0].Address, aliceAddress1) s.Require().Equal(true, expectedAliceRevealedAccounts[0].IsAirdropAddress) - s.checkRevealedAccounts(community.ID(), s.bob, expectedAliceRevealedAccounts) + _, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool { + return len(r.Communities()) == 1 && r.Communities()[0].IsTokenMaster() + }, "bob didn't receive token master role") + s.Require().NoError(err) + + s.waitForRevealedAddresses(s.bob, community.ID(), expectedAliceRevealedAccounts) } func (s *MessengerCommunitiesSharedMemberAddressSuite) TestTokenMasterReceivesAccountsAfterPendingRequestToJoinApproval() { @@ -769,27 +787,10 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestTokenMasterReceivesAc advertiseCommunityTo(&s.Suite, community, s.owner, s.alice) advertiseCommunityTo(&s.Suite, community, s.owner, s.bob) - aliceArray64Bytes := common.HashPublicKey(&s.alice.identity.PublicKey) - aliceSignature := append([]byte{0}, aliceArray64Bytes...) - aliceRequest := &requests.RequestToJoinCommunity{ - CommunityID: community.ID(), - AddressesToReveal: []string{aliceAddress1}, - AirdropAddress: aliceAddress1, - Signatures: []types.HexBytes{aliceSignature}, - } - + aliceRequest := createRequestToJoinCommunity(&s.Suite, community.ID(), s.alice, alicePassword, []string{aliceAddress1}) aliceRequestToJoinID := requestToJoinCommunity(&s.Suite, s.owner, s.alice, aliceRequest) - bobArray64Bytes := common.HashPublicKey(&s.bob.identity.PublicKey) - bobSignature := append([]byte{0}, bobArray64Bytes...) - bobRequest := &requests.RequestToJoinCommunity{ - CommunityID: community.ID(), - AddressesToReveal: []string{bobAddress}, - AirdropAddress: bobAddress, - Signatures: []types.HexBytes{bobSignature}, - } - - joinOnRequestCommunity(&s.Suite, community, s.owner, s.bob, bobRequest) + s.joinOnRequestCommunityAsTokenMaster(community) community, err = s.owner.communitiesManager.GetByID(community.ID()) s.Require().NoError(err) @@ -799,14 +800,7 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestTokenMasterReceivesAc s.Require().NoError(err) _, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool { - if r.RequestsToJoinCommunity() != nil { - for _, request := range r.RequestsToJoinCommunity() { - if request.PublicKey == s.alice.IdentityPublicKeyString() && request.State == communities.RequestToJoinStateAccepted { - return true - } - } - } - return false + return checkRequestToJoinInResponse(r, s.alice, communities.RequestToJoinStateAccepted, 1) }, "bob didn't receive accepted Alice request to join") s.Require().NoError(err) @@ -820,48 +814,21 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestTokenMasterReceivesAc } func (s *MessengerCommunitiesSharedMemberAddressSuite) TestMemberReceivesPendingRequestToJoinAfterAfterGettingTokenMasterRole() { - s.T().Skip("flaky test") - community, _ := createOnRequestCommunity(&s.Suite, s.owner) advertiseCommunityTo(&s.Suite, community, s.owner, s.alice) advertiseCommunityTo(&s.Suite, community, s.owner, s.bob) - aliceArray64Bytes := common.HashPublicKey(&s.alice.identity.PublicKey) - aliceSignature := append([]byte{0}, aliceArray64Bytes...) - aliceRequest := &requests.RequestToJoinCommunity{ - CommunityID: community.ID(), - AddressesToReveal: []string{aliceAddress1}, - AirdropAddress: aliceAddress1, - Signatures: []types.HexBytes{aliceSignature}, - } - + aliceRequest := createRequestToJoinCommunity(&s.Suite, community.ID(), s.alice, alicePassword, []string{aliceAddress1}) aliceRequestToJoinID := requestToJoinCommunity(&s.Suite, s.owner, s.alice, aliceRequest) - bobArray64Bytes := common.HashPublicKey(&s.bob.identity.PublicKey) - bobSignature := append([]byte{0}, bobArray64Bytes...) - bobRequest := &requests.RequestToJoinCommunity{ - CommunityID: community.ID(), - AddressesToReveal: []string{bobAddress}, - AirdropAddress: bobAddress, - Signatures: []types.HexBytes{bobSignature}, - } - - joinOnRequestCommunity(&s.Suite, community, s.owner, s.bob, bobRequest) + joinOnRequestCommunity(&s.Suite, community.ID(), s.owner, s.bob, bobPassword, []string{bobAddress}) tokenCriteria := createTokenMasterTokenCriteria() // make bob satisfy the Token Master criteria s.makeAddressSatisfyTheCriteria(testChainID1, bobAddress, tokenCriteria) - // wait for owner to send sync message for bob, who got a TM role - waitOnOwnerSendSyncMessage := waitOnCommunitiesEvent(s.owner, func(sub *communities.Subscription) bool { - return sub.CommunityPrivilegedMemberSyncMessage != nil && - sub.CommunityPrivilegedMemberSyncMessage.CommunityPrivilegedUserSyncMessage.Type == protobuf.CommunityPrivilegedUserSyncMessage_CONTROL_NODE_ALL_SYNC_REQUESTS_TO_JOIN && - len(sub.CommunityPrivilegedMemberSyncMessage.Receivers) == 1 && - sub.CommunityPrivilegedMemberSyncMessage.Receivers[0].Equal(&s.bob.identity.PublicKey) - }) - _, err := s.owner.CreateCommunityTokenPermission(&requests.CreateCommunityTokenPermission{ CommunityID: community.ID(), Type: protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER, @@ -869,9 +836,6 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestMemberReceivesPending }) s.Require().NoError(err) - err = <-waitOnOwnerSendSyncMessage - s.Require().NoError(err) - _, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool { return len(r.Communities()) == 1 && r.Communities()[0].IsTokenMaster() }, "bob didn't receive token master role") @@ -881,10 +845,7 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestMemberReceivesPending s.Require().NoError(err) _, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool { - return len(r.RequestsToJoinCommunity()) > 0 && - r.RequestsToJoinCommunity()[0].PublicKey == s.alice.IdentityPublicKeyString() && - r.RequestsToJoinCommunity()[0].State == communities.RequestToJoinStateAccepted - + return checkRequestToJoinInResponse(r, s.alice, communities.RequestToJoinStateAccepted, 1) }, "bob didn't receive accepted Alice request to join") s.Require().NoError(err) @@ -932,8 +893,8 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestHandlingOutdatedPrivi // check that bob received revealed address _, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool { - return len(r.RequestsToJoinCommunity()) == 1 && r.RequestsToJoinCommunity()[0].PublicKey == s.alice.IdentityPublicKeyString() - }, "user not accepted") + return checkRequestToJoinInResponse(r, s.alice, communities.RequestToJoinStateAccepted, 1) + }, "bob did not receive alice revealed addresses") s.Require().NoError(err) // handle outdated CommunityPrivilegedUserSyncMessage_CONTROL_NODE_ALL_SYNC_REQUESTS_TO_JOIN msg @@ -1009,16 +970,7 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestMemberReceivedEditedS s.Require().Equal(true, expectedAliceRevealedAccounts[0].IsAirdropAddress) // check that owner received edited shared adresses - _, err = WaitOnMessengerResponse(s.owner, func(r *MessengerResponse) bool { - revealedAccounts, err := s.owner.communitiesManager.GetRevealedAddresses(community.ID(), alicePubkey) - s.Require().NoError(err) - s.Require().Len(revealedAccounts, 1) - return revealedAccounts[0].Address == aliceAddress2 - - }, "owned did not receive alice shared address") - s.Require().NoError(err) - - s.checkRevealedAccounts(community.ID(), s.owner, expectedAliceRevealedAccounts) + s.waitForRevealedAddresses(s.owner, community.ID(), expectedAliceRevealedAccounts) advertiseCommunityTo(&s.Suite, community, s.owner, s.bob) s.joinCommunity(community, s.bob, bobPassword, []string{bobAddress}) @@ -1028,14 +980,6 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestMemberReceivedEditedS // make bob satisfy the Token Master criteria s.makeAddressSatisfyTheCriteria(testChainID1, bobAddress, tokenCriteria) - // wait for owner to send sync message for bob, who got a TM role - waitOnOwnerSendSyncMessage := waitOnCommunitiesEvent(s.owner, func(sub *communities.Subscription) bool { - return sub.CommunityPrivilegedMemberSyncMessage != nil && - sub.CommunityPrivilegedMemberSyncMessage.CommunityPrivilegedUserSyncMessage.Type == protobuf.CommunityPrivilegedUserSyncMessage_CONTROL_NODE_ALL_SYNC_REQUESTS_TO_JOIN && - len(sub.CommunityPrivilegedMemberSyncMessage.Receivers) == 1 && - sub.CommunityPrivilegedMemberSyncMessage.Receivers[0].Equal(&s.bob.identity.PublicKey) - }) - _, err = s.owner.CreateCommunityTokenPermission(&requests.CreateCommunityTokenPermission{ CommunityID: community.ID(), Type: protobuf.CommunityTokenPermission_BECOME_TOKEN_MASTER, @@ -1043,15 +987,12 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestMemberReceivedEditedS }) s.Require().NoError(err) - err = <-waitOnOwnerSendSyncMessage - s.Require().NoError(err) - _, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool { return len(r.Communities()) == 1 && r.Communities()[0].IsTokenMaster() }, "bob didn't receive token master role") s.Require().NoError(err) - s.checkRevealedAccounts(community.ID(), s.bob, expectedAliceRevealedAccounts) + s.waitForRevealedAddresses(s.bob, community.ID(), expectedAliceRevealedAccounts) } func (s *MessengerCommunitiesSharedMemberAddressSuite) TestMemberReceivesAccountsOnRoleChangeFromAdminToTokenMaster() { @@ -1112,9 +1053,7 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestMemberReceivesAccount // check that bob received alice request to join without revealed accounts _, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool { - return len(r.RequestsToJoinCommunity()) == 1 && - r.RequestsToJoinCommunity()[0].PublicKey == s.alice.IdentityPublicKeyString() && - len(r.RequestsToJoinCommunity()[0].RevealedAccounts) == 0 + return checkRequestToJoinInResponse(r, s.alice, communities.RequestToJoinStateAccepted, 0) }, "alice request to join was not delivered to admin bob") s.Require().NoError(err) @@ -1140,19 +1079,10 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestMemberReceivesAccount s.Require().NoError(err) // check that bob received alice request to join with revealed accounts - _, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool { - revealedAccounts, err := s.bob.communitiesManager.GetRevealedAddresses(community.ID(), alicePublicKey) - s.Require().NoError(err) - return len(revealedAccounts) > 0 - }, "alice request to join was not delivered to token master bob") - s.Require().NoError(err) - - s.checkRevealedAccounts(community.ID(), s.bob, expectedAliceRevealedAccounts) + s.waitForRevealedAddresses(s.bob, community.ID(), expectedAliceRevealedAccounts) } func (s *MessengerCommunitiesSharedMemberAddressSuite) TestOwnerRejectAndAcceptAliceRequestToJoin() { - s.T().Skip("flaky test") - community, _ := createOnRequestCommunity(&s.Suite, s.owner) s.Require().False(community.AutoAccept()) @@ -1173,26 +1103,7 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestOwnerRejectAndAcceptA s.Require().Len(community.TokenPermissions(), 1) advertiseCommunityTo(&s.Suite, community, s.owner, s.bob) - - aliceArray64Bytes := common.HashPublicKey(&s.alice.identity.PublicKey) - aliceSignature := append([]byte{0}, aliceArray64Bytes...) - aliceRequest := &requests.RequestToJoinCommunity{ - CommunityID: community.ID(), - AddressesToReveal: []string{aliceAddress1}, - AirdropAddress: aliceAddress1, - Signatures: []types.HexBytes{aliceSignature}, - } - - bobArray64Bytes := common.HashPublicKey(&s.bob.identity.PublicKey) - bobSignature := append([]byte{0}, bobArray64Bytes...) - bobRequest := &requests.RequestToJoinCommunity{ - CommunityID: community.ID(), - AddressesToReveal: []string{bobAddress}, - AirdropAddress: bobAddress, - Signatures: []types.HexBytes{bobSignature}, - } - - joinOnRequestCommunity(&s.Suite, community, s.owner, s.bob, bobRequest) + s.joinOnRequestCommunityAsTokenMaster(community) community, err = s.owner.communitiesManager.GetByID(community.ID()) s.Require().NoError(err) @@ -1200,13 +1111,12 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestOwnerRejectAndAcceptA advertiseCommunityTo(&s.Suite, community, s.owner, s.alice) + aliceRequest := createRequestToJoinCommunity(&s.Suite, community.ID(), s.alice, alicePassword, []string{aliceAddress1}) aliceRequestToJoinID := requestToJoinCommunity(&s.Suite, s.owner, s.alice, aliceRequest) // check that bob received alice request to join without revealed accounts due to pending state _, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool { - return len(r.RequestsToJoinCommunity()) == 1 && - r.RequestsToJoinCommunity()[0].State == communities.RequestToJoinStatePending && - r.RequestsToJoinCommunity()[0].PublicKey == s.alice.IdentityPublicKeyString() + return checkRequestToJoinInResponse(r, s.alice, communities.RequestToJoinStatePending, 0) }, "alice pending request to join was not delivered to token master bob") s.Require().NoError(err) @@ -1220,9 +1130,7 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestOwnerRejectAndAcceptA // check that bob received owner decline sync msg _, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool { - return len(r.RequestsToJoinCommunity()) == 1 && - r.RequestsToJoinCommunity()[0].State == communities.RequestToJoinStateDeclined && - r.RequestsToJoinCommunity()[0].PublicKey == s.alice.IdentityPublicKeyString() + return checkRequestToJoinInResponse(r, s.alice, communities.RequestToJoinStateDeclined, 0) }, "alice declined request to join was not delivered to token master bob") s.Require().NoError(err) @@ -1235,9 +1143,7 @@ func (s *MessengerCommunitiesSharedMemberAddressSuite) TestOwnerRejectAndAcceptA s.Require().NoError(err) _, err = WaitOnMessengerResponse(s.bob, func(r *MessengerResponse) bool { - return len(r.RequestsToJoinCommunity()) == 1 && - r.RequestsToJoinCommunity()[0].State == communities.RequestToJoinStateAccepted && - r.RequestsToJoinCommunity()[0].PublicKey == s.alice.IdentityPublicKeyString() + return checkRequestToJoinInResponse(r, s.alice, communities.RequestToJoinStateAccepted, len(aliceRequest.AddressesToReveal)) }, "bob didn't receive accepted Alice request to join") s.Require().NoError(err) diff --git a/protocol/communities_messenger_signers_test.go b/protocol/communities_messenger_signers_test.go index 208726139..54b3dfd32 100644 --- a/protocol/communities_messenger_signers_test.go +++ b/protocol/communities_messenger_signers_test.go @@ -10,22 +10,14 @@ import ( "github.com/stretchr/testify/suite" "go.uber.org/zap" - gethcommon "github.com/ethereum/go-ethereum/common" - hexutil "github.com/ethereum/go-ethereum/common/hexutil" - utils "github.com/status-im/status-go/common" - gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" - "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/protocol/common" "github.com/status-im/status-go/protocol/communities" "github.com/status-im/status-go/protocol/communities/token" "github.com/status-im/status-go/protocol/protobuf" "github.com/status-im/status-go/protocol/requests" - "github.com/status-im/status-go/protocol/tt" "github.com/status-im/status-go/services/wallet/bigint" - "github.com/status-im/status-go/services/wallet/thirdparty" - "github.com/status-im/status-go/waku" ) func TestMessengerCommunitiesSignersSuite(t *testing.T) { @@ -33,68 +25,32 @@ func TestMessengerCommunitiesSignersSuite(t *testing.T) { } type MessengerCommunitiesSignersSuite struct { - suite.Suite + CommunitiesMessengerTestSuiteBase john *Messenger bob *Messenger alice *Messenger - - shh types.Waku - logger *zap.Logger - - collectiblesServiceMock *CollectiblesServiceMock - - accountsTestData map[string]string - - mockedBalances communities.BalancesByChain - mockedCollectibles communities.CollectiblesByChain } func (s *MessengerCommunitiesSignersSuite) SetupTest() { - + s.CommunitiesMessengerTestSuiteBase.SetupTest() communities.SetValidateInterval(300 * time.Millisecond) - s.logger = tt.MustCreateTestLogger() - - s.collectiblesServiceMock = &CollectiblesServiceMock{} - - config := waku.DefaultConfig - config.MinimumAcceptedPoW = 0 - shh := waku.New(&config, s.logger) - s.shh = gethbridge.NewGethWakuWrapper(shh) - s.Require().NoError(shh.Start()) - - accountPassword := "QWERTY" - - s.mockedBalances = make(communities.BalancesByChain) - s.mockedBalances[testChainID1] = make(map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big) - s.mockedBalances[testChainID1][gethcommon.HexToAddress(aliceAddress1)] = make(map[gethcommon.Address]*hexutil.Big) - s.mockedBalances[testChainID1][gethcommon.HexToAddress(bobAddress)] = make(map[gethcommon.Address]*hexutil.Big) - - s.mockedCollectibles = make(communities.CollectiblesByChain) - s.mockedCollectibles[testChainID1] = make(map[gethcommon.Address]thirdparty.TokenBalancesPerContractAddress) - s.mockedCollectibles[testChainID1][gethcommon.HexToAddress(aliceAddress1)] = make(thirdparty.TokenBalancesPerContractAddress) - s.mockedCollectibles[testChainID1][gethcommon.HexToAddress(bobAddress)] = make(thirdparty.TokenBalancesPerContractAddress) - - s.john = s.newMessenger("", []string{}) - s.bob = s.newMessenger(accountPassword, []string{aliceAddress1}) - s.alice = s.newMessenger(accountPassword, []string{bobAddress}) + s.john = s.newMessenger(accountPassword, []string{commonAccountAddress}) + s.bob = s.newMessenger(accountPassword, []string{bobAddress}) + s.alice = s.newMessenger(accountPassword, []string{aliceAddress1}) _, err := s.john.Start() s.Require().NoError(err) _, err = s.bob.Start() s.Require().NoError(err) _, err = s.alice.Start() s.Require().NoError(err) - - s.accountsTestData = make(map[string]string) - s.accountsTestData[common.PubkeyToHex(&s.bob.identity.PublicKey)] = bobAddress - s.accountsTestData[common.PubkeyToHex(&s.alice.identity.PublicKey)] = aliceAddress1 } func (s *MessengerCommunitiesSignersSuite) TearDownTest() { TearDownMessenger(&s.Suite, s.john) TearDownMessenger(&s.Suite, s.bob) TearDownMessenger(&s.Suite, s.alice) - _ = s.logger.Sync() + s.CommunitiesMessengerTestSuiteBase.TearDownTest() } func (s *MessengerCommunitiesSignersSuite) newMessenger(password string, walletAddresses []string) *Messenger { @@ -102,17 +58,10 @@ func (s *MessengerCommunitiesSignersSuite) newMessenger(password string, walletA communities.WithAllowForcingCommunityMembersReevaluation(true), } - return newTestCommunitiesMessenger(&s.Suite, s.shh, testCommunitiesMessengerConfig{ - testMessengerConfig: testMessengerConfig{ - logger: s.logger, - extraOptions: []Option{WithCommunityManagerOptions(communityManagerOptions)}, - }, - password: password, - walletAddresses: walletAddresses, - mockedBalances: &s.mockedBalances, - mockedCollectibles: &s.mockedCollectibles, - collectiblesService: s.collectiblesServiceMock, - }) + return s.newMessengerWithConfig(testMessengerConfig{ + logger: s.logger, + extraOptions: []Option{WithCommunityManagerOptions(communityManagerOptions)}, + }, password, walletAddresses) } func (s *MessengerCommunitiesSignersSuite) createCommunity(controlNode *Messenger) *communities.Community { @@ -124,40 +73,6 @@ func (s *MessengerCommunitiesSignersSuite) advertiseCommunityTo(controlNode *Mes advertiseCommunityTo(&s.Suite, community, controlNode, user) } -func (s *MessengerCommunitiesSignersSuite) joinCommunity(controlNode *Messenger, community *communities.Community, user *Messenger) { - accTestData := s.accountsTestData[common.PubkeyToHex(&s.alice.identity.PublicKey)] - array64Bytes := common.HashPublicKey(&s.alice.identity.PublicKey) - signature := append([]byte{0}, array64Bytes...) - - request := &requests.RequestToJoinCommunity{ - CommunityID: community.ID(), - AddressesToReveal: []string{accTestData}, - AirdropAddress: accTestData, - Signatures: []types.HexBytes{signature}, - } - - joinCommunity(&s.Suite, community, controlNode, user, request, "") -} - -func (s *MessengerCommunitiesSignersSuite) joinOnRequestCommunity(controlNode *Messenger, community *communities.Community, user *Messenger) { - accTestData := s.accountsTestData[common.PubkeyToHex(&user.identity.PublicKey)] - array64Bytes := common.HashPublicKey(&user.identity.PublicKey) - signature := append([]byte{0}, array64Bytes...) - - request := &requests.RequestToJoinCommunity{ - CommunityID: community.ID(), - AddressesToReveal: []string{accTestData}, - AirdropAddress: accTestData, - Signatures: []types.HexBytes{signature}, - } - - joinOnRequestCommunity(&s.Suite, community, controlNode, user, request) -} - -func (s *MessengerCommunitiesSignersSuite) makeAddressSatisfyTheCriteria(chainID uint64, address string, criteria *protobuf.TokenCriteria) { - makeAddressSatisfyTheCriteria(&s.Suite, s.mockedBalances, s.mockedCollectibles, chainID, address, criteria) -} - // John crates a community // Ownership is transferred to Alice // Alice kick all members Bob and John @@ -174,8 +89,8 @@ func (s *MessengerCommunitiesSignersSuite) TestControlNodeUpdateSigner() { s.advertiseCommunityTo(s.john, community, s.bob) s.advertiseCommunityTo(s.john, community, s.alice) - s.joinCommunity(s.john, community, s.bob) - s.joinCommunity(s.john, community, s.alice) + s.joinCommunity(community, s.john, s.bob) + s.joinCommunity(community, s.john, s.alice) // john mints owner token var chainID uint64 = 1 @@ -311,7 +226,7 @@ func (s *MessengerCommunitiesSignersSuite) TestControlNodeUpdateSigner() { s.Require().False(community.IsOwner()) // John manually joins the community - s.joinCommunity(s.alice, community, s.john) + s.joinCommunity(community, s.alice, s.john) // Alice change community name @@ -370,8 +285,8 @@ func (s *MessengerCommunitiesSignersSuite) TestAutoAcceptOnOwnershipChangeReques s.advertiseCommunityTo(s.john, community, s.bob) s.advertiseCommunityTo(s.john, community, s.alice) - s.joinOnRequestCommunity(s.john, community, s.bob) - s.joinOnRequestCommunity(s.john, community, s.alice) + s.joinOnRequestCommunity(community, s.john, s.bob) + s.joinOnRequestCommunity(community, s.john, s.alice) // john mints owner token var chainID uint64 = 1 @@ -508,7 +423,7 @@ func (s *MessengerCommunitiesSignersSuite) TestNewOwnerAcceptRequestToJoin() { s.advertiseCommunityTo(s.john, community, s.alice) - s.joinCommunity(s.john, community, s.alice) + s.joinCommunity(community, s.john, s.alice) // john mints owner token var chainID uint64 = 1 @@ -595,7 +510,7 @@ func (s *MessengerCommunitiesSignersSuite) TestNewOwnerAcceptRequestToJoin() { s.Require().NoError(err) // Bob joins the community - s.joinCommunity(s.alice, community, s.bob) + s.joinCommunity(community, s.alice, s.bob) } @@ -632,7 +547,7 @@ func (s *MessengerCommunitiesSignersSuite) forceCommunityChange(community *commu func (s *MessengerCommunitiesSignersSuite) testSyncCommunity(mintOwnerToken bool) { community := s.createCommunity(s.john) s.advertiseCommunityTo(s.john, community, s.alice) - s.joinCommunity(s.john, community, s.alice) + s.joinCommunity(community, s.john, s.alice) // FIXME: Remove this workaround when fixed: // https://github.com/status-im/status-go/issues/4413 @@ -921,8 +836,8 @@ func (s *MessengerCommunitiesSignersSuite) TestControlNodeDeviceChanged() { err = <-waitOnBobCommunityValidation s.Require().NoError(err) - s.joinOnRequestCommunity(s.john, community, s.alice) - s.joinOnRequestCommunity(s.john, community, s.bob) + s.joinOnRequestCommunity(community, s.john, s.alice) + s.joinOnRequestCommunity(community, s.john, s.bob) community, err = s.john.communitiesManager.GetByID(community.ID()) s.Require().NoError(err) diff --git a/protocol/communities_messenger_test.go b/protocol/communities_messenger_test.go index a4029af91..c576d5394 100644 --- a/protocol/communities_messenger_test.go +++ b/protocol/communities_messenger_test.go @@ -24,7 +24,6 @@ import ( gethcommon "github.com/ethereum/go-ethereum/common" - gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" "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" @@ -41,7 +40,6 @@ import ( v1protocol "github.com/status-im/status-go/protocol/v1" "github.com/status-im/status-go/server" localnotifications "github.com/status-im/status-go/services/local-notifications" - "github.com/status-im/status-go/waku" ) func TestMessengerCommunitiesSuite(t *testing.T) { @@ -49,30 +47,20 @@ func TestMessengerCommunitiesSuite(t *testing.T) { } type MessengerCommunitiesSuite struct { - suite.Suite + CommunitiesMessengerTestSuiteBase owner *Messenger bob *Messenger alice *Messenger - // If one wants to send messages between different instances of Messenger, - // a single Waku service should be shared. - shh types.Waku - logger *zap.Logger } func (s *MessengerCommunitiesSuite) SetupTest() { - s.logger = tt.MustCreateTestLogger() + s.CommunitiesMessengerTestSuiteBase.SetupTest() - config := waku.DefaultConfig - config.MinimumAcceptedPoW = 0 - shh := waku.New(&config, s.logger) - s.shh = gethbridge.NewGethWakuWrapper(shh) - s.Require().NoError(shh.Start()) - - s.owner = s.newMessenger() + s.owner = s.newMessenger("", []string{}) s.owner.account.CustomizationColor = multiaccountscommon.CustomizationColorOrange - s.bob = s.newMessenger() + s.bob = s.newMessenger(bobPassword, []string{bobAccountAddress}) s.bob.account.CustomizationColor = multiaccountscommon.CustomizationColorBlue - s.alice = s.newMessenger() + s.alice = s.newMessenger(alicePassword, []string{aliceAccountAddress}) s.alice.account.CustomizationColor = multiaccountscommon.CustomizationColorArmy s.owner.communitiesManager.RekeyInterval = 50 * time.Millisecond @@ -93,23 +81,7 @@ func (s *MessengerCommunitiesSuite) TearDownTest() { TearDownMessenger(&s.Suite, s.owner) TearDownMessenger(&s.Suite, s.bob) TearDownMessenger(&s.Suite, s.alice) - _ = s.logger.Sync() -} - -func (s *MessengerCommunitiesSuite) newMessengerWithKey(privateKey *ecdsa.PrivateKey) *Messenger { - return newTestCommunitiesMessenger(&s.Suite, s.shh, testCommunitiesMessengerConfig{ - testMessengerConfig: testMessengerConfig{ - privateKey: privateKey, - logger: s.logger, - }, - }) -} - -func (s *MessengerCommunitiesSuite) newMessenger() *Messenger { - privateKey, err := crypto.GenerateKey() - s.Require().NoError(err) - - return s.newMessengerWithKey(privateKey) + s.CommunitiesMessengerTestSuiteBase.TearDownTest() } func (s *MessengerCommunitiesSuite) setMessengerDisplayName(m *Messenger, name string) { @@ -258,8 +230,7 @@ func (s *MessengerCommunitiesSuite) TestJoiningOpenCommunityReturnsChatsResponse s.Require().Len(response.Chats(), 1) // Alice request to join community - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - + request := s.createRequestToJoinCommunity(community.ID(), s.alice) response, err = s.alice.RequestToJoinCommunity(request) s.Require().NoError(err) s.Require().NotNil(response) @@ -518,11 +489,6 @@ func (s *MessengerCommunitiesSuite) advertiseCommunityTo(community *communities. advertiseCommunityTo(&s.Suite, community, owner, user) } -func (s *MessengerCommunitiesSuite) joinCommunity(community *communities.Community, owner *Messenger, user *Messenger) { - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - joinCommunity(&s.Suite, community, owner, user, request, "") -} - func (s *MessengerCommunitiesSuite) TestCommunityContactCodeAdvertisement() { // add bob's profile keypair bobProfileKp := accounts.GetProfileKeypairForTest(true, false, false) @@ -861,7 +827,7 @@ func (s *MessengerCommunitiesSuite) TestRequestAccess() { s.Require().NoError(err) - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} + request := s.createRequestToJoinCommunity(community.ID(), s.alice) // We try to join the org response, err = s.alice.RequestToJoinCommunity(request) s.Require().NoError(err) @@ -1067,7 +1033,7 @@ func (s *MessengerCommunitiesSuite) TestDeletePendingRequestAccess() { s.Require().NoError(err) // Alice request to join community - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} + request := s.createRequestToJoinCommunity(community.ID(), s.alice) response, err = s.alice.RequestToJoinCommunity(request) s.Require().NoError(err) s.Require().NotNil(response) @@ -1174,7 +1140,7 @@ func (s *MessengerCommunitiesSuite) TestDeletePendingRequestAccess() { s.Require().True(notification.Deleted) // Alice request to join community - request = &requests.RequestToJoinCommunity{CommunityID: community.ID()} + request = s.createRequestToJoinCommunity(community.ID(), s.alice) response, err = s.alice.RequestToJoinCommunity(request) s.Require().NoError(err) s.Require().NotNil(response) @@ -1258,7 +1224,7 @@ func (s *MessengerCommunitiesSuite) TestDeletePendingRequestAccessWithDeclinedSt s.Require().NoError(err) // Alice request to join community - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} + request := s.createRequestToJoinCommunity(community.ID(), s.alice) response, err = s.alice.RequestToJoinCommunity(request) s.Require().NoError(err) s.Require().NotNil(response) @@ -1426,7 +1392,7 @@ func (s *MessengerCommunitiesSuite) TestDeletePendingRequestAccessWithDeclinedSt s.Require().False(notificationState.HasSeen) // Alice request to join community - request = &requests.RequestToJoinCommunity{CommunityID: community.ID()} + request = s.createRequestToJoinCommunity(community.ID(), s.alice) response, err = s.alice.RequestToJoinCommunity(request) s.Require().NoError(err) s.Require().NotNil(response) @@ -1509,7 +1475,7 @@ func (s *MessengerCommunitiesSuite) TestCancelRequestAccess() { s.Require().NoError(err) - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} + request := s.createRequestToJoinCommunity(community.ID(), s.alice) // We try to join the org response, err = s.alice.RequestToJoinCommunity(request) s.Require().NoError(err) @@ -1658,7 +1624,7 @@ func (s *MessengerCommunitiesSuite) TestRequestAccessAgain() { s.advertiseCommunityTo(community, s.bob, s.alice) - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} + request := s.createRequestToJoinCommunity(community.ID(), s.alice) // We try to join the org response, err = s.alice.RequestToJoinCommunity(request) s.Require().NoError(err) @@ -1800,7 +1766,7 @@ func (s *MessengerCommunitiesSuite) TestRequestAccessAgain() { s.Require().Len(requestsToJoin, 0) // We request again - request2 := &requests.RequestToJoinCommunity{CommunityID: community.ID()} + request2 := s.createRequestToJoinCommunity(community.ID(), s.alice) // We try to join the org, it should error as we are already a member response, err = s.alice.RequestToJoinCommunity(request2) s.Require().Error(err) @@ -1858,7 +1824,7 @@ func (s *MessengerCommunitiesSuite) TestRequestAccessAgain() { s.Require().False(aliceCommunity.HasMember(&s.alice.identity.PublicKey)) // Alice can request access again - request3 := &requests.RequestToJoinCommunity{CommunityID: community.ID()} + request3 := s.createRequestToJoinCommunity(community.ID(), s.alice) response, err = s.alice.RequestToJoinCommunity(request3) s.Require().NoError(err) s.Require().NotNil(response) @@ -1950,7 +1916,7 @@ func (s *MessengerCommunitiesSuite) TestDeclineAccess() { s.Require().NoError(err) - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} + request := s.createRequestToJoinCommunity(community.ID(), s.alice) // We try to join the org response, err = s.alice.RequestToJoinCommunity(request) s.Require().NoError(err) @@ -2419,7 +2385,12 @@ func (s *MessengerCommunitiesSuite) TestBanUser() { } func (s *MessengerCommunitiesSuite) createOtherDevice(m1 *Messenger) *Messenger { - m2 := s.newMessengerWithKey(m1.identity) + userPk := m1.IdentityPublicKeyString() + addresses, exists := s.accountsTestData[userPk] + s.Require().True(exists) + password, exists := s.accountsPasswords[userPk] + s.Require().True(exists) + m2 := s.newMessengerWithKey(m1.identity, password, addresses) tcs, err := m2.communitiesManager.All() s.Require().NoError(err, "m2.communitiesManager.All") @@ -2820,7 +2791,8 @@ func (s *MessengerCommunitiesSuite) TestSyncCommunity_RequestToJoin() { } // Alice requests to join the new community - response, err = s.alice.RequestToJoinCommunity(&requests.RequestToJoinCommunity{CommunityID: community.ID()}) + request := s.createRequestToJoinCommunity(community.ID(), s.alice) + response, err = s.alice.RequestToJoinCommunity(request) s.Require().NoError(err) s.Require().NotNil(response) s.Require().Len(response.RequestsToJoinCommunity(), 1) @@ -3495,7 +3467,7 @@ func (s *MessengerCommunitiesSuite) TestCommunityBanUserRequestToJoin() { s.Require().NoError(err) s.Require().Len(response.Communities(), 1) - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} + request := s.createRequestToJoinCommunity(community.ID(), s.alice) // We try to join the org rtj := s.alice.communitiesManager.CreateRequestToJoin(request, s.alice.account.GetCustomizationColor()) @@ -3509,7 +3481,7 @@ func (s *MessengerCommunitiesSuite) TestCommunityBanUserRequestToJoin() { EnsName: rtj.ENSName, DisplayName: displayName, CommunityId: community.ID(), - RevealedAccounts: make([]*protobuf.RevealedAccount, 0), + RevealedAccounts: rtj.RevealedAccounts, } s.Require().NoError(err) @@ -3527,7 +3499,7 @@ func (s *MessengerCommunitiesSuite) TestCommunityBanUserRequestToJoin() { } func (s *MessengerCommunitiesSuite) TestCommunityMaxNumberOfMembers() { - john := s.newMessenger() + john := s.newMessenger("johnPassword", []string{"0x0765400000000000000000000000000000000000"}) _, err := john.Start() s.Require().NoError(err) @@ -3550,7 +3522,7 @@ func (s *MessengerCommunitiesSuite) TestCommunityMaxNumberOfMembers() { s.joinCommunity(community, s.owner, s.alice) // Bob also tries to join, but he will be put in the requests to join to approve and won't join - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} + request := s.createRequestToJoinCommunity(community.ID(), s.bob) response, err := s.bob.RequestToJoinCommunity(request) s.Require().NoError(err) s.Require().NotNil(response) @@ -3580,7 +3552,7 @@ func (s *MessengerCommunitiesSuite) TestCommunityMaxNumberOfMembers() { s.Require().Equal(protobuf.CommunityPermissions_MANUAL_ACCEPT, updatedCommunity.Permissions().Access) // John also tries to join, but he his request will be ignored as it exceeds the max number of pending requests - requestJohn := &requests.RequestToJoinCommunity{CommunityID: community.ID()} + requestJohn := s.createRequestToJoinCommunity(community.ID(), john) response, err = john.RequestToJoinCommunity(requestJohn) s.Require().NoError(err) s.Require().NotNil(response) @@ -3686,7 +3658,7 @@ func (s *MessengerCommunitiesSuite) TestStartCommunityRekeyLoop() { s.Require().True(community.Encrypted()) s.Require().True(community.ChannelEncrypted(chat.CommunityChatID())) - s.owner.communitiesManager.PermissionChecker = &testPermissionChecker{} + s.mockPermissionCheckerForAllMessenger() s.advertiseCommunityTo(community, s.owner, s.bob) s.advertiseCommunityTo(community, s.owner, s.alice) @@ -3763,7 +3735,7 @@ func (s *MessengerCommunitiesSuite) TestCommunityRekeyAfterBan() { s.advertiseCommunityTo(c, s.owner, s.bob) s.advertiseCommunityTo(c, s.owner, s.alice) - s.owner.communitiesManager.PermissionChecker = &testPermissionChecker{} + s.mockPermissionCheckerForAllMessenger() s.joinCommunity(c, s.owner, s.bob) s.joinCommunity(c, s.owner, s.alice) @@ -3866,7 +3838,7 @@ func (s *MessengerCommunitiesSuite) TestCommunityRekeyAfterBanDisableCompatibili s.advertiseCommunityTo(c, s.owner, s.bob) s.advertiseCommunityTo(c, s.owner, s.alice) - s.owner.communitiesManager.PermissionChecker = &testPermissionChecker{} + s.mockPermissionCheckerForAllMessenger() s.joinCommunity(c, s.owner, s.bob) s.joinCommunity(c, s.owner, s.alice) @@ -3973,7 +3945,7 @@ func (s *MessengerCommunitiesSuite) TestRequestAndCancelCommunityAdminOffline() community, _ := s.createCommunity() s.advertiseCommunityTo(community, s.owner, s.alice) - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} + request := s.createRequestToJoinCommunity(community.ID(), s.alice) // We try to join the org response, err := s.alice.RequestToJoinCommunity(request) s.Require().NoError(err) @@ -3998,10 +3970,11 @@ func (s *MessengerCommunitiesSuite) TestRequestAndCancelCommunityAdminOffline() statusMessage.TransportLayer.Dst = community.PublicKey() requestToJoinProto := &protobuf.CommunityRequestToJoin{ - Clock: requestToJoin1.Clock, - EnsName: requestToJoin1.ENSName, - DisplayName: "Alice", - CommunityId: community.ID(), + Clock: requestToJoin1.Clock, + EnsName: requestToJoin1.ENSName, + DisplayName: "Alice", + CommunityId: community.ID(), + RevealedAccounts: requestToJoin1.RevealedAccounts, } err = s.owner.HandleCommunityRequestToJoin(messageState, requestToJoinProto, &statusMessage) @@ -4527,13 +4500,11 @@ func (s *MessengerCommunitiesSuite) TestMemberMessagesHasImageLink() { addMediaServer(s.owner) community, communityChat := s.createCommunity() - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - advertiseCommunityTo(&s.Suite, community, s.owner, s.alice) - joinCommunity(&s.Suite, community, s.owner, s.alice, request, "") + s.joinCommunity(community, s.owner, s.alice) advertiseCommunityTo(&s.Suite, community, s.owner, s.bob) - joinCommunity(&s.Suite, community, s.owner, s.bob, request, "") + s.joinCommunity(community, s.owner, s.bob) // WHEN: alice sends an image message sentMessage := s.sendImageToCommunity(s.alice, communityChat.ID) @@ -4566,8 +4537,7 @@ func (s *MessengerCommunitiesSuite) TestOpenAndNotJoinedCommunityNewChannelIsNot // Bob joins the community advertiseCommunityTo(&s.Suite, community, s.owner, s.bob) - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - joinCommunity(&s.Suite, community, s.owner, s.bob, request, "") + s.joinCommunity(community, s.owner, s.bob) // Alice just observes the community advertiseCommunityTo(&s.Suite, community, s.owner, s.alice) @@ -4661,8 +4631,7 @@ func (s *MessengerCommunitiesSuite) TestAliceDoesNotReceiveMentionWhenSpectating // Bob JOINS the community advertiseCommunityTo(&s.Suite, community, s.owner, s.bob) - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - joinCommunity(&s.Suite, community, s.owner, s.bob, request, "") + s.joinCommunity(community, s.owner, s.bob) // Check Alice gets the updated community _, err = WaitOnMessengerResponse( @@ -4689,8 +4658,7 @@ func (s *MessengerCommunitiesSuite) TestAliceDoesNotReceiveMentionWhenSpectating s.Require().NoError(err) // Alice joins community - request = &requests.RequestToJoinCommunity{CommunityID: community.ID()} - joinCommunity(&s.Suite, community, s.owner, s.alice, request, "") + s.joinCommunity(community, s.owner, s.alice) // Bob sends a message with mention sentMessage = s.sendMention(s.bob, communityChat.ID) @@ -4714,8 +4682,7 @@ func (s *MessengerCommunitiesSuite) TestAliceDidNotProcessOutdatedCommunityReque community, _ := s.createCommunity() advertiseCommunityTo(&s.Suite, community, s.owner, s.alice) - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - joinCommunity(&s.Suite, community, s.owner, s.alice, request, "") + s.joinCommunity(community, s.owner, s.alice) response, err := s.alice.LeaveCommunity(community.ID()) s.Require().NoError(err) @@ -4765,7 +4732,9 @@ func (s *MessengerCommunitiesSuite) TestAliceDidNotProcessOutdatedCommunityReque s.Require().Error(err, ErrOutdatedCommunityRequestToJoin) // alice receives new request to join when she's already joined - requestToJoinResponse.Clock = requestToJoinResponse.Clock + 1 + // Note: requestToJoinResponse clock is stored as milliseconds, but requestToJoin in database stored + // as seconds + requestToJoinResponse.Clock = requestToJoinResponse.Clock + 1000 err = s.alice.HandleCommunityRequestToJoinResponse(state, requestToJoinResponse, nil) s.Require().NoError(err) } @@ -4832,3 +4801,9 @@ func (s *MessengerCommunitiesSuite) TestIgnoreOutdatedCommunityDescription() { s.Require().Len(communityFromDB.Members(), 3) } } + +func (s *MessengerCommunitiesSuite) mockPermissionCheckerForAllMessenger() { + s.owner.communitiesManager.PermissionChecker = &testPermissionChecker{} + s.alice.communitiesManager.PermissionChecker = &testPermissionChecker{} + s.bob.communitiesManager.PermissionChecker = &testPermissionChecker{} +} diff --git a/protocol/communities_messenger_test_suite_base_test.go b/protocol/communities_messenger_test_suite_base_test.go new file mode 100644 index 000000000..c5fb6aeb1 --- /dev/null +++ b/protocol/communities_messenger_test_suite_base_test.go @@ -0,0 +1,140 @@ +package protocol + +import ( + "crypto/ecdsa" + "math/big" + + "github.com/stretchr/testify/suite" + "go.uber.org/zap" + + gethcommon "github.com/ethereum/go-ethereum/common" + hexutil "github.com/ethereum/go-ethereum/common/hexutil" + + gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" + "github.com/status-im/status-go/eth-node/crypto" + "github.com/status-im/status-go/eth-node/types" + "github.com/status-im/status-go/protocol/communities" + "github.com/status-im/status-go/protocol/protobuf" + "github.com/status-im/status-go/protocol/requests" + "github.com/status-im/status-go/protocol/tt" + "github.com/status-im/status-go/waku" +) + +// TODO: in future adapt this struct to use waku v2 and switch all tests to waku v2 +type CommunitiesMessengerTestSuiteBase struct { + suite.Suite + // If one wants to send messages between different instances of Messenger, + // a single Waku service should be shared. + shh types.Waku + logger *zap.Logger + mockedBalances communities.BalancesByChain + mockedCollectibles communities.CollectiblesByChain + collectiblesServiceMock *CollectiblesServiceMock + collectiblesManagerMock *CollectiblesManagerMock + accountsTestData map[string][]string + accountsPasswords map[string]string +} + +func (s *CommunitiesMessengerTestSuiteBase) SetupTest() { + s.logger = tt.MustCreateTestLogger() + s.collectiblesServiceMock = &CollectiblesServiceMock{} + s.accountsTestData = make(map[string][]string) + s.accountsPasswords = make(map[string]string) + s.mockedCollectibles = make(communities.CollectiblesByChain) + s.collectiblesManagerMock = &CollectiblesManagerMock{ + Collectibles: &s.mockedCollectibles, + } + + s.mockedBalances = make(communities.BalancesByChain) + + config := waku.DefaultConfig + config.MinimumAcceptedPoW = 0 + shh := waku.New(&config, s.logger) + s.shh = gethbridge.NewGethWakuWrapper(shh) + s.Require().NoError(shh.Start()) +} + +func (s *CommunitiesMessengerTestSuiteBase) TearDownTest() { + _ = s.logger.Sync() +} + +func (s *CommunitiesMessengerTestSuiteBase) newMessenger(password string, walletAddresses []string) *Messenger { + privateKey, err := crypto.GenerateKey() + s.Require().NoError(err) + + return s.newMessengerWithConfig(testMessengerConfig{ + logger: s.logger, + privateKey: privateKey, + }, password, walletAddresses) +} + +func (s *CommunitiesMessengerTestSuiteBase) newMessengerWithKey(privateKey *ecdsa.PrivateKey, password string, walletAddresses []string) *Messenger { + return s.newMessengerWithConfig(testMessengerConfig{ + privateKey: privateKey, + logger: s.logger, + }, password, walletAddresses) +} + +func (s *CommunitiesMessengerTestSuiteBase) newMessengerWithConfig(config testMessengerConfig, password string, walletAddresses []string) *Messenger { + messenger := newTestCommunitiesMessenger(&s.Suite, s.shh, testCommunitiesMessengerConfig{ + testMessengerConfig: config, + password: password, + walletAddresses: walletAddresses, + mockedBalances: &s.mockedBalances, + collectiblesService: s.collectiblesServiceMock, + collectiblesManager: s.collectiblesManagerMock, + }) + + publicKey := messenger.IdentityPublicKeyString() + s.accountsTestData[publicKey] = walletAddresses + s.accountsPasswords[publicKey] = password + return messenger +} + +func (s *CommunitiesMessengerTestSuiteBase) joinCommunity(community *communities.Community, controlNode *Messenger, user *Messenger) { + userPk := user.IdentityPublicKeyString() + addresses, exists := s.accountsTestData[userPk] + s.Require().True(exists) + password, exists := s.accountsPasswords[userPk] + s.Require().True(exists) + joinCommunity(&s.Suite, community.ID(), controlNode, user, password, addresses) +} + +func (s *CommunitiesMessengerTestSuiteBase) joinOnRequestCommunity(community *communities.Community, controlNode *Messenger, user *Messenger) { + userPk := user.IdentityPublicKeyString() + addresses, exists := s.accountsTestData[userPk] + s.Require().True(exists) + password, exists := s.accountsPasswords[userPk] + s.Require().True(exists) + joinOnRequestCommunity(&s.Suite, community.ID(), controlNode, user, password, addresses) +} + +func (s *CommunitiesMessengerTestSuiteBase) createRequestToJoinCommunity(communityID types.HexBytes, user *Messenger) *requests.RequestToJoinCommunity { + userPk := user.IdentityPublicKeyString() + addresses, exists := s.accountsTestData[userPk] + s.Require().True(exists) + password, exists := s.accountsPasswords[userPk] + s.Require().True(exists) + return createRequestToJoinCommunity(&s.Suite, communityID, user, password, addresses) +} + +func (s *CommunitiesMessengerTestSuiteBase) makeAddressSatisfyTheCriteria(chainID uint64, address string, criteria *protobuf.TokenCriteria) { + walletAddress := gethcommon.HexToAddress(address) + contractAddress := gethcommon.HexToAddress(criteria.ContractAddresses[chainID]) + balance, ok := new(big.Int).SetString(criteria.AmountInWei, 10) + s.Require().True(ok) + + if _, exists := s.mockedBalances[chainID]; !exists { + s.mockedBalances[chainID] = make(map[gethcommon.Address]map[gethcommon.Address]*hexutil.Big) + } + + if _, exists := s.mockedBalances[chainID][walletAddress]; !exists { + s.mockedBalances[chainID][walletAddress] = make(map[gethcommon.Address]*hexutil.Big) + } + + if _, exists := s.mockedBalances[chainID][walletAddress][contractAddress]; !exists { + s.mockedBalances[chainID][walletAddress][contractAddress] = (*hexutil.Big)(balance) + } + + makeAddressSatisfyTheCriteria(&s.Suite, s.mockedBalances, s.mockedCollectibles, chainID, address, criteria) +} diff --git a/protocol/communities_messenger_token_permissions_test.go b/protocol/communities_messenger_token_permissions_test.go index c3dbf85c9..3cb64c83b 100644 --- a/protocol/communities_messenger_token_permissions_test.go +++ b/protocol/communities_messenger_token_permissions_test.go @@ -148,6 +148,9 @@ type MessengerCommunitiesTokenPermissionsSuite struct { mockedBalances communities.BalancesByChain mockedCollectibles communities.CollectiblesByChain collectiblesServiceMock *CollectiblesServiceMock + collectiblesManagerMock *CollectiblesManagerMock + accountsTestData map[string][]string + accountsPasswords map[string]string } func (s *MessengerCommunitiesTokenPermissionsSuite) SetupTest() { @@ -159,6 +162,13 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) SetupTest() { s.bobWaku = nil s.aliceWaku = nil + s.accountsTestData = make(map[string][]string) + s.accountsPasswords = make(map[string]string) + + s.mockedCollectibles = make(communities.CollectiblesByChain) + s.collectiblesManagerMock = &CollectiblesManagerMock{ + Collectibles: &s.mockedCollectibles, + } s.resetMockedBalances() s.logger = tt.MustCreateTestLogger() @@ -205,7 +215,7 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) newMessenger(password string } extraOptions = append(extraOptions, WithCommunityManagerOptions(communityManagerOptions)) - return newTestCommunitiesMessenger(&s.Suite, waku, testCommunitiesMessengerConfig{ + messenger := newTestCommunitiesMessenger(&s.Suite, waku, testCommunitiesMessengerConfig{ testMessengerConfig: testMessengerConfig{ logger: s.logger.Named(name), extraOptions: extraOptions, @@ -213,23 +223,32 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) newMessenger(password string password: password, walletAddresses: walletAddresses, mockedBalances: &s.mockedBalances, - mockedCollectibles: &s.mockedCollectibles, collectiblesService: s.collectiblesServiceMock, + collectiblesManager: s.collectiblesManagerMock, }) + + publicKey := messenger.IdentityPublicKeyString() + s.accountsTestData[publicKey] = walletAddresses + s.accountsPasswords[publicKey] = password + + return messenger } -func (s *MessengerCommunitiesTokenPermissionsSuite) joinCommunity(community *communities.Community, user *Messenger, password string, addresses []string) { - s.joinCommunityWithAirdropAddress(community, user, password, addresses, "") +func (s *MessengerCommunitiesTokenPermissionsSuite) createRequestToJoinCommunity(communityID types.HexBytes, user *Messenger) *requests.RequestToJoinCommunity { + userPk := user.IdentityPublicKeyString() + addresses, exists := s.accountsTestData[userPk] + s.Require().True(exists) + password, exists := s.accountsPasswords[userPk] + s.Require().True(exists) + return createRequestToJoinCommunity(&s.Suite, communityID, user, password, addresses) } -func (s *MessengerCommunitiesTokenPermissionsSuite) joinCommunityWithAirdropAddress(community *communities.Community, user *Messenger, password string, addresses []string, airdropAddress string) { - passwdHash := types.EncodeHex(crypto.Keccak256([]byte(password))) - if airdropAddress == "" && len(addresses) > 0 { - airdropAddress = addresses[0] - } - - request := &requests.RequestToJoinCommunity{CommunityID: community.ID(), AddressesToReveal: addresses, AirdropAddress: airdropAddress} - joinCommunity(&s.Suite, community, s.owner, user, request, passwdHash) +func (s *MessengerCommunitiesTokenPermissionsSuite) joinCommunity(community *communities.Community, user *Messenger) { + addresses, exists := s.accountsTestData[user.IdentityPublicKeyString()] + s.Require().True(exists) + password, exists := s.accountsPasswords[user.IdentityPublicKeyString()] + s.Require().True(exists) + joinCommunity(&s.Suite, community.ID(), s.owner, user, password, addresses) } func (s *MessengerCommunitiesTokenPermissionsSuite) advertiseCommunityTo(community *communities.Community, user *Messenger) { @@ -393,8 +412,10 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestCommunityTokensMetadata( s.Require().Equal(tokensMetadata[0].Version, newToken.Version) } +// Note: (mprakhov) after providing revealed addresses this test must be fixed func (s *MessengerCommunitiesTokenPermissionsSuite) TestRequestAccessWithENSTokenPermission() { - community, _ := s.createCommunity() + s.T().Skip("flaky test") + community, _ := createCommunity(&s.Suite, s.owner) createTokenPermission := &requests.CreateCommunityTokenPermission{ CommunityID: community.ID(), @@ -419,7 +440,7 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestRequestAccessWithENSToke s.Require().NoError(err) s.Require().Len(declinedRequests, 0) - requestToJoin := &requests.RequestToJoinCommunity{CommunityID: community.ID()} + requestToJoin := s.createRequestToJoinCommunity(community.ID(), s.alice) // We try to join the org response, err = s.alice.RequestToJoinCommunity(requestToJoin) s.Require().NoError(err) @@ -510,7 +531,7 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestBecomeMemberPermissions( // bob joins the community s.advertiseCommunityTo(community, s.bob) - s.joinCommunityWithAirdropAddress(community, s.bob, bobPassword, []string{bobAddress}, "") + s.joinCommunity(community, s.bob) messages := []string{ "1-message", // RandomLettersString(10), // successful message on open community @@ -609,7 +630,7 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestBecomeMemberPermissions( s.Require().NoError(err) // bob tries to join, but he doesn't satisfy so the request isn't sent - request := &requests.RequestToJoinCommunity{CommunityID: community.ID(), AddressesToReveal: []string{bobAddress}, AirdropAddress: bobAddress} + request := s.createRequestToJoinCommunity(community.ID(), s.bob) _, err = s.bob.RequestToJoinCommunity(request) s.Require().ErrorIs(err, communities.ErrPermissionToJoinNotSatisfied) @@ -631,7 +652,7 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestBecomeMemberPermissions( }) // bob re-joins the community - s.joinCommunity(community, s.bob, bobPassword, []string{bobAddress}) + s.joinCommunity(community, s.bob) err = <-waitOnCommunityKeyToBeDistributedToBob s.Require().NoError(err) @@ -686,7 +707,7 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestJoinCommunityWithAdminPe s.advertiseCommunityTo(community, s.bob) // Bob should still be able to join even if there is a permission to be an admin - s.joinCommunity(community, s.bob, bobPassword, []string{}) + s.joinCommunity(community, s.bob) // Verify that we have Bob's revealed account revealedAccounts, err := s.owner.GetRevealedAccounts(community.ID(), common.PubkeyToHex(&s.bob.identity.PublicKey)) @@ -756,7 +777,7 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestJoinCommunityAsMemberWit // Bob should still be able to join even though he doesn't satisfy the admin requirement // because he satisfies the member one - s.joinCommunity(community, s.bob, bobPassword, []string{}) + s.joinCommunity(community, s.bob) // Verify that we have Bob's revealed account revealedAccounts, err := s.owner.GetRevealedAccounts(community.ID(), common.PubkeyToHex(&s.bob.identity.PublicKey)) @@ -834,7 +855,7 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestJoinCommunityAsAdminWith // Bob should still be able to join even though he doesn't satisfy the member requirement // because he satisfies the admin one - s.joinCommunity(community, s.bob, bobPassword, []string{}) + s.joinCommunity(community, s.bob) // Verify that we have Bob's revealed account revealedAccounts, err := s.owner.GetRevealedAccounts(community.ID(), common.PubkeyToHex(&s.bob.identity.PublicKey)) @@ -865,7 +886,7 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) testViewChannelPermissions(v // bob joins the community s.advertiseCommunityTo(community, s.bob) - s.joinCommunity(community, s.bob, bobPassword, []string{}) + s.joinCommunity(community, s.bob) // send message to the channel msg := s.sendChatMessage(s.owner, chat.ID, "hello on open community") @@ -1042,7 +1063,7 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestAnnouncementsChannelPerm // bob joins the community s.advertiseCommunityTo(community, s.bob) - s.joinCommunity(community, s.bob, bobPassword, []string{}) + s.joinCommunity(community, s.bob) // setup view channel permission channelPermissionRequest := requests.CreateCommunityTokenPermission{ @@ -1135,7 +1156,7 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestSearchMessageinPermissio // bob joins the community s.advertiseCommunityTo(community, s.bob) - s.joinCommunity(community, s.bob, bobPassword, []string{}) + s.joinCommunity(community, s.bob) // send message to the original channel msg := s.sendChatMessage(s.owner, chat.ID, "hello on open community") @@ -1240,7 +1261,7 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestMemberRoleGetUpdatedWhen // bob joins the community s.advertiseCommunityTo(community, s.bob) - s.joinCommunity(community, s.bob, bobPassword, []string{}) + s.joinCommunity(community, s.bob) community, err := s.owner.communitiesManager.GetByID(community.ID()) s.Require().NoError(err) @@ -1499,7 +1520,7 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) testReevaluateMemberPrivileg s.makeAddressSatisfyTheCriteria(testChainID1, aliceAddress1, tokenPermission.TokenCriteria[0]) // join community as a privileged user - s.joinCommunity(community, s.alice, alicePassword, []string{aliceAddress1}) + s.joinCommunity(community, s.alice) community, err = s.owner.communitiesManager.GetByID(community.ID()) s.Require().NoError(err) @@ -1657,7 +1678,7 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) testReevaluateMemberPrivileg }) // join community as a privileged user - s.joinCommunity(community, s.alice, alicePassword, []string{aliceAddress1}) + s.joinCommunity(community, s.alice) community, err = s.owner.communitiesManager.GetByID(community.ID()) s.Require().NoError(err) @@ -1776,7 +1797,7 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestResendEncryptionKeyOnBac // bob joins the community s.advertiseCommunityTo(community, s.bob) - s.joinCommunity(community, s.bob, bobPassword, []string{}) + s.joinCommunity(community, s.bob) // setup view channel permission channelPermissionRequest := requests.CreateCommunityTokenPermission{ @@ -2166,7 +2187,7 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestImportDecryptedArchiveMe return ok }) - s.joinCommunity(community, s.bob, bobPassword, []string{}) + s.joinCommunity(community, s.bob) err = <-waitForKeysDistributedToBob s.Require().NoError(err) diff --git a/protocol/messenger_activity_center_test.go b/protocol/messenger_activity_center_test.go index 15a3ed302..f365cfcdf 100644 --- a/protocol/messenger_activity_center_test.go +++ b/protocol/messenger_activity_center_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/suite" + multiaccountscommon "github.com/status-im/status-go/multiaccounts/common" "github.com/status-im/status-go/protocol/common" "github.com/status-im/status-go/protocol/communities" "github.com/status-im/status-go/protocol/protobuf" @@ -26,19 +27,34 @@ func (s *MessengerActivityCenterMessageSuite) advertiseCommunityTo(community *co } func (s *MessengerActivityCenterMessageSuite) joinCommunity(community *communities.Community, owner *Messenger, user *Messenger) { - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - joinCommunity(&s.Suite, community, owner, user, request, "") + joinCommunity(&s.Suite, community.ID(), owner, user, accountPassword, []string{commonAccountAddress}) } type MessengerActivityCenterMessageSuite struct { - MessengerBaseTestSuite + CommunitiesMessengerTestSuiteBase + m *Messenger // main instance of Messenger +} + +func (s *MessengerActivityCenterMessageSuite) SetupTest() { + s.CommunitiesMessengerTestSuiteBase.SetupTest() + + s.m = s.newMessenger(alicePassword, []string{aliceAccountAddress}) + s.m.account.CustomizationColor = multiaccountscommon.CustomizationColorOrange + + _, err := s.m.Start() + s.Require().NoError(err) +} + +func (s *MessengerActivityCenterMessageSuite) TearDownTest() { + TearDownMessenger(&s.Suite, s.m) + s.CommunitiesMessengerTestSuiteBase.TearDownTest() } func (s *MessengerActivityCenterMessageSuite) TestDeleteOneToOneChat() { - theirMessenger := s.newMessenger() + theirMessenger := s.newMessenger(accountPassword, []string{commonAccountAddress}) defer TearDownMessenger(&s.Suite, theirMessenger) - theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport) + theirChat := CreateOneToOneChat("Their 1TO1", s.m.IdentityPublicKey(), s.m.transport) err := theirMessenger.SaveChat(theirChat) s.Require().NoError(err) @@ -89,7 +105,7 @@ func (s *MessengerActivityCenterMessageSuite) TestDeleteOneToOneChat() { func (s *MessengerActivityCenterMessageSuite) TestEveryoneMentionTag() { alice := s.m - bob := s.newMessenger() + bob := s.newMessenger(bobPassword, []string{bobAddress}) defer TearDownMessenger(&s.Suite, bob) // Create a community @@ -129,7 +145,7 @@ func (s *MessengerActivityCenterMessageSuite) TestEveryoneMentionTag() { func (s *MessengerActivityCenterMessageSuite) TestReplyWithImage() { alice := s.m - bob := s.newMessenger() + bob := s.newMessenger(bobPassword, []string{bobAddress}) defer TearDownMessenger(&s.Suite, bob) // create an http server @@ -211,7 +227,7 @@ func (s *MessengerActivityCenterMessageSuite) TestReplyWithImage() { func (s *MessengerActivityCenterMessageSuite) TestMuteCommunityActivityCenterNotifications() { alice := s.m - bob := s.newMessenger() + bob := s.newMessenger(bobPassword, []string{bobAddress}) defer TearDownMessenger(&s.Suite, bob) // Create a community @@ -261,7 +277,7 @@ func (s *MessengerActivityCenterMessageSuite) TestMuteCommunityActivityCenterNot func (s *MessengerActivityCenterMessageSuite) TestReadCommunityOverviewNotifications() { alice := s.m - bob := s.newMessenger() + bob := s.newMessenger(bobPassword, []string{bobAddress}) defer TearDownMessenger(&s.Suite, bob) // Create a community @@ -284,7 +300,7 @@ func (s *MessengerActivityCenterMessageSuite) TestReadCommunityOverviewNotificat func (s *MessengerActivityCenterMessageSuite) prepareCommunityChannelWithMentionAndReply() (*Messenger, *Messenger, *common.Message, *common.Message, *communities.Community) { alice := s.m - bob := s.newMessenger() + bob := s.newMessenger(bobPassword, []string{bobAddress}) defer TearDownMessenger(&s.Suite, bob) // Create a community @@ -458,7 +474,7 @@ func (s *MessengerActivityCenterMessageSuite) TestMarkAllActivityCenterNotificat func (s *MessengerActivityCenterMessageSuite) TestAliceDoesNotReceiveCommunityNotificationsBeforeJoined() { alice := s.m - bob := s.newMessenger() + bob := s.newMessenger(bobPassword, []string{bobAddress}) defer TearDownMessenger(&s.Suite, bob) // Create a community diff --git a/protocol/messenger_communities.go b/protocol/messenger_communities.go index 3012e1ea8..b47ecac98 100644 --- a/protocol/messenger_communities.go +++ b/protocol/messenger_communities.go @@ -1435,7 +1435,7 @@ func (m *Messenger) RequestToJoinCommunity(request *requests.RequestToJoinCommun logger := m.logger.Named("RequestToJoinCommunity") logger.Debug("Addresses to reveal", zap.Any("Addresses:", request.AddressesToReveal)) - if err := request.Validate(len(request.AddressesToReveal) > 0); err != nil { + if err := request.Validate(); err != nil { logger.Debug("request failed to validate", zap.Error(err), zap.Any("request", request)) return nil, err } diff --git a/protocol/messenger_communities_sharding_test.go b/protocol/messenger_communities_sharding_test.go index 8257e0ade..307df61ad 100644 --- a/protocol/messenger_communities_sharding_test.go +++ b/protocol/messenger_communities_sharding_test.go @@ -34,10 +34,24 @@ type MessengerCommunitiesShardingSuite struct { aliceUnhandledMessagesTracker *unhandledMessagesTracker logger *zap.Logger + + mockedBalances communities.BalancesByChain + mockedCollectibles communities.CollectiblesByChain + collectiblesServiceMock *CollectiblesServiceMock + collectiblesManagerMock *CollectiblesManagerMock + accountsTestData map[string][]string + accountsPasswords map[string]string } func (s *MessengerCommunitiesShardingSuite) SetupTest() { s.logger = tt.MustCreateTestLogger() + s.collectiblesServiceMock = &CollectiblesServiceMock{} + s.mockedCollectibles = make(communities.CollectiblesByChain) + s.collectiblesManagerMock = &CollectiblesManagerMock{ + Collectibles: &s.mockedCollectibles, + } + s.accountsTestData = make(map[string][]string) + s.accountsPasswords = make(map[string]string) wakuNodes := CreateWakuV2Network(&s.Suite, s.logger, []string{"owner", "alice"}) @@ -49,7 +63,11 @@ func (s *MessengerCommunitiesShardingSuite) SetupTest() { name: "owner", logger: s.logger, }, - nodeConfig: nodeConfig, + walletAddresses: []string{}, + password: "", + nodeConfig: nodeConfig, + mockedBalances: &s.mockedBalances, + collectiblesManager: s.collectiblesManagerMock, }) s.aliceUnhandledMessagesTracker = &unhandledMessagesTracker{ @@ -62,7 +80,10 @@ func (s *MessengerCommunitiesShardingSuite) SetupTest() { logger: s.logger, unhandledMessagesTracker: s.aliceUnhandledMessagesTracker, }, - nodeConfig: nodeConfig, + walletAddresses: []string{aliceAddress1}, + password: alicePassword, + nodeConfig: nodeConfig, + mockedBalances: &s.mockedBalances, }) _, err := s.owner.Start() @@ -119,7 +140,7 @@ func (s *MessengerCommunitiesShardingSuite) TestPostToCommunityChat() { community, chat := createCommunity(&s.Suite, s.owner) advertiseCommunityToUserOldWay(&s.Suite, community, s.owner, s.alice) - joinCommunity(&s.Suite, community, s.owner, s.alice, &requests.RequestToJoinCommunity{CommunityID: community.ID()}, "") + joinCommunity(&s.Suite, community.ID(), s.owner, s.alice, alicePassword, []string{aliceAddress1}) // Members should be able to receive messages in a community with sharding enabled. { @@ -153,7 +174,7 @@ func (s *MessengerCommunitiesShardingSuite) TestIgnoreOutdatedShardKey() { community, _ := createCommunity(&s.Suite, s.owner) advertiseCommunityToUserOldWay(&s.Suite, community, s.owner, s.alice) - joinCommunity(&s.Suite, community, s.owner, s.alice, &requests.RequestToJoinCommunity{CommunityID: community.ID()}, "") + joinCommunity(&s.Suite, community.ID(), s.owner, s.alice, alicePassword, []string{aliceAddress1}) shard := &shard.Shard{ Cluster: shard.MainStatusShardCluster, diff --git a/protocol/messenger_delete_message_for_everyone_test.go b/protocol/messenger_delete_message_for_everyone_test.go index 90b9022cb..81fb82ec4 100644 --- a/protocol/messenger_delete_message_for_everyone_test.go +++ b/protocol/messenger_delete_message_for_everyone_test.go @@ -5,17 +5,11 @@ import ( "testing" "github.com/stretchr/testify/suite" - "go.uber.org/zap" - "github.com/ethereum/go-ethereum/crypto" - gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" - "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/protocol/common" "github.com/status-im/status-go/protocol/communities" "github.com/status-im/status-go/protocol/protobuf" "github.com/status-im/status-go/protocol/requests" - "github.com/status-im/status-go/protocol/tt" - "github.com/status-im/status-go/waku" ) func TestMessengerDeleteMessageForEveryoneSuite(t *testing.T) { @@ -23,42 +17,31 @@ func TestMessengerDeleteMessageForEveryoneSuite(t *testing.T) { } type MessengerDeleteMessageForEveryoneSuite struct { - suite.Suite + CommunitiesMessengerTestSuiteBase admin *Messenger moderator *Messenger bob *Messenger - shh types.Waku - logger *zap.Logger } func (s *MessengerDeleteMessageForEveryoneSuite) SetupTest() { - s.logger = tt.MustCreateTestLogger() + s.CommunitiesMessengerTestSuiteBase.SetupTest() + s.admin = s.newMessenger("", []string{}) + s.bob = s.newMessenger(bobPassword, []string{bobPassword}) + s.moderator = s.newMessenger(aliceAccountAddress, []string{aliceAddress1}) - config := waku.DefaultConfig - config.MinimumAcceptedPoW = 0 - shh := waku.New(&config, s.logger) - s.shh = gethbridge.NewGethWakuWrapper(shh) - s.Require().NoError(shh.Start()) - - s.admin = s.newMessenger() - s.bob = s.newMessenger() - s.moderator = s.newMessenger() + _, err := s.admin.Start() + s.Require().NoError(err) + _, err = s.bob.Start() + s.Require().NoError(err) + _, err = s.moderator.Start() + s.Require().NoError(err) } func (s *MessengerDeleteMessageForEveryoneSuite) TearDownTest() { TearDownMessenger(&s.Suite, s.admin) TearDownMessenger(&s.Suite, s.bob) TearDownMessenger(&s.Suite, s.moderator) - _ = s.logger.Sync() -} - -func (s *MessengerDeleteMessageForEveryoneSuite) newMessenger() *Messenger { - privateKey, err := crypto.GenerateKey() - s.Require().NoError(err) - - messenger, err := newMessengerWithKey(s.shh, privateKey, s.logger, nil) - s.Require().NoError(err) - return messenger + s.CommunitiesMessengerTestSuiteBase.TearDownTest() } func (s *MessengerDeleteMessageForEveryoneSuite) testSendAndDeleteMessage(messageToSend *common.Message, shouldError bool) { @@ -99,13 +82,11 @@ func (s *MessengerDeleteMessageForEveryoneSuite) TestDeleteMessageForEveryone() community := s.createCommunity() communityChat := s.createCommunityChat(community) - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - advertiseCommunityTo(&s.Suite, community, s.admin, s.moderator) - joinCommunity(&s.Suite, community, s.admin, s.moderator, request, "") + joinCommunity(&s.Suite, community.ID(), s.admin, s.moderator, aliceAccountAddress, []string{aliceAddress1}) advertiseCommunityTo(&s.Suite, community, s.admin, s.bob) - joinCommunity(&s.Suite, community, s.admin, s.bob, request, "") + joinCommunity(&s.Suite, community.ID(), s.admin, s.bob, bobPassword, []string{bobAddress}) response, err := s.admin.AddRoleToMember(&requests.AddRoleToMember{ CommunityID: community.ID(), diff --git a/protocol/messenger_delete_messages_test.go b/protocol/messenger_delete_messages_test.go index b3890b4f2..1ee192da7 100644 --- a/protocol/messenger_delete_messages_test.go +++ b/protocol/messenger_delete_messages_test.go @@ -5,17 +5,11 @@ import ( "testing" "github.com/stretchr/testify/suite" - "go.uber.org/zap" - "github.com/ethereum/go-ethereum/crypto" - gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" - "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/protocol/common" "github.com/status-im/status-go/protocol/communities" "github.com/status-im/status-go/protocol/protobuf" "github.com/status-im/status-go/protocol/requests" - "github.com/status-im/status-go/protocol/tt" - "github.com/status-im/status-go/waku" ) func TestMessengerDeleteMessagesSuite(t *testing.T) { @@ -23,42 +17,32 @@ func TestMessengerDeleteMessagesSuite(t *testing.T) { } type MessengerDeleteMessagesSuite struct { - suite.Suite - owner *Messenger - admin *Messenger - bob *Messenger - shh types.Waku - logger *zap.Logger + CommunitiesMessengerTestSuiteBase + owner *Messenger + admin *Messenger + bob *Messenger } func (s *MessengerDeleteMessagesSuite) SetupTest() { - s.logger = tt.MustCreateTestLogger() + s.CommunitiesMessengerTestSuiteBase.SetupTest() - config := waku.DefaultConfig - config.MinimumAcceptedPoW = 0 - shh := waku.New(&config, s.logger) - s.shh = gethbridge.NewGethWakuWrapper(shh) - s.Require().NoError(shh.Start()) + s.owner = s.newMessenger("", []string{}) + s.bob = s.newMessenger(bobPassword, []string{bobAddress}) + s.admin = s.newMessenger(alicePassword, []string{aliceAddress1}) - s.owner = s.newMessenger() - s.bob = s.newMessenger() - s.admin = s.newMessenger() + _, err := s.owner.Start() + s.Require().NoError(err) + _, err = s.bob.Start() + s.Require().NoError(err) + _, err = s.admin.Start() + s.Require().NoError(err) } func (s *MessengerDeleteMessagesSuite) TearDownTest() { TearDownMessenger(&s.Suite, s.owner) TearDownMessenger(&s.Suite, s.bob) TearDownMessenger(&s.Suite, s.admin) - _ = s.logger.Sync() -} - -func (s *MessengerDeleteMessagesSuite) newMessenger() *Messenger { - privateKey, err := crypto.GenerateKey() - s.Require().NoError(err) - - messenger, err := newMessengerWithKey(s.shh, privateKey, s.logger, nil) - s.Require().NoError(err) - return messenger + s.CommunitiesMessengerTestSuiteBase.TearDownTest() } func (s *MessengerDeleteMessagesSuite) sendMessageAndCheckDelivery(sender *Messenger, text string, chatID string) *common.Message { @@ -120,13 +104,14 @@ func (s *MessengerDeleteMessagesSuite) checkAllMembersHasMemberMessages(memberPu func (s *MessengerDeleteMessagesSuite) TestDeleteMessageErrors() { community, communityChat := createCommunity(&s.Suite, s.owner) - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - advertiseCommunityTo(&s.Suite, community, s.owner, s.admin) - joinCommunity(&s.Suite, community, s.owner, s.admin, request, "") + joinCommunity(&s.Suite, community.ID(), s.owner, s.admin, alicePassword, []string{aliceAddress1}) + + community, err := s.owner.GetCommunityByID(community.ID()) + s.Require().NoError(err) advertiseCommunityTo(&s.Suite, community, s.owner, s.bob) - joinCommunity(&s.Suite, community, s.owner, s.bob, request, "") + joinCommunity(&s.Suite, community.ID(), s.owner, s.bob, bobPassword, []string{bobAddress}) grantPermission(&s.Suite, community, s.owner, s.admin, protobuf.CommunityMember_ROLE_ADMIN) @@ -138,7 +123,7 @@ func (s *MessengerDeleteMessagesSuite) TestDeleteMessageErrors() { // empty request deleteMessagesRequest := &requests.DeleteCommunityMemberMessages{} - _, err := s.owner.DeleteCommunityMemberMessages(deleteMessagesRequest) + _, err = s.owner.DeleteCommunityMemberMessages(deleteMessagesRequest) s.Require().ErrorIs(err, requests.ErrDeleteCommunityMemberMessagesInvalidCommunityID) // only community ID provided @@ -190,13 +175,11 @@ func (s *MessengerDeleteMessagesSuite) TestDeleteMessageErrors() { func (s *MessengerDeleteMessagesSuite) TestDeleteMessage() { community, communityChat := createCommunity(&s.Suite, s.owner) - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - advertiseCommunityTo(&s.Suite, community, s.owner, s.admin) - joinCommunity(&s.Suite, community, s.owner, s.admin, request, "") + joinCommunity(&s.Suite, community.ID(), s.owner, s.admin, alicePassword, []string{aliceAddress1}) advertiseCommunityTo(&s.Suite, community, s.owner, s.bob) - joinCommunity(&s.Suite, community, s.owner, s.bob, request, "") + joinCommunity(&s.Suite, community.ID(), s.owner, s.bob, bobPassword, []string{bobAddress}) grantPermission(&s.Suite, community, s.owner, s.admin, protobuf.CommunityMember_ROLE_ADMIN) @@ -308,13 +291,11 @@ func (s *MessengerDeleteMessagesSuite) TestDeleteMessage() { func (s *MessengerDeleteMessagesSuite) TestDeleteAllMemberMessage() { community, communityChat := createCommunity(&s.Suite, s.owner) - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - advertiseCommunityTo(&s.Suite, community, s.owner, s.admin) - joinCommunity(&s.Suite, community, s.owner, s.admin, request, "") + joinCommunity(&s.Suite, community.ID(), s.owner, s.admin, aliceAccountAddress, []string{aliceAddress1}) advertiseCommunityTo(&s.Suite, community, s.owner, s.bob) - joinCommunity(&s.Suite, community, s.owner, s.bob, request, "") + joinCommunity(&s.Suite, community.ID(), s.owner, s.bob, bobPassword, []string{bobAddress}) grantPermission(&s.Suite, community, s.owner, s.admin, protobuf.CommunityMember_ROLE_ADMIN) diff --git a/protocol/messenger_handler.go b/protocol/messenger_handler.go index 9b0c90505..41383041a 100644 --- a/protocol/messenger_handler.go +++ b/protocol/messenger_handler.go @@ -1661,11 +1661,18 @@ func (m *Messenger) HandleCommunityRequestToJoinResponse(state *ReceivedMessageS } // check if it is outdated approved request to join - if requestToJoin.State != communities.RequestToJoinStatePending && requestToJoinResponseProto.Clock <= community.Clock() { + clockSeconds := requestToJoinResponseProto.Clock / 1000 + isClockOutdated := clockSeconds < requestToJoin.Clock + isDuplicateAfterMemberLeaves := clockSeconds == requestToJoin.Clock && + requestToJoin.State == communities.RequestToJoinStateAccepted && !community.Joined() + + if requestToJoin.State != communities.RequestToJoinStatePending && + (isClockOutdated || isDuplicateAfterMemberLeaves) { m.logger.Error(ErrOutdatedCommunityRequestToJoin.Error(), zap.String("communityId", community.IDString()), - zap.Uint64("communityClock", community.Clock()), - zap.Uint64("requestToJoinClock", requestToJoinResponseProto.Clock), + zap.Bool("joined", community.Joined()), + zap.Uint64("requestToJoinResponseProto.Clock", requestToJoinResponseProto.Clock), + zap.Uint64("requestToJoin.Clock", requestToJoin.Clock), zap.Uint8("state", uint8(requestToJoin.State))) return ErrOutdatedCommunityRequestToJoin } diff --git a/protocol/messenger_offline_test.go b/protocol/messenger_offline_test.go index 1501354dc..e88521928 100644 --- a/protocol/messenger_offline_test.go +++ b/protocol/messenger_offline_test.go @@ -33,6 +33,12 @@ type MessengerOfflineSuite struct { aliceWaku types.Waku logger *zap.Logger + + mockedBalances communities.BalancesByChain + collectiblesManagerMock *CollectiblesManagerMock + collectiblesServiceMock *CollectiblesServiceMock + accountsTestData map[string][]string + accountsPasswords map[string]string } func TestMessengerOfflineSuite(t *testing.T) { @@ -42,19 +48,24 @@ func TestMessengerOfflineSuite(t *testing.T) { func (s *MessengerOfflineSuite) SetupTest() { s.logger = tt.MustCreateTestLogger() + s.collectiblesServiceMock = &CollectiblesServiceMock{} + s.collectiblesManagerMock = &CollectiblesManagerMock{} + s.accountsTestData = make(map[string][]string) + s.accountsPasswords = make(map[string]string) + wakuNodes := CreateWakuV2Network(&s.Suite, s.logger, []string{"owner", "bob", "alice"}) ownerLogger := s.logger.With(zap.String("name", "owner")) s.ownerWaku = wakuNodes[0] - s.owner = s.newMessenger(s.ownerWaku, ownerLogger) + s.owner = s.newMessenger(s.ownerWaku, ownerLogger, "", []string{}) bobLogger := s.logger.With(zap.String("name", "bob")) s.bobWaku = wakuNodes[1] - s.bob = s.newMessenger(s.bobWaku, bobLogger) + s.bob = s.newMessenger(s.bobWaku, bobLogger, bobPassword, []string{bobAccountAddress}) aliceLogger := s.logger.With(zap.String("name", "alice")) s.aliceWaku = wakuNodes[2] - s.alice = s.newMessenger(s.aliceWaku, aliceLogger) + s.alice = s.newMessenger(s.aliceWaku, aliceLogger, alicePassword, []string{aliceAddress1}) _, err := s.owner.Start() s.Require().NoError(err) @@ -89,7 +100,7 @@ func (s *MessengerOfflineSuite) TearDownTest() { _ = s.logger.Sync() } -func (s *MessengerOfflineSuite) newMessenger(waku types.Waku, logger *zap.Logger) *Messenger { +func (s *MessengerOfflineSuite) newMessenger(waku types.Waku, logger *zap.Logger, password string, accounts []string) *Messenger { return newTestCommunitiesMessenger(&s.Suite, waku, testCommunitiesMessengerConfig{ testMessengerConfig: testMessengerConfig{ logger: s.logger, @@ -97,6 +108,10 @@ func (s *MessengerOfflineSuite) newMessenger(waku types.Waku, logger *zap.Logger WithResendParams(minimumResendDelay, 1), }, }, + walletAddresses: accounts, + password: password, + mockedBalances: &s.mockedBalances, + collectiblesManager: s.collectiblesManagerMock, }) } @@ -104,11 +119,6 @@ func (s *MessengerOfflineSuite) advertiseCommunityTo(community *communities.Comm advertiseCommunityTo(&s.Suite, community, owner, user) } -func (s *MessengerOfflineSuite) joinCommunity(community *communities.Community, owner *Messenger, user *Messenger) { - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - joinCommunity(&s.Suite, community, owner, user, request, "") -} - func (s *MessengerOfflineSuite) TestCommunityOfflineEdit() { community, chat := createCommunity(&s.Suite, s.owner) @@ -121,7 +131,7 @@ func (s *MessengerOfflineSuite) TestCommunityOfflineEdit() { ctx := context.Background() s.advertiseCommunityTo(community, s.owner, s.alice) - s.joinCommunity(community, s.owner, s.alice) + joinCommunity(&s.Suite, community.ID(), s.owner, s.alice, aliceAccountAddress, []string{aliceAddress1}) _, err := s.alice.SendChatMessage(ctx, inputMessage) s.Require().NoError(err) diff --git a/protocol/messenger_peersyncing_test.go b/protocol/messenger_peersyncing_test.go index e901bde0c..995c2e63b 100644 --- a/protocol/messenger_peersyncing_test.go +++ b/protocol/messenger_peersyncing_test.go @@ -16,7 +16,6 @@ import ( "github.com/status-im/status-go/protocol/communities" "github.com/status-im/status-go/protocol/peersyncing" "github.com/status-im/status-go/protocol/protobuf" - "github.com/status-im/status-go/protocol/requests" "github.com/status-im/status-go/protocol/tt" "github.com/status-im/status-go/waku" ) @@ -33,8 +32,10 @@ type MessengerPeersyncingSuite struct { alice *Messenger // If one wants to send messages between different instances of Messenger, // a single Waku service should be shared. - shh types.Waku - logger *zap.Logger + shh types.Waku + logger *zap.Logger + accountsTestData map[string][]string + accountsPasswords map[string]string } func (s *MessengerPeersyncingSuite) SetupTest() { @@ -57,6 +58,14 @@ func (s *MessengerPeersyncingSuite) SetupTest() { s.owner.communitiesManager.RekeyInterval = 50 * time.Millisecond + s.accountsTestData = make(map[string][]string) + s.accountsTestData[common.PubkeyToHex(&s.bob.identity.PublicKey)] = []string{bobAddress} + s.accountsTestData[common.PubkeyToHex(&s.alice.identity.PublicKey)] = []string{aliceAddress1} + + s.accountsPasswords = make(map[string]string) + s.accountsPasswords[common.PubkeyToHex(&s.bob.identity.PublicKey)] = bobPassword + s.accountsPasswords[common.PubkeyToHex(&s.alice.identity.PublicKey)] = aliceAddress1 + _, err := s.owner.Start() s.Require().NoError(err) _, err = s.bob.Start() @@ -81,8 +90,11 @@ func (s *MessengerPeersyncingSuite) newMessenger() *Messenger { } func (s *MessengerPeersyncingSuite) joinCommunity(community *communities.Community, owner *Messenger, user *Messenger) { - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - joinCommunity(&s.Suite, community, owner, user, request, "") + addresses, exists := s.accountsTestData[user.IdentityPublicKeyString()] + s.Require().True(exists) + password, exists := s.accountsPasswords[user.IdentityPublicKeyString()] + s.Require().True(exists) + joinCommunity(&s.Suite, community.ID(), s.owner, user, password, addresses) } func (s *MessengerPeersyncingSuite) thirdPartyTest(community *communities.Community, chat *Chat) { diff --git a/protocol/messenger_profile_showcase_test.go b/protocol/messenger_profile_showcase_test.go index 8c724dee3..fb8953f98 100644 --- a/protocol/messenger_profile_showcase_test.go +++ b/protocol/messenger_profile_showcase_test.go @@ -2,18 +2,13 @@ package protocol import ( "context" - "crypto/ecdsa" "errors" "math/big" "testing" "time" - "github.com/stretchr/testify/suite" - "go.uber.org/zap" - gethcommon "github.com/ethereum/go-ethereum/common" - "github.com/status-im/status-go/appdatabase" - gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" + "github.com/status-im/status-go/eth-node/crypto" "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/multiaccounts/accounts" @@ -22,12 +17,11 @@ import ( "github.com/status-im/status-go/protocol/identity" "github.com/status-im/status-go/protocol/protobuf" "github.com/status-im/status-go/protocol/requests" - "github.com/status-im/status-go/protocol/sqlite" "github.com/status-im/status-go/protocol/tt" "github.com/status-im/status-go/services/wallet/bigint" "github.com/status-im/status-go/services/wallet/thirdparty" - "github.com/status-im/status-go/t/helpers" - "github.com/status-im/status-go/waku" + + "github.com/stretchr/testify/suite" ) func TestMessengerProfileShowcaseSuite(t *testing.T) { // nolint: deadcode,unused @@ -35,53 +29,20 @@ func TestMessengerProfileShowcaseSuite(t *testing.T) { // nolint: deadcode,unuse } type TestMessengerProfileShowcase struct { - suite.Suite - m *Messenger // main instance of Messenger - privateKey *ecdsa.PrivateKey // private key for the main instance of Messenger - // If one wants to send messages between different instances of Messenger, - // a single waku service should be shared. - shh types.Waku - logger *zap.Logger - collectiblesMock CollectiblesManagerMock + CommunitiesMessengerTestSuiteBase + m *Messenger // main instance of Messenger } func (s *TestMessengerProfileShowcase) SetupTest() { - s.logger = tt.MustCreateTestLogger() - - config := waku.DefaultConfig - config.MinimumAcceptedPoW = 0 - shh := waku.New(&config, s.logger) - s.shh = gethbridge.NewGethWakuWrapper(shh) - s.Require().NoError(shh.Start()) - - s.m = s.newMessengerForProfileShowcase() - s.privateKey = s.m.identity + s.CommunitiesMessengerTestSuiteBase.SetupTest() + s.m = s.newMessenger("", []string{}) + _, err := s.m.Start() + s.Require().NoError(err) } func (s *TestMessengerProfileShowcase) TearDownTest() { TearDownMessenger(&s.Suite, s.m) - _ = s.logger.Sync() -} - -func (s *TestMessengerProfileShowcase) newMessengerForProfileShowcase() *Messenger { - db, err := helpers.SetupTestMemorySQLDB(appdatabase.DbInitializer{}) - s.NoError(err, "creating sqlite db instance") - err = sqlite.Migrate(db) - s.NoError(err, "protocol migrate") - - privateKey, err := crypto.GenerateKey() - s.Require().NoError(err) - - s.collectiblesMock = CollectiblesManagerMock{} - - options := []Option{ - WithCollectiblesManager(&s.collectiblesMock), - } - - m, err := newMessengerWithKey(s.shh, privateKey, s.logger, options) - s.Require().NoError(err) - - return m + s.CommunitiesMessengerTestSuiteBase.TearDownTest() } func (s *TestMessengerProfileShowcase) mutualContact(theirMessenger *Messenger) { @@ -187,7 +148,7 @@ func (s *TestMessengerProfileShowcase) TestSaveAndGetProfileShowcasePreferences( TxTimestamp: 0, }, } - s.collectiblesMock.SetCollectibleOwnershipResponse(collectibleID, balances) + s.collectiblesManagerMock.SetCollectibleOwnershipResponse(collectibleID, balances) err = s.m.SetProfileShowcasePreferences(request, false) s.Require().NoError(err) @@ -258,7 +219,7 @@ func (s *TestMessengerProfileShowcase) TestFailToSaveProfileShowcasePreferencesW TxTimestamp: 0, }, } - s.collectiblesMock.SetCollectibleOwnershipResponse(collectibleID, balances) + s.collectiblesManagerMock.SetCollectibleOwnershipResponse(collectibleID, balances) err = s.m.SetProfileShowcasePreferences(request, false) s.Require().Equal(errorAccountVisibilityLowerThanCollectible, err) @@ -266,7 +227,10 @@ func (s *TestMessengerProfileShowcase) TestFailToSaveProfileShowcasePreferencesW func (s *TestMessengerProfileShowcase) TestEncryptAndDecryptProfileShowcaseEntries() { // Add mutual contact - theirMessenger := s.newMessengerForProfileShowcase() + theirMessenger := s.newMessenger(accountPassword, []string{commonAccountAddress}) + _, err := theirMessenger.Start() + s.Require().NoError(err) + defer TearDownMessenger(&s.Suite, theirMessenger) s.mutualContact(theirMessenger) @@ -441,7 +405,7 @@ func (s *TestMessengerProfileShowcase) TestShareShowcasePreferences() { TxTimestamp: 32443424, }, } - s.collectiblesMock.SetCollectibleOwnershipResponse(collectibleID, balances) + s.collectiblesManagerMock.SetCollectibleOwnershipResponse(collectibleID, balances) err = s.m.SetProfileShowcasePreferences(request, false) s.Require().NoError(err) @@ -457,13 +421,17 @@ func (s *TestMessengerProfileShowcase) TestShareShowcasePreferences() { s.Require().Len(profileShowcasePreferences.UnverifiedTokens, 2) // Add mutual contact - mutualContact := s.newMessengerForProfileShowcase() + mutualContact := s.newMessenger(alicePassword, []string{aliceAccountAddress}) + _, err = mutualContact.Start() + s.Require().NoError(err) defer TearDownMessenger(&s.Suite, mutualContact) s.mutualContact(mutualContact) // Add identity verified contact - verifiedContact := s.newMessengerForProfileShowcase() + verifiedContact := s.newMessenger(bobPassword, []string{bobAccountAddress}) + _, err = verifiedContact.Start() + s.Require().NoError(err) defer TearDownMessenger(&s.Suite, verifiedContact) s.mutualContact(verifiedContact) @@ -587,7 +555,9 @@ func (s *TestMessengerProfileShowcase) TestProfileShowcaseProofOfMembershipUnenc s.Require().NoError(err) // Add bob as a mutual contact - bob := s.newMessengerForProfileShowcase() + bob := s.newMessenger(bobPassword, []string{bobAccountAddress}) + _, err = bob.Start() + s.Require().NoError(err) defer TearDownMessenger(&s.Suite, bob) s.mutualContact(bob) @@ -652,7 +622,9 @@ func (s *TestMessengerProfileShowcase) TestProfileShowcaseProofOfMembershipEncry s.Require().NoError(err) // Add bob as a mutual contact - bob := s.newMessengerForProfileShowcase() + bob := s.newMessenger(bobPassword, []string{bobAccountAddress}) + _, err = bob.Start() + s.Require().NoError(err) defer TearDownMessenger(&s.Suite, bob) s.mutualContact(bob) @@ -735,7 +707,9 @@ func (s *TestMessengerProfileShowcase) TestProfileShowcaseCommuniesGrantExpires( s.Require().True(community.Encrypted()) // 2) Bob add Alice become a mutual contacts - bob := s.newMessengerForProfileShowcase() + bob := s.newMessenger(bobPassword, []string{bobAccountAddress}) + _, err = bob.Start() + s.Require().NoError(err) defer TearDownMessenger(&s.Suite, bob) s.mutualContact(bob) @@ -800,7 +774,9 @@ func (s *TestMessengerProfileShowcase) TestProfileShowcaseCommuniesDispatchOnGra s.Require().NoError(err) // 1) Owner creates an encrypted community - owner := s.newMessengerForProfileShowcase() + owner := s.newMessenger("", []string{}) + _, err = owner.Start() + s.Require().NoError(err) defer TearDownMessenger(&s.Suite, owner) owner.communitiesManager.PermissionChecker = &testPermissionChecker{} @@ -809,7 +785,9 @@ func (s *TestMessengerProfileShowcase) TestProfileShowcaseCommuniesDispatchOnGra s.Require().True(community.Encrypted()) // 2) Bob add Alice become a mutual contacts - bob := s.newMessengerForProfileShowcase() + bob := s.newMessenger(bobPassword, []string{bobAccountAddress}) + _, err = bob.Start() + s.Require().NoError(err) defer TearDownMessenger(&s.Suite, bob) s.mutualContact(bob) @@ -817,8 +795,9 @@ func (s *TestMessengerProfileShowcase) TestProfileShowcaseCommuniesDispatchOnGra // 3) Alice joins the community advertiseCommunityTo(&s.Suite, community, owner, alice) advertiseCommunityTo(&s.Suite, community, owner, bob) - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - joinCommunity(&s.Suite, community, owner, alice, request, "") + + alice.communitiesManager.PermissionChecker = &testPermissionChecker{} + joinCommunity(&s.Suite, community.ID(), owner, alice, aliceAccountAddress, []string{aliceAddress1}) joinedCommunities, err := alice.communitiesManager.Joined() s.Require().NoError(err) diff --git a/protocol/messenger_raw_message_resend_test.go b/protocol/messenger_raw_message_resend_test.go new file mode 100644 index 000000000..adb5bb87e --- /dev/null +++ b/protocol/messenger_raw_message_resend_test.go @@ -0,0 +1,200 @@ +package protocol + +import ( + "errors" + "testing" + + "github.com/golang/protobuf/proto" + "github.com/stretchr/testify/suite" + "go.uber.org/zap" + + gethbridge "github.com/status-im/status-go/eth-node/bridge/geth" + "github.com/status-im/status-go/eth-node/types" + "github.com/status-im/status-go/protocol/common" + "github.com/status-im/status-go/protocol/communities" + "github.com/status-im/status-go/protocol/protobuf" + "github.com/status-im/status-go/protocol/tt" +) + +func TestMessengerRawMessageResendTestSuite(t *testing.T) { + suite.Run(t, new(MessengerRawMessageResendTest)) +} + +type MessengerRawMessageResendTest struct { + suite.Suite + logger *zap.Logger + + aliceMessenger *Messenger + bobMessenger *Messenger + + aliceWaku types.Waku + bobWaku types.Waku + + mockedBalances communities.BalancesByChain +} + +func (s *MessengerRawMessageResendTest) SetupTest() { + s.logger = tt.MustCreateTestLogger() + s.mockedBalances = make(communities.BalancesByChain) + + wakuNodes := CreateWakuV2Network(&s.Suite, s.logger, []string{"alice", "bob"}) + + s.aliceWaku = wakuNodes[0] + s.aliceMessenger = newTestCommunitiesMessenger(&s.Suite, s.aliceWaku, testCommunitiesMessengerConfig{ + testMessengerConfig: testMessengerConfig{ + name: "alice", + logger: s.logger, + }, + walletAddresses: []string{aliceAddress1}, + password: accountPassword, + mockedBalances: &s.mockedBalances, + }) + + _, err := s.aliceMessenger.Start() + s.Require().NoError(err) + + s.bobWaku = wakuNodes[1] + s.bobMessenger = newTestCommunitiesMessenger(&s.Suite, s.bobWaku, testCommunitiesMessengerConfig{ + testMessengerConfig: testMessengerConfig{ + name: "bob", + logger: s.logger, + }, + walletAddresses: []string{bobAddress}, + password: bobPassword, + mockedBalances: &s.mockedBalances, + }) + + _, err = s.bobMessenger.Start() + s.Require().NoError(err) + + community, _ := createOnRequestCommunity(&s.Suite, s.aliceMessenger) + advertiseCommunityToUserOldWay(&s.Suite, community, s.aliceMessenger, s.bobMessenger) + joinOnRequestCommunity(&s.Suite, community.ID(), s.aliceMessenger, s.bobMessenger, bobPassword, []string{bobAddress}) +} + +func (s *MessengerRawMessageResendTest) TearDownTest() { + TearDownMessenger(&s.Suite, s.aliceMessenger) + TearDownMessenger(&s.Suite, s.bobMessenger) + if s.aliceWaku != nil { + s.Require().NoError(gethbridge.GetGethWakuV2From(s.aliceWaku).Stop()) + } + if s.bobWaku != nil { + s.Require().NoError(gethbridge.GetGethWakuV2From(s.bobWaku).Stop()) + } + _ = s.logger.Sync() +} + +func (s *MessengerRawMessageResendTest) waitForMessageSent(messageID string) { + err := tt.RetryWithBackOff(func() error { + rawMessage, err := s.bobMessenger.RawMessageByID(messageID) + s.Require().NoError(err) + s.Require().NotNil(rawMessage) + if rawMessage.SendCount > 0 { + return nil + } + return errors.New("raw message should be sent finally") + }) + s.Require().NoError(err) +} + +// TestMessageSent tests if ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN is in state `sent` without resending +func (s *MessengerRawMessageResendTest) TestMessageSent() { + ids, err := s.bobMessenger.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN) + s.Require().NoError(err) + // one request to join to control node and another to privileged member + s.Require().Len(ids, 2) + + s.waitForMessageSent(ids[0]) + s.waitForMessageSent(ids[1]) +} + +// TestMessageResend tests if ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN is resent +func (s *MessengerRawMessageResendTest) TestMessageResend() { + ids, err := s.bobMessenger.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN) + s.Require().NoError(err) + s.Require().Len(ids, 2) + // wait for Sent status for already sent message to make sure that sent message was delivered + // before testing resend + s.waitForMessageSent(ids[0]) + s.waitForMessageSent(ids[1]) + + rawMessage := s.GetRequestToJoinToControlNodeRawMessage(ids) + s.Require().NotNil(rawMessage) + s.Require().NoError(s.bobMessenger.UpdateRawMessageSent(rawMessage.ID, false)) + s.Require().NoError(s.bobMessenger.UpdateRawMessageLastSent(rawMessage.ID, 0)) + + err = tt.RetryWithBackOff(func() error { + msg, err := s.bobMessenger.RawMessageByID(rawMessage.ID) + s.Require().NoError(err) + s.Require().NotNil(msg) + if msg.SendCount < 2 { + return errors.New("message ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN was not resent yet") + } + return nil + }) + s.Require().NoError(err) + + waitOnMessengerResponse(&s.Suite, func(r *MessengerResponse) error { + if len(r.RequestsToJoinCommunity()) > 0 { + return nil + } + return errors.New("community request to join not received") + }, s.aliceMessenger) +} + +func (s *MessengerRawMessageResendTest) TestInvalidRawMessageToWatchDoesNotProduceResendLoop() { + ids, err := s.bobMessenger.RawMessagesIDsByType(protobuf.ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN) + s.Require().NoError(err) + s.Require().Len(ids, 2) + + s.waitForMessageSent(ids[0]) + s.waitForMessageSent(ids[1]) + + rawMessage := s.GetRequestToJoinToControlNodeRawMessage(ids) + s.Require().NotNil(rawMessage) + + requestToJoinProto := &protobuf.CommunityRequestToJoin{} + err = proto.Unmarshal(rawMessage.Payload, requestToJoinProto) + s.Require().NoError(err) + + requestToJoinProto.DisplayName = "invalid_ID" + payload, err := proto.Marshal(requestToJoinProto) + s.Require().NoError(err) + rawMessage.Payload = payload + + _, err = s.bobMessenger.AddRawMessageToWatch(rawMessage) + s.Require().Error(err, common.ErrModifiedRawMessage) + + // simulate storing msg with modified payload, but old message ID + _, err = s.bobMessenger.UpsertRawMessageToWatch(rawMessage) + s.Require().NoError(err) + s.Require().NoError(s.bobMessenger.UpdateRawMessageSent(rawMessage.ID, false)) + s.Require().NoError(s.bobMessenger.UpdateRawMessageLastSent(rawMessage.ID, 0)) + + // check counter increased for invalid message to escape the loop + err = tt.RetryWithBackOff(func() error { + msg, err := s.bobMessenger.RawMessageByID(rawMessage.ID) + s.Require().NoError(err) + s.Require().NotNil(msg) + if msg.SendCount < 2 { + return errors.New("message ApplicationMetadataMessage_COMMUNITY_REQUEST_TO_JOIN was not resent yet") + } + return nil + }) + s.Require().NoError(err) +} + +func (s *MessengerRawMessageResendTest) GetRequestToJoinToControlNodeRawMessage(ids []string) *common.RawMessage { + for _, messageID := range ids { + rawMessage, err := s.bobMessenger.RawMessageByID(messageID) + s.Require().NoError(err) + s.Require().NotNil(rawMessage) + + if rawMessage.ResendMethod == common.ResendMethodSendCommunityMessage { + return rawMessage + } + } + + s.Require().FailNow("rawMessage was not found") + return nil +} diff --git a/protocol/messenger_send_images_album_test.go b/protocol/messenger_send_images_album_test.go index 031614e28..0c7eef02f 100644 --- a/protocol/messenger_send_images_album_test.go +++ b/protocol/messenger_send_images_album_test.go @@ -18,7 +18,20 @@ func TestMessengerSendImagesAlbumSuite(t *testing.T) { } type MessengerSendImagesAlbumSuite struct { - MessengerBaseTestSuite + CommunitiesMessengerTestSuiteBase + m *Messenger // main instance of Messenger +} + +func (s *MessengerSendImagesAlbumSuite) SetupTest() { + s.CommunitiesMessengerTestSuiteBase.SetupTest() + s.m = s.newMessenger("", []string{}) + _, err := s.m.Start() + s.Require().NoError(err) +} + +func (s *MessengerSendImagesAlbumSuite) TearDownTest() { + TearDownMessenger(&s.Suite, s.m) + s.CommunitiesMessengerTestSuiteBase.TearDownTest() } func (s *MessengerSendImagesAlbumSuite) advertiseCommunityTo(community *communities.Community, user *Messenger) { @@ -26,16 +39,17 @@ func (s *MessengerSendImagesAlbumSuite) advertiseCommunityTo(community *communit } func (s *MessengerSendImagesAlbumSuite) joinCommunity(community *communities.Community, user *Messenger) { - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - joinCommunity(&s.Suite, community, s.m, user, request, "") + s.CommunitiesMessengerTestSuiteBase.joinCommunity(community, s.m, user) } func (s *MessengerSendImagesAlbumSuite) TestAlbumImageMessagesSend() { - theirMessenger := s.newMessenger() + theirMessenger := s.newMessenger(accountPassword, []string{commonAccountAddress}) + _, err := theirMessenger.Start() + s.Require().NoError(err) defer TearDownMessenger(&s.Suite, theirMessenger) - theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport) - err := theirMessenger.SaveChat(theirChat) + theirChat := CreateOneToOneChat("Their 1TO1", s.m.IdentityPublicKey(), s.m.transport) + err = theirMessenger.SaveChat(theirChat) s.Require().NoError(err) ourChat := CreateOneToOneChat("Our 1TO1", &theirMessenger.identity.PublicKey, s.m.transport) @@ -90,11 +104,13 @@ func (s *MessengerSendImagesAlbumSuite) TestAlbumImageMessagesSend() { } func (s *MessengerSendImagesAlbumSuite) TestAlbumImageMessagesWithMentionSend() { - theirMessenger := s.newMessenger() + theirMessenger := s.newMessenger(accountPassword, []string{commonAccountAddress}) + _, err := theirMessenger.Start() + s.Require().NoError(err) defer TearDownMessenger(&s.Suite, theirMessenger) - theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport) - err := theirMessenger.SaveChat(theirChat) + theirChat := CreateOneToOneChat("Their 1TO1", s.m.IdentityPublicKey(), s.m.transport) + err = theirMessenger.SaveChat(theirChat) s.Require().NoError(err) ourChat := CreateOneToOneChat("Our 1TO1", &theirMessenger.identity.PublicKey, s.m.transport) @@ -141,7 +157,9 @@ func (s *MessengerSendImagesAlbumSuite) TestAlbumImageMessagesWithMentionSend() // This test makes sure that if you get a mention with an image ina community, it sends it correctly and has a notif func (s *MessengerSendImagesAlbumSuite) TestSingleImageMessageWithMentionInCommunitySend() { - theirMessenger := s.newMessenger() + theirMessenger := s.newMessenger(accountPassword, []string{commonAccountAddress}) + _, err := theirMessenger.Start() + s.Require().NoError(err) defer TearDownMessenger(&s.Suite, theirMessenger) community, chat := createCommunity(&s.Suite, s.m) @@ -161,7 +179,7 @@ func (s *MessengerSendImagesAlbumSuite) TestSingleImageMessageWithMentionInCommu album = append(album, outgoingMessage) } - err := s.m.SaveChat(chat) + err = s.m.SaveChat(chat) s.NoError(err) response, err := s.m.SendChatMessages(context.Background(), album) s.NoError(err) @@ -190,10 +208,13 @@ func (s *MessengerSendImagesAlbumSuite) TestSingleImageMessageWithMentionInCommu } func (s *MessengerSendImagesAlbumSuite) TestAlbumImageEditText() { - theirMessenger := s.newMessenger() + theirMessenger := s.newMessenger(accountPassword, []string{commonAccountAddress}) + _, err := theirMessenger.Start() + s.Require().NoError(err) + defer TearDownMessenger(&s.Suite, theirMessenger) - theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport) - err := theirMessenger.SaveChat(theirChat) + theirChat := CreateOneToOneChat("Their 1TO1", s.m.IdentityPublicKey(), s.m.transport) + err = theirMessenger.SaveChat(theirChat) s.Require().NoError(err) ourChat := CreateOneToOneChat("Our 1TO1", &theirMessenger.identity.PublicKey, s.m.transport) @@ -271,7 +292,9 @@ func (s *MessengerSendImagesAlbumSuite) TestAlbumImageEditText() { // This test makes sure that if you get a mention with an album of images in a community, it sends it correctly and has correct AC notif with album func (s *MessengerSendImagesAlbumSuite) TestAlbumImagesMessageWithMentionInCommunitySend() { - theirMessenger := s.newMessenger() + theirMessenger := s.newMessenger(accountPassword, []string{commonAccountAddress}) + _, err := theirMessenger.Start() + s.Require().NoError(err) defer TearDownMessenger(&s.Suite, theirMessenger) community, chat := createCommunity(&s.Suite, s.m) @@ -291,7 +314,7 @@ func (s *MessengerSendImagesAlbumSuite) TestAlbumImagesMessageWithMentionInCommu album = append(album, outgoingMessage) } - err := s.m.SaveChat(chat) + err = s.m.SaveChat(chat) s.NoError(err) response, err := s.m.SendChatMessages(context.Background(), album) s.NoError(err) diff --git a/protocol/messenger_storenode_comunity_test.go b/protocol/messenger_storenode_comunity_test.go index 6309dfcb5..b3459d028 100644 --- a/protocol/messenger_storenode_comunity_test.go +++ b/protocol/messenger_storenode_comunity_test.go @@ -304,8 +304,7 @@ func (s *MessengerStoreNodeCommunitySuite) TestSetStorenodeForCommunity_fetchMes // 2. Bob joins the community advertiseCommunityTo(&s.Suite, community, s.owner, s.bob) - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - joinCommunity(&s.Suite, community, s.owner, s.bob, request, "") + joinCommunity(&s.Suite, community.ID(), s.owner, s.bob, bobPassword, []string{bobAccountAddress}) // waits for onwer and bob to connect to the community store node WaitForPeersConnected(&s.Suite, s.communityStoreNode, func() []string { diff --git a/protocol/messenger_sync_activity_center_test.go b/protocol/messenger_sync_activity_center_test.go index 705e7639e..071e75cb0 100644 --- a/protocol/messenger_sync_activity_center_test.go +++ b/protocol/messenger_sync_activity_center_test.go @@ -6,15 +6,12 @@ import ( "testing" "time" - "github.com/status-im/status-go/protocol/protobuf" - - "github.com/status-im/status-go/eth-node/crypto" + "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/protocol/common" + "github.com/status-im/status-go/protocol/protobuf" "github.com/status-im/status-go/protocol/requests" "github.com/stretchr/testify/suite" - - "github.com/status-im/status-go/eth-node/types" ) const ( @@ -22,29 +19,38 @@ const ( actionDecline = "Decline" ) -type MessengerSyncActivityCenterSuite struct { - MessengerBaseTestSuite - m2 *Messenger -} - func TestMessengerSyncActivityCenter(t *testing.T) { suite.Run(t, new(MessengerSyncActivityCenterSuite)) } +type MessengerSyncActivityCenterSuite struct { + CommunitiesMessengerTestSuiteBase + m *Messenger + m2 *Messenger +} + func (s *MessengerSyncActivityCenterSuite) SetupTest() { - s.MessengerBaseTestSuite.SetupTest() + s.CommunitiesMessengerTestSuiteBase.SetupTest() - m2, err := newMessengerWithKey(s.shh, s.privateKey, s.logger, nil) + s.m = s.newMessenger(alicePassword, []string{aliceAccountAddress}) + + _, err := s.m.Start() s.Require().NoError(err) - s.m2 = m2 - PairDevices(&s.Suite, m2, s.m) - PairDevices(&s.Suite, s.m, m2) + s.m2 = s.newMessengerWithKey(s.m.identity, alicePassword, []string{aliceAccountAddress}) + s.Require().NoError(err) + + _, err = s.m2.Start() + s.Require().NoError(err) + + PairDevices(&s.Suite, s.m2, s.m) + PairDevices(&s.Suite, s.m, s.m2) } func (s *MessengerSyncActivityCenterSuite) TearDownTest() { TearDownMessenger(&s.Suite, s.m2) - s.MessengerBaseTestSuite.TearDownTest() + TearDownMessenger(&s.Suite, s.m) + s.CommunitiesMessengerTestSuiteBase.TearDownTest() } func (s *MessengerSyncActivityCenterSuite) createAndSaveNotification(m *Messenger, t ActivityCenterType, read bool) types.HexBytes { @@ -116,16 +122,22 @@ func (s *MessengerSyncActivityCenterSuite) TestSyncCommunityRequestDecisionDecli } func (s *MessengerSyncActivityCenterSuite) testSyncCommunityRequestDecision(action string) { - userB := s.createUserB() + + userB := s.newMessenger(accountPassword, []string{commonAccountAddress}) defer func() { s.Require().NoError(userB.Shutdown()) }() + _, err := userB.Start() + s.Require().NoError(err) + communityID := s.createClosedCommunity() s.addContactAndShareCommunity(userB, communityID) - s.requestToJoinCommunity(userB, communityID) + request := createRequestToJoinCommunity(&s.Suite, communityID, userB, accountPassword, []string{commonAccountAddress}) + _, err = userB.RequestToJoinCommunity(request) + s.Require().NoError(err) requestToJoinID := s.waitForRequestToJoin(s.m) @@ -145,14 +157,6 @@ func (s *MessengerSyncActivityCenterSuite) testSyncCommunityRequestDecision(acti s.waitForDecisionOnDevice2(requestToJoinID, action) } -func (s *MessengerSyncActivityCenterSuite) createUserB() *Messenger { - key, err := crypto.GenerateKey() - s.Require().NoError(err) - userB, err := newMessengerWithKey(s.shh, key, s.logger, nil) - s.Require().NoError(err) - return userB -} - func (s *MessengerSyncActivityCenterSuite) createClosedCommunity() types.HexBytes { response, err := s.m.CreateClosedCommunity() s.Require().NoError(err) @@ -220,11 +224,6 @@ func (s *MessengerSyncActivityCenterSuite) addContactAndShareCommunity(userB *Me advertiseCommunityToUserOldWay(&s.Suite, community, s.m, userB) } -func (s *MessengerSyncActivityCenterSuite) requestToJoinCommunity(userB *Messenger, communityID types.HexBytes) { - _, err := userB.RequestToJoinCommunity(&requests.RequestToJoinCommunity{CommunityID: communityID}) - s.Require().NoError(err) -} - func (s *MessengerSyncActivityCenterSuite) waitForRequestToJoin(messenger *Messenger) types.HexBytes { var requestToJoinID types.HexBytes _, err := WaitOnMessengerResponse(messenger, func(r *MessengerResponse) bool { diff --git a/protocol/push_notification_test.go b/protocol/push_notification_test.go index 048a104da..0285d9955 100644 --- a/protocol/push_notification_test.go +++ b/protocol/push_notification_test.go @@ -922,8 +922,8 @@ func (s *MessengerPushNotificationSuite) TestReceivePushNotificationCommunityReq return nil }) - request := &requests.RequestToJoinCommunity{CommunityID: community.ID()} - + request := createRequestToJoinCommunity(&s.Suite, community.ID(), alice, alicePassword, []string{aliceAddress1}) + alice.communitiesManager.PermissionChecker = &testPermissionChecker{} // We try to join the org response, err = alice.RequestToJoinCommunity(request) s.Require().NoError(err) diff --git a/protocol/requests/request_to_join_community.go b/protocol/requests/request_to_join_community.go index f283fabf0..2a7812869 100644 --- a/protocol/requests/request_to_join_community.go +++ b/protocol/requests/request_to_join_community.go @@ -23,19 +23,11 @@ type RequestToJoinCommunity struct { ShareFutureAddresses bool `json:"shareFutureAddresses"` } -func (j *RequestToJoinCommunity) Validate(full bool) error { - // TODO: A parital validation, in case `full` is set to `false` should check `AddressesToReveal` as well. But because of changes - // that need to be done in tests we cannot do that now. - // Also in the line 61, we should remove `len(signature) > 0` from the condition, but from the same reason we cannot do that now. - +func (j *RequestToJoinCommunity) Validate() error { if len(j.CommunityID) == 0 { return ErrRequestToJoinCommunityInvalidCommunityID } - if !full { - return nil - } - if len(j.AddressesToReveal) == 0 { return ErrRequestToJoinCommunityNoAddressesToReveal } @@ -57,7 +49,7 @@ func (j *RequestToJoinCommunity) Validate(full bool) error { } for _, signature := range j.Signatures { - if len(signature) > 0 && len(signature) != crypto.SignatureLength { + if len(signature) != crypto.SignatureLength { return ErrRequestToJoinCommunityInvalidSignature } }