github.com/status-im/status-go@v1.1.0/protocol/messenger_peersyncing_test.go (about)

     1  package protocol
     2  
     3  import (
     4  	"context"
     5  	"encoding/hex"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/suite"
    10  	"go.uber.org/zap"
    11  
    12  	gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
    13  	"github.com/status-im/status-go/eth-node/crypto"
    14  	"github.com/status-im/status-go/eth-node/types"
    15  	"github.com/status-im/status-go/protocol/common"
    16  	"github.com/status-im/status-go/protocol/communities"
    17  	"github.com/status-im/status-go/protocol/peersyncing"
    18  	"github.com/status-im/status-go/protocol/protobuf"
    19  	"github.com/status-im/status-go/protocol/tt"
    20  	"github.com/status-im/status-go/waku"
    21  )
    22  
    23  func TestMessengerPeersyncingSuite(t *testing.T) {
    24  	t.Skip("broken test") // FIXME
    25  	suite.Run(t, new(MessengerPeersyncingSuite))
    26  }
    27  
    28  type MessengerPeersyncingSuite struct {
    29  	suite.Suite
    30  	owner *Messenger
    31  	bob   *Messenger
    32  	alice *Messenger
    33  	// If one wants to send messages between different instances of Messenger,
    34  	// a single Waku service should be shared.
    35  	shh               types.Waku
    36  	logger            *zap.Logger
    37  	accountsTestData  map[string][]string
    38  	accountsPasswords map[string]string
    39  }
    40  
    41  func (s *MessengerPeersyncingSuite) SetupTest() {
    42  	s.logger = tt.MustCreateTestLogger()
    43  	peerSyncingLoopInterval = 500 * time.Millisecond
    44  
    45  	config := waku.DefaultConfig
    46  	config.MinimumAcceptedPoW = 0
    47  	shh := waku.New(&config, s.logger)
    48  	s.shh = gethbridge.NewGethWakuWrapper(shh)
    49  	s.Require().NoError(shh.Start())
    50  
    51  	s.owner = s.newMessenger()
    52  	s.bob = s.newMessenger()
    53  	s.alice = s.newMessenger()
    54  
    55  	s.alice.featureFlags.ResendRawMessagesDisabled = true
    56  	s.bob.featureFlags.ResendRawMessagesDisabled = true
    57  	s.owner.featureFlags.ResendRawMessagesDisabled = true
    58  
    59  	s.owner.communitiesManager.RekeyInterval = 50 * time.Millisecond
    60  
    61  	s.accountsTestData = make(map[string][]string)
    62  	s.accountsTestData[common.PubkeyToHex(&s.bob.identity.PublicKey)] = []string{bobAddress}
    63  	s.accountsTestData[common.PubkeyToHex(&s.alice.identity.PublicKey)] = []string{aliceAddress1}
    64  
    65  	s.accountsPasswords = make(map[string]string)
    66  	s.accountsPasswords[common.PubkeyToHex(&s.bob.identity.PublicKey)] = bobPassword
    67  	s.accountsPasswords[common.PubkeyToHex(&s.alice.identity.PublicKey)] = aliceAddress1
    68  
    69  	_, err := s.owner.Start()
    70  	s.Require().NoError(err)
    71  	_, err = s.bob.Start()
    72  	s.Require().NoError(err)
    73  	_, err = s.alice.Start()
    74  	s.Require().NoError(err)
    75  }
    76  
    77  func (s *MessengerPeersyncingSuite) TearDownTest() {
    78  	TearDownMessenger(&s.Suite, s.owner)
    79  	TearDownMessenger(&s.Suite, s.bob)
    80  	TearDownMessenger(&s.Suite, s.alice)
    81  	_ = s.logger.Sync()
    82  }
    83  
    84  func (s *MessengerPeersyncingSuite) newMessenger() *Messenger {
    85  	return newTestCommunitiesMessenger(&s.Suite, s.shh, testCommunitiesMessengerConfig{
    86  		testMessengerConfig: testMessengerConfig{
    87  			logger: s.logger,
    88  		},
    89  	})
    90  }
    91  
    92  func (s *MessengerPeersyncingSuite) joinCommunity(community *communities.Community, owner *Messenger, user *Messenger) {
    93  	addresses, exists := s.accountsTestData[user.IdentityPublicKeyString()]
    94  	s.Require().True(exists)
    95  	password, exists := s.accountsPasswords[user.IdentityPublicKeyString()]
    96  	s.Require().True(exists)
    97  	joinCommunity(&s.Suite, community.ID(), s.owner, user, password, addresses)
    98  }
    99  
   100  func (s *MessengerPeersyncingSuite) thirdPartyTest(community *communities.Community, chat *Chat) {
   101  	// We disable resending to make sure that the message is not re-transmitted
   102  	s.alice.featureFlags.Peersyncing = false
   103  	s.owner.featureFlags.Peersyncing = true
   104  	s.bob.featureFlags.Peersyncing = true
   105  	s.owner.communitiesManager.PermissionChecker = &testPermissionChecker{}
   106  
   107  	advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
   108  
   109  	s.joinCommunity(community, s.owner, s.alice)
   110  
   111  	chatID := chat.ID
   112  	inputMessage := common.NewMessage()
   113  	inputMessage.ChatId = chatID
   114  	inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN
   115  	inputMessage.Text = "some text"
   116  	ctx := context.Background()
   117  
   118  	if community.Encrypted() {
   119  
   120  		_, err := WaitOnMessengerResponse(
   121  			s.alice,
   122  			func(r *MessengerResponse) bool {
   123  				keys, err := s.alice.encryptor.GetKeysForGroup([]byte(chat.ID))
   124  				return err == nil && len(keys) > 0
   125  			},
   126  			"keys not received",
   127  		)
   128  		s.Require().NoError(err)
   129  	}
   130  
   131  	// Send message, it should be received
   132  	response, err := s.alice.SendChatMessage(ctx, inputMessage)
   133  	s.Require().NoError(err)
   134  	s.Require().Len(response.Messages(), 1)
   135  	messageID := response.Messages()[0].ID
   136  
   137  	// Make sure the message makes it to the owner
   138  	response, err = WaitOnMessengerResponse(
   139  		s.owner,
   140  		func(r *MessengerResponse) bool {
   141  			return len(r.Communities()) > 0 && len(r.Messages()) == 1 && r.Messages()[0].ID == messageID
   142  		},
   143  		"message not received",
   144  	)
   145  	s.Require().NoError(err)
   146  	s.Require().NotNil(response)
   147  
   148  	msg, err := s.owner.peersyncing.AvailableMessages()
   149  	s.Require().NoError(err)
   150  	s.Require().Len(msg, 1)
   151  
   152  	// Bob joins the community
   153  	advertiseCommunityTo(&s.Suite, community, s.owner, s.bob)
   154  
   155  	s.joinCommunity(community, s.owner, s.bob)
   156  
   157  	// Bob should now send an offer
   158  	_, err = WaitOnMessengerResponse(
   159  		s.bob,
   160  		func(r *MessengerResponse) bool {
   161  			return s.bob.peersyncingOffers[messageID[2:]] != 0
   162  		},
   163  		"offer not sent",
   164  	)
   165  	s.Require().NoError(err)
   166  
   167  	// Owner should now reply to the offer
   168  	_, err = WaitOnMessengerResponse(
   169  		s.owner,
   170  		func(r *MessengerResponse) bool {
   171  			return s.owner.peersyncingRequests[s.bob.myHexIdentity()+messageID[2:]] != 0
   172  		},
   173  		"request not sent",
   174  	)
   175  	s.Require().NoError(err)
   176  
   177  	// Bob should receive the message
   178  	_, err = WaitOnMessengerResponse(
   179  		s.bob,
   180  		func(r *MessengerResponse) bool {
   181  			return len(r.Messages()) == 1 && r.Messages()[0].ID == messageID
   182  		},
   183  		"message not received",
   184  	)
   185  	s.Require().NoError(err)
   186  
   187  }
   188  
   189  // Owner creates a community
   190  // Owner sends a message
   191  // Alice joins
   192  // Alice receives the message
   193  func (s *MessengerPeersyncingSuite) TestSyncWithPeerCommunitySender() {
   194  
   195  	s.alice.featureFlags.Peersyncing = true
   196  	s.owner.featureFlags.Peersyncing = true
   197  
   198  	// create community and make alice join it
   199  	community, chat := createCommunity(&s.Suite, s.owner)
   200  
   201  	chatID := chat.ID
   202  	inputMessage := common.NewMessage()
   203  	inputMessage.ChatId = chatID
   204  	inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN
   205  	inputMessage.Text = "some text"
   206  
   207  	// Send message, it should be received
   208  	response, err := s.owner.SendChatMessage(context.Background(), inputMessage)
   209  	s.Require().NoError(err)
   210  
   211  	messageID := response.Messages()[0].ID
   212  
   213  	msg, err := s.owner.peersyncing.AvailableMessages()
   214  	s.Require().NoError(err)
   215  	s.Require().Len(msg, 1)
   216  
   217  	advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
   218  	s.joinCommunity(community, s.owner, s.alice)
   219  
   220  	// Alice should now receive the message
   221  	_, err = WaitOnMessengerResponse(
   222  		s.alice,
   223  		func(r *MessengerResponse) bool {
   224  			_, err := s.owner.RetrieveAll()
   225  			if err != nil {
   226  				return false
   227  			}
   228  			return len(r.Messages()) == 1 && r.Messages()[0].ID == messageID
   229  		},
   230  		"message not received",
   231  	)
   232  	s.Require().NoError(err)
   233  }
   234  
   235  // Owner creates a community
   236  // Alice joins
   237  // Alice sends a message
   238  // Owner receives the message
   239  // Bob joins the community
   240  // They should retrieve the message from the owner
   241  
   242  func (s *MessengerPeersyncingSuite) TestSyncWithPeerCommunityThirdPartyEncrypted() {
   243  	community, chat := createEncryptedCommunity(&s.Suite, s.owner)
   244  	s.thirdPartyTest(community, chat)
   245  }
   246  
   247  func (s *MessengerPeersyncingSuite) TestSyncWithPeerCommunityThirdPartyNotEncrypted() {
   248  	community, chat := createCommunity(&s.Suite, s.owner)
   249  	s.thirdPartyTest(community, chat)
   250  }
   251  
   252  func (s *MessengerPeersyncingSuite) TestCanSyncMessageWith() {
   253  	community, chat := createCommunity(&s.Suite, s.owner)
   254  
   255  	advertiseCommunityTo(&s.Suite, community, s.owner, s.alice)
   256  	s.joinCommunity(community, s.owner, s.alice)
   257  
   258  	syncMessage := peersyncing.SyncMessage{
   259  		ID:        []byte("test-id"),
   260  		ChatID:    []byte(chat.ID),
   261  		Type:      peersyncing.SyncMessageCommunityType,
   262  		Payload:   []byte("some-payload"),
   263  		Timestamp: 1,
   264  	}
   265  	s.Require().NoError(s.owner.peersyncing.Add(syncMessage))
   266  
   267  	community, err := s.owner.communitiesManager.GetByID(community.ID())
   268  	s.Require().NoError(err)
   269  
   270  	canSyncWithBob, err := s.owner.canSyncCommunityMessageWith(chat, community, &s.bob.identity.PublicKey)
   271  	s.Require().NoError(err)
   272  	s.Require().False(canSyncWithBob)
   273  
   274  	canSyncWithAlice, err := s.owner.canSyncCommunityMessageWith(chat, community, &s.alice.identity.PublicKey)
   275  	s.Require().NoError(err)
   276  	s.Require().True(canSyncWithAlice)
   277  }
   278  
   279  func (s *MessengerPeersyncingSuite) TestSyncOneToOne() {
   280  	s.alice.featureFlags.Peersyncing = true
   281  	s.owner.featureFlags.Peersyncing = true
   282  
   283  	pkString := hex.EncodeToString(crypto.FromECDSAPub(&s.alice.identity.PublicKey))
   284  	chat := CreateOneToOneChat(pkString, &s.alice.identity.PublicKey, s.owner.transport)
   285  
   286  	chat.LastClockValue = uint64(100000000000000)
   287  	err := s.owner.SaveChat(chat)
   288  	s.NoError(err)
   289  	_, err = s.alice.Join(chat)
   290  	s.NoError(err)
   291  
   292  	chatID := chat.ID
   293  	inputMessage := common.NewMessage()
   294  	inputMessage.ChatId = chatID
   295  	inputMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN
   296  	inputMessage.Text = "some text"
   297  
   298  	ctx := context.Background()
   299  
   300  	// Send message, it should be received
   301  	response, err := s.alice.SendChatMessage(ctx, inputMessage)
   302  	s.Require().NoError(err)
   303  	s.Require().Len(response.Messages(), 1)
   304  	messageID := response.Messages()[0].ID
   305  
   306  	// Make sure the message makes it to the owner
   307  	response, err = WaitOnMessengerResponse(
   308  		s.owner,
   309  		func(r *MessengerResponse) bool {
   310  			return len(r.Messages()) == 1 && r.Messages()[0].ID == messageID
   311  		},
   312  		"message not received",
   313  	)
   314  	s.Require().NoError(err)
   315  	s.Require().NotNil(response)
   316  
   317  	msg, err := s.owner.peersyncing.AvailableMessages()
   318  	s.Require().NoError(err)
   319  	s.Require().Len(msg, 1)
   320  
   321  	// Alice should now send an offer
   322  	_, err = WaitOnMessengerResponse(
   323  		s.alice,
   324  		func(r *MessengerResponse) bool {
   325  			return s.alice.peersyncingOffers[messageID[2:]] != 0
   326  		},
   327  		"offer not sent",
   328  	)
   329  	s.Require().NoError(err)
   330  
   331  	// Owner should now reply to the offer
   332  	_, err = WaitOnMessengerResponse(
   333  		s.owner,
   334  		func(r *MessengerResponse) bool {
   335  			return s.owner.peersyncingRequests[s.alice.myHexIdentity()+messageID[2:]] != 0
   336  		},
   337  		"request not sent",
   338  	)
   339  	s.Require().NoError(err)
   340  }
   341  
   342  func (s *MessengerPeersyncingSuite) TestCanSyncOneToOneMessageWith() {
   343  	s.alice.featureFlags.Peersyncing = true
   344  	s.owner.featureFlags.Peersyncing = true
   345  
   346  	pkString := hex.EncodeToString(crypto.FromECDSAPub(&s.alice.identity.PublicKey))
   347  	chat := CreateOneToOneChat(pkString, &s.alice.identity.PublicKey, s.owner.transport)
   348  
   349  	chat.LastClockValue = uint64(100000000000000)
   350  	err := s.owner.SaveChat(chat)
   351  	s.NoError(err)
   352  	_, err = s.alice.Join(chat)
   353  	s.NoError(err)
   354  
   355  	syncMessage := peersyncing.SyncMessage{
   356  		ID:        []byte("test-id"),
   357  		ChatID:    []byte(chat.ID),
   358  		Type:      peersyncing.SyncMessageOneToOneType,
   359  		Payload:   []byte("some-payload"),
   360  		Timestamp: chat.LastClockValue,
   361  	}
   362  	s.Require().NoError(s.owner.peersyncing.Add(syncMessage))
   363  
   364  	canSyncWithBob, err := s.owner.canSyncOneToOneMessageWith(chat, &s.bob.identity.PublicKey)
   365  	s.Require().NoError(err)
   366  	s.Require().False(canSyncWithBob)
   367  
   368  	canSyncWithAlice, err := s.owner.canSyncOneToOneMessageWith(chat, &s.alice.identity.PublicKey)
   369  	s.Require().NoError(err)
   370  	s.Require().True(canSyncWithAlice)
   371  }