Move envelopes tracking to status-protocol-go

This commit moves envelopes tracking to status-go.
Post endpoint is not going to track envelopes anymore, as that's taken
care on status-protocol-go side, so this is a breaking change, and
version is updated accordingly.
This commit is contained in:
Andrea Maria Piana 2019-08-09 09:03:10 +02:00
parent 1a37e6b25a
commit 9ae7d2b6d5
28 changed files with 377 additions and 1375 deletions

View File

@ -1 +1 @@
0.31.0-beta.1
0.32.0-beta.0

7
go.mod
View File

@ -8,8 +8,10 @@ require (
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d
github.com/ethereum/go-ethereum v1.8.27
github.com/golang-migrate/migrate/v4 v4.5.0 // indirect
github.com/go-playground/locales v0.12.1 // indirect
github.com/go-playground/universal-translator v0.16.0 // indirect
github.com/golang/mock v1.2.0
github.com/leodido/go-urn v1.1.0 // indirect
github.com/lib/pq v1.0.0
github.com/libp2p/go-libp2p-core v0.0.3
github.com/multiformats/go-multiaddr v0.0.4
@ -19,13 +21,14 @@ require (
github.com/status-im/doubleratchet v2.0.0+incompatible
github.com/status-im/migrate/v4 v4.3.1-status
github.com/status-im/rendezvous v1.3.0
github.com/status-im/status-protocol-go v0.0.0-20190701094942-baa579640f175976472cdf47e0b97d2a5881409d
github.com/status-im/status-protocol-go v0.0.0-20190701094942-e1f4f17bafc4ac757933fb6a801fe9fed68b6c4d
github.com/status-im/whisper v1.4.14
github.com/stretchr/testify v1.3.0
github.com/syndtr/goleveldb v1.0.0
go.uber.org/zap v1.10.0
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
golang.org/x/text v0.3.2
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
gopkg.in/go-playground/validator.v9 v9.29.0
gopkg.in/natefinch/lumberjack.v2 v2.0.0
)

9
go.sum
View File

@ -132,8 +132,6 @@ github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang-migrate/migrate v3.5.4+incompatible h1:R7OzwvCJTCgwapPCiX6DyBiu2czIUMDCB118gFTKTUA=
github.com/golang-migrate/migrate v3.5.4+incompatible/go.mod h1:IsVUlFN5puWOmXrqjgGUfIRIbU7mr8oNBE2tyERd9Wk=
github.com/golang-migrate/migrate/v4 v4.4.0 h1:bQVSVUJCZkAf6ci1J4aUNFO0FyXVoncZvHEFCVD2ezE=
github.com/golang-migrate/migrate/v4 v4.4.0/go.mod h1:SzAcz2l+yDJVhQC7fwiF7T2MAFPMIkigJz98klRJ4OE=
github.com/golang-migrate/migrate/v4 v4.5.0 h1:ucd2qJu1BAKTtmjh7QlWYiq01DwlE/xXYQkOPE0ZTsI=
github.com/golang-migrate/migrate/v4 v4.5.0/go.mod h1:SzAcz2l+yDJVhQC7fwiF7T2MAFPMIkigJz98klRJ4OE=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@ -452,9 +450,8 @@ github.com/status-im/migrate/v4 v4.3.1-status h1:tJwsEYLgbFkvlTSMk89APwRDfpr4yG8
github.com/status-im/migrate/v4 v4.3.1-status/go.mod h1:r8HggRBZ/k7TRwByq/Hp3P/ubFppIna0nvyavVK0pjA=
github.com/status-im/rendezvous v1.3.0 h1:7RK/MXXW+tlm0asKm1u7Qp7Yni6AO29a7j8+E4Lbjg4=
github.com/status-im/rendezvous v1.3.0/go.mod h1:+hzjuP+j/XzLPeF6E50b88pWOTLdTcwjvNYt+Gh1W1s=
github.com/status-im/status-go v0.29.0-beta.3/go.mod h1:8OHekmRoYTn9oZgMsBdhMEgeyfaQ4eI4ycOFHJCoX7M=
github.com/status-im/status-protocol-go v0.0.0-20190701094942-baa579640f175976472cdf47e0b97d2a5881409d h1:gw4vJi9f2cDg2JhQA+UOnhGufAHPUFVWGtB3k4xPnpA=
github.com/status-im/status-protocol-go v0.0.0-20190701094942-baa579640f175976472cdf47e0b97d2a5881409d/go.mod h1:K1sZNTGahmrliIsVDTPrruKMZqbbqd8inbfbfh9Wmw4=
github.com/status-im/status-protocol-go v0.0.0-20190701094942-e1f4f17bafc4ac757933fb6a801fe9fed68b6c4d h1:3Cnw7SrJ4AeTHFcZf/xQuvQSO+f/vNp3kinIes3nFIs=
github.com/status-im/status-protocol-go v0.0.0-20190701094942-e1f4f17bafc4ac757933fb6a801fe9fed68b6c4d/go.mod h1:thrQ4V0ZUmLZPDf74xVzub1gxgSNFaSTeTQdxtRJnTU=
github.com/status-im/whisper v1.4.14 h1:9VHqx4+PUYfhDnYYtDxHkg/3cfVvkHjPNciY4LO83yc=
github.com/status-im/whisper v1.4.14/go.mod h1:WS6z39YJQ8WJa9s+DmTuEM/s2nVF6Iz3B1SZYw5cYf0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -602,8 +599,6 @@ gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v9 v9.9.3 h1:Jp2VeUxCViEo9Gst3entIFWiSkZH29YU9iRgl6ePzl4=
gopkg.in/go-playground/validator.v9 v9.9.3/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/go-playground/validator.v9 v9.29.0 h1:5ofssLNYgAA/inWn6rTZ4juWpRJUwEnXc1LG2IeXwgQ=
gopkg.in/go-playground/validator.v9 v9.29.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=

View File

@ -25,7 +25,7 @@ import (
statusproto "github.com/status-im/status-protocol-go"
"github.com/status-im/status-protocol-go/encryption/multidevice"
"github.com/status-im/status-protocol-go/transport/whisper/filter"
statustransp "github.com/status-im/status-protocol-go/transport/whisper"
)
const (
@ -447,11 +447,7 @@ func (api *PublicAPI) ConfirmMessagesProcessedByID(messageIDs [][]byte) error {
// It's important to call PublicAPI.afterSend() so that the client receives a signal
// with confirmation that the message left the device.
func (api *PublicAPI) Post(ctx context.Context, newMessage whisper.NewMessage) (hexutil.Bytes, error) {
hash, err := api.publicAPI.Post(ctx, newMessage)
if err != nil {
return nil, err
}
return api.service.afterPost(hash, newMessage), nil
return api.publicAPI.Post(ctx, newMessage)
}
// SendPublicMessage sends a public chat message to the underlying transport.
@ -462,11 +458,7 @@ func (api *PublicAPI) SendPublicMessage(ctx context.Context, msg SendPublicMessa
chat := statusproto.Chat{
Name: msg.Chat,
}
hash, newMessage, err := api.service.messenger.SendRaw(ctx, chat, msg.Payload)
if err != nil {
return nil, err
}
return api.service.afterPost(hash, newMessage), nil
return api.service.messenger.SendRaw(ctx, chat, msg.Payload)
}
// SendDirectMessage sends a 1:1 chat message to the underlying transport
@ -482,11 +474,7 @@ func (api *PublicAPI) SendDirectMessage(ctx context.Context, msg SendDirectMessa
PublicKey: publicKey,
}
hash, newMessage, err := api.service.messenger.SendRaw(ctx, chat, msg.Payload)
if err != nil {
return nil, err
}
return api.service.afterPost(hash, newMessage), nil
return api.service.messenger.SendRaw(ctx, chat, msg.Payload)
}
func (api *PublicAPI) requestMessagesUsingPayload(request db.HistoryRequest, peer, symkeyID string, payload []byte, force bool, timeout time.Duration, topics []whisper.TopicType) (hash common.Hash, err error) {
@ -597,7 +585,7 @@ func (api *PublicAPI) CompleteRequest(parent context.Context, hex string) (err e
return err
}
func (api *PublicAPI) LoadFilters(parent context.Context, chats []*filter.Chat) ([]*filter.Chat, error) {
func (api *PublicAPI) LoadFilters(parent context.Context, chats []*statustransp.Filter) ([]*statustransp.Filter, error) {
return api.service.messenger.LoadFilters(chats)
}
@ -621,7 +609,7 @@ func (api *PublicAPI) Contacts(parent context.Context) ([]*statusproto.Contact,
return api.service.messenger.Contacts()
}
func (api *PublicAPI) RemoveFilters(parent context.Context, chats []*filter.Chat) error {
func (api *PublicAPI) RemoveFilters(parent context.Context, chats []*statustransp.Filter) error {
return api.service.messenger.RemoveFilters(chats)
}

View File

@ -4,16 +4,12 @@ import (
"context"
"encoding/hex"
"fmt"
"github.com/ethereum/go-ethereum/crypto"
"github.com/status-im/status-go/params"
"io/ioutil"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/status-im/status-go/mailserver"
protocol "github.com/status-im/status-protocol-go"
whisper "github.com/status-im/whisper/whisperv6"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -241,55 +237,3 @@ func TestExpiredOrCompleted(t *testing.T) {
require.EqualError(t, err, fmt.Sprintf("request %x expired", hash))
}
}
func TestAfterPostIsCalled(t *testing.T) {
shhConfig := whisper.DefaultConfig
shhConfig.MinimumAcceptedPOW = 0
w := whisper.New(&shhConfig)
symKeyID, err := w.AddSymKeyFromPassword("abc")
require.NoError(t, err)
identity, err := crypto.GenerateKey()
require.NoError(t, err)
dbPath, err := ioutil.TempFile("", "test-after-post.sql")
require.NoError(t, err)
service := New(w, nil, nil, params.ShhextConfig{})
service.messenger, err = protocol.NewMessenger(
identity,
nil,
w,
"installation1",
protocol.WithDatabaseConfig(dbPath.Name(), "encKey"),
)
require.NoError(t, err)
api := NewPublicAPI(service)
// Using api.Post()
hash1, err := api.Post(context.Background(), whisper.NewMessage{
SymKeyID: symKeyID,
Topic: stringToTopic("topic"),
})
require.NoError(t, err)
require.Equal(t, EnvelopePosted, service.envelopesMonitor.GetMessageState(common.BytesToHash(hash1)))
// Using api.SendPublicMessage()
hash2, err := api.SendPublicMessage(context.Background(), SendPublicMessageRPC{
Chat: "test-channel",
Payload: []byte("abc"),
})
require.NoError(t, err)
require.Equal(t, EnvelopePosted, service.envelopesMonitor.GetMessageState(common.BytesToHash(hash2)))
// Using api.SendDirectMessage()
recipient, err := crypto.GenerateKey()
require.NoError(t, err)
hash3, err := api.SendDirectMessage(context.Background(), SendDirectMessageRPC{
PubKey: crypto.FromECDSAPub(&recipient.PublicKey),
Payload: []byte("abc"),
})
require.NoError(t, err)
require.Equal(t, EnvelopePosted, service.envelopesMonitor.GetMessageState(common.BytesToHash(hash3)))
}

View File

@ -1,103 +0,0 @@
package shhext
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/status-im/status-go/services/shhext/mailservers"
whisper "github.com/status-im/whisper/whisperv6"
"github.com/stretchr/testify/suite"
"github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/storage"
)
type EnvelopesMonitorSuite struct {
suite.Suite
monitor *EnvelopesMonitor
}
func (s *EnvelopesMonitorSuite) SetupTest() {
db, err := leveldb.Open(storage.NewMemStorage(), nil)
s.Require().NoError(err)
s.monitor = &EnvelopesMonitor{
envelopes: map[common.Hash]EnvelopeState{},
batches: map[common.Hash]map[common.Hash]struct{}{},
mailPeers: mailservers.NewPeerStore(mailservers.NewCache(db)),
}
}
func (s *EnvelopesMonitorSuite) TestConfirmed() {
s.monitor.Add(testHash, whisper.NewMessage{})
s.Contains(s.monitor.envelopes, testHash)
s.Equal(EnvelopePosted, s.monitor.envelopes[testHash])
s.monitor.handleEvent(whisper.EnvelopeEvent{
Event: whisper.EventEnvelopeSent,
Hash: testHash,
})
s.Contains(s.monitor.envelopes, testHash)
s.Equal(EnvelopeSent, s.monitor.envelopes[testHash])
}
func (s *EnvelopesMonitorSuite) TestConfirmedWithAcknowledge() {
testBatch := common.Hash{1}
pkey, err := crypto.GenerateKey()
s.Require().NoError(err)
node := enode.NewV4(&pkey.PublicKey, nil, 0, 0)
s.Require().NoError(s.monitor.mailPeers.Update([]*enode.Node{node}))
s.monitor.Add(testHash, whisper.NewMessage{})
s.Contains(s.monitor.envelopes, testHash)
s.Equal(EnvelopePosted, s.monitor.envelopes[testHash])
s.monitor.handleEvent(whisper.EnvelopeEvent{
Event: whisper.EventEnvelopeSent,
Hash: testHash,
Batch: testBatch,
})
s.Equal(EnvelopePosted, s.monitor.envelopes[testHash])
s.monitor.handleEvent(whisper.EnvelopeEvent{
Event: whisper.EventBatchAcknowledged,
Batch: testBatch,
Peer: node.ID(),
})
s.Contains(s.monitor.envelopes, testHash)
s.Equal(EnvelopeSent, s.monitor.envelopes[testHash])
}
func (s *EnvelopesMonitorSuite) TestIgnored() {
s.monitor.handleEvent(whisper.EnvelopeEvent{
Event: whisper.EventEnvelopeSent,
Hash: testHash,
})
s.NotContains(s.monitor.envelopes, testHash)
}
func (s *EnvelopesMonitorSuite) TestRemoved() {
s.monitor.Add(testHash, whisper.NewMessage{})
s.Contains(s.monitor.envelopes, testHash)
s.monitor.handleEvent(whisper.EnvelopeEvent{
Event: whisper.EventEnvelopeExpired,
Hash: testHash,
})
s.NotContains(s.monitor.envelopes, testHash)
}
func (s *EnvelopesMonitorSuite) TestIgnoreNotFromMailserver() {
// enables filter in the tracker to drop confirmations from non-mailserver peers
s.monitor.mailServerConfirmation = true
s.monitor.Add(testHash, whisper.NewMessage{})
s.monitor.handleEvent(whisper.EnvelopeEvent{
Event: whisper.EventEnvelopeSent,
Hash: testHash,
Peer: enode.ID{1}, // could be empty, doesn't impact test behaviour
})
s.Require().Equal(EnvelopePosted, s.monitor.GetState(testHash))
}
func (s *EnvelopesMonitorSuite) TestReceived() {
s.monitor.Add(testHash, whisper.NewMessage{})
s.Contains(s.monitor.envelopes, testHash)
s.monitor.handleEvent(whisper.EnvelopeEvent{
Event: whisper.EventEnvelopeReceived,
Hash: testHash})
s.NotContains(s.monitor.envelopes, testHash)
}

View File

@ -1,38 +0,0 @@
package shhext
import (
"crypto/ecdsa"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
)
type server struct {
server *p2p.Server
}
func (s *server) NodeID() *ecdsa.PrivateKey {
return s.server.PrivateKey
}
func (s *server) Online() bool {
return s.server.PeerCount() != 0
}
func (s *server) AddPeer(url string) error {
parsedNode, err := enode.ParseV4(url)
if err != nil {
return err
}
s.server.AddPeer(parsedNode)
return nil
}
func (s *server) Connected(id enode.ID) (bool, error) {
for _, p := range s.server.Peers() {
if p.ID() == id {
return true, nil
}
}
return false, nil
}

View File

@ -4,7 +4,6 @@ import (
"context"
"crypto/ecdsa"
"fmt"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/status-im/status-go/logutils"
"os"
"path/filepath"
@ -24,8 +23,10 @@ import (
"github.com/status-im/status-go/signal"
protocol "github.com/status-im/status-protocol-go"
protocolwhisper "github.com/status-im/status-protocol-go/transport/whisper"
whisper "github.com/status-im/whisper/whisperv6"
"github.com/syndtr/goleveldb/leveldb"
"go.uber.org/zap"
"golang.org/x/crypto/sha3"
)
@ -38,8 +39,8 @@ const (
// EnvelopeEventsHandler used for two different event types.
type EnvelopeEventsHandler interface {
EnvelopeSent(common.Hash)
EnvelopeExpired(common.Hash, error)
EnvelopeSent([][]byte)
EnvelopeExpired([][]byte, error)
MailServerRequestCompleted(common.Hash, common.Hash, []byte, error)
MailServerRequestExpired(common.Hash)
}
@ -52,7 +53,6 @@ type Service struct {
storage db.TransactionalStorage
w *whisper.Whisper
config params.ShhextConfig
envelopesMonitor *EnvelopesMonitor
mailMonitor *MailRequestMonitor
requestsRegistry *RequestsRegistry
historyUpdates *HistoryUpdateReactor
@ -84,12 +84,10 @@ func New(w *whisper.Whisper, handler EnvelopeEventsHandler, ldb *leveldb.DB, con
cache: map[common.Hash]EnvelopeState{},
requestsRegistry: requestsRegistry,
}
envelopesMonitor := NewEnvelopesMonitor(w, handler, config.MailServerConfirmations, ps, config.MaxMessageDeliveryAttempts)
return &Service{
storage: db.NewLevelDBStorage(ldb),
w: w,
config: config,
envelopesMonitor: envelopesMonitor,
mailMonitor: mailMonitor,
requestsRegistry: requestsRegistry,
historyUpdates: historyUpdates,
@ -185,11 +183,23 @@ func (s *Service) initProtocol(address, encKey, password string) error { // noli
}
}
options, err := buildMessengerOptions(s.config, v4Path, encKey)
// Create a custom zap.Logger which will forward logs from status-protocol-go to status-go logger.
zapLogger, err := logutils.NewZapLoggerWithAdapter(logutils.Logger())
if err != nil {
return err
}
envelopesMonitorConfig := &protocolwhisper.EnvelopesMonitorConfig{
MaxAttempts: s.config.MaxMessageDeliveryAttempts,
MailserverConfirmationsEnabled: s.config.MailServerConfirmations,
IsMailserver: func(peer enode.ID) bool {
return s.peerStore.Exist(peer)
},
EnvelopeEventsHandler: EnvelopeSignalHandler{},
Logger: zapLogger,
}
options := buildMessengerOptions(s.config, v4Path, encKey, envelopesMonitorConfig, zapLogger)
selectedKeyID := s.w.SelectedKeyPairID()
identity, err := s.w.GetPrivateKey(selectedKeyID)
if err != nil {
@ -198,7 +208,6 @@ func (s *Service) initProtocol(address, encKey, password string) error { // noli
messenger, err := protocol.NewMessenger(
identity,
&server{server: s.server},
s.w,
s.config.InstallationID,
options...,
@ -323,7 +332,6 @@ func (s *Service) Start(server *p2p.Server) error {
s.lastUsedMonitor = mailservers.NewLastUsedConnectionMonitor(s.peerStore, s.cache, s.w)
s.lastUsedMonitor.Start()
}
s.envelopesMonitor.Start()
s.mailMonitor.Start()
s.nodeID = server.PrivateKey
s.server = server
@ -340,7 +348,6 @@ func (s *Service) Stop() error {
s.lastUsedMonitor.Stop()
}
s.requestsRegistry.Clear()
s.envelopesMonitor.Stop()
s.mailMonitor.Stop()
if s.cancelMessenger != nil {
@ -405,16 +412,12 @@ func (s *Service) syncMessages(ctx context.Context, mailServerID []byte, r whisp
}
}
func buildMessengerOptions(config params.ShhextConfig, dbPath, dbKey string) ([]protocol.Option, error) {
// Create a custom zap.Logger which will forward logs from status-protocol-go to status-go logger.
zapLogger, err := logutils.NewZapLoggerWithAdapter(logutils.Logger())
if err != nil {
return nil, err
}
func buildMessengerOptions(config params.ShhextConfig, dbPath, dbKey string, envelopesMonitorConfig *protocolwhisper.EnvelopesMonitorConfig, logger *zap.Logger) []protocol.Option {
options := []protocol.Option{
protocol.WithCustomLogger(zapLogger),
protocol.WithCustomLogger(logger),
protocol.WithDatabaseConfig(dbPath, dbKey),
protocol.WithEnvelopesMonitorConfig(envelopesMonitorConfig),
}
if !config.DisableGenericDiscoveryTopic {
@ -428,11 +431,5 @@ func buildMessengerOptions(config params.ShhextConfig, dbPath, dbKey string) ([]
if config.SendV1Messages {
options = append(options, protocol.WithSendV1Messages())
}
return options, nil
}
func (s *Service) afterPost(hash []byte, newMessage whisper.NewMessage) hexutil.Bytes {
s.envelopesMonitor.Add(common.BytesToHash(hash), newMessage)
mID := messageID(newMessage)
return mID[:]
return options
}

View File

@ -35,19 +35,17 @@ import (
const (
// internal whisper protocol codes
statusCode = 0
messagesCode = 1
batchAcknowledgeCode = 11
p2pRequestCompleteCode = 125
)
type failureMessage struct {
Hash common.Hash
IDs [][]byte
Error error
}
func newHandlerMock(buf int) handlerMock {
return handlerMock{
confirmations: make(chan common.Hash, buf),
confirmations: make(chan [][]byte, buf),
expirations: make(chan failureMessage, buf),
requestsCompleted: make(chan common.Hash, buf),
requestsExpired: make(chan common.Hash, buf),
@ -56,19 +54,19 @@ func newHandlerMock(buf int) handlerMock {
}
type handlerMock struct {
confirmations chan common.Hash
confirmations chan [][]byte
expirations chan failureMessage
requestsCompleted chan common.Hash
requestsExpired chan common.Hash
requestsFailed chan common.Hash
}
func (t handlerMock) EnvelopeSent(hash common.Hash) {
t.confirmations <- hash
func (t handlerMock) EnvelopeSent(ids [][]byte) {
t.confirmations <- ids
}
func (t handlerMock) EnvelopeExpired(hash common.Hash, err error) {
t.expirations <- failureMessage{Hash: hash, Error: err}
func (t handlerMock) EnvelopeExpired(ids [][]byte, err error) {
t.expirations <- failureMessage{IDs: ids, Error: err}
}
func (t handlerMock) MailServerRequestCompleted(requestID common.Hash, lastEnvelopeHash common.Hash, cursor []byte, err error) {
@ -144,7 +142,6 @@ func (s *ShhExtSuite) SetupTest() {
s.Require().NoError(stack.Start())
s.nodes[i] = stack
}
s.services[0].envelopesMonitor.handler = newHandlerMock(1)
}
func (s *ShhExtSuite) TestInitProtocol() {
@ -178,78 +175,6 @@ func (s *ShhExtSuite) TestInitProtocol() {
s.NoError(err)
}
func (s *ShhExtSuite) TestPostMessageWithConfirmation() {
mock := newHandlerMock(1)
s.services[0].envelopesMonitor.handler = mock
s.Require().NoError(s.services[0].UpdateMailservers([]*enode.Node{s.nodes[1].Server().Self()}))
s.nodes[0].Server().AddPeer(s.nodes[1].Server().Self())
symID, err := s.whisper[0].GenerateSymKey()
s.NoError(err)
client, err := s.nodes[0].Attach()
s.NoError(err)
var hash common.Hash
message := whisper.NewMessage{
SymKeyID: symID,
PowTarget: whisper.DefaultMinimumPoW,
PowTime: 200,
Topic: whisper.TopicType{0x01, 0x01, 0x01, 0x01},
Payload: []byte("hello"),
}
mid := messageID(message)
s.NoError(client.Call(&hash, "shhext_post", message))
s.NoError(err)
select {
case confirmed := <-mock.confirmations:
s.Equal(mid, confirmed)
case <-time.After(5 * time.Second):
s.Fail("timed out while waiting for confirmation")
}
}
func (s *ShhExtSuite) testWaitMessageExpired(expectedError string, ttl uint32) {
mock := newHandlerMock(1)
s.services[0].envelopesMonitor.handler = mock
symID, err := s.whisper[0].GenerateSymKey()
s.NoError(err)
client, err := s.nodes[0].Attach()
s.NoError(err)
var hash common.Hash
message := whisper.NewMessage{
SymKeyID: symID,
PowTarget: whisper.DefaultMinimumPoW,
PowTime: 200,
TTL: ttl,
Topic: whisper.TopicType{0x01, 0x01, 0x01, 0x01},
Payload: []byte("hello"),
}
mid := messageID(message)
s.NoError(client.Call(&hash, "shhext_post", message))
s.NoError(err)
select {
case expired := <-mock.expirations:
s.Equal(mid, expired.Hash)
s.EqualError(expired.Error, expectedError)
case confirmed := <-mock.confirmations:
s.Fail("unexpected confirmation for hash", confirmed)
case <-time.After(10 * time.Second):
s.Fail("timed out while waiting for confirmation")
}
}
func (s *ShhExtSuite) TestWaitMessageExpired() {
s.testWaitMessageExpired("envelope expired due to connectivity issues", 1)
}
func (s *ShhExtSuite) TestErrorOnEnvelopeDelivery() {
// in the test we are sending message from peer 0 to peer 1
s.nodes[0].Server().AddPeer(s.nodes[1].Server().Self())
s.Require().NoError(s.services[0].UpdateMailservers([]*enode.Node{s.nodes[1].Server().Self()}))
s.whisper[1].SetTimeSource(func() time.Time {
return time.Now().Add(time.Hour)
})
s.testWaitMessageExpired("envelope wasn't delivered due to time sync issues", 100)
}
func (s *ShhExtSuite) TestRequestMessagesErrors() {
var err error
@ -425,7 +350,6 @@ func (s *ShhExtSuite) TestRequestMessagesSuccess() {
})
s.Require().NoError(err)
s.Require().NotNil(hash)
s.Require().NoError(waitForHashInMonitor(api.service.mailMonitor, common.BytesToHash(hash), MailServerRequestSent, time.Second))
// Send a request without a symmetric key. In this case,
// a public key extracted from MailServerPeer will be used.
hash, err = api.RequestMessages(context.TODO(), MessagesRequest{
@ -434,7 +358,6 @@ func (s *ShhExtSuite) TestRequestMessagesSuccess() {
})
s.Require().NoError(err)
s.Require().NotNil(hash)
s.Require().NoError(waitForHashInMonitor(api.service.mailMonitor, common.BytesToHash(hash), MailServerRequestSent, time.Second))
}
// TestRetrieveMessageLoopNoMessages verifies that there are no signals sent
@ -531,21 +454,6 @@ func (s *ShhExtSuite) TearDown() {
}
}
func waitForHashInMonitor(mon *MailRequestMonitor, hash common.Hash, state EnvelopeState, deadline time.Duration) error {
after := time.After(deadline)
ticker := time.Tick(100 * time.Millisecond)
for {
select {
case <-after:
return fmt.Errorf("failed while waiting for %s to get into state %d", hash, state)
case <-ticker:
if mon.GetState(hash) == state {
return nil
}
}
}
}
type WhisperNodeMockSuite struct {
suite.Suite
@ -554,8 +462,7 @@ type WhisperNodeMockSuite struct {
localNode *enode.Node
remoteRW *p2p.MsgPipeRW
localService *Service
localEnvelopesMonitor *EnvelopesMonitor
localService *Service
}
func (s *WhisperNodeMockSuite) SetupTest() {
@ -583,28 +490,12 @@ func (s *WhisperNodeMockSuite) SetupTest() {
s.localService = New(w, nil, db, params.ShhextConfig{MailServerConfirmations: true, MaxMessageDeliveryAttempts: 3})
s.Require().NoError(s.localService.UpdateMailservers([]*enode.Node{node}))
s.localEnvelopesMonitor = s.localService.envelopesMonitor
s.localEnvelopesMonitor.Start()
s.localWhisperAPI = whisper.NewPublicWhisperAPI(w)
s.localAPI = NewPublicAPI(s.localService)
s.localNode = node
s.remoteRW = rw1
}
func (s *WhisperNodeMockSuite) PostMessage(message whisper.NewMessage) common.Hash {
envBytes, err := s.localAPI.Post(context.TODO(), message)
envHash := common.BytesToHash(envBytes)
s.Require().NoError(err)
s.Require().NoError(utils.Eventually(func() error {
if state := s.localEnvelopesMonitor.GetMessageState(envHash); state != EnvelopePosted {
return fmt.Errorf("envelope with hash %s wasn't posted", envHash.String())
}
return nil
}, 2*time.Second, 100*time.Millisecond))
return envHash
}
func TestRequestMessagesSync(t *testing.T) {
suite.Run(t, new(RequestMessagesSyncSuite))
}
@ -681,40 +572,6 @@ type WhisperConfirmationSuite struct {
WhisperNodeMockSuite
}
func (s *WhisperConfirmationSuite) TestEnvelopeReceived() {
symID, err := s.localWhisperAPI.GenerateSymKeyFromPassword(context.TODO(), "test")
s.Require().NoError(err)
envHash := s.PostMessage(whisper.NewMessage{
SymKeyID: symID,
TTL: 1000,
Topic: whisper.TopicType{0x01},
})
// enable auto-replies once message got registered internally
go func() {
for {
msg, err := s.remoteRW.ReadMsg()
s.Require().NoError(err)
if msg.Code != messagesCode {
s.Require().NoError(msg.Discard())
continue
}
// reply with same envelopes. we could probably just write same data to remoteRW, but this works too.
var envs []*whisper.Envelope
s.Require().NoError(msg.Decode(&envs))
s.Require().NoError(p2p.Send(s.remoteRW, messagesCode, envs))
}
}()
// wait for message to be removed because it was delivered by remoteRW
s.Require().NoError(utils.Eventually(func() error {
if state := s.localEnvelopesMonitor.GetMessageState(envHash); state == EnvelopePosted {
return fmt.Errorf("envelope with hash %s wasn't posted", envHash.String())
}
return nil
}, 2*time.Second, 100*time.Millisecond))
}
func TestWhisperRetriesSuite(t *testing.T) {
suite.Run(t, new(WhisperRetriesSuite))
}
@ -723,91 +580,6 @@ type WhisperRetriesSuite struct {
WhisperNodeMockSuite
}
func (s *WhisperRetriesSuite) TestUseAllAvaiableAttempts() {
var attempts int32
go func() {
for {
msg, err := s.remoteRW.ReadMsg()
s.Require().NoError(err)
s.Require().NoError(msg.Discard())
if msg.Code != messagesCode {
continue
}
atomic.AddInt32(&attempts, 1)
}
}()
symID, err := s.localWhisperAPI.GenerateSymKeyFromPassword(context.TODO(), "test")
s.Require().NoError(err)
message := whisper.NewMessage{
SymKeyID: symID,
PowTarget: whisper.DefaultMinimumPoW,
PowTime: 200,
TTL: 1,
Topic: whisper.TopicType{0x01, 0x01, 0x01, 0x01},
Payload: []byte("hello"),
}
s.Require().NotNil(s.PostMessage(message))
s.Require().NoError(utils.Eventually(func() error {
madeAttempts := atomic.LoadInt32(&attempts)
if madeAttempts != int32(s.localEnvelopesMonitor.maxAttempts) {
return fmt.Errorf("made unexpected number of attempts to deliver a message: %d != %d", s.localEnvelopesMonitor.maxAttempts, madeAttempts)
}
return nil
}, 10*time.Second, 500*time.Millisecond))
}
func (s *WhisperRetriesSuite) testDelivery(target int) {
go func() {
attempt := 0
for {
msg, err := s.remoteRW.ReadMsg()
s.Require().NoError(err)
if msg.Code != messagesCode {
s.Require().NoError(msg.Discard())
continue
}
attempt++
if attempt != target {
s.Require().NoError(msg.Discard())
continue
}
data, err := ioutil.ReadAll(msg.Payload)
s.Require().NoError(err)
// without this hack event from the whisper read loop will be sent sooner than event from write loop
// i don't think that this is realistic situation and can be reproduced only in test with in-memory
// connection mock
time.Sleep(time.Nanosecond)
s.Require().NoError(p2p.Send(s.remoteRW, batchAcknowledgeCode, crypto.Keccak256Hash(data)))
}
}()
symID, err := s.localWhisperAPI.GenerateSymKeyFromPassword(context.TODO(), "test")
s.Require().NoError(err)
message := whisper.NewMessage{
SymKeyID: symID,
PowTarget: whisper.DefaultMinimumPoW,
PowTime: 200,
TTL: 1,
Topic: whisper.TopicType{0x01, 0x01, 0x01, 0x01},
Payload: []byte("hello"),
}
mID := messageID(message)
s.Require().NotNil(s.PostMessage(message))
s.Require().NoError(utils.Eventually(func() error {
if state := s.localEnvelopesMonitor.GetMessageState(mID); state != EnvelopeSent {
return fmt.Errorf("message with ID %s wasn't sent", mID.String())
}
return nil
}, 3*time.Second, 100*time.Millisecond))
}
func (s *WhisperRetriesSuite) TestDeliveredFromFirstAttempt() {
s.testDelivery(1)
}
func (s *WhisperRetriesSuite) TestDeliveredFromSecondAttempt() {
s.testDelivery(2)
}
func TestRequestWithTrackingHistorySuite(t *testing.T) {
suite.Run(t, new(RequestWithTrackingHistorySuite))
}

View File

@ -9,13 +9,13 @@ import (
type EnvelopeSignalHandler struct{}
// EnvelopeSent triggered when envelope delivered atleast to 1 peer.
func (h EnvelopeSignalHandler) EnvelopeSent(hash common.Hash) {
signal.SendEnvelopeSent(hash)
func (h EnvelopeSignalHandler) EnvelopeSent(identifiers [][]byte) {
signal.SendEnvelopeSent(identifiers)
}
// EnvelopeExpired triggered when envelope is expired but wasn't delivered to any peer.
func (h EnvelopeSignalHandler) EnvelopeExpired(hash common.Hash, err error) {
signal.SendEnvelopeExpired(hash, err)
func (h EnvelopeSignalHandler) EnvelopeExpired(identifiers [][]byte, err error) {
signal.SendEnvelopeExpired(identifiers, err)
}
// MailServerRequestCompleted triggered when the mailserver sends a message to notify that the request has been completed

View File

@ -4,10 +4,11 @@ import (
"encoding/hex"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/status-im/status-go/services/shhext/dedup"
whisper "github.com/status-im/whisper/whisperv6"
"github.com/status-im/status-protocol-go/transport/whisper/filter"
statustransp "github.com/status-im/status-protocol-go/transport/whisper"
)
const (
@ -45,8 +46,9 @@ const (
// EnvelopeSignal includes hash of the envelope.
type EnvelopeSignal struct {
Hash common.Hash `json:"hash"`
Message string `json:"message"`
IDs []hexutil.Bytes `json:"ids"`
Hash common.Hash `json:"hash"`
Message string `json:"message"`
}
// MailServerResponseSignal holds the data received in the response from the mailserver.
@ -93,17 +95,29 @@ type NewMessagesSignal struct {
}
// SendEnvelopeSent triggered when envelope delivered at least to 1 peer.
func SendEnvelopeSent(hash common.Hash) {
send(EventEnvelopeSent, EnvelopeSignal{Hash: hash})
func SendEnvelopeSent(identifiers [][]byte) {
var hexIdentifiers []hexutil.Bytes
for _, i := range identifiers {
hexIdentifiers = append(hexIdentifiers, i)
}
send(EventEnvelopeSent, EnvelopeSignal{
IDs: hexIdentifiers,
})
}
// SendEnvelopeExpired triggered when envelope delivered at least to 1 peer.
func SendEnvelopeExpired(hash common.Hash, err error) {
func SendEnvelopeExpired(identifiers [][]byte, err error) {
var message string
if err != nil {
message = err.Error()
}
send(EventEnvelopeExpired, EnvelopeSignal{Hash: hash, Message: message})
var hexIdentifiers []hexutil.Bytes
for _, i := range identifiers {
hexIdentifiers = append(hexIdentifiers, i)
}
send(EventEnvelopeExpired, EnvelopeSignal{IDs: hexIdentifiers, Message: message})
}
// SendMailServerRequestCompleted triggered when mail server response has been received
@ -135,7 +149,7 @@ type EnodeDiscoveredSignal struct {
type Messages struct {
Error error `json:"error"`
Messages []dedup.DeduplicateMessage `json:"messages"`
Chat filter.Chat `json:"chat"`
Chat statustransp.Filter `json:"chat"` // not a mistake, it's called chat in status-react
}
// SendEnodeDiscovered tiggered when an enode is discovered.

View File

@ -1,18 +1,13 @@
package whisper
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/status-im/status-go/node"
"github.com/status-im/status-go/signal"
"github.com/status-im/status-go/t/utils"
whisper "github.com/status-im/whisper/whisperv6"
"github.com/stretchr/testify/suite"
)
@ -39,90 +34,6 @@ func (s *WhisperExtensionSuite) SetupTest() {
}
}
func (s *WhisperExtensionSuite) TestSentSignal() {
node1 := s.nodes[0].GethNode()
s.NotNil(node1)
node2 := s.nodes[1].GethNode()
s.NotNil(node2)
node1.Server().AddPeer(node2.Server().Self())
confirmed := make(chan common.Hash, 1)
signal.SetDefaultNodeNotificationHandler(func(rawSignal string) {
var sg struct {
Type string
Event json.RawMessage
}
s.NoError(json.Unmarshal([]byte(rawSignal), &sg))
if sg.Type == signal.EventEnvelopeSent {
var event signal.EnvelopeSignal
s.NoError(json.Unmarshal(sg.Event, &event))
confirmed <- event.Hash
}
})
defer signal.ResetDefaultNodeNotificationHandler()
client := s.nodes[0].RPCPrivateClient()
s.NotNil(client)
var symID string
s.NoError(client.Call(&symID, "shh_newSymKey"))
msg := whisper.NewMessage{
SymKeyID: symID,
PowTarget: whisper.DefaultMinimumPoW,
PowTime: 200,
Topic: whisper.TopicType{0x01, 0x01, 0x01, 0x01},
Payload: []byte("hello"),
TTL: 5,
}
var hash common.Hash
s.NoError(client.Call(&hash, "shhext_post", msg))
s.NotEqual(common.Hash{}, hash)
select {
case conf := <-confirmed:
s.Equal(hash, conf)
case <-time.After(5 * time.Second):
s.Fail("timed out while waiting for confirmation")
}
}
func (s *WhisperExtensionSuite) TestExpiredSignal() {
expired := make(chan common.Hash, 1)
signal.SetDefaultNodeNotificationHandler(func(rawSignal string) {
var sg struct {
Type string
Event json.RawMessage
}
fmt.Println(rawSignal)
s.NoError(json.Unmarshal([]byte(rawSignal), &sg))
if sg.Type == signal.EventEnvelopeExpired {
var event signal.EnvelopeSignal
s.NoError(json.Unmarshal(sg.Event, &event))
expired <- event.Hash
}
})
defer signal.ResetDefaultNodeNotificationHandler()
client := s.nodes[0].RPCPrivateClient()
s.NotNil(client)
var symID string
s.NoError(client.Call(&symID, "shh_newSymKey"))
msg := whisper.NewMessage{
SymKeyID: symID,
PowTarget: whisper.DefaultMinimumPoW,
PowTime: 200,
TTL: 1,
Topic: whisper.TopicType{0x01, 0x01, 0x01, 0x01},
Payload: []byte("hello"),
}
var hash common.Hash
s.NoError(client.Call(&hash, "shhext_post", msg))
s.NotEqual(common.Hash{}, hash)
select {
case exp := <-expired:
s.Equal(hash, exp)
case <-time.After(5 * time.Second):
s.Fail("timed out while waiting for expiration")
}
}
func (s *WhisperExtensionSuite) TearDown() {
for _, n := range s.nodes {
cfg := n.Config()

View File

@ -2,4 +2,5 @@
This is the Status Protocol implementation in Go.
TBD

View File

@ -7,12 +7,10 @@ import (
"go.uber.org/zap"
"github.com/status-im/status-protocol-go/encryption/sharedsecret"
"github.com/status-im/status-protocol-go/transport/whisper/filter"
"github.com/ethereum/go-ethereum/crypto"
"github.com/golang/protobuf/proto"
"github.com/pkg/errors"
"github.com/status-im/status-protocol-go/encryption/sharedsecret"
whisper "github.com/status-im/whisper/whisperv6"
"github.com/status-im/status-protocol-go/encryption"
@ -22,6 +20,7 @@ import (
"github.com/status-im/status-protocol-go/datasync"
datasyncpeer "github.com/status-im/status-protocol-go/datasync/peer"
datasyncproto "github.com/vacp2p/mvds/protobuf"
)
// Whisper message properties.
@ -67,7 +66,7 @@ func newWhisperAdapter(
if featureFlags.datasync {
// We pass our encryption/transport handling to the datasync
// so it's correctly encrypted.
d.Init(adapter.encryptAndSend)
d.Init(adapter.sendDataSync)
}
return adapter
@ -186,14 +185,14 @@ func (a *whisperAdapter) handleRetrievedMessages(messages []*whisper.ReceivedMes
}
// DEPRECATED
func (a *whisperAdapter) RetrieveRawAll() (map[filter.Chat][]*protocol.StatusMessage, error) {
func (a *whisperAdapter) RetrieveRawAll() (map[transport.Filter][]*protocol.StatusMessage, error) {
chatWithMessages, err := a.transport.RetrieveRawAll()
if err != nil {
return nil, err
}
logger := a.logger.With(zap.String("site", "RetrieveRawAll"))
result := make(map[filter.Chat][]*protocol.StatusMessage)
result := make(map[transport.Filter][]*protocol.StatusMessage)
for chat, messages := range chatWithMessages {
for _, message := range messages {
@ -290,7 +289,7 @@ func (a *whisperAdapter) handleErrDeviceNotFound(ctx context.Context, publicKey
ctx, cancel := context.WithTimeout(ctx, time.Second)
defer cancel()
_, err = a.sendMessageSpec(ctx, publicKey, messageSpec)
_, _, err = a.sendMessageSpec(ctx, publicKey, messageSpec)
if err != nil {
return err
}
@ -331,23 +330,26 @@ func (a *whisperAdapter) SendPublic(ctx context.Context, chatName, chatID string
return nil, err
}
_, err = a.transport.SendPublic(ctx, newMessage, chatName)
hash, err := a.transport.SendPublic(ctx, &newMessage, chatName)
if err != nil {
return nil, err
}
messageID := protocol.MessageID(&a.privateKey.PublicKey, wrappedMessage)
return protocol.MessageID(&a.privateKey.PublicKey, wrappedMessage), nil
a.transport.Track([][]byte{messageID}, hash, newMessage)
return messageID, nil
}
// SendPublicRaw takes encoded data, encrypts it and sends through the wire.
// DEPRECATED
func (a *whisperAdapter) SendPublicRaw(ctx context.Context, chatName string, data []byte) ([]byte, whisper.NewMessage, error) {
func (a *whisperAdapter) SendPublicRaw(ctx context.Context, chatName string, data []byte) ([]byte, error) {
var newMessage whisper.NewMessage
wrappedMessage, err := a.tryWrapMessageV1(data)
if err != nil {
return nil, newMessage, errors.Wrap(err, "failed to wrap message")
return nil, errors.Wrap(err, "failed to wrap message")
}
newMessage = whisper.NewMessage{
@ -357,8 +359,16 @@ func (a *whisperAdapter) SendPublicRaw(ctx context.Context, chatName string, dat
PowTime: whisperPoWTime,
}
hash, err := a.transport.SendPublic(ctx, newMessage, chatName)
return hash, newMessage, err
hash, err := a.transport.SendPublic(ctx, &newMessage, chatName)
if err != nil {
return nil, err
}
messageID := protocol.MessageID(&a.privateKey.PublicKey, wrappedMessage)
a.transport.Track([][]byte{messageID}, hash, newMessage)
return messageID, nil
}
func (a *whisperAdapter) SendContactCode(ctx context.Context, messageSpec *encryption.ProtocolMessageSpec) ([]byte, error) {
@ -367,7 +377,7 @@ func (a *whisperAdapter) SendContactCode(ctx context.Context, messageSpec *encry
return nil, err
}
return a.transport.SendPublic(ctx, newMessage, filter.ContactCodeTopic(&a.privateKey.PublicKey))
return a.transport.SendPublic(ctx, &newMessage, transport.ContactCodeTopic(&a.privateKey.PublicKey))
}
func (a *whisperAdapter) tryWrapMessageV1(encodedMessage []byte) ([]byte, error) {
@ -464,73 +474,102 @@ func (a *whisperAdapter) SendPrivateRaw(
ctx context.Context,
publicKey *ecdsa.PublicKey,
data []byte,
) ([]byte, whisper.NewMessage, error) {
) ([]byte, error) {
a.logger.Debug(
"sending a private message",
zap.Binary("public-key", crypto.FromECDSAPub(publicKey)),
zap.String("site", "SendPrivateRaw"),
)
var newMessage whisper.NewMessage
wrappedMessage, err := a.tryWrapMessageV1(data)
if err != nil {
return nil, newMessage, errors.Wrap(err, "failed to wrap message")
return nil, errors.Wrap(err, "failed to wrap message")
}
messageSpec, err := a.protocol.BuildDirectMessage(a.privateKey, publicKey, wrappedMessage)
if err != nil {
return nil, newMessage, errors.Wrap(err, "failed to encrypt message")
return nil, errors.Wrap(err, "failed to encrypt message")
}
newMessage, err = a.messageSpecToWhisper(messageSpec)
if err != nil {
return nil, newMessage, errors.Wrap(err, "failed to convert ProtocolMessageSpec to whisper.NewMessage")
}
messageID := protocol.MessageID(&a.privateKey.PublicKey, wrappedMessage)
if a.featureFlags.datasync {
if err := a.sendWithDataSync(publicKey, wrappedMessage); err != nil {
return nil, newMessage, errors.Wrap(err, "failed to send message with datasync")
return nil, errors.Wrap(err, "failed to send message with datasync")
}
return nil, newMessage, err
return messageID, nil
}
hash, err := a.sendMessageSpec(ctx, publicKey, messageSpec)
return hash, newMessage, err
hash, newMessage, err := a.sendMessageSpec(ctx, publicKey, messageSpec)
a.transport.Track([][]byte{messageID}, hash, *newMessage)
return messageID, err
}
func (a *whisperAdapter) sendMessageSpec(ctx context.Context, publicKey *ecdsa.PublicKey, messageSpec *encryption.ProtocolMessageSpec) ([]byte, error) {
func (a *whisperAdapter) sendMessageSpec(ctx context.Context, publicKey *ecdsa.PublicKey, messageSpec *encryption.ProtocolMessageSpec) ([]byte, *whisper.NewMessage, error) {
var err error
var hash []byte
newMessage, err := a.messageSpecToWhisper(messageSpec)
if err != nil {
return nil, err
return nil, nil, err
}
logger := a.logger.With(zap.String("site", "sendMessageSpec"))
switch {
case messageSpec.SharedSecret != nil:
logger.Debug("sending using shared secret")
return a.transport.SendPrivateWithSharedSecret(ctx, newMessage, publicKey, messageSpec.SharedSecret)
hash, err = a.transport.SendPrivateWithSharedSecret(ctx, &newMessage, publicKey, messageSpec.SharedSecret)
case messageSpec.PartitionedTopicMode() == encryption.PartitionTopicV1:
logger.Debug("sending partitioned topic")
return a.transport.SendPrivateWithPartitioned(ctx, newMessage, publicKey)
hash, err = a.transport.SendPrivateWithPartitioned(ctx, &newMessage, publicKey)
case !a.featureFlags.genericDiscoveryTopicEnabled:
logger.Debug("sending partitioned topic (generic discovery topic disabled)")
return a.transport.SendPrivateWithPartitioned(ctx, newMessage, publicKey)
hash, err = a.transport.SendPrivateWithPartitioned(ctx, &newMessage, publicKey)
default:
logger.Debug("sending using discovery topic")
return a.transport.SendPrivateOnDiscovery(ctx, newMessage, publicKey)
hash, err = a.transport.SendPrivateOnDiscovery(ctx, &newMessage, publicKey)
}
if err != nil {
return nil, nil, err
}
return hash, &newMessage, nil
}
func (a *whisperAdapter) encryptAndSend(ctx context.Context, publicKey *ecdsa.PublicKey, encodedMessage []byte) error {
func (a *whisperAdapter) sendDataSync(ctx context.Context, publicKey *ecdsa.PublicKey, encodedMessage []byte, datasyncPayload *datasyncproto.Payload) error {
var messageIDs [][]byte
for _, payload := range datasyncPayload.Messages {
messageIDs = append(messageIDs, protocol.MessageID(&a.privateKey.PublicKey, payload.Body))
}
messageSpec, err := a.protocol.BuildDirectMessage(a.privateKey, publicKey, encodedMessage)
if err != nil {
return errors.Wrap(err, "failed to encrypt message")
}
_, err = a.sendMessageSpec(ctx, publicKey, messageSpec)
hash, newMessage, err := a.sendMessageSpec(ctx, publicKey, messageSpec)
if err != nil {
return err
}
a.transport.Track(messageIDs, hash, *newMessage)
return nil
}
func (a *whisperAdapter) encryptAndSend(ctx context.Context, publicKey *ecdsa.PublicKey, encodedMessage []byte) error {
messageID := protocol.MessageID(&a.privateKey.PublicKey, encodedMessage)
messageSpec, err := a.protocol.BuildDirectMessage(a.privateKey, publicKey, encodedMessage)
if err != nil {
return errors.Wrap(err, "failed to encrypt message")
}
hash, newMessage, err := a.sendMessageSpec(ctx, publicKey, messageSpec)
if err != nil {
return err
}
a.transport.Track([][]byte{messageID}, hash, *newMessage)
return nil
}
@ -556,7 +595,7 @@ func (a *whisperAdapter) handleSharedSecrets(secrets []*sharedsecret.Secret) err
for _, secret := range secrets {
logger.Debug("received shared secret", zap.Binary("identity", crypto.FromECDSAPub(secret.Identity)))
fSecret := filter.NegotiatedSecret{
fSecret := transport.NegotiatedSecret{
PublicKey: secret.Identity,
Key: secret.Key,
}
@ -567,6 +606,10 @@ func (a *whisperAdapter) handleSharedSecrets(secrets []*sharedsecret.Secret) err
return nil
}
func (a *whisperAdapter) Stop() {
a.transport.Stop()
}
// isPubKeyEqual checks that two public keys are equal
func isPubKeyEqual(a, b *ecdsa.PublicKey) bool {
// the curve is always the same, just compare the points

View File

@ -45,8 +45,6 @@ func (d *DataSync) Handle(sender *ecdsa.PublicKey, payload []byte) [][]byte {
logger.Debug("handling datasync message")
// datasync message
for _, message := range datasyncMessage.Messages {
//copiedMessage := statusMessage.Copy()
//copiedMessage.DataSyncLayerInfo.Payload = message.Body
payloads = append(payloads, message.Body)
}
if d.sendingEnabled {

View File

@ -15,7 +15,7 @@ var errNotInitialized = errors.New("Datasync transport not initialized")
type DataSyncNodeTransport struct {
packets chan transport.Packet
dispatch func(context.Context, *ecdsa.PublicKey, []byte) error
dispatch func(context.Context, *ecdsa.PublicKey, []byte, *protobuf.Payload) error
}
func NewDataSyncNodeTransport() *DataSyncNodeTransport {
@ -24,7 +24,7 @@ func NewDataSyncNodeTransport() *DataSyncNodeTransport {
}
}
func (t *DataSyncNodeTransport) Init(dispatch func(context.Context, *ecdsa.PublicKey, []byte) error) {
func (t *DataSyncNodeTransport) Init(dispatch func(context.Context, *ecdsa.PublicKey, []byte, *protobuf.Payload) error) {
t.dispatch = dispatch
}
@ -51,7 +51,7 @@ func (t *DataSyncNodeTransport) Send(_ state.PeerID, peer state.PeerID, payload
return err
}
return t.dispatch(context.TODO(), publicKey, data)
return t.dispatch(context.TODO(), publicKey, data, &payload)
}
// CalculateSendTime calculates the next epoch

View File

@ -6,16 +6,20 @@ require (
github.com/aristanetworks/goarista v0.0.0-20190704150520-f44d68189fd7 // indirect
github.com/deckarep/golang-set v1.7.1 // indirect
github.com/ethereum/go-ethereum v1.8.27
github.com/golang-migrate/migrate v3.5.4+incompatible // indirect
github.com/golang-migrate/migrate/v4 v4.5.0 // indirect
github.com/golang/protobuf v1.3.2
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8
github.com/leodido/go-urn v1.1.0 // indirect
github.com/mutecomm/go-sqlcipher v0.0.0-20170920224653-f799951b4ab2
github.com/onsi/ginkgo v1.8.0 // indirect
github.com/onsi/gomega v1.5.0 // indirect
github.com/pkg/errors v0.8.1
github.com/rs/cors v1.6.0 // indirect
github.com/russolsen/ohyeah v0.0.0-20160324131710-f4938c005315 // indirect
github.com/russolsen/same v0.0.0-20160222130632-f089df61f51d // indirect
github.com/russolsen/transit v0.0.0-20180705123435-0794b4c4505a
github.com/status-im/doubleratchet v2.0.0+incompatible
github.com/status-im/migrate/v4 v4.3.1-status
github.com/status-im/status-go v0.29.0-beta.3
github.com/status-im/whisper v1.4.14
github.com/stretchr/testify v1.3.0
github.com/vacp2p/mvds v0.0.19
@ -24,7 +28,6 @@ require (
go.uber.org/zap v1.10.0
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
golang.org/x/net v0.0.0-20190628185345-da137c7871d7 // indirect
gopkg.in/go-playground/validator.v9 v9.29.0 // indirect
)
replace github.com/ethereum/go-ethereum v1.8.27 => github.com/status-im/go-ethereum v1.8.27-status.4

View File

@ -2,56 +2,39 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxo
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/Azure/azure-pipeline-go v0.0.0-20180607212504-7571e8eb0876/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
github.com/Azure/azure-storage-blob-go v0.0.0-20180712005634-eaae161d9d5e/go.mod h1:x2mtS6O3mnMEZOJp7d7oldh8IvatBrMfReiyQ+cKgKY=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y=
github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6nK2Q=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/NaySoftware/go-fcm v0.0.0-20190516140123-808e978ddcd2/go.mod h1:3qVrdgWvoMZMoRG+/nusrCNrcP4RYU4MWGv467XjqLI=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156 h1:hh7BAWFHv41r0gce0KRYtDJpL4erKfmB1/mpgoSADeI=
github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20190502180301-283422fc1708/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aristanetworks/goarista v0.0.0-20190704150520-f44d68189fd7 h1:fKnuvQ/O22ZpD7HaJjGQXn/GxOdDJOQFL8bpM8Xe3X8=
github.com/aristanetworks/goarista v0.0.0-20190704150520-f44d68189fd7/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 h1:Eey/GGQ/E5Xp1P2Lyx1qj007hLZfbi0+CoVeJruGCtI=
github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ=
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q=
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8=
github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f/go.mod h1:8S58EK26zhXSxzv7NQFpnliaOQsmDUxvoQO3rt154Vg=
github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc=
@ -62,7 +45,6 @@ github.com/cznic/ql v1.2.0/go.mod h1:FbpzhyZrqr0PVlK6ury+PoW3T0ODUV22OeWIxcaOrSE
github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ=
github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc=
github.com/cznic/zappy v0.0.0-20160723133515-2533cb5b45cc/go.mod h1:Y1SNZ4dRUOKXshKUbwUapqNncRrho4mkjQebgEHZLj8=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -70,9 +52,7 @@ github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vs
github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ=
github.com/dgrijalva/jwt-go v0.0.0-20170201225849-2268707a8f08/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dhui/dktest v0.3.0 h1:kwX5a7EkLcjo7VpsPQSYJcKGbXBXdjI9FGjuUj1jn6I=
github.com/dhui/dktest v0.3.0/go.mod h1:cyzIUfGsBEbZ6BT7tnXqAShHSXCZhSNmFl70sZ7c1yc=
github.com/docker/distribution v2.7.0+incompatible h1:neUDAlf3wX6Ml4HdqTrbcOHXtfRN0TFIwt6YFL7N9RU=
@ -85,28 +65,21 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/elastic/gosigar v0.0.0-20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
github.com/ethereum/go-ethereum v1.8.20/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk=
github.com/gizak/termui v0.0.0-20170117222342-991cd3d38091/go.mod h1:PkJoWUt/zacQKysNfQtcw1RW+eK2SxkieVBtl+4ovLA=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc=
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM=
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.5.4/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
@ -118,14 +91,13 @@ github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang-migrate/migrate v3.5.4+incompatible h1:R7OzwvCJTCgwapPCiX6DyBiu2czIUMDCB118gFTKTUA=
github.com/golang-migrate/migrate v3.5.4+incompatible/go.mod h1:IsVUlFN5puWOmXrqjgGUfIRIbU7mr8oNBE2tyERd9Wk=
github.com/golang-migrate/migrate/v4 v4.4.0 h1:bQVSVUJCZkAf6ci1J4aUNFO0FyXVoncZvHEFCVD2ezE=
github.com/golang-migrate/migrate/v4 v4.4.0/go.mod h1:SzAcz2l+yDJVhQC7fwiF7T2MAFPMIkigJz98klRJ4OE=
github.com/golang-migrate/migrate/v4 v4.5.0 h1:ucd2qJu1BAKTtmjh7QlWYiq01DwlE/xXYQkOPE0ZTsI=
github.com/golang-migrate/migrate/v4 v4.5.0/go.mod h1:SzAcz2l+yDJVhQC7fwiF7T2MAFPMIkigJz98klRJ4OE=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v0.0.0-20170726212829-748d386b5c1e/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
@ -141,16 +113,11 @@ github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+u
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.1 h1:Dw4jY2nghMMRsh1ol8dv1axHkDwMQK2DHerMNJsIpJU=
github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU=
github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48=
github.com/gyuho/goraph v0.0.0-20171001060514-a7a4454fd3eb/go.mod h1:NtSxZCD+s3sZFwbW6WceOcUD83HM9XD5OE2r4c0P8eg=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@ -161,36 +128,16 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3 h1:DqD8eigqlUm0+znmx7zhL0xvTW3+e1jCekJMfBUADWI=
github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag=
github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo=
github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
github.com/influxdata/influxdb v0.0.0-20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE=
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8=
github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc=
github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc=
github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM=
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ=
github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA=
github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458 h1:LPECOO5LcZx5tvkxraIptrg6AiAUf+28rFV9+noSZFA=
github.com/jackpal/go-nat-pmp v0.0.0-20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA=
github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs=
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod h1:8GXXJV31xl8whumTzdZsTt3RnUIiPqzkyf7mxToRCMs=
github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY=
github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8 h1:mGIXW/lubQ4B+3bXTLxcTMTjUNDqoF6T/HUW9LbFx9s=
github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/julienschmidt/httprouter v0.0.0-20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
@ -198,11 +145,9 @@ github.com/karalabe/hid v0.0.0-20181128192157-d815e0c1a2e2/go.mod h1:YvbcH+3Wo6X
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@ -210,84 +155,19 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE=
github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ=
github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ=
github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM=
github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc=
github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8=
github.com/libp2p/go-libp2p v0.1.1/go.mod h1:I00BRo1UuUSdpuc8Q2mN7yDF/oTUTRAX6JWpTiK9Rp8=
github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8=
github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro=
github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8=
github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco=
github.com/libp2p/go-libp2p-core v0.0.3/go.mod h1:j+YQMNz9WNSkNezXOsahp9kwZBKBvxLpKD316QWSJXE=
github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI=
github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g=
github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90=
github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo=
github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE=
github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY=
github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU=
github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY=
github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY=
github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8=
github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4=
github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA=
github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8=
github.com/libp2p/go-libp2p-yamux v0.2.1/go.mod h1:1FBXiHDk1VyRM1C0aez2bCfHQ4vMZKkAQzZbkSQt5fI=
github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q=
github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0=
github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU=
github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ=
github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI=
github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA=
github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs=
github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14=
github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc=
github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc=
github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo=
github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow=
github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow=
github.com/maruel/panicparse v0.0.0-20160720141634-ad661195ed0e/go.mod h1:nty42YY5QByNC5MM7q/nj938VbgPU7avs45z6NClpxI=
github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-isatty v0.0.0-20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/mongodb/mongo-go-driver v0.3.0/go.mod h1:NK/HWDIIZkaYsnYa0hmtP443T5ELr0KDecmIioVuuyU=
github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA=
github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44=
github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44=
github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44=
github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q=
github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q=
github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q=
github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU=
github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs=
github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po=
github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg=
github.com/mutecomm/go-sqlcipher v0.0.0-20170920224653-f799951b4ab2 h1:Q5L04ENac5Rx1K+vuxM7cjsrCgqSJNumYy3SHOQC4ec=
github.com/mutecomm/go-sqlcipher v0.0.0-20170920224653-f799951b4ab2/go.mod h1:S9Hougr2LhvUtZGY1fCTj9nr9P53lfsCCQ2XqVMFZX8=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@ -307,7 +187,6 @@ github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQ
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opentracing/opentracing-go v0.0.0-20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 h1:goeTyGkArOZIVOMA0dQbyuPWGNQJZGPwPu/QS9GlpnA=
github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
@ -320,17 +199,14 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 h1:D+CiwcpGTW6pL6bv6KI3KbyEyCKyS+1JWS2h8PNDnGA=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f h1:BVwpUVJDADN2ufcGik7W992pyps0wZ888b/y9GXcLTU=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/prometheus v0.0.0-20170814170113-3101606756c5/go.mod h1:oAIUtOny2rjMX0OWN5vPR5/q/twIROJvdqnQKDdil/s=
@ -353,20 +229,12 @@ github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9Nz
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0=
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/status-im/doubleratchet v2.0.0+incompatible h1:s77lF1lDubK0RKftxN2vH8G9gwtVVp13ggWfyY4O1q4=
github.com/status-im/doubleratchet v2.0.0+incompatible/go.mod h1:1sqR0+yhiM/bd+wrdX79AOt2csZuJOni0nUDzKNuqOU=
github.com/status-im/go-ethereum v1.8.27-status.4 h1:8jTQsYDLtKd/XCa++ZkexTPHfANIDh084JbO2SBAwp4=
github.com/status-im/go-ethereum v1.8.27-status.4/go.mod h1:Ulij8LMpMvXnbnPcmDqrpI+iXoXSjxItuY/wmbasTZU=
github.com/status-im/go-multiaddr-ethv4 v1.2.0/go.mod h1:2VQ3C+9zEurcceasz12gPAtmEzCeyLUGPeKLSXYQKHo=
github.com/status-im/migrate/v4 v4.3.1-status h1:tJwsEYLgbFkvlTSMk89APwRDfpr4yG8wcwPeudsqPwo=
github.com/status-im/migrate/v4 v4.3.1-status/go.mod h1:r8HggRBZ/k7TRwByq/Hp3P/ubFppIna0nvyavVK0pjA=
github.com/status-im/rendezvous v1.3.0/go.mod h1:+hzjuP+j/XzLPeF6E50b88pWOTLdTcwjvNYt+Gh1W1s=
github.com/status-im/status-go v0.29.0-beta.3 h1:0MzV9p1r+CVxCBrg+OrGDQ8v/6p+k6Cd3ITQ4XCjFdw=
github.com/status-im/status-go v0.29.0-beta.3/go.mod h1:8OHekmRoYTn9oZgMsBdhMEgeyfaQ4eI4ycOFHJCoX7M=
github.com/status-im/whisper v1.4.14 h1:9VHqx4+PUYfhDnYYtDxHkg/3cfVvkHjPNciY4LO83yc=
github.com/status-im/whisper v1.4.14/go.mod h1:WS6z39YJQ8WJa9s+DmTuEM/s2nVF6Iz3B1SZYw5cYf0=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
@ -378,20 +246,13 @@ github.com/stretchr/testify v0.0.0-20190716104307-221dbe5ed46703ee255b1da0dec050
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2 h1:GnOzE5fEFN3b2zDhJJABEofdb51uMRNb8eqIVtdducs=
github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/uber/jaeger-client-go v0.0.0-20180607151842-f7e0d4744fa6/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/uber/jaeger-lib v0.0.0-20180615202729-a51202d6f4a7/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
github.com/vacp2p/mvds v0.0.19 h1:ZXopUNicQPzmIsggqa9Pbd6cqphFiyhthe3kneuJpC8=
github.com/vacp2p/mvds v0.0.19/go.mod h1:MxvN/VFp5zkjhUfJdBft+NrsVDwMsvueDIP2x0h6Tx8=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc=
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM=
github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8=
github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA=
github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4=
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI=
github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
@ -404,16 +265,11 @@ go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -425,15 +281,12 @@ golang.org/x/net v0.0.0-20180112015858-5ccada7d0a7b/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@ -458,9 +311,6 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190214214411-e77772198cdc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190426135247-a129542de9ae h1:mQLHiymj/JXKnnjc62tb7nD5pZLs940/sXJu+Xp3DBA=
golang.org/x/sys v0.0.0-20190426135247-a129542de9ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -491,7 +341,6 @@ google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb h1:i1Ppqkc3WQXikh8bXiwHqAN5Rv3/qDCcRk0/Otx73BY=
@ -508,14 +357,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v9 v9.9.3/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/go-playground/validator.v9 v9.29.0 h1:5ofssLNYgAA/inWn6rTZ4juWpRJUwEnXc1LG2IeXwgQ=
gopkg.in/go-playground/validator.v9 v9.29.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20180302121509-abf0ba0be5d5/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=

View File

@ -18,7 +18,6 @@ import (
"github.com/status-im/status-protocol-go/encryption/sharedsecret"
"github.com/status-im/status-protocol-go/sqlite"
transport "github.com/status-im/status-protocol-go/transport/whisper"
"github.com/status-im/status-protocol-go/transport/whisper/filter"
protocol "github.com/status-im/status-protocol-go/v1"
datasyncnode "github.com/vacp2p/mvds/node"
datasyncpeers "github.com/vacp2p/mvds/peers"
@ -77,6 +76,9 @@ type config struct {
// DEPRECATED: no need to expose it
onSendContactCodeHandler func(*encryption.ProtocolMessageSpec)
// Config for the envelopes monitor
envelopesMonitorConfig *transport.EnvelopesMonitorConfig
messagesPersistenceEnabled bool
featureFlags featureFlags
@ -153,9 +155,15 @@ func WithDatasync() func(c *config) error {
}
}
func WithEnvelopesMonitorConfig(emc *transport.EnvelopesMonitorConfig) Option {
return func(c *config) error {
c.envelopesMonitorConfig = emc
return nil
}
}
func NewMessenger(
identity *ecdsa.PrivateKey,
server transport.Server,
shh *whisper.Whisper,
installationID string,
opts ...Option,
@ -237,11 +245,11 @@ func NewMessenger(
// Initialize transport layer.
t, err := transport.NewWhisperServiceTransport(
server,
shh,
identity,
database,
nil,
c.envelopesMonitorConfig,
logger,
)
if err != nil {
@ -290,6 +298,7 @@ func NewMessenger(
// Currently this often fails, seems like it's safe to ignore them
// https://github.com/uber-go/zap/issues/328
func() error { _ = logger.Sync; return nil },
func() error { adapter.Stop(); return nil },
},
logger: logger,
}
@ -443,13 +452,13 @@ func (m *Messenger) Send(ctx context.Context, chat Chat, data []byte) ([]byte, e
// SendRaw takes encoded data, encrypts it and sends through the wire.
// DEPRECATED
func (m *Messenger) SendRaw(ctx context.Context, chat Chat, data []byte) ([]byte, whisper.NewMessage, error) {
func (m *Messenger) SendRaw(ctx context.Context, chat Chat, data []byte) ([]byte, error) {
if chat.PublicKey != nil {
return m.adapter.SendPrivateRaw(ctx, chat.PublicKey, data)
} else if chat.Name != "" {
return m.adapter.SendPublicRaw(ctx, chat.Name, data)
}
return nil, whisper.NewMessage{}, errors.New("chat is neither public nor private")
return nil, errors.New("chat is neither public nor private")
}
type RetrieveConfig struct {
@ -576,17 +585,17 @@ func (m *Messenger) retrieveSaved(ctx context.Context, chatID string, c Retrieve
}
// DEPRECATED
func (m *Messenger) RetrieveRawAll() (map[filter.Chat][]*protocol.StatusMessage, error) {
func (m *Messenger) RetrieveRawAll() (map[transport.Filter][]*protocol.StatusMessage, error) {
return m.adapter.RetrieveRawAll()
}
// DEPRECATED
func (m *Messenger) LoadFilters(chats []*filter.Chat) ([]*filter.Chat, error) {
func (m *Messenger) LoadFilters(chats []*transport.Filter) ([]*transport.Filter, error) {
return m.adapter.transport.LoadFilters(chats, m.featureFlags.genericDiscoveryTopicEnabled)
}
// DEPRECATED
func (m *Messenger) RemoveFilters(chats []*filter.Chat) error {
func (m *Messenger) RemoveFilters(chats []*transport.Filter) error {
return m.adapter.transport.RemoveFilters(chats)
}

View File

@ -1,42 +1,66 @@
package shhext
package whisper
import (
"context"
"errors"
"hash/fnv"
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/status-im/status-go/services/shhext/mailservers"
whisper "github.com/status-im/whisper/whisperv6"
"go.uber.org/zap"
)
func messageID(message whisper.NewMessage) common.Hash {
hash := fnv.New32()
_, _ = hash.Write(message.Payload)
_, _ = hash.Write(message.Topic[:])
return common.BytesToHash(hash.Sum(nil))
// EnvelopeState in local tracker
type EnvelopeState int
const (
// NotRegistered returned if asked hash wasn't registered in the tracker.
NotRegistered EnvelopeState = -1
// EnvelopePosted is set when envelope was added to a local whisper queue.
EnvelopePosted EnvelopeState = iota
// EnvelopeSent is set when envelope is sent to atleast one peer.
EnvelopeSent
)
type EnvelopesMonitorConfig struct {
EnvelopeEventsHandler EnvelopeEventsHandler
MaxAttempts int
MailserverConfirmationsEnabled bool
IsMailserver func(enode.ID) bool
Logger *zap.Logger
}
// EnvelopeEventsHandler used for two different event types.
type EnvelopeEventsHandler interface {
EnvelopeSent([][]byte)
EnvelopeExpired([][]byte, error)
MailServerRequestCompleted(common.Hash, common.Hash, []byte, error)
MailServerRequestExpired(common.Hash)
}
// NewEnvelopesMonitor returns a pointer to an instance of the EnvelopesMonitor.
func NewEnvelopesMonitor(w *whisper.Whisper, handler EnvelopeEventsHandler, mailServerConfirmation bool, mailPeers *mailservers.PeerStore, maxAttempts int) *EnvelopesMonitor {
func NewEnvelopesMonitor(w *whisper.Whisper, config *EnvelopesMonitorConfig) *EnvelopesMonitor {
logger := config.Logger
if logger == nil {
logger = zap.NewNop()
}
return &EnvelopesMonitor{
w: w,
whisperAPI: whisper.NewPublicWhisperAPI(w),
handler: handler,
mailServerConfirmation: mailServerConfirmation,
mailPeers: mailPeers,
maxAttempts: maxAttempts,
handler: config.EnvelopeEventsHandler,
mailServerConfirmation: config.MailserverConfirmationsEnabled,
maxAttempts: config.MaxAttempts,
isMailserver: config.IsMailserver,
logger: logger.With(zap.Namespace("EnvelopesMonitor")),
// key is envelope hash (event.Hash)
envelopes: map[common.Hash]EnvelopeState{},
messages: map[common.Hash]whisper.NewMessage{},
attempts: map[common.Hash]int{},
// key is messageID
messageToEnvelope: map[common.Hash]common.Hash{},
envelopes: map[common.Hash]EnvelopeState{},
messages: map[common.Hash]whisper.NewMessage{},
attempts: map[common.Hash]int{},
identifiers: make(map[common.Hash][][]byte),
// key is hash of the batch (event.Batch)
batches: map[common.Hash]map[common.Hash]struct{}{},
@ -55,14 +79,15 @@ type EnvelopesMonitor struct {
envelopes map[common.Hash]EnvelopeState
batches map[common.Hash]map[common.Hash]struct{}
messageToEnvelope map[common.Hash]common.Hash
messages map[common.Hash]whisper.NewMessage
attempts map[common.Hash]int
messages map[common.Hash]whisper.NewMessage
attempts map[common.Hash]int
identifiers map[common.Hash][][]byte
mailPeers *mailservers.PeerStore
wg sync.WaitGroup
quit chan struct{}
isMailserver func(peer enode.ID) bool
wg sync.WaitGroup
quit chan struct{}
logger *zap.Logger
}
// Start processing events.
@ -82,13 +107,13 @@ func (m *EnvelopesMonitor) Stop() {
}
// Add hash to a tracker.
func (m *EnvelopesMonitor) Add(envelopeHash common.Hash, message whisper.NewMessage) {
func (m *EnvelopesMonitor) Add(identifiers [][]byte, envelopeHash common.Hash, message whisper.NewMessage) {
m.mu.Lock()
defer m.mu.Unlock()
m.envelopes[envelopeHash] = EnvelopePosted
m.identifiers[envelopeHash] = identifiers
m.messages[envelopeHash] = message
m.attempts[envelopeHash] = 1
m.messageToEnvelope[messageID(message)] = envelopeHash
}
func (m *EnvelopesMonitor) GetState(hash common.Hash) EnvelopeState {
@ -101,20 +126,6 @@ func (m *EnvelopesMonitor) GetState(hash common.Hash) EnvelopeState {
return state
}
func (m *EnvelopesMonitor) GetMessageState(mID common.Hash) EnvelopeState {
m.mu.Lock()
defer m.mu.Unlock()
envelope, exist := m.messageToEnvelope[mID]
if !exist {
return NotRegistered
}
state, exist := m.envelopes[envelope]
if !exist {
return NotRegistered
}
return state
}
// handleEnvelopeEvents processes whisper envelope events
func (m *EnvelopesMonitor) handleEnvelopeEvents() {
events := make(chan whisper.EnvelopeEvent, 100) // must be buffered to prevent blocking whisper
@ -160,25 +171,21 @@ func (m *EnvelopesMonitor) handleEventEnvelopeSent(event whisper.EnvelopeEvent)
if !ok || state == EnvelopeSent {
return
}
log.Debug("envelope is sent", "hash", event.Hash, "peer", event.Peer)
m.logger.Debug("envelope is sent", zap.String("hash", event.Hash.String()), zap.String("peer", event.Peer.String()))
if event.Batch != (common.Hash{}) {
if _, ok := m.batches[event.Batch]; !ok {
m.batches[event.Batch] = map[common.Hash]struct{}{}
}
m.batches[event.Batch][event.Hash] = struct{}{}
log.Debug("waiting for a confirmation", "batch", event.Batch)
m.logger.Debug("waiting for a confirmation", zap.String("batch", event.Batch.String()))
} else {
m.envelopes[event.Hash] = EnvelopeSent
if m.handler != nil {
m.handler.EnvelopeSent(messageID(m.messages[event.Hash]))
m.handler.EnvelopeSent(m.identifiers[event.Hash])
}
}
}
func (m *EnvelopesMonitor) isMailserver(peer enode.ID) bool {
return m.mailPeers.Exist(peer)
}
func (m *EnvelopesMonitor) handleAcknowledgedBatch(event whisper.EnvelopeEvent) {
if m.mailServerConfirmation {
if !m.isMailserver(event.Peer) {
@ -191,19 +198,19 @@ func (m *EnvelopesMonitor) handleAcknowledgedBatch(event whisper.EnvelopeEvent)
envelopes, ok := m.batches[event.Batch]
if !ok {
log.Debug("batch is not found", "batch", event.Batch)
m.logger.Debug("batch is not found", zap.String("batch", event.Batch.String()))
}
log.Debug("received a confirmation", "batch", event.Batch, "peer", event.Peer)
m.logger.Debug("received a confirmation", zap.String("batch", event.Batch.String()), zap.String("peer", event.Peer.String()))
envelopeErrors, ok := event.Data.([]whisper.EnvelopeError)
if event.Data != nil && !ok {
log.Error("received unexpected data in the the confirmation event", "batch", event.Batch)
m.logger.Error("received unexpected data in the the confirmation event", zap.String("batch", event.Batch.String()))
}
failedEnvelopes := map[common.Hash]struct{}{}
for i := range envelopeErrors {
envelopeError := envelopeErrors[i]
_, exist := m.envelopes[envelopeError.Hash]
if exist {
log.Warn("envelope that was posted by us is discarded", "hash", envelopeError.Hash, "peer", event.Peer, "error", envelopeError.Description)
m.logger.Warn("envelope that was posted by us is discarded", zap.String("hash", envelopeError.Hash.String()), zap.String("peer", event.Peer.String()), zap.String("error", envelopeError.Description))
var err error
switch envelopeError.Code {
case whisper.EnvelopeTimeNotSynced:
@ -224,7 +231,7 @@ func (m *EnvelopesMonitor) handleAcknowledgedBatch(event whisper.EnvelopeEvent)
}
m.envelopes[hash] = EnvelopeSent
if m.handler != nil {
m.handler.EnvelopeSent(messageID(m.messages[hash]))
m.handler.EnvelopeSent(m.identifiers[hash])
}
}
delete(m.batches, event.Batch)
@ -242,29 +249,32 @@ func (m *EnvelopesMonitor) handleEnvelopeFailure(hash common.Hash, err error) {
if state, ok := m.envelopes[hash]; ok {
message, exist := m.messages[hash]
if !exist {
log.Error("message was deleted erroneously", "envelope hash", hash)
m.logger.Error("message was deleted erroneously", zap.String("envelope hash", hash.String()))
}
mID := messageID(message)
attempt := m.attempts[hash]
identifiers := m.identifiers[hash]
m.clearMessageState(hash)
if state == EnvelopeSent {
return
}
if attempt < m.maxAttempts {
log.Debug("retrying to send a message", "message id", mID, "attempt", attempt+1)
m.logger.Debug("retrying to send a message", zap.String("hash", hash.String()), zap.Int("attempt", attempt+1))
hex, err := m.whisperAPI.Post(context.TODO(), message)
if err != nil {
log.Error("failed to retry sending message", "message id", mID, "attempt", attempt+1)
m.logger.Error("failed to retry sending message", zap.String("hash", hash.String()), zap.Int("attempt", attempt+1), zap.Error(err))
if m.handler != nil {
m.handler.EnvelopeExpired(identifiers, err)
}
}
envelopeID := common.BytesToHash(hex)
m.messageToEnvelope[mID] = envelopeID
m.envelopes[envelopeID] = EnvelopePosted
m.messages[envelopeID] = message
m.attempts[envelopeID] = attempt + 1
} else {
log.Debug("envelope expired", "hash", hash, "state", state)
m.logger.Debug("envelope expired", zap.String("hash", hash.String()))
if m.handler != nil {
m.handler.EnvelopeExpired(mID, err)
m.handler.EnvelopeExpired(identifiers, err)
}
}
}
@ -282,10 +292,10 @@ func (m *EnvelopesMonitor) handleEventEnvelopeReceived(event whisper.EnvelopeEve
if !ok || state != EnvelopePosted {
return
}
log.Debug("expected envelope received", "hash", event.Hash, "peer", event.Peer)
m.logger.Debug("expected envelope received", zap.String("hash", event.Hash.String()), zap.String("peer", event.Peer.String()))
m.envelopes[event.Hash] = EnvelopeSent
if m.handler != nil {
m.handler.EnvelopeSent(messageID(m.messages[event.Hash]))
m.handler.EnvelopeSent(m.identifiers[event.Hash])
}
}
@ -293,8 +303,7 @@ func (m *EnvelopesMonitor) handleEventEnvelopeReceived(event whisper.EnvelopeEve
// not thread-safe, should be protected on a higher level.
func (m *EnvelopesMonitor) clearMessageState(envelopeID common.Hash) {
delete(m.envelopes, envelopeID)
mID := messageID(m.messages[envelopeID])
delete(m.messageToEnvelope, mID)
delete(m.messages, envelopeID)
delete(m.attempts, envelopeID)
delete(m.identifiers, envelopeID)
}

View File

@ -1,4 +1,4 @@
package filter
package whisper
import (
"crypto/ecdsa"
@ -15,7 +15,7 @@ import (
)
const (
DiscoveryTopic = "contact-discovery"
discoveryTopic = "contact-discovery"
)
var (
@ -24,7 +24,7 @@ var (
minPow = 0.0
)
type Filter struct {
type whisperFilter struct {
FilterID string
Topic whisper.TopicType
SymKeyID string
@ -36,16 +36,16 @@ type NegotiatedSecret struct {
}
// TODO: revise fields encoding/decoding. Some are encoded using hexutil and some using encoding/hex.
type Chat struct {
type Filter struct {
// ChatID is the identifier of the chat
ChatID string `json:"chatId"`
// FilterID the whisper filter id generated
FilterID string `json:"filterId"`
// SymKeyID is the symmetric key id used for symmetric chats
// SymKeyID is the symmetric key id used for symmetric filters
SymKeyID string `json:"symKeyId"`
// OneToOne tells us if we need to use asymmetric encryption for this chat
OneToOne bool `json:"oneToOne"`
// Identity is the public key of the other recipient for non-public chats.
// Identity is the public key of the other recipient for non-public filters.
// It's encoded using encoding/hex.
Identity string `json:"identity"`
// Topic is the whisper topic
@ -58,25 +58,25 @@ type Chat struct {
Listen bool `json:"listen"`
}
func (c *Chat) IsPublic() bool {
func (c *Filter) IsPublic() bool {
return !c.OneToOne
}
type ChatsManager struct {
type filtersManager struct {
whisper *whisper.Whisper
persistence *sqlitePersistence
privateKey *ecdsa.PrivateKey
keys map[string][]byte // a cache of symmetric keys derived from passwords
keys map[string][]byte // a cache of symmetric manager derived from passwords
logger *zap.Logger
genericDiscoveryTopicEnabled bool
mutex sync.Mutex
chats map[string]*Chat
mutex sync.Mutex
filters map[string]*Filter
}
// New returns a new ChatsManager service
func New(db *sql.DB, w *whisper.Whisper, privateKey *ecdsa.PrivateKey, logger *zap.Logger) (*ChatsManager, error) {
// newFiltersManager returns a new filtersManager.
func newFiltersManager(db *sql.DB, w *whisper.Whisper, privateKey *ecdsa.PrivateKey, logger *zap.Logger) (*filtersManager, error) {
if logger == nil {
logger = zap.NewNop()
}
@ -88,21 +88,21 @@ func New(db *sql.DB, w *whisper.Whisper, privateKey *ecdsa.PrivateKey, logger *z
return nil, err
}
return &ChatsManager{
return &filtersManager{
privateKey: privateKey,
whisper: w,
persistence: persistence,
keys: keys,
chats: make(map[string]*Chat),
logger: logger.With(zap.Namespace("ChatsManager")),
filters: make(map[string]*Filter),
logger: logger.With(zap.Namespace("filtersManager")),
}, nil
}
func (s *ChatsManager) Init(
func (s *filtersManager) Init(
chatIDs []string,
publicKeys []*ecdsa.PublicKey,
genericDiscoveryTopicEnabled bool,
) ([]*Chat, error) {
) ([]*Filter, error) {
logger := s.logger.With(zap.String("site", "Init"))
logger.Info("initializing")
@ -127,7 +127,7 @@ func (s *ChatsManager) Init(
return nil, err
}
// Add public, one-to-one and negotiated chats.
// Add public, one-to-one and negotiated filters.
for _, chatID := range chatIDs {
_, err := s.LoadPublic(chatID)
if err != nil {
@ -145,15 +145,15 @@ func (s *ChatsManager) Init(
s.mutex.Lock()
defer s.mutex.Unlock()
var allChats []*Chat
for _, chat := range s.chats {
var allChats []*Filter
for _, chat := range s.filters {
allChats = append(allChats, chat)
}
return allChats, nil
}
// DEPRECATED
func (s *ChatsManager) InitWithChats(chats []*Chat, genericDiscoveryTopicEnabled bool) ([]*Chat, error) {
func (s *filtersManager) InitWithChats(chats []*Filter, genericDiscoveryTopicEnabled bool) ([]*Filter, error) {
var (
chatIDs []string
publicKeys []*ecdsa.PublicKey
@ -174,11 +174,11 @@ func (s *ChatsManager) InitWithChats(chats []*Chat, genericDiscoveryTopicEnabled
return s.Init(chatIDs, publicKeys, genericDiscoveryTopicEnabled)
}
func (s *ChatsManager) Reset() error {
var chats []*Chat
func (s *filtersManager) Reset() error {
var chats []*Filter
s.mutex.Lock()
for _, chat := range s.chats {
for _, chat := range s.filters {
chats = append(chats, chat)
}
s.mutex.Unlock()
@ -186,11 +186,11 @@ func (s *ChatsManager) Reset() error {
return s.Remove(chats...)
}
func (s *ChatsManager) Chats() (result []*Chat) {
func (s *filtersManager) Chats() (result []*Filter) {
s.mutex.Lock()
defer s.mutex.Unlock()
for _, chat := range s.chats {
for _, chat := range s.filters {
result = append(result, chat)
}
@ -198,16 +198,16 @@ func (s *ChatsManager) Chats() (result []*Chat) {
}
// ChatByID returns a chat by id.
func (s *ChatsManager) ChatByID(chatID string) *Chat {
func (s *filtersManager) ChatByID(chatID string) *Filter {
s.mutex.Lock()
defer s.mutex.Unlock()
return s.chats[chatID]
return s.filters[chatID]
}
func (s *ChatsManager) ChatByFilterID(filterID string) *Chat {
func (s *filtersManager) ChatByFilterID(filterID string) *Filter {
s.mutex.Lock()
defer s.mutex.Unlock()
for _, chat := range s.chats {
for _, chat := range s.filters {
if chat.FilterID == filterID {
return chat
}
@ -215,13 +215,13 @@ func (s *ChatsManager) ChatByFilterID(filterID string) *Chat {
return nil
}
func (s *ChatsManager) ChatsByPublicKey(publicKey *ecdsa.PublicKey) (result []*Chat) {
func (s *filtersManager) ChatsByPublicKey(publicKey *ecdsa.PublicKey) (result []*Filter) {
s.mutex.Lock()
defer s.mutex.Unlock()
identityStr := publicKeyToStr(publicKey)
for _, chat := range s.chats {
for _, chat := range s.filters {
if chat.Identity == identityStr {
result = append(result, chat)
}
@ -231,7 +231,7 @@ func (s *ChatsManager) ChatsByPublicKey(publicKey *ecdsa.PublicKey) (result []*C
}
// Remove remove all the filters associated with a chat/identity
func (s *ChatsManager) Remove(chats ...*Chat) error {
func (s *filtersManager) Remove(chats ...*Filter) error {
s.mutex.Lock()
defer s.mutex.Unlock()
@ -242,28 +242,28 @@ func (s *ChatsManager) Remove(chats ...*Chat) error {
if chat.SymKeyID != "" {
s.whisper.DeleteSymKey(chat.SymKeyID)
}
delete(s.chats, chat.ChatID)
delete(s.filters, chat.ChatID)
}
return nil
}
// LoadPartitioned creates a filter for a partitioned topic.
func (s *ChatsManager) LoadPartitioned(publicKey *ecdsa.PublicKey) (*Chat, error) {
func (s *filtersManager) LoadPartitioned(publicKey *ecdsa.PublicKey) (*Filter, error) {
return s.loadPartitioned(publicKey, false)
}
func (s *ChatsManager) loadMyPartitioned() (*Chat, error) {
func (s *filtersManager) loadMyPartitioned() (*Filter, error) {
return s.loadPartitioned(&s.privateKey.PublicKey, true)
}
func (s *ChatsManager) loadPartitioned(publicKey *ecdsa.PublicKey, listen bool) (*Chat, error) {
func (s *filtersManager) loadPartitioned(publicKey *ecdsa.PublicKey, listen bool) (*Filter, error) {
s.mutex.Lock()
defer s.mutex.Unlock()
chatID := partitionedTopic(publicKey)
if _, ok := s.chats[chatID]; ok {
return s.chats[chatID], nil
if _, ok := s.filters[chatID]; ok {
return s.filters[chatID], nil
}
// We set up a filter so we can publish,
@ -273,7 +273,7 @@ func (s *ChatsManager) loadPartitioned(publicKey *ecdsa.PublicKey, listen bool)
return nil, err
}
chat := &Chat{
chat := &Filter{
ChatID: chatID,
FilterID: filter.FilterID,
Topic: filter.Topic,
@ -282,20 +282,20 @@ func (s *ChatsManager) loadPartitioned(publicKey *ecdsa.PublicKey, listen bool)
OneToOne: true,
}
s.chats[chatID] = chat
s.filters[chatID] = chat
return chat, nil
}
// LoadNegotiated loads a negotiated secret as a filter.
func (s *ChatsManager) LoadNegotiated(secret NegotiatedSecret) (*Chat, error) {
func (s *filtersManager) LoadNegotiated(secret NegotiatedSecret) (*Filter, error) {
s.mutex.Lock()
defer s.mutex.Unlock()
chatID := negotiatedTopic(secret.PublicKey)
if _, ok := s.chats[chatID]; ok {
return s.chats[chatID], nil
if _, ok := s.filters[chatID]; ok {
return s.filters[chatID], nil
}
keyString := hex.EncodeToString(secret.Key)
@ -304,7 +304,7 @@ func (s *ChatsManager) LoadNegotiated(secret NegotiatedSecret) (*Chat, error) {
return nil, err
}
chat := &Chat{
chat := &Filter{
ChatID: chatID,
Topic: filter.Topic,
SymKeyID: filter.SymKeyID,
@ -315,31 +315,31 @@ func (s *ChatsManager) LoadNegotiated(secret NegotiatedSecret) (*Chat, error) {
OneToOne: true,
}
s.chats[chat.ChatID] = chat
s.filters[chat.ChatID] = chat
return chat, nil
}
// LoadDiscovery adds 1-2 discovery filters: one for generic discovery topic (if enabled)
// and one for the personal discovery topic.
func (s *ChatsManager) LoadDiscovery() ([]*Chat, error) {
func (s *filtersManager) LoadDiscovery() ([]*Filter, error) {
s.mutex.Lock()
defer s.mutex.Unlock()
personalDiscoveryTopic := personalDiscoveryTopic(&s.privateKey.PublicKey)
// Check if chats are already loaded.
var result []*Chat
// Check if filters are already loaded.
var result []*Filter
expectedTopicCount := 1
if s.genericDiscoveryTopicEnabled {
expectedTopicCount = 2
if chat, ok := s.chats[DiscoveryTopic]; ok {
if chat, ok := s.filters[discoveryTopic]; ok {
result = append(result, chat)
}
}
if chat, ok := s.chats[personalDiscoveryTopic]; ok {
if chat, ok := s.filters[personalDiscoveryTopic]; ok {
result = append(result, chat)
}
@ -347,12 +347,12 @@ func (s *ChatsManager) LoadDiscovery() ([]*Chat, error) {
return result, nil
}
var discoveryResponse *Filter
var discoveryResponse *whisperFilter
var err error
identityStr := publicKeyToStr(&s.privateKey.PublicKey)
// Load personal discovery
personalDiscoveryChat := &Chat{
personalDiscoveryChat := &Filter{
ChatID: personalDiscoveryTopic,
Identity: identityStr,
Discovery: true,
@ -368,12 +368,12 @@ func (s *ChatsManager) LoadDiscovery() ([]*Chat, error) {
personalDiscoveryChat.Topic = discoveryResponse.Topic
personalDiscoveryChat.FilterID = discoveryResponse.FilterID
s.chats[personalDiscoveryChat.ChatID] = personalDiscoveryChat
s.filters[personalDiscoveryChat.ChatID] = personalDiscoveryChat
if s.genericDiscoveryTopicEnabled {
// Load generic discovery topic.
discoveryChat := &Chat{
ChatID: DiscoveryTopic,
discoveryChat := &Filter{
ChatID: discoveryTopic,
Identity: identityStr,
Discovery: true,
Listen: true,
@ -388,20 +388,20 @@ func (s *ChatsManager) LoadDiscovery() ([]*Chat, error) {
discoveryChat.Topic = discoveryResponse.Topic
discoveryChat.FilterID = discoveryResponse.FilterID
s.chats[discoveryChat.ChatID] = discoveryChat
s.filters[discoveryChat.ChatID] = discoveryChat
return []*Chat{discoveryChat, personalDiscoveryChat}, nil
return []*Filter{discoveryChat, personalDiscoveryChat}, nil
}
return []*Chat{personalDiscoveryChat}, nil
return []*Filter{personalDiscoveryChat}, nil
}
// LoadPublic adds a filter for a public chat.
func (s *ChatsManager) LoadPublic(chatID string) (*Chat, error) {
func (s *filtersManager) LoadPublic(chatID string) (*Filter, error) {
s.mutex.Lock()
defer s.mutex.Unlock()
if chat, ok := s.chats[chatID]; ok {
if chat, ok := s.filters[chatID]; ok {
return chat, nil
}
@ -410,7 +410,7 @@ func (s *ChatsManager) LoadPublic(chatID string) (*Chat, error) {
return nil, err
}
chat := &Chat{
chat := &Filter{
ChatID: chatID,
FilterID: filterAndTopic.FilterID,
SymKeyID: filterAndTopic.SymKeyID,
@ -419,20 +419,20 @@ func (s *ChatsManager) LoadPublic(chatID string) (*Chat, error) {
OneToOne: false,
}
s.chats[chatID] = chat
s.filters[chatID] = chat
return chat, nil
}
// LoadContactCode creates a filter for the advertise topic for a given public key.
func (s *ChatsManager) LoadContactCode(pubKey *ecdsa.PublicKey) (*Chat, error) {
func (s *filtersManager) LoadContactCode(pubKey *ecdsa.PublicKey) (*Filter, error) {
s.mutex.Lock()
defer s.mutex.Unlock()
chatID := contactCodeTopic(pubKey)
if _, ok := s.chats[chatID]; ok {
return s.chats[chatID], nil
if _, ok := s.filters[chatID]; ok {
return s.filters[chatID], nil
}
contactCodeFilter, err := s.addSymmetric(chatID)
@ -440,7 +440,7 @@ func (s *ChatsManager) LoadContactCode(pubKey *ecdsa.PublicKey) (*Chat, error) {
return nil, err
}
chat := &Chat{
chat := &Filter{
ChatID: chatID,
FilterID: contactCodeFilter.FilterID,
Topic: contactCodeFilter.Topic,
@ -449,12 +449,12 @@ func (s *ChatsManager) LoadContactCode(pubKey *ecdsa.PublicKey) (*Chat, error) {
Listen: true,
}
s.chats[chatID] = chat
s.filters[chatID] = chat
return chat, nil
}
// addSymmetric adds a symmetric key filter
func (s *ChatsManager) addSymmetric(chatID string) (*Filter, error) {
func (s *filtersManager) addSymmetric(chatID string) (*whisperFilter, error) {
var symKeyID string
var err error
@ -496,7 +496,7 @@ func (s *ChatsManager) addSymmetric(chatID string) (*Filter, error) {
return nil, err
}
return &Filter{
return &whisperFilter{
FilterID: id,
SymKeyID: symKeyID,
Topic: whisper.BytesToTopic(topic),
@ -505,7 +505,7 @@ func (s *ChatsManager) addSymmetric(chatID string) (*Filter, error) {
// addAsymmetricFilter adds a filter with our private key
// and set minPow according to the listen parameter.
func (s *ChatsManager) addAsymmetric(chatID string, listen bool) (*Filter, error) {
func (s *filtersManager) addAsymmetric(chatID string, listen bool) (*whisperFilter, error) {
var (
err error
pow = 1.0 // use PoW high enough to discard all messages for the filter
@ -530,22 +530,22 @@ func (s *ChatsManager) addAsymmetric(chatID string, listen bool) (*Filter, error
if err != nil {
return nil, err
}
return &Filter{FilterID: id, Topic: whisper.BytesToTopic(topic)}, nil
return &whisperFilter{FilterID: id, Topic: whisper.BytesToTopic(topic)}, nil
}
// GetNegotiated returns a negotiated chat given an identity
func (s *ChatsManager) GetNegotiated(identity *ecdsa.PublicKey) *Chat {
func (s *filtersManager) GetNegotiated(identity *ecdsa.PublicKey) *Filter {
s.mutex.Lock()
defer s.mutex.Unlock()
return s.chats[negotiatedTopic(identity)]
return s.filters[negotiatedTopic(identity)]
}
// toTopic converts a string to a whisper topic.
func toTopic(s string) []byte {
return crypto.Keccak256([]byte(s))[:whisper.TopicLength]
}
// ToTopic converts a string to a whisper topic.
func ToTopic(s string) []byte {
return toTopic(s)
}
@ -574,12 +574,6 @@ func partitionedTopic(publicKey *ecdsa.PublicKey) string {
return "contact-discovery-" + strconv.FormatInt(partition.Int64(), 10)
}
// PublicKeyToPartitionedTopicBytes returns the bytes of the partitioned topic
// associated with the given public key
func PublicKeyToPartitionedTopicBytes(publicKey *ecdsa.PublicKey) []byte {
return toTopic(partitionedTopic(publicKey))
}
func ContactCodeTopic(publicKey *ecdsa.PublicKey) string {
return contactCodeTopic(publicKey)
}

View File

@ -1,3 +0,0 @@
package filter
// TODO: describe all types of filters.

View File

@ -1,59 +0,0 @@
package whisper
import (
"context"
"crypto/ecdsa"
"time"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/pkg/errors"
)
type Server interface {
Connected(enode.ID) (bool, error)
AddPeer(string) error
NodeID() *ecdsa.PrivateKey
}
// dialOpts used in Dial function.
type dialOpts struct {
// PollInterval is used for time.Ticker. Must be greated then zero.
PollInterval time.Duration
}
// dial selected peer and wait until it is connected.
func dial(ctx context.Context, srv Server, peer string, opts dialOpts) error {
if opts.PollInterval == 0 {
return errors.New("poll interval cannot be zero")
}
if err := srv.AddPeer(peer); err != nil {
return err
}
parsed, err := enode.ParseV4(peer)
if err != nil {
return err
}
connected, err := srv.Connected(parsed.ID())
if err != nil {
return err
}
if connected {
return nil
}
period := time.NewTicker(opts.PollInterval)
defer period.Stop()
for {
select {
case <-ctx.Done():
return ctx.Err()
case <-period.C:
connected, err := srv.Connected(parsed.ID())
if err != nil {
return err
}
if connected {
return nil
}
}
}
}

View File

@ -1,10 +0,0 @@
package whisper
import (
"math/rand"
)
func randomItem(items []string) string {
l := len(items)
return items[rand.Intn(l)]
}

View File

@ -4,28 +4,14 @@ import (
"context"
"crypto/ecdsa"
"database/sql"
"encoding/hex"
"fmt"
"math/big"
"sync"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/rlp"
"github.com/pkg/errors"
"github.com/status-im/status-go/mailserver"
whisper "github.com/status-im/whisper/whisperv6"
"go.uber.org/zap"
"github.com/status-im/status-protocol-go/transport/whisper/filter"
)
const (
// defaultRequestTimeout is the default request timeout in seconds
defaultRequestTimeout = 10
)
var (
@ -72,35 +58,40 @@ func (m *whisperServiceKeysManager) RawSymKey(id string) ([]byte, error) {
// WhisperServiceTransport is a transport based on Whisper service.
type WhisperServiceTransport struct {
node Server
shh *whisper.Whisper
shhAPI *whisper.PublicWhisperAPI // only PublicWhisperAPI implements logic to send messages
keysManager *whisperServiceKeysManager
chats *filter.ChatsManager
chats *filtersManager
logger *zap.Logger
mailservers []string
selectedMailServerEnode string
mailservers []string
envelopesMonitor *EnvelopesMonitor
}
// NewWhisperService returns a new WhisperServiceTransport.
func NewWhisperServiceTransport(
node Server,
shh *whisper.Whisper,
privateKey *ecdsa.PrivateKey,
db *sql.DB,
mailservers []string,
envelopesMonitorConfig *EnvelopesMonitorConfig,
logger *zap.Logger,
) (*WhisperServiceTransport, error) {
chats, err := filter.New(db, shh, privateKey, logger)
chats, err := newFiltersManager(db, shh, privateKey, logger)
if err != nil {
return nil, err
}
var envelopesMonitor *EnvelopesMonitor
if envelopesMonitorConfig != nil {
envelopesMonitor = NewEnvelopesMonitor(shh, envelopesMonitorConfig)
envelopesMonitor.Start()
}
return &WhisperServiceTransport{
node: node,
shh: shh,
shhAPI: whisper.NewPublicWhisperAPI(shh),
shh: shh,
shhAPI: whisper.NewPublicWhisperAPI(shh),
envelopesMonitor: envelopesMonitor,
keysManager: &whisperServiceKeysManager{
shh: shh,
privateKey: privateKey,
@ -113,12 +104,12 @@ func NewWhisperServiceTransport(
}
// DEPRECATED
func (a *WhisperServiceTransport) LoadFilters(chats []*filter.Chat, genericDiscoveryTopicEnabled bool) ([]*filter.Chat, error) {
func (a *WhisperServiceTransport) LoadFilters(chats []*Filter, genericDiscoveryTopicEnabled bool) ([]*Filter, error) {
return a.chats.InitWithChats(chats, genericDiscoveryTopicEnabled)
}
// DEPRECATED
func (a *WhisperServiceTransport) RemoveFilters(chats []*filter.Chat) error {
func (a *WhisperServiceTransport) RemoveFilters(chats []*Filter) error {
return a.chats.Remove(chats...)
}
@ -126,7 +117,7 @@ func (a *WhisperServiceTransport) Reset() error {
return a.chats.Reset()
}
func (a *WhisperServiceTransport) ProcessNegotiatedSecret(secret filter.NegotiatedSecret) error {
func (a *WhisperServiceTransport) ProcessNegotiatedSecret(secret NegotiatedSecret) error {
_, err := a.chats.LoadNegotiated(secret)
return err
}
@ -218,8 +209,8 @@ func (a *WhisperServiceTransport) RetrievePrivateMessages(publicKey *ecdsa.Publi
}
// DEPRECATED
func (a *WhisperServiceTransport) RetrieveRawAll() (map[filter.Chat][]*whisper.ReceivedMessage, error) {
result := make(map[filter.Chat][]*whisper.ReceivedMessage)
func (a *WhisperServiceTransport) RetrieveRawAll() (map[Filter][]*whisper.ReceivedMessage, error) {
result := make(map[Filter][]*whisper.ReceivedMessage)
allChats := a.chats.Chats()
for _, chat := range allChats {
@ -244,10 +235,10 @@ func (a *WhisperServiceTransport) RetrieveRaw(filterID string) ([]*whisper.Recei
}
// SendPublic sends a new message using the Whisper service.
// For public chats, chat name is used as an ID as well as
// For public filters, chat name is used as an ID as well as
// a topic.
func (a *WhisperServiceTransport) SendPublic(ctx context.Context, newMessage whisper.NewMessage, chatName string) ([]byte, error) {
if err := a.addSig(&newMessage); err != nil {
func (a *WhisperServiceTransport) SendPublic(ctx context.Context, newMessage *whisper.NewMessage, chatName string) ([]byte, error) {
if err := a.addSig(newMessage); err != nil {
return nil, err
}
@ -259,15 +250,15 @@ func (a *WhisperServiceTransport) SendPublic(ctx context.Context, newMessage whi
newMessage.SymKeyID = chat.SymKeyID
newMessage.Topic = chat.Topic
return a.shhAPI.Post(ctx, newMessage)
return a.shhAPI.Post(ctx, *newMessage)
}
func (a *WhisperServiceTransport) SendPrivateWithSharedSecret(ctx context.Context, newMessage whisper.NewMessage, publicKey *ecdsa.PublicKey, secret []byte) ([]byte, error) {
if err := a.addSig(&newMessage); err != nil {
func (a *WhisperServiceTransport) SendPrivateWithSharedSecret(ctx context.Context, newMessage *whisper.NewMessage, publicKey *ecdsa.PublicKey, secret []byte) ([]byte, error) {
if err := a.addSig(newMessage); err != nil {
return nil, err
}
chat, err := a.chats.LoadNegotiated(filter.NegotiatedSecret{
chat, err := a.chats.LoadNegotiated(NegotiatedSecret{
PublicKey: publicKey,
Key: secret,
})
@ -279,11 +270,11 @@ func (a *WhisperServiceTransport) SendPrivateWithSharedSecret(ctx context.Contex
newMessage.Topic = chat.Topic
newMessage.PublicKey = nil
return a.shhAPI.Post(ctx, newMessage)
return a.shhAPI.Post(ctx, *newMessage)
}
func (a *WhisperServiceTransport) SendPrivateWithPartitioned(ctx context.Context, newMessage whisper.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error) {
if err := a.addSig(&newMessage); err != nil {
func (a *WhisperServiceTransport) SendPrivateWithPartitioned(ctx context.Context, newMessage *whisper.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error) {
if err := a.addSig(newMessage); err != nil {
return nil, err
}
@ -295,11 +286,11 @@ func (a *WhisperServiceTransport) SendPrivateWithPartitioned(ctx context.Context
newMessage.Topic = chat.Topic
newMessage.PublicKey = crypto.FromECDSAPub(publicKey)
return a.shhAPI.Post(ctx, newMessage)
return a.shhAPI.Post(ctx, *newMessage)
}
func (a *WhisperServiceTransport) SendPrivateOnDiscovery(ctx context.Context, newMessage whisper.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error) {
if err := a.addSig(&newMessage); err != nil {
func (a *WhisperServiceTransport) SendPrivateOnDiscovery(ctx context.Context, newMessage *whisper.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error) {
if err := a.addSig(newMessage); err != nil {
return nil, err
}
@ -310,11 +301,11 @@ func (a *WhisperServiceTransport) SendPrivateOnDiscovery(ctx context.Context, ne
// and idempotent.
newMessage.Topic = whisper.BytesToTopic(
filter.ToTopic(filter.DiscoveryTopic),
ToTopic(discoveryTopic),
)
newMessage.PublicKey = crypto.FromECDSAPub(publicKey)
return a.shhAPI.Post(ctx, newMessage)
return a.shhAPI.Post(ctx, *newMessage)
}
func (a *WhisperServiceTransport) addSig(newMessage *whisper.NewMessage) error {
@ -326,61 +317,16 @@ func (a *WhisperServiceTransport) addSig(newMessage *whisper.NewMessage) error {
return nil
}
// Request requests messages from mail servers.
func (a *WhisperServiceTransport) Request(ctx context.Context, options RequestOptions) error {
// TODO: remove from here. MailServerEnode must be provided in the params.
enode, err := a.selectAndAddMailServer()
if err != nil {
return err
func (a *WhisperServiceTransport) Track(identifiers [][]byte, hash []byte, newMessage whisper.NewMessage) {
if a.envelopesMonitor != nil {
a.envelopesMonitor.Add(identifiers, common.BytesToHash(hash), newMessage)
}
keyID, err := a.keysManager.AddOrGetSymKeyFromPassword(options.Password)
if err != nil {
return err
}
req, err := createRequestMessagesParam(enode, keyID, options)
if err != nil {
return err
}
_, err = a.requestMessages(ctx, req, true)
return err
}
func (a *WhisperServiceTransport) requestMessages(ctx context.Context, req MessagesRequest, followCursor bool) (resp MessagesResponse, err error) {
logger := a.logger.With(zap.String("site", "requestMessages"))
logger.Debug("request for a chunk", zap.Uint32("message-limit", req.Limit))
start := time.Now()
resp, err = a.requestMessagesWithRetry(RetryConfig{
BaseTimeout: time.Second * 10,
StepTimeout: time.Second,
MaxRetries: 3,
}, req)
if err != nil {
logger.Error("failed requesting messages", zap.Error(err))
return
func (a *WhisperServiceTransport) Stop() {
if a.envelopesMonitor != nil {
a.envelopesMonitor.Stop()
}
logger.Debug("message delivery summary",
zap.Uint32("message-limit", req.Limit),
zap.Duration("duration", time.Since(start)),
zap.Any("response", resp),
)
if resp.Error != nil {
err = resp.Error
return
}
if !followCursor || resp.Cursor == "" {
return
}
req.Cursor = resp.Cursor
logger.Debug("requesting messages with cursor", zap.String("cursor", req.Cursor))
return a.requestMessages(ctx, req, true)
}
// MessagesRequest is a RequestMessages() request payload.
@ -423,26 +369,6 @@ type MessagesRequest struct {
Force bool `json:"force"`
}
func (r *MessagesRequest) setDefaults(now time.Time) {
// set From and To defaults
if r.To == 0 {
r.To = uint32(now.UTC().Unix())
}
if r.From == 0 {
oneDay := uint32(86400) // -24 hours
if r.To < oneDay {
r.From = 0
} else {
r.From = r.To - oneDay
}
}
if r.Timeout == 0 {
r.Timeout = defaultRequestTimeout
}
}
type MessagesResponse struct {
// Cursor from the response can be used to retrieve more messages
// for the previous request.
@ -460,236 +386,3 @@ type RetryConfig struct {
StepTimeout time.Duration
MaxRetries int
}
func (a *WhisperServiceTransport) requestMessagesWithRetry(conf RetryConfig, r MessagesRequest) (MessagesResponse, error) {
var (
resp MessagesResponse
requestID hexutil.Bytes
err error
retries int
)
logger := a.logger.With(zap.String("site", "requestMessagesWithRetry"))
events := make(chan whisper.EnvelopeEvent, 10)
for retries <= conf.MaxRetries {
sub := a.shh.SubscribeEnvelopeEvents(events)
r.Timeout = conf.BaseTimeout + conf.StepTimeout*time.Duration(retries)
timeout := r.Timeout
// FIXME this weird conversion is required because MessagesRequest expects seconds but defines time.Duration
r.Timeout = time.Duration(int(r.Timeout.Seconds()))
requestID, err = a.requestMessagesSync(context.Background(), r)
if err != nil {
sub.Unsubscribe()
return resp, err
}
mailServerResp, err := waitForExpiredOrCompleted(common.BytesToHash(requestID), events, timeout)
sub.Unsubscribe()
if err == nil {
resp.Cursor = hex.EncodeToString(mailServerResp.Cursor)
resp.Error = mailServerResp.Error
return resp, nil
}
retries++
logger.Warn("requestMessagesSync failed, retrying", zap.Int("retries", retries), zap.Error(err))
}
return resp, fmt.Errorf("failed to request messages after %d retries", retries)
}
// RequestMessages sends a request for historic messages to a MailServer.
func (a *WhisperServiceTransport) requestMessagesSync(_ context.Context, r MessagesRequest) (hexutil.Bytes, error) {
now := a.shh.GetCurrentTime()
r.setDefaults(now)
if r.From > r.To {
return nil, fmt.Errorf("Query range is invalid: from > to (%d > %d)", r.From, r.To)
}
// TODO: bring mailserverspackage here
mailServerNode, err := enode.ParseV4(r.MailServerPeer)
if err != nil {
return nil, fmt.Errorf("invalid MailServerPeer: %v", err)
}
var (
symKey []byte
publicKey *ecdsa.PublicKey
)
if r.SymKeyID != "" {
symKey, err = a.shh.GetSymKey(r.SymKeyID)
if err != nil {
return nil, fmt.Errorf("invalid SymKeyID: %v", err)
}
} else {
publicKey = mailServerNode.Pubkey()
}
payload, err := makeMessagesRequestPayload(r)
if err != nil {
return nil, err
}
envelope, err := makeEnvelop(
payload,
symKey,
publicKey,
a.node.NodeID(),
a.shh.MinPow(),
now,
)
if err != nil {
return nil, err
}
hash := envelope.Hash()
if err := a.shh.RequestHistoricMessagesWithTimeout(mailServerNode.ID().Bytes(), envelope, r.Timeout*time.Second); err != nil {
return nil, err
}
return hash[:], nil
}
func (a *WhisperServiceTransport) selectAndAddMailServer() (string, error) {
logger := a.logger.With(zap.String("site", "selectAndAddMailServer"))
var enodeAddr string
if a.selectedMailServerEnode != "" {
enodeAddr = a.selectedMailServerEnode
} else {
if len(a.mailservers) == 0 {
return "", ErrNoMailservers
}
enodeAddr = randomItem(a.mailservers)
}
logger.Debug("dialing mail server", zap.String("enode", enodeAddr))
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
err := dial(ctx, a.node, enodeAddr, dialOpts{PollInterval: 200 * time.Millisecond})
cancel()
if err == nil {
a.selectedMailServerEnode = enodeAddr
return enodeAddr, nil
}
return "", fmt.Errorf("peer %s failed to connect: %v", enodeAddr, err)
}
func createRequestMessagesParam(enode, symKeyID string, options RequestOptions) (MessagesRequest, error) {
req := MessagesRequest{
MailServerPeer: enode,
From: uint32(options.From), // TODO: change to int in status-go
To: uint32(options.To), // TODO: change to int in status-go
Limit: uint32(options.Limit), // TODO: change to int in status-go
SymKeyID: symKeyID,
Topics: options.Topics,
}
return req, nil
}
func waitForExpiredOrCompleted(requestID common.Hash, events chan whisper.EnvelopeEvent, timeout time.Duration) (*whisper.MailServerResponse, error) {
expired := fmt.Errorf("request %x expired", requestID)
after := time.NewTimer(timeout)
defer after.Stop()
for {
var ev whisper.EnvelopeEvent
select {
case ev = <-events:
case <-after.C:
return nil, expired
}
if ev.Hash != requestID {
continue
}
switch ev.Event {
case whisper.EventMailServerRequestCompleted:
data, ok := ev.Data.(*whisper.MailServerResponse)
if ok {
return data, nil
}
return nil, errors.New("invalid event data type")
case whisper.EventMailServerRequestExpired:
return nil, expired
}
}
}
// makeMessagesRequestPayload makes a specific payload for MailServer
// to request historic messages.
func makeMessagesRequestPayload(r MessagesRequest) ([]byte, error) {
cursor, err := hex.DecodeString(r.Cursor)
if err != nil {
return nil, fmt.Errorf("invalid cursor: %v", err)
}
if len(cursor) > 0 && len(cursor) != mailserver.CursorLength {
return nil, fmt.Errorf("invalid cursor size: expected %d but got %d", mailserver.CursorLength, len(cursor))
}
payload := mailserver.MessagesRequestPayload{
Lower: r.From,
Upper: r.To,
Bloom: createBloomFilter(r),
Limit: r.Limit,
Cursor: cursor,
// Client must tell the MailServer if it supports batch responses.
// This can be removed in the future.
Batch: true,
}
return rlp.EncodeToBytes(payload)
}
// makeEnvelop makes an envelop for a historic messages request.
// Symmetric key is used to authenticate to MailServer.
// PK is the current node ID.
func makeEnvelop(
payload []byte,
symKey []byte,
publicKey *ecdsa.PublicKey,
nodeID *ecdsa.PrivateKey,
pow float64,
now time.Time,
) (*whisper.Envelope, error) {
params := whisper.MessageParams{
PoW: pow,
Payload: payload,
WorkTime: DefaultWhisperMessage().PowTime,
Src: nodeID,
}
// Either symKey or public key is required.
// This condition is verified in `message.Wrap()` method.
if len(symKey) > 0 {
params.KeySym = symKey
} else if publicKey != nil {
params.Dst = publicKey
}
message, err := whisper.NewSentMessage(&params)
if err != nil {
return nil, err
}
return message.Wrap(&params, now)
}
func createBloomFilter(r MessagesRequest) []byte {
if len(r.Topics) > 0 {
return topicsToBloom(r.Topics...)
}
return whisper.TopicToBloom(r.Topic)
}
func topicsToBloom(topics ...whisper.TopicType) []byte {
i := new(big.Int)
for _, topic := range topics {
bloom := whisper.TopicToBloom(topic)
i.Or(i, new(big.Int).SetBytes(bloom[:]))
}
combined := make([]byte, whisper.BloomFilterSize)
data := i.Bytes()
copy(combined[whisper.BloomFilterSize-len(data):], data[:])
return combined
}

View File

@ -144,9 +144,9 @@ func EncodeMessage(value Message) ([]byte, error) {
return buf.Bytes(), nil
}
// MessageID calculates the messageID, by appending the sha3-256 to the compress pubkey
// MessageID calculates the messageID, by appending the sha3-256 to the pubkey bytes
func MessageID(author *ecdsa.PublicKey, data []byte) []byte {
keyBytes := crypto.CompressPubkey(author)
keyBytes := crypto.FromECDSAPub(author)
return crypto.Keccak256(append(keyBytes, data...))
}

7
vendor/modules.txt vendored
View File

@ -317,19 +317,18 @@ github.com/status-im/migrate/v4/database/sqlcipher
github.com/status-im/rendezvous
github.com/status-im/rendezvous/protocol
github.com/status-im/rendezvous/server
# github.com/status-im/status-protocol-go v0.0.0-20190701094942-baa579640f175976472cdf47e0b97d2a5881409d
# github.com/status-im/status-protocol-go v0.0.0-20190701094942-e1f4f17bafc4ac757933fb6a801fe9fed68b6c4d
github.com/status-im/status-protocol-go/zaputil
github.com/status-im/status-protocol-go
github.com/status-im/status-protocol-go/encryption/multidevice
github.com/status-im/status-protocol-go/sqlite
github.com/status-im/status-protocol-go/transport/whisper/filter
github.com/status-im/status-protocol-go/transport/whisper
github.com/status-im/status-protocol-go/datasync
github.com/status-im/status-protocol-go/datasync/peer
github.com/status-im/status-protocol-go/encryption
github.com/status-im/status-protocol-go/encryption/migrations
github.com/status-im/status-protocol-go/encryption/sharedsecret
github.com/status-im/status-protocol-go/migrations
github.com/status-im/status-protocol-go/transport/whisper
github.com/status-im/status-protocol-go/transport/whisper/migrations
github.com/status-im/status-protocol-go/v1
github.com/status-im/status-protocol-go/crypto
@ -357,9 +356,9 @@ github.com/syndtr/goleveldb/leveldb/table
# github.com/vacp2p/mvds v0.0.19
github.com/vacp2p/mvds/node
github.com/vacp2p/mvds/peers
github.com/vacp2p/mvds/protobuf
github.com/vacp2p/mvds/state
github.com/vacp2p/mvds/store
github.com/vacp2p/mvds/protobuf
github.com/vacp2p/mvds/transport
# github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc
github.com/whyrusleeping/go-logging