status-go/messaging/publisher/publisher_test.go

214 lines
6.3 KiB
Go
Raw Normal View History

2019-06-03 14:29:14 +00:00
package publisher
import (
"crypto/ecdsa"
"fmt"
"io/ioutil"
2019-07-01 09:39:51 +00:00
"path/filepath"
2019-06-03 14:29:14 +00:00
"testing"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/ecies"
2019-07-01 09:39:51 +00:00
"github.com/status-im/status-go/messaging/chat"
"github.com/status-im/status-go/messaging/filter"
"github.com/status-im/status-go/messaging/multidevice"
"github.com/status-im/status-go/messaging/sharedsecret"
2019-06-03 14:29:14 +00:00
"github.com/status-im/status-go/services/shhext/whisperutils"
whisper "github.com/status-im/whisper/whisperv6"
"github.com/stretchr/testify/suite"
)
func TestServiceTestSuite(t *testing.T) {
suite.Run(t, new(ServiceTestSuite))
}
type TestKey struct {
privateKey *ecdsa.PrivateKey
keyID string
publicKeyBytes hexutil.Bytes
}
type ServiceTestSuite struct {
suite.Suite
2019-07-01 09:39:51 +00:00
alice *Publisher
bob *Publisher
2019-06-03 14:29:14 +00:00
aliceKey *TestKey
bobKey *TestKey
}
2019-07-01 09:39:51 +00:00
func (s *ServiceTestSuite) createPublisher(installationID string) (*Publisher, *TestKey) {
dir, err := ioutil.TempDir("", "publisher-test")
2019-06-03 14:29:14 +00:00
s.Require().NoError(err)
2019-07-01 09:39:51 +00:00
config := Config{PFSEnabled: true}
2019-06-03 14:29:14 +00:00
2019-07-01 09:39:51 +00:00
whisper := whisper.New(nil)
err = whisper.SetMinimumPoW(0)
2019-06-03 14:29:14 +00:00
s.Require().NoError(err)
2019-07-01 09:39:51 +00:00
publisher := New(whisper, config)
2019-06-03 14:29:14 +00:00
2019-07-01 09:39:51 +00:00
pk, err := crypto.GenerateKey()
2019-06-03 14:29:14 +00:00
s.Require().NoError(err)
2019-07-01 09:39:51 +00:00
keyID, err := whisper.AddKeyPair(pk)
2019-06-03 14:29:14 +00:00
s.Require().NoError(err)
2019-07-01 09:39:51 +00:00
testKey := TestKey{
privateKey: pk,
keyID: keyID,
publicKeyBytes: crypto.FromECDSAPub(&pk.PublicKey),
2019-06-03 14:29:14 +00:00
}
2019-07-01 09:39:51 +00:00
persistence, err := chat.NewSQLLitePersistence(filepath.Join(dir, "db1.sql"), "pass")
2019-06-03 14:29:14 +00:00
s.Require().NoError(err)
2019-07-01 09:39:51 +00:00
sharedSecretService := sharedsecret.NewService(persistence.GetSharedSecretStorage())
2019-06-03 14:29:14 +00:00
2019-07-01 10:00:46 +00:00
filterService := filter.New(whisper, filter.NewSQLLitePersistence(persistence.DB), sharedSecretService, func([]*filter.Messages) {})
2019-06-03 14:29:14 +00:00
2019-07-01 09:39:51 +00:00
multideviceConfig := &multidevice.Config{
InstallationID: installationID,
ProtocolVersion: chat.ProtocolVersion,
MaxInstallations: 3,
2019-06-03 14:29:14 +00:00
}
2019-07-01 09:39:51 +00:00
multideviceService := multidevice.New(multideviceConfig, persistence.GetMultideviceStorage())
2019-06-03 14:29:14 +00:00
2019-07-01 09:39:51 +00:00
protocolService := chat.NewProtocolService(
chat.NewEncryptionService(
persistence,
chat.DefaultEncryptionServiceConfig(installationID)),
sharedSecretService,
multideviceService,
func(addedBundles []*multidevice.Installation) {},
func(sharedSecrets []*sharedsecret.Secret) {
for _, sharedSecret := range sharedSecrets {
_, _ = filterService.ProcessNegotiatedSecret(sharedSecret)
}
},
)
2019-06-03 14:29:14 +00:00
2019-07-01 09:39:51 +00:00
publisher.Init(persistence.DB, protocolService, filterService)
2019-06-03 14:29:14 +00:00
2019-07-01 09:39:51 +00:00
err = publisher.Start(func() bool { return true }, false)
2019-06-03 14:29:14 +00:00
s.Require().NoError(err)
2019-07-01 09:39:51 +00:00
return publisher, &testKey
}
2019-06-03 14:29:14 +00:00
2019-07-01 09:39:51 +00:00
func (s *ServiceTestSuite) SetupTest() {
s.alice, s.aliceKey = s.createPublisher("installation-1")
_, err := s.alice.LoadFilters([]*filter.Chat{})
2019-06-03 14:29:14 +00:00
s.Require().NoError(err)
2019-07-01 09:39:51 +00:00
s.bob, s.bobKey = s.createPublisher("installation-2")
_, err = s.bob.LoadFilters([]*filter.Chat{})
2019-06-03 14:29:14 +00:00
s.Require().NoError(err)
}
func (s *ServiceTestSuite) TestCreateDirectMessage() {
newMessage, err := s.alice.CreateDirectMessage(s.aliceKey.privateKey, &s.bobKey.privateKey.PublicKey, false, []byte("hello"))
2019-06-03 14:29:14 +00:00
s.Require().NoError(err)
message := &whisper.Message{
Sig: s.aliceKey.publicKeyBytes,
Topic: newMessage.Topic,
Payload: newMessage.Payload,
Dst: newMessage.PublicKey,
}
2019-07-01 09:39:51 +00:00
err = s.bob.ProcessMessage(message, []byte("1"))
2019-06-03 14:29:14 +00:00
s.Require().NoError(err)
s.Require().Equal([]byte("hello"), message.Payload)
}
func (s *ServiceTestSuite) TestTopic() {
// We build an initial message
newMessage1, err := s.alice.CreateDirectMessage(s.aliceKey.privateKey, &s.bobKey.privateKey.PublicKey, false, []byte("hello"))
2019-06-03 14:29:14 +00:00
s.Require().NoError(err)
message1 := &whisper.Message{
Sig: s.aliceKey.publicKeyBytes,
Topic: newMessage1.Topic,
Payload: newMessage1.Payload,
Dst: newMessage1.PublicKey,
}
// We have no information, it should use the discovery topic
s.Require().Equal(whisperutils.DiscoveryTopicBytes, message1.Topic)
// We build a contact code from user 2
newMessage2, err := s.bob.sendContactCode()
s.Require().NoError(err)
s.Require().NotNil(newMessage2)
message2 := &whisper.Message{
Sig: s.bobKey.publicKeyBytes,
Topic: newMessage2.Topic,
Payload: newMessage2.Payload,
Dst: newMessage2.PublicKey,
}
// We receive the contact code
2019-07-01 09:39:51 +00:00
err = s.alice.ProcessMessage(message2, []byte("1"))
s.Require().EqualError(err, chat.ErrNoPayload.Error())
2019-06-03 14:29:14 +00:00
// We build another message, this time it should use the partitioned topic
newMessage3, err := s.alice.CreateDirectMessage(s.aliceKey.privateKey, &s.bobKey.privateKey.PublicKey, false, []byte("hello"))
2019-06-03 14:29:14 +00:00
s.Require().NoError(err)
message3 := &whisper.Message{
Sig: s.aliceKey.publicKeyBytes,
Topic: newMessage3.Topic,
Payload: newMessage3.Payload,
Dst: newMessage3.PublicKey,
}
expectedTopic3 := whisper.BytesToTopic(filter.PublicKeyToPartitionedTopicBytes(&s.bobKey.privateKey.PublicKey))
s.Require().Equal(expectedTopic3, message3.Topic)
// We receive the message
2019-07-01 09:39:51 +00:00
err = s.bob.ProcessMessage(message3, []byte("1"))
2019-06-03 14:29:14 +00:00
s.Require().NoError(err)
// We build another message, this time it should use the negotiated topic
newMessage4, err := s.bob.CreateDirectMessage(s.bobKey.privateKey, &s.aliceKey.privateKey.PublicKey, false, []byte("hello"))
2019-06-03 14:29:14 +00:00
s.Require().NoError(err)
message4 := &whisper.Message{
Sig: s.bobKey.publicKeyBytes,
Topic: newMessage4.Topic,
Payload: newMessage4.Payload,
Dst: newMessage4.PublicKey,
}
sharedSecret, err := ecies.ImportECDSA(s.bobKey.privateKey).GenerateShared(
ecies.ImportECDSAPublic(&s.aliceKey.privateKey.PublicKey),
16,
16)
s.Require().NoError(err)
keyString := fmt.Sprintf("%x", sharedSecret)
negotiatedTopic := whisper.BytesToTopic(filter.ToTopic(keyString))
s.Require().Equal(negotiatedTopic, message4.Topic)
// We receive the message
2019-07-01 09:39:51 +00:00
err = s.alice.ProcessMessage(message4, []byte("1"))
2019-06-03 14:29:14 +00:00
s.Require().NoError(err)
// Alice sends another message to Bob, this time it should use the negotiated topic
newMessage5, err := s.alice.CreateDirectMessage(s.aliceKey.privateKey, &s.bobKey.privateKey.PublicKey, false, []byte("hello"))
2019-06-03 14:29:14 +00:00
s.Require().NoError(err)
message5 := &whisper.Message{
Sig: s.aliceKey.publicKeyBytes,
Topic: newMessage5.Topic,
Payload: newMessage5.Payload,
Dst: newMessage5.PublicKey,
}
s.Require().NoError(err)
s.Require().Equal(negotiatedTopic, message5.Topic)
}