package protocol import ( "context" "crypto/ecdsa" "testing" "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/crypto" "github.com/status-im/status-go/eth-node/types" "github.com/status-im/status-go/protocol/encryption/multidevice" "github.com/status-im/status-go/protocol/tt" "github.com/status-im/status-go/waku" ) func TestMessengerSyncKeycardChangeSuite(t *testing.T) { suite.Run(t, new(MessengerSyncKeycardChangeSuite)) } type MessengerSyncKeycardChangeSuite struct { suite.Suite main *Messenger // main instance of Messenger paired with `other` other *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 } func (s *MessengerSyncKeycardChangeSuite) 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.main = s.newMessenger(s.shh) s.privateKey = s.main.identity // Start the main messenger in order to receive installations _, err := s.main.Start() s.Require().NoError(err) // Create new device and add main account to s.other, err = newMessengerWithKey(s.shh, s.main.identity, s.logger, nil) s.Require().NoError(err) // Pair devices (main and other) imOther := &multidevice.InstallationMetadata{ Name: "other-device", DeviceType: "other-device-type", } err = s.other.SetInstallationMetadata(s.other.installationID, imOther) s.Require().NoError(err) response, err := s.other.SendPairInstallation(context.Background(), nil) s.Require().NoError(err) s.Require().NotNil(response) // Wait for the message to reach its destination _, err = WaitOnMessengerResponse( s.main, func(r *MessengerResponse) bool { return len(r.Installations) > 0 }, "installation not received", ) s.Require().NoError(err) err = s.main.EnableInstallation(s.other.installationID) s.Require().NoError(err) } func (s *MessengerSyncKeycardChangeSuite) TearDownTest() { s.Require().NoError(s.other.Shutdown()) s.Require().NoError(s.main.Shutdown()) } func (s *MessengerSyncKeycardChangeSuite) newMessenger(shh types.Waku) *Messenger { privateKey, err := crypto.GenerateKey() s.Require().NoError(err) messenger, err := newMessengerWithKey(s.shh, privateKey, s.logger, nil) s.Require().NoError(err) return messenger } func (s *MessengerSyncKeycardChangeSuite) TestAddingNewKeycards() { dbOnReceiver := s.other.settings // Add key cards on sender allKeycardsToSync := getKeycardsForTest()[:2] for _, kp := range allKeycardsToSync { added, err := s.main.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(context.Background(), kp) s.Require().NoError(err) s.Require().Equal(true, added) } // Wait for the response _, err := WaitOnMessengerResponse( s.other, func(r *MessengerResponse) bool { return len(r.KeycardActions()) == len(allKeycardsToSync) }, "expected to receive keycard activities", ) s.Require().NoError(err) syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() s.Require().NoError(err) s.Require().Equal(len(allKeycardsToSync), len(syncedKeycards)) s.Require().True(haveSameElements(syncedKeycards, allKeycardsToSync, sameKeycards)) } func (s *MessengerSyncKeycardChangeSuite) TestAddingAccountsToKeycard() { senderDb := s.main.settings dbOnReceiver := s.other.settings // Add keycard on sender keycardToSync := getKeycardsForTest()[:1][0] addedKc, addedAccs, err := senderDb.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Add the same keycard on receiver addedKc, addedAccs, err = dbOnReceiver.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Add additional accounts to sender updatedKeycard := getKeycardsForTest()[:1][0] updatedKeycard.AccountsAddresses = []types.Address{{0x011}, {0x022}, {0x033}, {0x044}} added, err := s.main.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(context.Background(), updatedKeycard) s.Require().NoError(err) s.Require().Equal(true, added) // Add accounts that we can check for results later updatedKeycard.AccountsAddresses = append(updatedKeycard.AccountsAddresses, keycardToSync.AccountsAddresses...) // Wait for the response _, err = WaitOnMessengerResponse( s.other, func(r *MessengerResponse) bool { return len(r.KeycardActions()) == 1 }, "expected to receive keycard activities", ) s.Require().NoError(err) syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() s.Require().NoError(err) s.Require().Equal(1, len(syncedKeycards)) s.Require().True(sameKeycards(syncedKeycards[0], updatedKeycard)) } func (s *MessengerSyncKeycardChangeSuite) TestRemovingAccountsFromKeycard() { senderDb := s.main.settings dbOnReceiver := s.other.settings // Add keycard on sender keycardToSync := getKeycardsForTest()[:1][0] addedKc, addedAccs, err := senderDb.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Add the same keycard on receiver addedKc, addedAccs, err = dbOnReceiver.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) var accountAddressesToRemove []string for _, acc := range keycardToSync.AccountsAddresses[:2] { accountAddressesToRemove = append(accountAddressesToRemove, acc.String()) } // Remove accounts from sender updatedKeycard := getKeycardsForTest()[:1][0] updatedKeycard.AccountsAddresses = updatedKeycard.AccountsAddresses[2:] err = s.main.RemoveMigratedAccountsForKeycard(context.Background(), keycardToSync.KeycardUID, accountAddressesToRemove, keycardToSync.LastUpdateClock) s.Require().NoError(err) // Wait for the response _, err = WaitOnMessengerResponse( s.other, func(r *MessengerResponse) bool { return len(r.KeycardActions()) == 1 }, "expected to receive keycard activities", ) s.Require().NoError(err) syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() s.Require().NoError(err) s.Require().Equal(1, len(syncedKeycards)) s.Require().True(sameKeycards(updatedKeycard, syncedKeycards[0])) } func (s *MessengerSyncKeycardChangeSuite) TestRemovingAllAccountsFromKeycard() { senderDb := s.main.settings dbOnReceiver := s.other.settings // Add keycard on sender keycardToSync := getKeycardsForTest()[:1][0] addedKc, addedAccs, err := senderDb.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Add the same keycard on receiver addedKc, addedAccs, err = dbOnReceiver.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) var accountAddressesToRemove []string for _, acc := range keycardToSync.AccountsAddresses { accountAddressesToRemove = append(accountAddressesToRemove, acc.String()) } // Remove all accounts from sender err = s.main.RemoveMigratedAccountsForKeycard(context.Background(), keycardToSync.KeycardUID, accountAddressesToRemove, keycardToSync.LastUpdateClock) s.Require().NoError(err) // Wait for the response _, err = WaitOnMessengerResponse( s.other, func(r *MessengerResponse) bool { return len(r.KeycardActions()) == 1 }, "expected to receive keycard activities", ) s.Require().NoError(err) syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() s.Require().NoError(err) s.Require().Equal(0, len(syncedKeycards)) } func (s *MessengerSyncKeycardChangeSuite) TestDeleteKeycard() { senderDb := s.main.settings dbOnReceiver := s.other.settings // Add keycard on sender keycardToSync := getKeycardsForTest()[:1][0] addedKc, addedAccs, err := senderDb.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Add the same keycard on receiver addedKc, addedAccs, err = dbOnReceiver.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Remove keycard from sender err = s.main.DeleteKeycard(context.Background(), keycardToSync.KeycardUID, keycardToSync.LastUpdateClock) s.Require().NoError(err) // Wait for the response _, err = WaitOnMessengerResponse( s.other, func(r *MessengerResponse) bool { return len(r.KeycardActions()) == 1 }, "expected to receive keycard activities", ) s.Require().NoError(err) syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() s.Require().NoError(err) s.Require().Equal(0, len(syncedKeycards)) } func (s *MessengerSyncKeycardChangeSuite) TestSettingKeycardName() { senderDb := s.main.settings dbOnReceiver := s.other.settings // Add keycard on sender keycardToSync := getKeycardsForTest()[:1][0] addedKc, addedAccs, err := senderDb.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Add the same keycard on receiver addedKc, addedAccs, err = dbOnReceiver.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Set new keycard name to sender updatedKeycard := getKeycardsForTest()[:1][0] updatedKeycard.KeycardName = "New Keycard Name" updatedKeycard.LastUpdateClock = updatedKeycard.LastUpdateClock + 1 err = s.main.SetKeycardName(context.Background(), updatedKeycard.KeycardUID, updatedKeycard.KeycardName, updatedKeycard.LastUpdateClock) s.Require().NoError(err) // Wait for the response _, err = WaitOnMessengerResponse( s.other, func(r *MessengerResponse) bool { return len(r.KeycardActions()) == 1 }, "expected to receive keycard activities", ) s.Require().NoError(err) syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() s.Require().NoError(err) s.Require().Equal(1, len(syncedKeycards)) s.Require().True(sameKeycards(updatedKeycard, syncedKeycards[0])) } func (s *MessengerSyncKeycardChangeSuite) TestSettingKeycardNameWithOlderClock() { senderDb := s.main.settings dbOnReceiver := s.other.settings // Add keycard on sender keycardToSync := getKeycardsForTest()[:1][0] addedKc, addedAccs, err := senderDb.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Add the same keycard on receiver addedKc, addedAccs, err = dbOnReceiver.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Set new keycard name to sender updatedKeycard := getKeycardsForTest()[:1][0] updatedKeycard.KeycardName = "New Keycard Name" updatedKeycard.LastUpdateClock = updatedKeycard.LastUpdateClock - 1 err = s.main.SetKeycardName(context.Background(), updatedKeycard.KeycardUID, updatedKeycard.KeycardName, updatedKeycard.LastUpdateClock) s.Require().NoError(err) // Wait for the response _, err = WaitOnMessengerResponse( s.other, func(r *MessengerResponse) bool { return len(r.KeycardActions()) == 1 }, "expected to receive keycard activities", ) s.Require().NoError(err) syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() s.Require().NoError(err) s.Require().Equal(1, len(syncedKeycards)) s.Require().True(sameKeycards(keycardToSync, syncedKeycards[0])) } func (s *MessengerSyncKeycardChangeSuite) TestSettingKeycardLocked() { senderDb := s.main.settings dbOnReceiver := s.other.settings // Add keycard on sender keycardToSync := getKeycardsForTest()[:1][0] addedKc, addedAccs, err := senderDb.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Add the same keycard on receiver addedKc, addedAccs, err = dbOnReceiver.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Set keycard locked on sender updatedKeycard := getKeycardsForTest()[:1][0] updatedKeycard.KeycardLocked = true updatedKeycard.LastUpdateClock = updatedKeycard.LastUpdateClock + 1 err = s.main.KeycardLocked(context.Background(), updatedKeycard.KeycardUID, updatedKeycard.LastUpdateClock) s.Require().NoError(err) // Wait for the response _, err = WaitOnMessengerResponse( s.other, func(r *MessengerResponse) bool { return len(r.KeycardActions()) == 1 }, "expected to receive keycard activities", ) s.Require().NoError(err) syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() s.Require().NoError(err) s.Require().Equal(1, len(syncedKeycards)) s.Require().True(sameKeycards(updatedKeycard, syncedKeycards[0])) } func (s *MessengerSyncKeycardChangeSuite) TestSettingKeycardLockedOlderClock() { senderDb := s.main.settings dbOnReceiver := s.other.settings // Add keycard on sender keycardToSync := getKeycardsForTest()[:1][0] addedKc, addedAccs, err := senderDb.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Add the same keycard on receiver addedKc, addedAccs, err = dbOnReceiver.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Set keycard locked on sender updatedKeycard := getKeycardsForTest()[:1][0] updatedKeycard.KeycardLocked = true updatedKeycard.LastUpdateClock = updatedKeycard.LastUpdateClock - 1 err = s.main.KeycardLocked(context.Background(), updatedKeycard.KeycardUID, updatedKeycard.LastUpdateClock) s.Require().NoError(err) // Wait for the response _, err = WaitOnMessengerResponse( s.other, func(r *MessengerResponse) bool { return len(r.KeycardActions()) == 1 }, "expected to receive keycard activities", ) s.Require().NoError(err) syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() s.Require().NoError(err) s.Require().Equal(1, len(syncedKeycards)) s.Require().True(sameKeycards(keycardToSync, syncedKeycards[0])) } func (s *MessengerSyncKeycardChangeSuite) TestSettingKeycardUnlocked() { senderDb := s.main.settings dbOnReceiver := s.other.settings // Add keycard on sender keycardToSync := getKeycardsForTest()[:1][0] keycardToSync.KeycardLocked = true addedKc, addedAccs, err := senderDb.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Add the same keycard on receiver addedKc, addedAccs, err = dbOnReceiver.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Set keycard unlocked on sender updatedKeycard := getKeycardsForTest()[:1][0] updatedKeycard.KeycardLocked = false updatedKeycard.LastUpdateClock = updatedKeycard.LastUpdateClock + 1 err = s.main.KeycardUnlocked(context.Background(), updatedKeycard.KeycardUID, updatedKeycard.LastUpdateClock) s.Require().NoError(err) // Wait for the response _, err = WaitOnMessengerResponse( s.other, func(r *MessengerResponse) bool { return len(r.KeycardActions()) == 1 }, "expected to receive keycard activities", ) s.Require().NoError(err) syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() s.Require().NoError(err) s.Require().Equal(1, len(syncedKeycards)) s.Require().True(sameKeycards(updatedKeycard, syncedKeycards[0])) } func (s *MessengerSyncKeycardChangeSuite) TestSettingKeycardUnlockedOlderClock() { senderDb := s.main.settings dbOnReceiver := s.other.settings // Add keycard on sender keycardToSync := getKeycardsForTest()[:1][0] keycardToSync.KeycardLocked = true addedKc, addedAccs, err := senderDb.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Add the same keycard on receiver addedKc, addedAccs, err = dbOnReceiver.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Set keycard unlocked on sender updatedKeycard := getKeycardsForTest()[:1][0] updatedKeycard.KeycardLocked = false updatedKeycard.LastUpdateClock = updatedKeycard.LastUpdateClock - 1 err = s.main.KeycardLocked(context.Background(), updatedKeycard.KeycardUID, updatedKeycard.LastUpdateClock) s.Require().NoError(err) // Wait for the response _, err = WaitOnMessengerResponse( s.other, func(r *MessengerResponse) bool { return len(r.KeycardActions()) == 1 }, "expected to receive keycard activities", ) s.Require().NoError(err) syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() s.Require().NoError(err) s.Require().Equal(1, len(syncedKeycards)) s.Require().True(sameKeycards(keycardToSync, syncedKeycards[0])) } func (s *MessengerSyncKeycardChangeSuite) TestUpdatingKeycardUid() { senderDb := s.main.settings dbOnReceiver := s.other.settings // Add keycard on sender keycardToSync := getKeycardsForTest()[:1][0] addedKc, addedAccs, err := senderDb.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Add the same keycard on receiver addedKc, addedAccs, err = dbOnReceiver.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Set keycard unlocked on sender updatedKeycard := getKeycardsForTest()[:1][0] updatedKeycard.KeycardUID = "00000000000000000000000000000000" updatedKeycard.LastUpdateClock = updatedKeycard.LastUpdateClock + 1 err = s.main.UpdateKeycardUID(context.Background(), keycardToSync.KeycardUID, updatedKeycard.KeycardUID, updatedKeycard.LastUpdateClock) s.Require().NoError(err) // Wait for the response _, err = WaitOnMessengerResponse( s.other, func(r *MessengerResponse) bool { return len(r.KeycardActions()) == 1 }, "expected to receive keycard activities", ) s.Require().NoError(err) syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() s.Require().NoError(err) s.Require().Equal(1, len(syncedKeycards)) s.Require().True(sameKeycards(updatedKeycard, syncedKeycards[0])) } func (s *MessengerSyncKeycardChangeSuite) TestUpdatingKeycardUidOldClock() { senderDb := s.main.settings dbOnReceiver := s.other.settings // Add keycard on sender keycardToSync := getKeycardsForTest()[:1][0] addedKc, addedAccs, err := senderDb.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Add the same keycard on receiver addedKc, addedAccs, err = dbOnReceiver.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*keycardToSync) s.Require().NoError(err) s.Require().Equal(true, addedKc) s.Require().Equal(false, addedAccs) // Set keycard unlocked on sender updatedKeycard := getKeycardsForTest()[:1][0] updatedKeycard.KeycardUID = "00000000000000000000000000000000" updatedKeycard.LastUpdateClock = updatedKeycard.LastUpdateClock - 1 err = s.main.UpdateKeycardUID(context.Background(), keycardToSync.KeycardUID, updatedKeycard.KeycardUID, updatedKeycard.LastUpdateClock) s.Require().NoError(err) // Wait for the response _, err = WaitOnMessengerResponse( s.other, func(r *MessengerResponse) bool { return len(r.KeycardActions()) == 1 }, "expected to receive keycard activities", ) s.Require().NoError(err) syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards() s.Require().NoError(err) s.Require().Equal(1, len(syncedKeycards)) s.Require().True(sameKeycards(keycardToSync, syncedKeycards[0])) }