mirror of
https://github.com/status-im/status-protocol-go.git
synced 2025-03-03 20:10:32 +00:00
We only generate the bundle once every 6 hours (or if pairing information changes). This means that in some cases where many devices appear/disappear, new devices are not picked up until the bundle is refreshed. For example: Alice creates a device with timestamp t1 A1 Alice creates a device with timestamp t2 A2 Alice creates a device with timestamp t3 A3 Alice creates a device with timestamp t4 A4 Alice propagates this to bob, bob's list of active devices for alice is now: t2 A2, t3 A3, t4 A4 as we only keep maximum 3. If Alice sends a message to Bob from A1, previously it would be still using t1 (as long as less than 6 hours have passed). Now instead the new bundle will have t5 instead, so upon receiving the message bob will have: t3 A3, t4 A4, t5 A1. This commit changes the behavior to always update the timestamp before publishing the bundle, so that as soon as a message is received from a new device, it will increase the timestamp for that device.
This commit is contained in:
parent
5c6039f77f
commit
7623131be4
@ -265,3 +265,74 @@ func (s *EncryptionServiceMultiDeviceSuite) TestMaxDevices() {
|
||||
s.Require().NotNil(payload["alice2"])
|
||||
s.Require().NotNil(payload["alice3"])
|
||||
}
|
||||
|
||||
func (s *EncryptionServiceMultiDeviceSuite) TestMaxDevicesRefreshedBundle() {
|
||||
alice1 := s.services[aliceUser].services[0]
|
||||
alice2 := s.services[aliceUser].services[1]
|
||||
alice3 := s.services[aliceUser].services[2]
|
||||
alice4 := s.services[aliceUser].services[3]
|
||||
bob1 := s.services[bobUser].services[0]
|
||||
bobKey := s.services[bobUser].key
|
||||
aliceKey := s.services[aliceUser].key
|
||||
|
||||
// We create alice bundles, in order
|
||||
alice1Bundle, err := alice1.GetBundle(aliceKey)
|
||||
s.Require().NoError(err)
|
||||
|
||||
alice2Bundle, err := alice2.GetBundle(aliceKey)
|
||||
s.Require().NoError(err)
|
||||
|
||||
alice3Bundle, err := alice3.GetBundle(aliceKey)
|
||||
s.Require().NoError(err)
|
||||
|
||||
alice4Bundle, err := alice4.GetBundle(aliceKey)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// We send all the bundles to bob
|
||||
_, err = bob1.ProcessPublicBundle(bobKey, alice1Bundle)
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = bob1.ProcessPublicBundle(bobKey, alice2Bundle)
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = bob1.ProcessPublicBundle(bobKey, alice3Bundle)
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = bob1.ProcessPublicBundle(bobKey, alice4Bundle)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Bob sends a message to alice
|
||||
msg1, err := bob1.BuildDirectMessage(bobKey, &aliceKey.PublicKey, []byte("test"))
|
||||
s.Require().NoError(err)
|
||||
payload := msg1.Message.GetDirectMessage()
|
||||
s.Require().Equal(3, len(payload))
|
||||
// Alice1 is the oldest bundle and is rotated out
|
||||
// as we send maximum to 3 devices
|
||||
s.Require().Nil(payload["alice1"])
|
||||
s.Require().NotNil(payload["alice2"])
|
||||
s.Require().NotNil(payload["alice3"])
|
||||
s.Require().NotNil(payload["alice4"])
|
||||
|
||||
// We send a message to bob from alice1, the timestamp should be refreshed
|
||||
msg2, err := alice1.BuildDirectMessage(aliceKey, &bobKey.PublicKey, []byte("test"))
|
||||
s.Require().NoError(err)
|
||||
|
||||
alice1Bundle = msg2.Message.GetBundle()
|
||||
|
||||
// Bob processes the bundle
|
||||
_, err = bob1.ProcessPublicBundle(bobKey, alice1Bundle)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// Bob sends a message to alice
|
||||
msg3, err := bob1.BuildDirectMessage(bobKey, &aliceKey.PublicKey, []byte("test"))
|
||||
s.Require().NoError(err)
|
||||
payload = msg3.Message.GetDirectMessage()
|
||||
s.Require().Equal(3, len(payload))
|
||||
// Alice 1 is added back to the list of active devices
|
||||
s.Require().NotNil(payload["alice1"])
|
||||
// Alice 2 is rotated out as the oldest device in terms of activity
|
||||
s.Require().Nil(payload["alice2"])
|
||||
// Alice 3, 4 are still in
|
||||
s.Require().NotNil(payload["alice3"])
|
||||
s.Require().NotNil(payload["alice4"])
|
||||
}
|
||||
|
@ -88,7 +88,8 @@ func (s *EncryptionServiceTestSuite) TestGetBundle() {
|
||||
|
||||
aliceBundle2, err := s.alice.GetBundle(aliceKey)
|
||||
s.Require().NoError(err)
|
||||
s.Equal(aliceBundle1, aliceBundle2, "It returns the same bundle")
|
||||
s.Equal(aliceBundle1.GetSignedPreKeys(), aliceBundle2.GetSignedPreKeys(), "It returns the same signed pre keys")
|
||||
s.NotEqual(aliceBundle1.Timestamp, aliceBundle2.Timestamp, "It refreshes the timestamp")
|
||||
}
|
||||
|
||||
// Alice sends Bob an encrypted message with DH using an ephemeral key
|
||||
|
@ -44,7 +44,9 @@ func buildSignatureMaterial(bundle *Bundle) []byte {
|
||||
|
||||
}
|
||||
|
||||
// SignBundle signs the bundle and refreshes the timestamps
|
||||
func SignBundle(identity *ecdsa.PrivateKey, bundleContainer *BundleContainer) error {
|
||||
bundleContainer.Bundle.Timestamp = time.Now().UnixNano()
|
||||
signatureMaterial := buildSignatureMaterial(bundleContainer.GetBundle())
|
||||
|
||||
signature, err := crypto.Sign(crypto.Keccak256(signatureMaterial), identity)
|
||||
|
@ -81,7 +81,7 @@ func (s *MessengerSuite) SetupTest() {
|
||||
config := whisper.DefaultConfig
|
||||
config.MinimumAcceptedPOW = 0
|
||||
shh := whisper.New(&config)
|
||||
shh.Start(nil)
|
||||
s.Require().NoError(shh.Start(nil))
|
||||
|
||||
s.m, err = NewMessenger(
|
||||
s.privateKey,
|
||||
|
Loading…
x
Reference in New Issue
Block a user