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

     1  package protocol
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"reflect"
     8  	"testing"
     9  	"time"
    10  
    11  	"go.uber.org/zap"
    12  
    13  	"github.com/ethereum/go-ethereum/common"
    14  	"github.com/ethereum/go-ethereum/event"
    15  	v1protocol "github.com/status-im/status-go/protocol/v1"
    16  	"github.com/status-im/status-go/protocol/wakusync"
    17  	"github.com/status-im/status-go/services/accounts/accountsevent"
    18  
    19  	"github.com/stretchr/testify/suite"
    20  
    21  	"github.com/status-im/status-go/eth-node/crypto"
    22  	"github.com/status-im/status-go/eth-node/types"
    23  	"github.com/status-im/status-go/images"
    24  	"github.com/status-im/status-go/multiaccounts/accounts"
    25  	"github.com/status-im/status-go/multiaccounts/settings"
    26  	"github.com/status-im/status-go/protocol/protobuf"
    27  	"github.com/status-im/status-go/protocol/requests"
    28  )
    29  
    30  func TestMessengerBackupSuite(t *testing.T) {
    31  	suite.Run(t, new(MessengerBackupSuite))
    32  }
    33  
    34  type MessengerBackupSuite struct {
    35  	MessengerBaseTestSuite
    36  }
    37  
    38  func (s *MessengerBackupSuite) TestBackupContacts() {
    39  	bob1 := s.m
    40  	// Create bob2
    41  	bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, nil)
    42  	s.Require().NoError(err)
    43  	defer TearDownMessenger(&s.Suite, bob2)
    44  
    45  	// Create 2 contacts
    46  
    47  	contact1Key, err := crypto.GenerateKey()
    48  	s.Require().NoError(err)
    49  	contactID1 := types.EncodeHex(crypto.FromECDSAPub(&contact1Key.PublicKey))
    50  
    51  	_, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: contactID1})
    52  	s.Require().NoError(err)
    53  
    54  	contact2Key, err := crypto.GenerateKey()
    55  	s.Require().NoError(err)
    56  	contactID2 := types.EncodeHex(crypto.FromECDSAPub(&contact2Key.PublicKey))
    57  
    58  	_, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: contactID2})
    59  	s.Require().NoError(err)
    60  
    61  	s.Require().Len(bob1.Contacts(), 2)
    62  
    63  	actualContacts := bob1.Contacts()
    64  	if actualContacts[0].ID == contactID1 {
    65  		s.Require().Equal(actualContacts[0].ID, contactID1)
    66  		s.Require().Equal(actualContacts[1].ID, contactID2)
    67  	} else {
    68  		s.Require().Equal(actualContacts[0].ID, contactID2)
    69  		s.Require().Equal(actualContacts[1].ID, contactID1)
    70  	}
    71  
    72  	s.Require().Equal(ContactRequestStateSent, actualContacts[0].ContactRequestLocalState)
    73  	s.Require().Equal(ContactRequestStateSent, actualContacts[1].ContactRequestLocalState)
    74  	s.Require().True(actualContacts[0].added())
    75  	s.Require().True(actualContacts[1].added())
    76  
    77  	// Backup
    78  
    79  	clock, err := bob1.BackupData(context.Background())
    80  	s.Require().NoError(err)
    81  
    82  	// Safety check
    83  	s.Require().Len(bob2.Contacts(), 0)
    84  
    85  	// Wait for the message to reach its destination
    86  	_, err = WaitOnMessengerResponse(
    87  		bob2,
    88  		func(r *MessengerResponse) bool {
    89  			return r.BackupHandled
    90  		},
    91  		"no messages",
    92  	)
    93  	s.Require().NoError(err)
    94  	s.Require().Len(bob2.AddedContacts(), 2)
    95  
    96  	actualContacts = bob2.AddedContacts()
    97  	if actualContacts[0].ID == contactID1 {
    98  		s.Require().Equal(actualContacts[0].ID, contactID1)
    99  		s.Require().Equal(actualContacts[1].ID, contactID2)
   100  	} else {
   101  		s.Require().Equal(actualContacts[0].ID, contactID2)
   102  		s.Require().Equal(actualContacts[1].ID, contactID1)
   103  	}
   104  	s.Require().Equal(ContactRequestStateSent, actualContacts[0].ContactRequestLocalState)
   105  	s.Require().Equal(ContactRequestStateSent, actualContacts[1].ContactRequestLocalState)
   106  	lastBackup, err := bob1.lastBackup()
   107  	s.Require().NoError(err)
   108  	s.Require().NotEmpty(lastBackup)
   109  	s.Require().Equal(clock, lastBackup)
   110  }
   111  
   112  func (s *MessengerBackupSuite) TestBackupProfile() {
   113  	const bob1DisplayName = "bobby"
   114  
   115  	// Create bob1
   116  	bob1 := s.m
   117  
   118  	bobProfileKp := accounts.GetProfileKeypairForTest(true, false, false)
   119  	bobProfileKp.KeyUID = bob1.account.KeyUID
   120  	bobProfileKp.Accounts[0].KeyUID = bob1.account.KeyUID
   121  
   122  	err := bob1.settings.SaveOrUpdateKeypair(bobProfileKp)
   123  	s.Require().NoError(err)
   124  
   125  	err = bob1.SetDisplayName(bob1DisplayName)
   126  	s.Require().NoError(err)
   127  	bob1KeyUID := bob1.account.KeyUID
   128  	imagesExpected := fmt.Sprintf(`[{"keyUid":"%s","type":"large","uri":"data:image/png;base64,iVBORw0KGgoAAAANSUg=","width":240,"height":300,"fileSize":1024,"resizeTarget":240,"clock":0},{"keyUid":"%s","type":"thumbnail","uri":"data:image/jpeg;base64,/9j/2wCEAFA3PEY8MlA=","width":80,"height":80,"fileSize":256,"resizeTarget":80,"clock":0}]`,
   129  		bob1KeyUID, bob1KeyUID)
   130  
   131  	iis := images.SampleIdentityImages()
   132  	s.Require().NoError(bob1.multiAccounts.StoreIdentityImages(bob1KeyUID, iis, false))
   133  
   134  	bob1EnsUsernameDetail, err := bob1.saveEnsUsernameDetailProto(&protobuf.SyncEnsUsernameDetail{
   135  		Clock:    1,
   136  		Username: "bob1.eth",
   137  		ChainId:  1,
   138  		Removed:  false,
   139  	})
   140  	s.Require().NoError(err)
   141  
   142  	profileShowcasePreferences := DummyProfileShowcasePreferences(false)
   143  	err = bob1.SetProfileShowcasePreferences(profileShowcasePreferences, false)
   144  	s.Require().NoError(err)
   145  
   146  	// Create bob2
   147  	bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, nil)
   148  	s.Require().NoError(err)
   149  	defer TearDownMessenger(&s.Suite, bob2)
   150  
   151  	// Check bob1
   152  	storedBob1DisplayName, err := bob1.settings.DisplayName()
   153  	s.Require().NoError(err)
   154  	s.Require().Equal(bob1DisplayName, storedBob1DisplayName)
   155  
   156  	bob1Images, err := bob1.multiAccounts.GetIdentityImages(bob1KeyUID)
   157  	s.Require().NoError(err)
   158  	jBob1Images, err := json.Marshal(bob1Images)
   159  	s.Require().NoError(err)
   160  	s.Require().Equal(imagesExpected, string(jBob1Images))
   161  
   162  	bob1EnsUsernameDetails, err := bob1.getEnsUsernameDetails()
   163  	s.Require().NoError(err)
   164  	s.Require().Equal(1, len(bob1EnsUsernameDetails))
   165  
   166  	bob1ProfileShowcasePreferences, err := bob1.GetProfileShowcasePreferences()
   167  	s.Require().NoError(err)
   168  	s.Require().NotNil(bob1ProfileShowcasePreferences)
   169  	s.Require().Greater(bob1ProfileShowcasePreferences.Clock, uint64(0))
   170  	profileShowcasePreferences.Clock = bob1ProfileShowcasePreferences.Clock // override clock for simpler comparison
   171  	s.Require().True(reflect.DeepEqual(profileShowcasePreferences, bob1ProfileShowcasePreferences))
   172  
   173  	// Check bob2
   174  	storedBob2DisplayName, err := bob2.settings.DisplayName()
   175  	s.Require().NoError(err)
   176  	s.Require().Equal(DefaultProfileDisplayName, storedBob2DisplayName)
   177  
   178  	var expectedEmpty []*images.IdentityImage
   179  	bob2Images, err := bob2.multiAccounts.GetIdentityImages(bob1KeyUID)
   180  	s.Require().NoError(err)
   181  	s.Require().Equal(expectedEmpty, bob2Images)
   182  
   183  	bob2EnsUsernameDetails, err := bob2.getEnsUsernameDetails()
   184  	s.Require().NoError(err)
   185  	s.Require().Equal(0, len(bob2EnsUsernameDetails))
   186  
   187  	bob2ProfileShowcasePreferences, err := bob2.GetProfileShowcasePreferences()
   188  	s.Require().NoError(err)
   189  	s.Require().NotNil(bob2ProfileShowcasePreferences)
   190  	s.Require().Equal(uint64(0), bob2ProfileShowcasePreferences.Clock)
   191  	s.Require().Len(bob2ProfileShowcasePreferences.Communities, 0)
   192  	s.Require().Len(bob2ProfileShowcasePreferences.Accounts, 0)
   193  	s.Require().Len(bob2ProfileShowcasePreferences.Collectibles, 0)
   194  	s.Require().Len(bob2ProfileShowcasePreferences.VerifiedTokens, 0)
   195  	s.Require().Len(bob2ProfileShowcasePreferences.UnverifiedTokens, 0)
   196  	s.Require().Len(bob2ProfileShowcasePreferences.SocialLinks, 0)
   197  
   198  	// Backup
   199  	clock, err := bob1.BackupData(context.Background())
   200  	s.Require().NoError(err)
   201  
   202  	// Wait for the message to reach its destination
   203  	_, err = WaitOnMessengerResponse(
   204  		bob2,
   205  		func(r *MessengerResponse) bool {
   206  			return r.BackupHandled
   207  		},
   208  		"no messages",
   209  	)
   210  	s.Require().NoError(err)
   211  
   212  	// Check bob2
   213  	storedBob2DisplayName, err = bob2.settings.DisplayName()
   214  	s.Require().NoError(err)
   215  	s.Require().Equal(bob1DisplayName, storedBob2DisplayName)
   216  
   217  	bob2Images, err = bob2.multiAccounts.GetIdentityImages(bob1KeyUID)
   218  	s.Require().NoError(err)
   219  	s.Require().Equal(2, len(bob2Images))
   220  	s.Require().Equal(bob2Images[0].Payload, bob1Images[0].Payload)
   221  	s.Require().Equal(bob2Images[1].Payload, bob1Images[1].Payload)
   222  
   223  	bob2EnsUsernameDetails, err = bob2.getEnsUsernameDetails()
   224  	s.Require().NoError(err)
   225  	s.Require().Equal(1, len(bob2EnsUsernameDetails))
   226  	s.Require().Equal(bob1EnsUsernameDetail, bob2EnsUsernameDetails[0])
   227  
   228  	bob2ProfileShowcasePreferences, err = bob1.GetProfileShowcasePreferences()
   229  	s.Require().NoError(err)
   230  	s.Require().True(reflect.DeepEqual(bob1ProfileShowcasePreferences, bob2ProfileShowcasePreferences))
   231  
   232  	lastBackup, err := bob1.lastBackup()
   233  	s.Require().NoError(err)
   234  	s.Require().NotEmpty(lastBackup)
   235  	s.Require().Equal(clock, lastBackup)
   236  }
   237  
   238  func (s *MessengerBackupSuite) TestBackupProfileWithInvalidDisplayName() {
   239  	// Create bob1
   240  	bob1 := s.m
   241  
   242  	state := ReceivedMessageState{
   243  		Response: &MessengerResponse{},
   244  	}
   245  
   246  	err := bob1.HandleBackup(
   247  		&state,
   248  		&protobuf.Backup{
   249  			Profile: &protobuf.BackedUpProfile{
   250  				DisplayName: "bad-display-name_eth",
   251  			},
   252  			Clock: 1,
   253  		},
   254  		&v1protocol.StatusMessage{},
   255  	)
   256  	// The backup will still work, but the display name will be skipped
   257  	s.Require().NoError(err)
   258  	storedBob1DisplayName, err := bob1.settings.DisplayName()
   259  	s.Require().NoError(err)
   260  	s.Require().Equal("", storedBob1DisplayName)
   261  }
   262  
   263  func (s *MessengerBackupSuite) TestBackupSettings() {
   264  	s.T().Skip("flaky test")
   265  	const (
   266  		bob1DisplayName               = "bobby"
   267  		bob1Currency                  = "eur"
   268  		bob1MessagesFromContactsOnly  = true
   269  		bob1ProfilePicturesShowTo     = settings.ProfilePicturesShowToEveryone
   270  		bob1ProfilePicturesVisibility = settings.ProfilePicturesVisibilityEveryone
   271  		bob1Bio                       = "bio"
   272  		bob1Mnemonic                  = ""
   273  		bob1MnemonicRemoved           = true
   274  		bob1PreferredName             = "talent"
   275  		bob1UrlUnfUnfurlingMode       = settings.URLUnfurlingEnableAll
   276  	)
   277  
   278  	// Create bob1 and set fields which are supposed to be backed up to/fetched from waku
   279  	bob1 := s.m
   280  	err := bob1.settings.SaveSettingField(settings.DisplayName, bob1DisplayName)
   281  	s.Require().NoError(err)
   282  	err = bob1.settings.SaveSettingField(settings.Currency, bob1Currency)
   283  	s.Require().NoError(err)
   284  	err = bob1.settings.SaveSettingField(settings.MessagesFromContactsOnly, bob1MessagesFromContactsOnly)
   285  	s.Require().NoError(err)
   286  	err = bob1.settings.SaveSettingField(settings.ProfilePicturesShowTo, bob1ProfilePicturesShowTo)
   287  	s.Require().NoError(err)
   288  	err = bob1.settings.SaveSettingField(settings.ProfilePicturesVisibility, bob1ProfilePicturesVisibility)
   289  	s.Require().NoError(err)
   290  	err = bob1.settings.SaveSettingField(settings.Bio, bob1Bio)
   291  	s.Require().NoError(err)
   292  	err = bob1.settings.SaveSettingField(settings.Mnemonic, bob1Mnemonic)
   293  	s.Require().NoError(err)
   294  	err = bob1.settings.SaveSettingField(settings.PreferredName, bob1PreferredName)
   295  	s.Require().NoError(err)
   296  	err = bob1.settings.SaveSettingField(settings.URLUnfurlingMode, bob1UrlUnfUnfurlingMode)
   297  	s.Require().NoError(err)
   298  
   299  	// Create bob2
   300  	bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, nil)
   301  	s.Require().NoError(err)
   302  	defer TearDownMessenger(&s.Suite, bob2)
   303  
   304  	// Check bob1
   305  	storedBob1DisplayName, err := bob1.settings.DisplayName()
   306  	s.Require().NoError(err)
   307  	s.Require().Equal(bob1DisplayName, storedBob1DisplayName)
   308  	storedBob1Currency, err := bob1.settings.GetCurrency()
   309  	s.Require().NoError(err)
   310  	s.Require().Equal(bob1Currency, storedBob1Currency)
   311  	storedBob1MessagesFromContactsOnly, err := bob1.settings.GetMessagesFromContactsOnly()
   312  	s.Require().NoError(err)
   313  	s.Require().Equal(bob1MessagesFromContactsOnly, storedBob1MessagesFromContactsOnly)
   314  	storedBob1ProfilePicturesShowTo, err := bob1.settings.GetProfilePicturesShowTo()
   315  	s.Require().NoError(err)
   316  	s.Require().Equal(int64(bob1ProfilePicturesShowTo), storedBob1ProfilePicturesShowTo)
   317  	storedBob1ProfilePicturesVisibility, err := bob1.settings.GetProfilePicturesVisibility()
   318  	s.Require().NoError(err)
   319  	s.Require().Equal(int(bob1ProfilePicturesVisibility), storedBob1ProfilePicturesVisibility)
   320  	storedBob1Bio, err := bob1.settings.Bio()
   321  	s.Require().NoError(err)
   322  	s.Require().Equal(bob1Bio, storedBob1Bio)
   323  	storedMnemonic, err := bob1.settings.Mnemonic()
   324  	s.Require().NoError(err)
   325  	s.Require().Equal(bob1Mnemonic, storedMnemonic)
   326  	storedMnemonicRemoved, err := bob1.settings.MnemonicRemoved()
   327  	s.Require().NoError(err)
   328  	s.Require().Equal(bob1MnemonicRemoved, storedMnemonicRemoved)
   329  	storedPreferredName, err := bob1.settings.GetPreferredUsername()
   330  	s.NoError(err)
   331  	s.Require().Equal(bob1PreferredName, storedPreferredName)
   332  	storedBob1UrlUnfurlingMode, err := bob1.settings.URLUnfurlingMode()
   333  	s.NoError(err)
   334  	s.Require().Equal(int64(bob1UrlUnfUnfurlingMode), storedBob1UrlUnfurlingMode)
   335  
   336  	// Check bob2
   337  	storedBob2DisplayName, err := bob2.settings.DisplayName()
   338  	s.Require().NoError(err)
   339  	s.Require().NotEqual(storedBob1DisplayName, storedBob2DisplayName)
   340  	storedBob2Currency, err := bob2.settings.GetCurrency()
   341  	s.Require().NoError(err)
   342  	s.Require().NotEqual(storedBob1Currency, storedBob2Currency)
   343  	storedBob2MessagesFromContactsOnly, err := bob2.settings.GetMessagesFromContactsOnly()
   344  	s.Require().NoError(err)
   345  	s.Require().NotEqual(storedBob1MessagesFromContactsOnly, storedBob2MessagesFromContactsOnly)
   346  	storedBob2ProfilePicturesShowTo, err := bob2.settings.GetProfilePicturesShowTo()
   347  	s.Require().NoError(err)
   348  	s.Require().NotEqual(storedBob1ProfilePicturesShowTo, storedBob2ProfilePicturesShowTo)
   349  	storedBob2ProfilePicturesVisibility, err := bob2.settings.GetProfilePicturesVisibility()
   350  	s.Require().NoError(err)
   351  	s.Require().NotEqual(storedBob1ProfilePicturesVisibility, storedBob2ProfilePicturesVisibility)
   352  	storedBob2Bio, err := bob2.settings.Bio()
   353  	s.Require().NoError(err)
   354  	s.Require().NotEqual(storedBob1Bio, storedBob2Bio)
   355  	storedBob2MnemonicRemoved, err := bob2.settings.MnemonicRemoved()
   356  	s.Require().NoError(err)
   357  	s.Require().Equal(false, storedBob2MnemonicRemoved)
   358  	storedBob2PreferredName, err := bob2.settings.GetPreferredUsername()
   359  	s.NoError(err)
   360  	s.Require().Equal("", storedBob2PreferredName)
   361  	storedBob2UrlUnfurlingMode, err := bob2.settings.URLUnfurlingMode()
   362  	s.NoError(err)
   363  	s.Require().Equal(int64(settings.URLUnfurlingAlwaysAsk), storedBob2UrlUnfurlingMode)
   364  
   365  	// Backup
   366  	clock, err := bob1.BackupData(context.Background())
   367  	s.Require().NoError(err)
   368  
   369  	// Wait for the message to reach its destination
   370  	_, err = WaitOnSignaledSendWakuFetchingBackupProgress(bob2, func(r *wakusync.WakuBackedUpDataResponse) bool {
   371  		detailsMap := r.FetchingBackedUpDataDetails()
   372  		if settingDetails, ok := detailsMap[SyncWakuSectionKeySettings]; ok {
   373  			return settingDetails.DataNumber == settingDetails.TotalNumber
   374  		}
   375  		return false
   376  	}, "no messages")
   377  	s.Require().NoError(err)
   378  
   379  	// Check bob2
   380  	storedBob2DisplayName, err = bob2.settings.DisplayName()
   381  	s.Require().NoError(err)
   382  	s.Require().Equal(storedBob1DisplayName, storedBob2DisplayName)
   383  	storedBob2Currency, err = bob2.settings.GetCurrency()
   384  	s.Require().NoError(err)
   385  	s.Require().Equal(storedBob1Currency, storedBob2Currency)
   386  	storedBob2MessagesFromContactsOnly, err = bob2.settings.GetMessagesFromContactsOnly()
   387  	s.Require().NoError(err)
   388  	s.Require().Equal(storedBob1MessagesFromContactsOnly, storedBob2MessagesFromContactsOnly)
   389  	storedBob2ProfilePicturesShowTo, err = bob2.settings.GetProfilePicturesShowTo()
   390  	s.Require().NoError(err)
   391  	s.Require().Equal(storedBob1ProfilePicturesShowTo, storedBob2ProfilePicturesShowTo)
   392  	storedBob2ProfilePicturesVisibility, err = bob2.settings.GetProfilePicturesVisibility()
   393  	s.Require().NoError(err)
   394  	s.Require().Equal(storedBob1ProfilePicturesVisibility, storedBob2ProfilePicturesVisibility)
   395  	storedBob2Bio, err = bob2.settings.Bio()
   396  	s.Require().NoError(err)
   397  	s.Require().Equal(storedBob1Bio, storedBob2Bio)
   398  	storedBob2MnemonicRemoved, err = bob2.settings.MnemonicRemoved()
   399  	s.Require().NoError(err)
   400  	s.Require().Equal(bob1MnemonicRemoved, storedBob2MnemonicRemoved)
   401  	storedBob2PreferredName, err = bob2.settings.GetPreferredUsername()
   402  	s.NoError(err)
   403  	s.Require().Equal(bob1PreferredName, storedBob2PreferredName)
   404  	s.Require().Equal(bob1PreferredName, bob2.account.Name)
   405  	storedBob2UrlUnfurlingMode, err = bob2.settings.URLUnfurlingMode()
   406  	s.NoError(err)
   407  	s.Require().Equal(storedBob1UrlUnfurlingMode, storedBob2UrlUnfurlingMode)
   408  
   409  	lastBackup, err := bob1.lastBackup()
   410  	s.Require().NoError(err)
   411  	s.Require().NotEmpty(lastBackup)
   412  	s.Require().Equal(clock, lastBackup)
   413  }
   414  
   415  func (s *MessengerBackupSuite) TestBackupContactsGreaterThanBatch() {
   416  	bob1 := s.m
   417  	// Create bob2
   418  	bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, nil)
   419  	s.Require().NoError(err)
   420  	defer TearDownMessenger(&s.Suite, bob2)
   421  
   422  	// Create contacts
   423  
   424  	for i := 0; i < BackupContactsPerBatch*2; i++ {
   425  
   426  		contactKey, err := crypto.GenerateKey()
   427  		s.Require().NoError(err)
   428  		contactID := types.EncodeHex(crypto.FromECDSAPub(&contactKey.PublicKey))
   429  
   430  		_, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: contactID})
   431  		s.Require().NoError(err)
   432  
   433  	}
   434  	// Backup
   435  
   436  	_, err = bob1.BackupData(context.Background())
   437  	s.Require().NoError(err)
   438  
   439  	// Safety check
   440  	s.Require().Len(bob2.Contacts(), 0)
   441  
   442  	// Wait for the message to reach its destination
   443  	_, err = WaitOnMessengerResponse(
   444  		bob2,
   445  		func(r *MessengerResponse) bool {
   446  			return r.BackupHandled
   447  		},
   448  		"no messages",
   449  	)
   450  	s.Require().NoError(err)
   451  
   452  	s.Require().Equal(BackupContactsPerBatch*2, len(bob2.Contacts()))
   453  	s.Require().Len(bob2.AddedContacts(), BackupContactsPerBatch*2)
   454  }
   455  
   456  func (s *MessengerBackupSuite) TestBackupRemovedContact() {
   457  	bob1 := s.m
   458  	// Create bob2
   459  	bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, nil)
   460  	s.Require().NoError(err)
   461  	defer TearDownMessenger(&s.Suite, bob2)
   462  
   463  	// Create 2 contacts on bob 1
   464  
   465  	contact1Key, err := crypto.GenerateKey()
   466  	s.Require().NoError(err)
   467  	contactID1 := types.EncodeHex(crypto.FromECDSAPub(&contact1Key.PublicKey))
   468  
   469  	_, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: contactID1})
   470  	s.Require().NoError(err)
   471  
   472  	contact2Key, err := crypto.GenerateKey()
   473  	s.Require().NoError(err)
   474  	contactID2 := types.EncodeHex(crypto.FromECDSAPub(&contact2Key.PublicKey))
   475  
   476  	_, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: contactID2})
   477  	s.Require().NoError(err)
   478  
   479  	s.Require().Len(bob1.Contacts(), 2)
   480  
   481  	actualContacts := bob1.Contacts()
   482  	if actualContacts[0].ID == contactID1 {
   483  		s.Require().Equal(actualContacts[0].ID, contactID1)
   484  		s.Require().Equal(actualContacts[1].ID, contactID2)
   485  	} else {
   486  		s.Require().Equal(actualContacts[0].ID, contactID2)
   487  		s.Require().Equal(actualContacts[1].ID, contactID1)
   488  	}
   489  
   490  	// Bob 2 add one of the same contacts
   491  
   492  	_, err = bob2.AddContact(context.Background(), &requests.AddContact{ID: contactID2})
   493  	s.Require().NoError(err)
   494  
   495  	// Bob 1 now removes one of the contact that was also on bob 2
   496  
   497  	_, err = bob1.RemoveContact(context.Background(), contactID2)
   498  	s.Require().NoError(err)
   499  
   500  	// Backup
   501  
   502  	clock, err := bob1.BackupData(context.Background())
   503  	s.Require().NoError(err)
   504  
   505  	// Safety check
   506  	s.Require().Len(bob2.Contacts(), 1)
   507  
   508  	// Wait for the message to reach its destination
   509  	_, err = WaitOnMessengerResponse(
   510  		bob2,
   511  		func(r *MessengerResponse) bool {
   512  			return r.BackupHandled
   513  		},
   514  		"no messages",
   515  	)
   516  	// Bob 2 should remove the contact
   517  	s.Require().NoError(err)
   518  
   519  	s.Require().Len(bob2.AddedContacts(), 1)
   520  	s.Require().Equal(contactID1, bob2.AddedContacts()[0].ID)
   521  
   522  	lastBackup, err := bob1.lastBackup()
   523  	s.Require().NoError(err)
   524  	s.Require().NotEmpty(lastBackup)
   525  	s.Require().Equal(clock, lastBackup)
   526  }
   527  
   528  func (s *MessengerBackupSuite) TestBackupLocalNickname() {
   529  	bob1 := s.m
   530  	// Create bob2
   531  	bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, nil)
   532  	nickname := "don van vliet"
   533  	s.Require().NoError(err)
   534  	defer TearDownMessenger(&s.Suite, bob2)
   535  
   536  	// Set contact nickname
   537  
   538  	contact1Key, err := crypto.GenerateKey()
   539  	s.Require().NoError(err)
   540  	contactID1 := types.EncodeHex(crypto.FromECDSAPub(&contact1Key.PublicKey))
   541  
   542  	_, err = bob1.SetContactLocalNickname(&requests.SetContactLocalNickname{ID: types.Hex2Bytes(contactID1), Nickname: nickname})
   543  	s.Require().NoError(err)
   544  
   545  	// Backup
   546  
   547  	clock, err := bob1.BackupData(context.Background())
   548  	s.Require().NoError(err)
   549  
   550  	// Safety check
   551  	s.Require().Len(bob2.Contacts(), 0)
   552  
   553  	var actualContact *Contact
   554  	// Wait for the message to reach its destination
   555  	_, err = WaitOnMessengerResponse(
   556  		bob2,
   557  		func(r *MessengerResponse) bool {
   558  			return r.BackupHandled
   559  		},
   560  		"no messages",
   561  	)
   562  	s.Require().NoError(err)
   563  
   564  	for _, c := range bob2.Contacts() {
   565  		if c.ID == contactID1 {
   566  			actualContact = c
   567  			break
   568  		}
   569  	}
   570  
   571  	s.Require().Equal(actualContact.LocalNickname, nickname)
   572  	lastBackup, err := bob1.lastBackup()
   573  	s.Require().NoError(err)
   574  	s.Require().NotEmpty(lastBackup)
   575  	s.Require().Equal(clock, lastBackup)
   576  }
   577  
   578  func (s *MessengerBackupSuite) TestBackupBlockedContacts() {
   579  	bob1 := s.m
   580  	// Create bob2
   581  	bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, nil)
   582  	s.Require().NoError(err)
   583  	defer TearDownMessenger(&s.Suite, bob2)
   584  
   585  	// Create contact
   586  	contact1Key, err := crypto.GenerateKey()
   587  	s.Require().NoError(err)
   588  	contactID1 := types.EncodeHex(crypto.FromECDSAPub(&contact1Key.PublicKey))
   589  
   590  	_, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: contactID1})
   591  	s.Require().NoError(err)
   592  
   593  	// Backup
   594  	_, err = bob1.BackupData(context.Background())
   595  	s.Require().NoError(err)
   596  
   597  	// Safety check
   598  	s.Require().Len(bob2.Contacts(), 0)
   599  
   600  	// Wait for the message to reach its destination
   601  	_, err = WaitOnMessengerResponse(
   602  		bob2,
   603  		func(r *MessengerResponse) bool {
   604  			return r.BackupHandled
   605  		},
   606  		"no messages",
   607  	)
   608  	s.Require().NoError(err)
   609  
   610  	s.Require().Len(bob2.AddedContacts(), 1)
   611  
   612  	actualContacts := bob2.AddedContacts()
   613  	s.Require().Equal(actualContacts[0].ID, contactID1)
   614  
   615  	_, err = bob1.BlockContact(context.Background(), contactID1, false)
   616  	s.Require().NoError(err)
   617  
   618  	// Backup
   619  	_, err = bob1.BackupData(context.Background())
   620  	s.Require().NoError(err)
   621  
   622  	_, err = WaitOnMessengerResponse(
   623  		bob2,
   624  		func(r *MessengerResponse) bool {
   625  			return r.BackupHandled
   626  		},
   627  		"no messages",
   628  	)
   629  	s.Require().NoError(err)
   630  	s.Require().Len(bob2.BlockedContacts(), 1)
   631  }
   632  
   633  func (s *MessengerBackupSuite) TestBackupCommunities() {
   634  	bob1 := s.m
   635  	// Create bob2
   636  	bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, nil)
   637  	s.Require().NoError(err)
   638  	defer TearDownMessenger(&s.Suite, bob2)
   639  
   640  	// Create a communitie
   641  
   642  	description := &requests.CreateCommunity{
   643  		Membership:  protobuf.CommunityPermissions_AUTO_ACCEPT,
   644  		Name:        "status",
   645  		Color:       "#ffffff",
   646  		Description: "status community description",
   647  	}
   648  
   649  	// Create a community chat
   650  	response, err := bob1.CreateCommunity(description, true)
   651  	s.Require().NoError(err)
   652  	s.Require().NotNil(response)
   653  	s.Require().Len(response.Communities(), 1)
   654  
   655  	// Backup
   656  	clock, err := bob1.BackupData(context.Background())
   657  	s.Require().NoError(err)
   658  
   659  	// Safety check
   660  	communities, err := bob2.Communities()
   661  	s.Require().NoError(err)
   662  	s.Require().Len(communities, 0)
   663  
   664  	// Wait for the message to reach its destination
   665  	_, err = WaitOnMessengerResponse(
   666  		bob2,
   667  		func(r *MessengerResponse) bool {
   668  			return r.BackupHandled
   669  		},
   670  		"no messages",
   671  	)
   672  
   673  	s.Require().NoError(err)
   674  
   675  	communities, err = bob2.JoinedCommunities()
   676  	s.Require().NoError(err)
   677  	s.Require().Len(communities, 1)
   678  
   679  	lastBackup, err := bob1.lastBackup()
   680  	s.Require().NoError(err)
   681  	s.Require().NotEmpty(lastBackup)
   682  	s.Require().Equal(clock, lastBackup)
   683  }
   684  
   685  func (s *MessengerBackupSuite) TestBackupKeypairs() {
   686  	// Create bob1
   687  	bob1 := s.m
   688  	profileKp := accounts.GetProfileKeypairForTest(true, true, true)
   689  	seedKp := accounts.GetSeedImportedKeypair1ForTest()
   690  
   691  	// Create a main account on bob1
   692  	err := bob1.settings.SaveOrUpdateKeypair(profileKp)
   693  	s.Require().NoError(err, "profile keypair bob1")
   694  	err = bob1.settings.SaveOrUpdateKeypair(seedKp)
   695  	s.Require().NoError(err, "seed keypair bob1")
   696  
   697  	// Check account is present in the db for bob1
   698  	dbProfileKp1, err := bob1.settings.GetKeypairByKeyUID(profileKp.KeyUID)
   699  	s.Require().NoError(err)
   700  	s.Require().True(accounts.SameKeypairs(profileKp, dbProfileKp1))
   701  	dbSeedKp1, err := bob1.settings.GetKeypairByKeyUID(seedKp.KeyUID)
   702  	s.Require().NoError(err)
   703  	s.Require().True(accounts.SameKeypairs(seedKp, dbSeedKp1))
   704  
   705  	// Create bob2
   706  	accountsFeed := &event.Feed{}
   707  	bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, []Option{WithAccountsFeed(accountsFeed)})
   708  	s.Require().NoError(err)
   709  	s.Require().NotNil(bob2.config.accountsFeed)
   710  	ch := make(chan accountsevent.Event, 20)
   711  	sub := bob2.config.accountsFeed.Subscribe(ch)
   712  	defer TearDownMessenger(&s.Suite, bob2)
   713  
   714  	// Backup
   715  	_, err = bob1.BackupData(context.Background())
   716  	s.Require().NoError(err)
   717  
   718  	// Wait for the message to reach its destination
   719  	_, err = WaitOnMessengerResponse(
   720  		bob2,
   721  		func(r *MessengerResponse) bool {
   722  			return r.BackupHandled
   723  		},
   724  		"no messages",
   725  	)
   726  	s.Require().NoError(err)
   727  
   728  	// Check account is present in the db for bob2
   729  	dbProfileKp2, err := bob2.settings.GetKeypairByKeyUID(profileKp.KeyUID)
   730  	s.Require().NoError(err)
   731  	s.Require().Equal(profileKp.Name, dbProfileKp2.Name)
   732  	s.Require().Equal(accounts.SyncedFromBackup, dbProfileKp2.SyncedFrom)
   733  
   734  	for _, acc := range profileKp.Accounts {
   735  		s.Require().True(accounts.Contains(dbProfileKp2.Accounts, acc, accounts.SameAccounts))
   736  	}
   737  
   738  	dbSeedKp2, err := bob2.settings.GetKeypairByKeyUID(seedKp.KeyUID)
   739  	s.Require().NoError(err)
   740  	s.Require().True(accounts.SameKeypairsWithDifferentSyncedFrom(seedKp, dbSeedKp2, false, accounts.SyncedFromBackup, accounts.AccountNonOperable))
   741  
   742  	keypairs, err := bob2.settings.GetAllKeypairs()
   743  	s.Require().NoError(err)
   744  
   745  	// Check whether accounts added event is sent
   746  	expectedAddresses := make(map[common.Address]struct{}, 0)
   747  	for _, acc := range dbProfileKp2.Accounts {
   748  		if acc.Chat {
   749  			continue
   750  		}
   751  		expectedAddresses[common.Address(acc.Address)] = struct{}{}
   752  	}
   753  
   754  	for _, acc := range dbSeedKp2.Accounts {
   755  		expectedAddresses[common.Address(acc.Address)] = struct{}{}
   756  	}
   757  
   758  	for i := 0; i < len(keypairs); i++ {
   759  		select {
   760  		case <-time.After(1 * time.Second):
   761  			s.Fail("Timed out waiting for accountsevent")
   762  		case event := <-ch:
   763  			switch event.Type {
   764  			case accountsevent.EventTypeAdded:
   765  				for _, address := range event.Accounts {
   766  					if _, exists := expectedAddresses[address]; !exists {
   767  						s.logger.Debug("missing address in the accounts event", zap.Any("address", address))
   768  						s.Fail("address not received in the event")
   769  					}
   770  				}
   771  			}
   772  		}
   773  	}
   774  	sub.Unsubscribe()
   775  }
   776  
   777  func (s *MessengerBackupSuite) TestBackupKeycards() {
   778  	// Create bob1
   779  	bob1 := s.m
   780  
   781  	kp1 := accounts.GetProfileKeypairForTest(true, true, true)
   782  	keycard1 := accounts.GetProfileKeycardForTest()
   783  
   784  	kp2 := accounts.GetSeedImportedKeypair1ForTest()
   785  	keycard2 := accounts.GetKeycardForSeedImportedKeypair1ForTest()
   786  
   787  	keycard2Copy := accounts.GetKeycardForSeedImportedKeypair1ForTest()
   788  	keycard2Copy.KeycardUID = keycard2Copy.KeycardUID + "C"
   789  	keycard2Copy.KeycardName = keycard2Copy.KeycardName + "Copy"
   790  
   791  	kp3 := accounts.GetSeedImportedKeypair2ForTest()
   792  	keycard3 := accounts.GetKeycardForSeedImportedKeypair2ForTest()
   793  
   794  	// Pre-condition
   795  	err := bob1.settings.SaveOrUpdateKeypair(kp1)
   796  	s.Require().NoError(err)
   797  	err = bob1.settings.SaveOrUpdateKeypair(kp2)
   798  	s.Require().NoError(err)
   799  	err = bob1.settings.SaveOrUpdateKeypair(kp3)
   800  	s.Require().NoError(err)
   801  	dbKeypairs, err := bob1.settings.GetActiveKeypairs()
   802  	s.Require().NoError(err)
   803  	s.Require().Equal(3, len(dbKeypairs))
   804  
   805  	err = bob1.settings.SaveOrUpdateKeycard(*keycard1, 0, false)
   806  	s.Require().NoError(err)
   807  	err = bob1.settings.SaveOrUpdateKeycard(*keycard2, 0, false)
   808  	s.Require().NoError(err)
   809  	err = bob1.settings.SaveOrUpdateKeycard(*keycard2Copy, 0, false)
   810  	s.Require().NoError(err)
   811  	err = bob1.settings.SaveOrUpdateKeycard(*keycard3, 0, false)
   812  	s.Require().NoError(err)
   813  
   814  	// Create bob2
   815  	bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, nil)
   816  	s.Require().NoError(err)
   817  	defer TearDownMessenger(&s.Suite, bob2)
   818  
   819  	// Backup
   820  	_, err = bob1.BackupData(context.Background())
   821  	s.Require().NoError(err)
   822  
   823  	// Wait for the message to reach its destination
   824  	_, err = WaitOnMessengerResponse(
   825  		bob2,
   826  		func(r *MessengerResponse) bool {
   827  			syncedKeycards, err := bob2.settings.GetAllKnownKeycards()
   828  			s.Require().NoError(err)
   829  			return r.BackupHandled && len(syncedKeycards) == 4
   830  
   831  		},
   832  		"no messages",
   833  	)
   834  	s.Require().NoError(err)
   835  
   836  	syncedKeycards, err := bob2.settings.GetAllKnownKeycards()
   837  	s.Require().NoError(err)
   838  	s.Require().Equal(4, len(syncedKeycards))
   839  	s.Require().True(accounts.Contains(syncedKeycards, keycard1, accounts.SameKeycards))
   840  	s.Require().True(accounts.Contains(syncedKeycards, keycard2, accounts.SameKeycards))
   841  	s.Require().True(accounts.Contains(syncedKeycards, keycard2Copy, accounts.SameKeycards))
   842  	s.Require().True(accounts.Contains(syncedKeycards, keycard3, accounts.SameKeycards))
   843  }
   844  
   845  func (s *MessengerBackupSuite) TestBackupWatchOnlyAccounts() {
   846  	// Create bob1
   847  	bob1 := s.m
   848  
   849  	woAccounts := accounts.GetWatchOnlyAccountsForTest()
   850  	err := bob1.settings.SaveOrUpdateAccounts(woAccounts, false)
   851  	s.Require().NoError(err)
   852  	dbWoAccounts1, err := bob1.settings.GetActiveWatchOnlyAccounts()
   853  	s.Require().NoError(err)
   854  	s.Require().Equal(len(woAccounts), len(dbWoAccounts1))
   855  	s.Require().True(haveSameElements(woAccounts, dbWoAccounts1, accounts.SameAccounts))
   856  
   857  	// Create bob2
   858  	accountsFeed := &event.Feed{}
   859  	bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, []Option{WithAccountsFeed(accountsFeed)})
   860  	s.Require().NoError(err)
   861  	s.Require().NotNil(bob2.config.accountsFeed)
   862  	ch := make(chan accountsevent.Event, 20)
   863  	sub := bob2.config.accountsFeed.Subscribe(ch)
   864  	defer TearDownMessenger(&s.Suite, bob2)
   865  
   866  	// Backup
   867  	_, err = bob1.BackupData(context.Background())
   868  	s.Require().NoError(err)
   869  
   870  	// Wait for the message to reach its destination
   871  	_, err = WaitOnMessengerResponse(
   872  		bob2,
   873  		func(r *MessengerResponse) bool {
   874  			c, err := bob2.settings.GetActiveWatchOnlyAccounts()
   875  			if err != nil {
   876  				return false
   877  			}
   878  			return r.BackupHandled && len(woAccounts) == len(c)
   879  
   880  		},
   881  		"no messages",
   882  	)
   883  	s.Require().NoError(err)
   884  
   885  	dbWoAccounts2, err := bob2.settings.GetActiveWatchOnlyAccounts()
   886  	s.Require().NoError(err)
   887  	s.Require().Equal(len(woAccounts), len(dbWoAccounts2))
   888  	s.Require().True(haveSameElements(woAccounts, dbWoAccounts2, accounts.SameAccounts))
   889  
   890  	// Check whether accounts added event is sent
   891  	select {
   892  	case <-time.After(1 * time.Second):
   893  		s.Fail("Timed out waiting for accountsevent")
   894  	case event := <-ch:
   895  		switch event.Type {
   896  		case accountsevent.EventTypeAdded:
   897  			s.Require().Len(event.Accounts, 1)
   898  			s.Require().Equal(common.Address(dbWoAccounts2[0].Address), event.Accounts[0])
   899  		}
   900  	}
   901  	sub.Unsubscribe()
   902  }
   903  
   904  func (s *MessengerBackupSuite) TestBackupChats() {
   905  	// Create bob1
   906  	bob1 := s.m
   907  
   908  	response, err := bob1.CreateGroupChatWithMembers(context.Background(), "group", []string{})
   909  	s.NoError(err)
   910  	s.Require().Len(response.Chats(), 1)
   911  
   912  	ourGroupChat := response.Chats()[0]
   913  
   914  	err = bob1.SaveChat(ourGroupChat)
   915  	s.NoError(err)
   916  
   917  	alice := s.newMessenger()
   918  	defer TearDownMessenger(&s.Suite, alice)
   919  
   920  	ourOneOneChat := CreateOneToOneChat("Our 1TO1", &alice.identity.PublicKey, alice.transport)
   921  	err = bob1.SaveChat(ourOneOneChat)
   922  	s.Require().NoError(err)
   923  
   924  	// Create bob2
   925  	bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, nil)
   926  	s.Require().NoError(err)
   927  	defer TearDownMessenger(&s.Suite, bob2)
   928  
   929  	// Backup
   930  	_, err = bob1.BackupData(context.Background())
   931  	s.Require().NoError(err)
   932  
   933  	// Wait for the message to reach its destination
   934  	response, err = WaitOnMessengerResponse(
   935  		bob2,
   936  		func(r *MessengerResponse) bool {
   937  			return r.BackupHandled
   938  		},
   939  		"no messages",
   940  	)
   941  	s.Require().NoError(err)
   942  
   943  	// -- Group chat
   944  	// Check response
   945  	chat, ok := response.chats[ourGroupChat.ID]
   946  	s.Require().True(ok)
   947  	s.Require().Equal(ourGroupChat.Name, chat.Name)
   948  	// Check stored chats
   949  	chat, ok = bob2.allChats.Load(ourGroupChat.ID)
   950  	s.Require().True(ok)
   951  	s.Require().Equal(ourGroupChat.Name, chat.Name)
   952  
   953  	// -- One to One chat
   954  	// Check response
   955  	chat, ok = response.chats[ourOneOneChat.ID]
   956  	s.Require().True(ok)
   957  	s.Require().Equal("", chat.Name) // We set 1-1 chat names to "" because the name is not good
   958  	// Check stored chats
   959  	chat, ok = bob2.allChats.Load(ourOneOneChat.ID)
   960  	s.Require().True(ok)
   961  	s.Require().Equal("", chat.Name)
   962  }
   963  
   964  func (s *MessengerBackupSuite) TestLeftCommunitiesAreBackedUp() {
   965  	bob1 := s.m
   966  	// Create bob2
   967  	bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, nil)
   968  	s.Require().NoError(err)
   969  	defer TearDownMessenger(&s.Suite, bob2)
   970  
   971  	description := &requests.CreateCommunity{
   972  		Membership:  protobuf.CommunityPermissions_MANUAL_ACCEPT,
   973  		Name:        "other-status",
   974  		Color:       "#fffff4",
   975  		Description: "other status community description",
   976  	}
   977  
   978  	// Create another community chat
   979  	response, err := bob1.CreateCommunity(description, true)
   980  	s.Require().NoError(err)
   981  	s.Require().NotNil(response)
   982  	s.Require().Len(response.Communities(), 1)
   983  
   984  	newCommunity := response.Communities()[0]
   985  
   986  	response, err = bob1.LeaveCommunity(newCommunity.ID())
   987  	s.Require().NoError(err)
   988  	s.Require().NotNil(response)
   989  
   990  	// trigger artificial Backup
   991  	_, err = bob1.BackupData(context.Background())
   992  	s.Require().NoError(err)
   993  
   994  	communities, err := bob1.Communities()
   995  	s.Require().NoError(err)
   996  	s.Require().Len(communities, 1)
   997  
   998  	// Safety check
   999  	communities, err = bob2.Communities()
  1000  	s.Require().NoError(err)
  1001  	s.Require().Len(communities, 0)
  1002  
  1003  	// Wait for the message to reach its destination
  1004  	_, err = WaitOnMessengerResponse(
  1005  		bob2,
  1006  		func(r *MessengerResponse) bool {
  1007  			return r.BackupHandled
  1008  		},
  1009  		"no messages",
  1010  	)
  1011  
  1012  	s.Require().NoError(err)
  1013  
  1014  	communities, err = bob2.JoinedCommunities()
  1015  	s.Require().NoError(err)
  1016  	s.Require().Len(communities, 0)
  1017  }