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 }