438 lines
14 KiB
Go
438 lines
14 KiB
Go
|
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/multiaccounts/keypairs"
|
||
|
"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 TestMessengerSyncKeycardsStateSuite(t *testing.T) {
|
||
|
suite.Run(t, new(MessengerSyncKeycardsStateSuite))
|
||
|
}
|
||
|
|
||
|
type MessengerSyncKeycardsStateSuite 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 *MessengerSyncKeycardsStateSuite) 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())
|
||
|
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 *MessengerSyncKeycardsStateSuite) TearDownTest() {
|
||
|
s.Require().NoError(s.other.Shutdown())
|
||
|
s.Require().NoError(s.main.Shutdown())
|
||
|
}
|
||
|
|
||
|
func (s *MessengerSyncKeycardsStateSuite) 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 sameKeycards(a, b *keypairs.KeyPair) bool {
|
||
|
same := a.KeycardUID == b.KeycardUID &&
|
||
|
a.KeyUID == b.KeyUID &&
|
||
|
a.KeycardName == b.KeycardName &&
|
||
|
a.KeycardLocked == b.KeycardLocked &&
|
||
|
a.LastUpdateClock == b.LastUpdateClock &&
|
||
|
len(a.AccountsAddresses) == len(b.AccountsAddresses)
|
||
|
|
||
|
if same {
|
||
|
for i := range a.AccountsAddresses {
|
||
|
found := false
|
||
|
for j := range b.AccountsAddresses {
|
||
|
if a.AccountsAddresses[i] == b.AccountsAddresses[j] {
|
||
|
found = true
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if !found {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return same
|
||
|
}
|
||
|
|
||
|
func getKeycardsForTest() []*keypairs.KeyPair {
|
||
|
keyPair1 := keypairs.KeyPair{
|
||
|
KeycardUID: "00000000000000000000000000000001",
|
||
|
KeycardName: "Card01",
|
||
|
KeycardLocked: false,
|
||
|
AccountsAddresses: []types.Address{{0x01}, {0x02}, {0x03}, {0x04}},
|
||
|
KeyUID: "0000000000000000000000000000000000000000000000000000000000000001",
|
||
|
LastUpdateClock: 100,
|
||
|
}
|
||
|
keyPair2 := keypairs.KeyPair{
|
||
|
KeycardUID: "00000000000000000000000000000002",
|
||
|
KeycardName: "Card02",
|
||
|
KeycardLocked: false,
|
||
|
AccountsAddresses: []types.Address{{0x01}, {0x02}},
|
||
|
KeyUID: "0000000000000000000000000000000000000000000000000000000000000002",
|
||
|
LastUpdateClock: 200,
|
||
|
}
|
||
|
keyPair3 := keypairs.KeyPair{
|
||
|
KeycardUID: "00000000000000000000000000000003",
|
||
|
KeycardName: "Card02 Copy",
|
||
|
KeycardLocked: false,
|
||
|
AccountsAddresses: []types.Address{{0x01}, {0x02}},
|
||
|
KeyUID: "0000000000000000000000000000000000000000000000000000000000000002",
|
||
|
LastUpdateClock: 300,
|
||
|
}
|
||
|
keyPair4 := keypairs.KeyPair{
|
||
|
KeycardUID: "00000000000000000000000000000004",
|
||
|
KeycardName: "Card04",
|
||
|
KeycardLocked: false,
|
||
|
AccountsAddresses: []types.Address{{0x01}, {0x02}, {0x03}},
|
||
|
KeyUID: "0000000000000000000000000000000000000000000000000000000000000004",
|
||
|
LastUpdateClock: 400,
|
||
|
}
|
||
|
|
||
|
return []*keypairs.KeyPair{&keyPair1, &keyPair2, &keyPair3, &keyPair4}
|
||
|
}
|
||
|
|
||
|
func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverHasNoKeycards() {
|
||
|
senderDb := s.main.settings
|
||
|
dbOnReceiver := s.other.settings
|
||
|
|
||
|
// Add keycards on sender
|
||
|
allKeycardsToSync := getKeycardsForTest()
|
||
|
for _, kp := range allKeycardsToSync {
|
||
|
addedKc, addedAccs, err := senderDb.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*kp)
|
||
|
s.Require().NoError(err)
|
||
|
s.Require().Equal(true, addedKc)
|
||
|
s.Require().Equal(false, addedAccs)
|
||
|
}
|
||
|
|
||
|
// Trigger's a sync between devices
|
||
|
err := s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil)
|
||
|
s.Require().NoError(err)
|
||
|
|
||
|
// Wait for the response
|
||
|
_, err = WaitOnMessengerResponse(
|
||
|
s.other,
|
||
|
func(r *MessengerResponse) bool {
|
||
|
return len(r.AllKnownKeycards()) == len(allKeycardsToSync)
|
||
|
},
|
||
|
"expected to receive keycards",
|
||
|
)
|
||
|
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 *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverHasKeycardsOlderThanSender() {
|
||
|
senderDb := s.main.settings
|
||
|
dbOnReceiver := s.other.settings
|
||
|
|
||
|
// Add keycards on sender
|
||
|
allKeycardsToSync := getKeycardsForTest()
|
||
|
for _, kp := range allKeycardsToSync {
|
||
|
addedKc, addedAccs, err := senderDb.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*kp)
|
||
|
s.Require().NoError(err)
|
||
|
s.Require().Equal(true, addedKc)
|
||
|
s.Require().Equal(false, addedAccs)
|
||
|
}
|
||
|
|
||
|
// Add keycards on receiver
|
||
|
keycardsOnReceiver := getKeycardsForTest()[:2]
|
||
|
keycardsOnReceiver[0].KeycardName = "CardNameToBeChanged-0"
|
||
|
keycardsOnReceiver[0].AccountsAddresses = keycardsOnReceiver[0].AccountsAddresses[2:3]
|
||
|
keycardsOnReceiver[0].LastUpdateClock = keycardsOnReceiver[0].LastUpdateClock - 1
|
||
|
keycardsOnReceiver[1].KeycardName = "CardNameToBeChanged-1"
|
||
|
keycardsOnReceiver[1].LastUpdateClock = keycardsOnReceiver[1].LastUpdateClock - 1
|
||
|
|
||
|
for _, kp := range keycardsOnReceiver {
|
||
|
addedKc, addedAccs, err := dbOnReceiver.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*kp)
|
||
|
s.Require().NoError(err)
|
||
|
s.Require().Equal(true, addedKc)
|
||
|
s.Require().Equal(false, addedAccs)
|
||
|
}
|
||
|
|
||
|
// Trigger's a sync between devices
|
||
|
err := s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil)
|
||
|
s.Require().NoError(err)
|
||
|
|
||
|
// Wait for the response
|
||
|
_, err = WaitOnMessengerResponse(
|
||
|
s.other,
|
||
|
func(r *MessengerResponse) bool {
|
||
|
return len(r.AllKnownKeycards()) == len(allKeycardsToSync)
|
||
|
},
|
||
|
"expected to receive keycards",
|
||
|
)
|
||
|
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 *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfKeycardsWereDeletedOnSenderSide() {
|
||
|
senderDb := s.main.settings
|
||
|
dbOnReceiver := s.other.settings
|
||
|
|
||
|
// Add keycards on sender
|
||
|
allKeycardsToSync := getKeycardsForTest()[:2]
|
||
|
for _, kp := range allKeycardsToSync {
|
||
|
addedKc, addedAccs, err := senderDb.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*kp)
|
||
|
s.Require().NoError(err)
|
||
|
s.Require().Equal(true, addedKc)
|
||
|
s.Require().Equal(false, addedAccs)
|
||
|
}
|
||
|
|
||
|
// Add keycards on receiver
|
||
|
keycardsOnReceiver := getKeycardsForTest()
|
||
|
for _, kp := range keycardsOnReceiver {
|
||
|
addedKc, addedAccs, err := dbOnReceiver.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*kp)
|
||
|
s.Require().NoError(err)
|
||
|
s.Require().Equal(true, addedKc)
|
||
|
s.Require().Equal(false, addedAccs)
|
||
|
}
|
||
|
|
||
|
// Trigger's a sync between devices
|
||
|
err := s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil)
|
||
|
s.Require().NoError(err)
|
||
|
|
||
|
// Wait for the response
|
||
|
_, err = WaitOnMessengerResponse(
|
||
|
s.other,
|
||
|
func(r *MessengerResponse) bool {
|
||
|
return len(r.AllKnownKeycards()) == len(allKeycardsToSync)
|
||
|
},
|
||
|
"expected to receive keycards",
|
||
|
)
|
||
|
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 *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverHasNewerKeycardsThanTheSameAreDeletedOnSenderSide() {
|
||
|
senderDb := s.main.settings
|
||
|
dbOnReceiver := s.other.settings
|
||
|
|
||
|
// Add keycards on sender
|
||
|
allKeycardsToSync := getKeycardsForTest()[:2]
|
||
|
for _, kp := range allKeycardsToSync {
|
||
|
addedKc, addedAccs, err := senderDb.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*kp)
|
||
|
s.Require().NoError(err)
|
||
|
s.Require().Equal(true, addedKc)
|
||
|
s.Require().Equal(false, addedAccs)
|
||
|
}
|
||
|
|
||
|
// Add keycards on receiver
|
||
|
keycardsOnReceiver := getKeycardsForTest()
|
||
|
clock, _ := s.other.getLastClockWithRelatedChat()
|
||
|
keycardsOnReceiver[2].KeycardName = "NewerCardName-2"
|
||
|
keycardsOnReceiver[2].LastUpdateClock = clock + 1000
|
||
|
keycardsOnReceiver[3].KeycardName = "NewerCardName-3"
|
||
|
keycardsOnReceiver[3].LastUpdateClock = clock + 1000
|
||
|
for _, kp := range keycardsOnReceiver {
|
||
|
addedKc, addedAccs, err := dbOnReceiver.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*kp)
|
||
|
s.Require().NoError(err)
|
||
|
s.Require().Equal(true, addedKc)
|
||
|
s.Require().Equal(false, addedAccs)
|
||
|
}
|
||
|
|
||
|
// Trigger's a sync between devices
|
||
|
err := s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil)
|
||
|
s.Require().NoError(err)
|
||
|
|
||
|
// Wait for the response
|
||
|
_, err = WaitOnMessengerResponse(
|
||
|
s.other,
|
||
|
func(r *MessengerResponse) bool {
|
||
|
return len(r.AllKnownKeycards()) >= len(allKeycardsToSync)
|
||
|
},
|
||
|
"expected to receive keycards",
|
||
|
)
|
||
|
s.Require().NoError(err)
|
||
|
|
||
|
syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards()
|
||
|
s.Require().NoError(err)
|
||
|
s.Require().Equal(len(keycardsOnReceiver), len(syncedKeycards))
|
||
|
for _, kc := range allKeycardsToSync {
|
||
|
s.Require().True(contains(syncedKeycards, kc, sameKeycards))
|
||
|
}
|
||
|
for _, kc := range keycardsOnReceiver {
|
||
|
s.Require().True(contains(syncedKeycards, kc, sameKeycards))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverAndSenderHasNoKeycardsInCommon() {
|
||
|
senderDb := s.main.settings
|
||
|
dbOnReceiver := s.other.settings
|
||
|
|
||
|
// Add keycards on sender
|
||
|
allKeycardsToSync := getKeycardsForTest()[:2]
|
||
|
for _, kp := range allKeycardsToSync {
|
||
|
addedKc, addedAccs, err := senderDb.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*kp)
|
||
|
s.Require().NoError(err)
|
||
|
s.Require().Equal(true, addedKc)
|
||
|
s.Require().Equal(false, addedAccs)
|
||
|
}
|
||
|
|
||
|
// Add keycards on receiver
|
||
|
keycardsOnReceiver := getKeycardsForTest()[2:]
|
||
|
clock, _ := s.other.getLastClockWithRelatedChat()
|
||
|
keycardsOnReceiver[0].KeycardName = "NewerCardName-0"
|
||
|
keycardsOnReceiver[0].LastUpdateClock = clock + 1000
|
||
|
keycardsOnReceiver[1].KeycardName = "NewerCardName-1"
|
||
|
keycardsOnReceiver[1].LastUpdateClock = clock + 1000
|
||
|
|
||
|
for _, kp := range keycardsOnReceiver {
|
||
|
addedKc, addedAccs, err := dbOnReceiver.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*kp)
|
||
|
s.Require().NoError(err)
|
||
|
s.Require().Equal(true, addedKc)
|
||
|
s.Require().Equal(false, addedAccs)
|
||
|
}
|
||
|
|
||
|
// Trigger's a sync between devices
|
||
|
err := s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil)
|
||
|
s.Require().NoError(err)
|
||
|
|
||
|
// Wait for the response
|
||
|
_, err = WaitOnMessengerResponse(
|
||
|
s.other,
|
||
|
func(r *MessengerResponse) bool {
|
||
|
return len(r.AllKnownKeycards()) >= len(allKeycardsToSync)
|
||
|
},
|
||
|
"expected to receive keycards",
|
||
|
)
|
||
|
s.Require().NoError(err)
|
||
|
|
||
|
syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards()
|
||
|
s.Require().NoError(err)
|
||
|
s.Require().Equal(len(allKeycardsToSync)+len(keycardsOnReceiver), len(syncedKeycards))
|
||
|
for _, kc := range allKeycardsToSync {
|
||
|
s.Require().True(contains(syncedKeycards, kc, sameKeycards))
|
||
|
}
|
||
|
for _, kc := range keycardsOnReceiver {
|
||
|
s.Require().True(contains(syncedKeycards, kc, sameKeycards))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (s *MessengerSyncKeycardsStateSuite) TestSyncKeycardsIfReceiverHasNewerKeycardThanSender() {
|
||
|
senderDb := s.main.settings
|
||
|
dbOnReceiver := s.other.settings
|
||
|
|
||
|
// Add keycards on sender
|
||
|
allKeycardsToSync := getKeycardsForTest()
|
||
|
for _, kp := range allKeycardsToSync {
|
||
|
addedKc, addedAccs, err := senderDb.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*kp)
|
||
|
s.Require().NoError(err)
|
||
|
s.Require().Equal(true, addedKc)
|
||
|
s.Require().Equal(false, addedAccs)
|
||
|
}
|
||
|
|
||
|
// Add keycards on receiver
|
||
|
keycardsOnReceiver := getKeycardsForTest()[2:]
|
||
|
clock, _ := s.other.getLastClockWithRelatedChat()
|
||
|
keycardsOnReceiver[0].KeycardName = "NewerCardName-0"
|
||
|
keycardsOnReceiver[0].LastUpdateClock = clock + 1000
|
||
|
keycardsOnReceiver[1].KeycardName = "NewerCardName-1"
|
||
|
keycardsOnReceiver[1].LastUpdateClock = clock + 1000
|
||
|
|
||
|
for _, kp := range keycardsOnReceiver {
|
||
|
addedKc, addedAccs, err := dbOnReceiver.AddMigratedKeyPairOrAddAccountsIfKeyPairIsAdded(*kp)
|
||
|
s.Require().NoError(err)
|
||
|
s.Require().Equal(true, addedKc)
|
||
|
s.Require().Equal(false, addedAccs)
|
||
|
}
|
||
|
|
||
|
// Trigger's a sync between devices
|
||
|
err := s.main.SyncDevices(context.Background(), "ens-name", "profile-image", nil)
|
||
|
s.Require().NoError(err)
|
||
|
|
||
|
// Wait for the response
|
||
|
_, err = WaitOnMessengerResponse(
|
||
|
s.other,
|
||
|
func(r *MessengerResponse) bool {
|
||
|
return len(r.AllKnownKeycards()) == len(allKeycardsToSync)
|
||
|
},
|
||
|
"expected to receive keycards",
|
||
|
)
|
||
|
s.Require().NoError(err)
|
||
|
|
||
|
syncedKeycards, err := dbOnReceiver.GetAllKnownKeycards()
|
||
|
s.Require().NoError(err)
|
||
|
s.Require().Equal(len(allKeycardsToSync), len(syncedKeycards))
|
||
|
for _, kc := range allKeycardsToSync[:2] {
|
||
|
s.Require().True(contains(syncedKeycards, kc, sameKeycards))
|
||
|
}
|
||
|
for _, kc := range keycardsOnReceiver {
|
||
|
s.Require().True(contains(syncedKeycards, kc, sameKeycards))
|
||
|
}
|
||
|
}
|