Make shhext and protocol work with Waku (#1777)
This change makes shhext and protocol submodule work with Waku and Whisper.
This commit is contained in:
parent
330d177de6
commit
44aa313981
2
Makefile
2
Makefile
|
@ -163,7 +163,7 @@ setup-build: lint-install release-install gomobile-install ##@other Prepare proj
|
|||
setup: setup-build setup-dev tidy ##@other Prepare project for development and building
|
||||
|
||||
generate: ##@other Regenerate assets and other auto-generated stuff
|
||||
go generate ./static ./static/mailserver_db_migrations ./t ./multiaccounts/... ./appdatabase/...
|
||||
go generate ./static ./static/mailserver_db_migrations ./t ./multiaccounts/... ./appdatabase/...
|
||||
|
||||
prepare-release: clean-release
|
||||
mkdir -p $(RELEASE_DIR)
|
||||
|
|
|
@ -90,7 +90,7 @@ func _0001_appDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "0001_app.down.sql", size: 387, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
|
||||
info := bindataFileInfo{name: "0001_app.down.sql", size: 387, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xbc, 0x9c, 0xd2, 0xe1, 0x1d, 0x8, 0x34, 0x6a, 0xc8, 0x37, 0x13, 0xb3, 0x9f, 0x26, 0x23, 0x33, 0xd4, 0x25, 0x8, 0xed, 0x53, 0xe6, 0xd, 0x46, 0xc9, 0xf4, 0x24, 0xf8, 0x1, 0x1f, 0xf5, 0xc8}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ func _0001_appUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "0001_app.up.sql", size: 3088, mode: os.FileMode(0644), modTime: time.Unix(1576661249, 0)}
|
||||
info := bindataFileInfo{name: "0001_app.up.sql", size: 3088, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x93, 0xb8, 0x68, 0x17, 0x49, 0x51, 0xc0, 0xe8, 0xbc, 0x36, 0xa4, 0x29, 0xc9, 0x93, 0x6c, 0x3e, 0xdf, 0x3d, 0x23, 0x22, 0xab, 0x18, 0x49, 0xbd, 0x6, 0xf, 0xc5, 0xec, 0xf8, 0xcf, 0x1b, 0x6a}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ func _0002_tokensDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "0002_tokens.down.sql", size: 19, mode: os.FileMode(0644), modTime: time.Unix(1576226192, 0)}
|
||||
info := bindataFileInfo{name: "0002_tokens.down.sql", size: 19, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd1, 0x31, 0x2, 0xcc, 0x2f, 0x38, 0x90, 0xf7, 0x58, 0x37, 0x47, 0xf4, 0x18, 0xf7, 0x72, 0x74, 0x67, 0x14, 0x7e, 0xf3, 0xb1, 0xd6, 0x5f, 0xb0, 0xd5, 0xe7, 0x91, 0xf4, 0x26, 0x77, 0x8e, 0x68}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ func _0002_tokensUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "0002_tokens.up.sql", size: 248, mode: os.FileMode(0644), modTime: time.Unix(1576226192, 0)}
|
||||
info := bindataFileInfo{name: "0002_tokens.up.sql", size: 248, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xcc, 0xd6, 0xde, 0xd3, 0x7b, 0xee, 0x92, 0x11, 0x38, 0xa4, 0xeb, 0x84, 0xca, 0xcb, 0x37, 0x75, 0x5, 0x77, 0x7f, 0x14, 0x39, 0xee, 0xa1, 0x8b, 0xd4, 0x5c, 0x6e, 0x55, 0x6, 0x50, 0x16, 0xd4}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ func _0003_settingsDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "0003_settings.down.sql", size: 118, mode: os.FileMode(0644), modTime: time.Unix(1578050942, 0)}
|
||||
info := bindataFileInfo{name: "0003_settings.down.sql", size: 118, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe5, 0xa6, 0xf5, 0xc0, 0x60, 0x64, 0x77, 0xe2, 0xe7, 0x3c, 0x9b, 0xb1, 0x52, 0xa9, 0x95, 0x16, 0xf8, 0x60, 0x2f, 0xa5, 0xeb, 0x46, 0xb9, 0xb9, 0x8f, 0x4c, 0xf4, 0xfd, 0xbb, 0xe7, 0xe5, 0xe5}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ func _0003_settingsUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "0003_settings.up.sql", size: 1311, mode: os.FileMode(0644), modTime: time.Unix(1578050942, 0)}
|
||||
info := bindataFileInfo{name: "0003_settings.up.sql", size: 1311, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xea, 0x35, 0x0, 0xeb, 0xe2, 0x33, 0x68, 0xb9, 0xf4, 0xf6, 0x8e, 0x9e, 0x10, 0xe9, 0x58, 0x68, 0x28, 0xb, 0xcd, 0xec, 0x74, 0x71, 0xa7, 0x9a, 0x5a, 0x77, 0x59, 0xb1, 0x13, 0x1c, 0xa1, 0x5b}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ func docGo() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "doc.go", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
|
||||
info := bindataFileInfo{name: "doc.go", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xde, 0x7c, 0x28, 0xcd, 0x47, 0xf2, 0xfa, 0x7c, 0x51, 0x2d, 0xd8, 0x38, 0xb, 0xb0, 0x34, 0x9d, 0x4c, 0x62, 0xa, 0x9e, 0x28, 0xc3, 0x31, 0x23, 0xd9, 0xbb, 0x89, 0x9f, 0xa0, 0x89, 0x1f, 0xe8}}
|
||||
return a, nil
|
||||
}
|
||||
|
|
|
@ -2,11 +2,25 @@ package gethbridge
|
|||
|
||||
import (
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/waku"
|
||||
"github.com/status-im/status-go/whisper/v6"
|
||||
)
|
||||
|
||||
// NewGethEnvelopeErrorWrapper returns a types.EnvelopeError object that mimics Geth's EnvelopeError
|
||||
func NewGethEnvelopeErrorWrapper(envelopeError *whisper.EnvelopeError) *types.EnvelopeError {
|
||||
// NewWhisperEnvelopeErrorWrapper returns a types.EnvelopeError object that mimics Geth's EnvelopeError
|
||||
func NewWhisperEnvelopeErrorWrapper(envelopeError *whisper.EnvelopeError) *types.EnvelopeError {
|
||||
if envelopeError == nil {
|
||||
panic("envelopeError should not be nil")
|
||||
}
|
||||
|
||||
return &types.EnvelopeError{
|
||||
Hash: types.Hash(envelopeError.Hash),
|
||||
Code: mapGethErrorCode(envelopeError.Code),
|
||||
Description: envelopeError.Description,
|
||||
}
|
||||
}
|
||||
|
||||
// NewWakuEnvelopeErrorWrapper returns a types.EnvelopeError object that mimics Geth's EnvelopeError
|
||||
func NewWakuEnvelopeErrorWrapper(envelopeError *waku.EnvelopeError) *types.EnvelopeError {
|
||||
if envelopeError == nil {
|
||||
panic("envelopeError should not be nil")
|
||||
}
|
||||
|
@ -21,8 +35,10 @@ func NewGethEnvelopeErrorWrapper(envelopeError *whisper.EnvelopeError) *types.En
|
|||
func mapGethErrorCode(code uint) uint {
|
||||
switch code {
|
||||
case whisper.EnvelopeTimeNotSynced:
|
||||
case waku.EnvelopeTimeNotSynced:
|
||||
return types.EnvelopeTimeNotSynced
|
||||
case whisper.EnvelopeOtherError:
|
||||
case waku.EnvelopeOtherError:
|
||||
return types.EnvelopeOtherError
|
||||
}
|
||||
return types.EnvelopeOtherError
|
||||
|
|
|
@ -2,11 +2,12 @@ package gethbridge
|
|||
|
||||
import (
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/waku"
|
||||
"github.com/status-im/status-go/whisper/v6"
|
||||
)
|
||||
|
||||
// NewGethEnvelopeEventWrapper returns a types.EnvelopeEvent object that mimics Geth's EnvelopeEvent
|
||||
func NewGethEnvelopeEventWrapper(envelopeEvent *whisper.EnvelopeEvent) *types.EnvelopeEvent {
|
||||
// NewWhisperEnvelopeEventWrapper returns a types.EnvelopeEvent object that mimics Geth's EnvelopeEvent
|
||||
func NewWhisperEnvelopeEventWrapper(envelopeEvent *whisper.EnvelopeEvent) *types.EnvelopeEvent {
|
||||
if envelopeEvent == nil {
|
||||
panic("envelopeEvent should not be nil")
|
||||
}
|
||||
|
@ -16,10 +17,10 @@ func NewGethEnvelopeEventWrapper(envelopeEvent *whisper.EnvelopeEvent) *types.En
|
|||
case []whisper.EnvelopeError:
|
||||
wrappedData := make([]types.EnvelopeError, len(data))
|
||||
for index, envError := range data {
|
||||
wrappedData[index] = *NewGethEnvelopeErrorWrapper(&envError)
|
||||
wrappedData[index] = *NewWhisperEnvelopeErrorWrapper(&envError)
|
||||
}
|
||||
case *whisper.MailServerResponse:
|
||||
wrappedData = NewGethMailServerResponseWrapper(data)
|
||||
wrappedData = NewWhisperMailServerResponseWrapper(data)
|
||||
case whisper.SyncEventResponse:
|
||||
wrappedData = NewGethSyncEventResponseWrapper(data)
|
||||
}
|
||||
|
@ -31,3 +32,28 @@ func NewGethEnvelopeEventWrapper(envelopeEvent *whisper.EnvelopeEvent) *types.En
|
|||
Data: wrappedData,
|
||||
}
|
||||
}
|
||||
|
||||
// NewWakuEnvelopeEventWrapper returns a types.EnvelopeEvent object that mimics Geth's EnvelopeEvent
|
||||
func NewWakuEnvelopeEventWrapper(envelopeEvent *waku.EnvelopeEvent) *types.EnvelopeEvent {
|
||||
if envelopeEvent == nil {
|
||||
panic("envelopeEvent should not be nil")
|
||||
}
|
||||
|
||||
wrappedData := envelopeEvent.Data
|
||||
switch data := envelopeEvent.Data.(type) {
|
||||
case []waku.EnvelopeError:
|
||||
wrappedData := make([]types.EnvelopeError, len(data))
|
||||
for index, envError := range data {
|
||||
wrappedData[index] = *NewWakuEnvelopeErrorWrapper(&envError)
|
||||
}
|
||||
case *waku.MailServerResponse:
|
||||
wrappedData = NewWakuMailServerResponseWrapper(data)
|
||||
}
|
||||
return &types.EnvelopeEvent{
|
||||
Event: types.EventType(envelopeEvent.Event),
|
||||
Hash: types.Hash(envelopeEvent.Hash),
|
||||
Batch: types.Hash(envelopeEvent.Batch),
|
||||
Peer: types.EnodeID(envelopeEvent.Peer),
|
||||
Data: wrappedData,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
package gethbridge
|
||||
|
||||
import (
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/whisper/v6"
|
||||
)
|
||||
|
||||
type gethFilterWrapper struct {
|
||||
filter *whisper.Filter
|
||||
id string
|
||||
}
|
||||
|
||||
// NewGethFilterWrapper returns an object that wraps Geth's Filter in a types interface
|
||||
func NewGethFilterWrapper(f *whisper.Filter, id string) types.Filter {
|
||||
if f.Messages == nil {
|
||||
panic("Messages should not be nil")
|
||||
}
|
||||
|
||||
return &gethFilterWrapper{
|
||||
filter: f,
|
||||
id: id,
|
||||
}
|
||||
}
|
||||
|
||||
// GetGethFilterFrom retrieves the underlying whisper Filter struct from a wrapped Filter interface
|
||||
func GetGethFilterFrom(f types.Filter) *whisper.Filter {
|
||||
return f.(*gethFilterWrapper).filter
|
||||
}
|
||||
|
||||
// ID returns the filter ID
|
||||
func (w *gethFilterWrapper) ID() string {
|
||||
return w.id
|
||||
}
|
|
@ -2,11 +2,25 @@ package gethbridge
|
|||
|
||||
import (
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/waku"
|
||||
"github.com/status-im/status-go/whisper/v6"
|
||||
)
|
||||
|
||||
// NewGethMailServerResponseWrapper returns a types.MailServerResponse object that mimics Geth's MailServerResponse
|
||||
func NewGethMailServerResponseWrapper(mailServerResponse *whisper.MailServerResponse) *types.MailServerResponse {
|
||||
// NewWhisperMailServerResponseWrapper returns a types.MailServerResponse object that mimics Geth's MailServerResponse
|
||||
func NewWhisperMailServerResponseWrapper(mailServerResponse *whisper.MailServerResponse) *types.MailServerResponse {
|
||||
if mailServerResponse == nil {
|
||||
panic("mailServerResponse should not be nil")
|
||||
}
|
||||
|
||||
return &types.MailServerResponse{
|
||||
LastEnvelopeHash: types.Hash(mailServerResponse.LastEnvelopeHash),
|
||||
Cursor: mailServerResponse.Cursor,
|
||||
Error: mailServerResponse.Error,
|
||||
}
|
||||
}
|
||||
|
||||
// NewWakuMailServerResponseWrapper returns a types.MailServerResponse object that mimics Geth's MailServerResponse
|
||||
func NewWakuMailServerResponseWrapper(mailServerResponse *waku.MailServerResponse) *types.MailServerResponse {
|
||||
if mailServerResponse == nil {
|
||||
panic("mailServerResponse should not be nil")
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package gethbridge
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/status-im/status-go/waku"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
|
@ -41,12 +44,35 @@ func (w *gethNodeWrapper) GetWhisper(ctx interface{}) (types.Whisper, error) {
|
|||
}
|
||||
}
|
||||
if nativeWhisper == nil {
|
||||
panic("Whisper service is not available")
|
||||
return nil, errors.New("whisper service is not available")
|
||||
}
|
||||
|
||||
return NewGethWhisperWrapper(nativeWhisper), nil
|
||||
}
|
||||
|
||||
func (w *gethNodeWrapper) GetWaku(ctx interface{}) (types.Waku, error) {
|
||||
var nativeWaku *waku.Waku
|
||||
if ctx == nil || ctx == w {
|
||||
err := w.stack.Service(&nativeWaku)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
switch serviceProvider := ctx.(type) {
|
||||
case *node.ServiceContext:
|
||||
err := serviceProvider.Service(&nativeWaku)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
if nativeWaku == nil {
|
||||
return nil, errors.New("waku service is not available")
|
||||
}
|
||||
|
||||
return NewGethWakuWrapper(nativeWaku), nil
|
||||
}
|
||||
|
||||
func (w *gethNodeWrapper) AddPeer(url string) error {
|
||||
parsedNode, err := enode.ParseV4(url)
|
||||
if err != nil {
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
package gethbridge
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/waku"
|
||||
)
|
||||
|
||||
type gethPublicWakuAPIWrapper struct {
|
||||
api *waku.PublicWakuAPI
|
||||
}
|
||||
|
||||
// NewGethPublicWakuAPIWrapper returns an object that wraps Geth's PublicWakuAPI in a types interface
|
||||
func NewGethPublicWakuAPIWrapper(api *waku.PublicWakuAPI) types.PublicWakuAPI {
|
||||
if api == nil {
|
||||
panic("PublicWakuAPI cannot be nil")
|
||||
}
|
||||
|
||||
return &gethPublicWakuAPIWrapper{
|
||||
api: api,
|
||||
}
|
||||
}
|
||||
|
||||
// AddPrivateKey imports the given private key.
|
||||
func (w *gethPublicWakuAPIWrapper) AddPrivateKey(ctx context.Context, privateKey types.HexBytes) (string, error) {
|
||||
return w.api.AddPrivateKey(ctx, hexutil.Bytes(privateKey))
|
||||
}
|
||||
|
||||
// GenerateSymKeyFromPassword derives a key from the given password, stores it, and returns its ID.
|
||||
func (w *gethPublicWakuAPIWrapper) GenerateSymKeyFromPassword(ctx context.Context, passwd string) (string, error) {
|
||||
return w.api.GenerateSymKeyFromPassword(ctx, passwd)
|
||||
}
|
||||
|
||||
// DeleteKeyPair removes the key with the given key if it exists.
|
||||
func (w *gethPublicWakuAPIWrapper) DeleteKeyPair(ctx context.Context, key string) (bool, error) {
|
||||
return w.api.DeleteKeyPair(ctx, key)
|
||||
}
|
||||
|
||||
// NewMessageFilter creates a new filter that can be used to poll for
|
||||
// (new) messages that satisfy the given criteria.
|
||||
func (w *gethPublicWakuAPIWrapper) NewMessageFilter(req types.Criteria) (string, error) {
|
||||
topics := make([]waku.TopicType, len(req.Topics))
|
||||
for index, tt := range req.Topics {
|
||||
topics[index] = waku.TopicType(tt)
|
||||
}
|
||||
|
||||
criteria := waku.Criteria{
|
||||
SymKeyID: req.SymKeyID,
|
||||
PrivateKeyID: req.PrivateKeyID,
|
||||
Sig: req.Sig,
|
||||
MinPow: req.MinPow,
|
||||
Topics: topics,
|
||||
AllowP2P: req.AllowP2P,
|
||||
}
|
||||
return w.api.NewMessageFilter(criteria)
|
||||
}
|
||||
|
||||
// GetFilterMessages returns the messages that match the filter criteria and
|
||||
// are received between the last poll and now.
|
||||
func (w *gethPublicWakuAPIWrapper) GetFilterMessages(id string) ([]*types.Message, error) {
|
||||
msgs, err := w.api.GetFilterMessages(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wrappedMsgs := make([]*types.Message, len(msgs))
|
||||
for index, msg := range msgs {
|
||||
wrappedMsgs[index] = &types.Message{
|
||||
Sig: msg.Sig,
|
||||
TTL: msg.TTL,
|
||||
Timestamp: msg.Timestamp,
|
||||
Topic: types.TopicType(msg.Topic),
|
||||
Payload: msg.Payload,
|
||||
Padding: msg.Padding,
|
||||
PoW: msg.PoW,
|
||||
Hash: msg.Hash,
|
||||
Dst: msg.Dst,
|
||||
P2P: msg.P2P,
|
||||
}
|
||||
}
|
||||
return wrappedMsgs, nil
|
||||
}
|
||||
|
||||
// Post posts a message on the network.
|
||||
// returns the hash of the message in case of success.
|
||||
func (w *gethPublicWakuAPIWrapper) Post(ctx context.Context, req types.NewMessage) ([]byte, error) {
|
||||
msg := waku.NewMessage{
|
||||
SymKeyID: req.SymKeyID,
|
||||
PublicKey: req.PublicKey,
|
||||
Sig: req.SigID, // Sig is really a SigID
|
||||
TTL: req.TTL,
|
||||
Topic: waku.TopicType(req.Topic),
|
||||
Payload: req.Payload,
|
||||
Padding: req.Padding,
|
||||
PowTime: req.PowTime,
|
||||
PowTarget: req.PowTarget,
|
||||
TargetPeer: req.TargetPeer,
|
||||
}
|
||||
return w.api.Post(ctx, msg)
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
package gethbridge
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"time"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/waku"
|
||||
)
|
||||
|
||||
type gethWakuWrapper struct {
|
||||
waku *waku.Waku
|
||||
}
|
||||
|
||||
// NewGethWakuWrapper returns an object that wraps Geth's Waku in a types interface
|
||||
func NewGethWakuWrapper(w *waku.Waku) types.Waku {
|
||||
if w == nil {
|
||||
panic("waku cannot be nil")
|
||||
}
|
||||
|
||||
return &gethWakuWrapper{
|
||||
waku: w,
|
||||
}
|
||||
}
|
||||
|
||||
// GetGethWhisperFrom retrieves the underlying whisper Whisper struct from a wrapped Whisper interface
|
||||
func GetGethWakuFrom(m types.Waku) *waku.Waku {
|
||||
return m.(*gethWakuWrapper).waku
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) PublicWakuAPI() types.PublicWakuAPI {
|
||||
return NewGethPublicWakuAPIWrapper(waku.NewPublicWakuAPI(w.waku))
|
||||
}
|
||||
|
||||
// MinPow returns the PoW value required by this node.
|
||||
func (w *gethWakuWrapper) MinPow() float64 {
|
||||
return w.waku.MinPow()
|
||||
}
|
||||
|
||||
// BloomFilter returns the aggregated bloom filter for all the topics of interest.
|
||||
// The nodes are required to send only messages that match the advertised bloom filter.
|
||||
// If a message does not match the bloom, it will tantamount to spam, and the peer will
|
||||
// be disconnected.
|
||||
func (w *gethWakuWrapper) BloomFilter() []byte {
|
||||
return w.waku.BloomFilter()
|
||||
}
|
||||
|
||||
// GetCurrentTime returns current time.
|
||||
func (w *gethWakuWrapper) GetCurrentTime() time.Time {
|
||||
return w.waku.CurrentTime()
|
||||
}
|
||||
|
||||
// SetTimeSource assigns a particular source of time to a whisper object.
|
||||
func (w *gethWakuWrapper) SetTimeSource(timesource func() time.Time) {
|
||||
w.waku.SetTimeSource(timesource)
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) SubscribeEnvelopeEvents(eventsProxy chan<- types.EnvelopeEvent) types.Subscription {
|
||||
events := make(chan waku.EnvelopeEvent, 100) // must be buffered to prevent blocking whisper
|
||||
go func() {
|
||||
for e := range events {
|
||||
eventsProxy <- *NewWakuEnvelopeEventWrapper(&e)
|
||||
}
|
||||
}()
|
||||
|
||||
return NewGethSubscriptionWrapper(w.waku.SubscribeEnvelopeEvents(events))
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) {
|
||||
return w.waku.GetPrivateKey(id)
|
||||
}
|
||||
|
||||
// AddKeyPair imports a asymmetric private key and returns a deterministic identifier.
|
||||
func (w *gethWakuWrapper) AddKeyPair(key *ecdsa.PrivateKey) (string, error) {
|
||||
return w.waku.AddKeyPair(key)
|
||||
}
|
||||
|
||||
// DeleteKeyPair deletes the key with the specified ID if it exists.
|
||||
func (w *gethWakuWrapper) DeleteKeyPair(keyID string) bool {
|
||||
return w.waku.DeleteKeyPair(keyID)
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) AddSymKeyDirect(key []byte) (string, error) {
|
||||
return w.waku.AddSymKeyDirect(key)
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) AddSymKeyFromPassword(password string) (string, error) {
|
||||
return w.waku.AddSymKeyFromPassword(password)
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) DeleteSymKey(id string) bool {
|
||||
return w.waku.DeleteSymKey(id)
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) GetSymKey(id string) ([]byte, error) {
|
||||
return w.waku.GetSymKey(id)
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) Subscribe(opts *types.SubscriptionOptions) (string, error) {
|
||||
var (
|
||||
err error
|
||||
keyAsym *ecdsa.PrivateKey
|
||||
keySym []byte
|
||||
)
|
||||
|
||||
if opts.SymKeyID != "" {
|
||||
keySym, err = w.GetSymKey(opts.SymKeyID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
if opts.PrivateKeyID != "" {
|
||||
keyAsym, err = w.GetPrivateKey(opts.PrivateKeyID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
f, err := w.createFilterWrapper("", keyAsym, keySym, opts.PoW, opts.Topics)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
id, err := w.waku.Subscribe(GetWakuFilterFrom(f))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
f.(*wakuFilterWrapper).id = id
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) GetFilter(id string) types.Filter {
|
||||
return NewWakuFilterWrapper(w.waku.GetFilter(id), id)
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) Unsubscribe(id string) error {
|
||||
return w.waku.Unsubscribe(id)
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) createFilterWrapper(id string, keyAsym *ecdsa.PrivateKey, keySym []byte, pow float64, topics [][]byte) (types.Filter, error) {
|
||||
return NewWakuFilterWrapper(&waku.Filter{
|
||||
KeyAsym: keyAsym,
|
||||
KeySym: keySym,
|
||||
PoW: pow,
|
||||
AllowP2P: true,
|
||||
Topics: topics,
|
||||
Messages: waku.NewMemoryMessageStore(),
|
||||
}, id), nil
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) SendMessagesRequest(peerID []byte, r types.MessagesRequest) error {
|
||||
return w.waku.SendMessagesRequest(peerID, waku.MessagesRequest{
|
||||
ID: r.ID,
|
||||
From: r.From,
|
||||
To: r.To,
|
||||
Limit: r.Limit,
|
||||
Cursor: r.Cursor,
|
||||
Bloom: r.Bloom,
|
||||
})
|
||||
}
|
||||
|
||||
// RequestHistoricMessages sends a message with p2pRequestCode to a specific peer,
|
||||
// which is known to implement MailServer interface, and is supposed to process this
|
||||
// request and respond with a number of peer-to-peer messages (possibly expired),
|
||||
// which are not supposed to be forwarded any further.
|
||||
// The whisper protocol is agnostic of the format and contents of envelope.
|
||||
func (w *gethWakuWrapper) RequestHistoricMessagesWithTimeout(peerID []byte, envelope types.Envelope, timeout time.Duration) error {
|
||||
return w.waku.RequestHistoricMessagesWithTimeout(peerID, MustUnwrapWakuEnvelope(envelope), timeout)
|
||||
}
|
||||
|
||||
type wakuFilterWrapper struct {
|
||||
filter *waku.Filter
|
||||
id string
|
||||
}
|
||||
|
||||
// NewWakuFilterWrapper returns an object that wraps Geth's Filter in a types interface
|
||||
func NewWakuFilterWrapper(f *waku.Filter, id string) types.Filter {
|
||||
if f.Messages == nil {
|
||||
panic("Messages should not be nil")
|
||||
}
|
||||
|
||||
return &wakuFilterWrapper{
|
||||
filter: f,
|
||||
id: id,
|
||||
}
|
||||
}
|
||||
|
||||
// GetWakuFilterFrom retrieves the underlying whisper Filter struct from a wrapped Filter interface
|
||||
func GetWakuFilterFrom(f types.Filter) *waku.Filter {
|
||||
return f.(*wakuFilterWrapper).filter
|
||||
}
|
||||
|
||||
// ID returns the filter ID
|
||||
func (w *wakuFilterWrapper) ID() string {
|
||||
return w.id
|
||||
}
|
|
@ -59,7 +59,7 @@ func (w *gethWhisperWrapper) SubscribeEnvelopeEvents(eventsProxy chan<- types.En
|
|||
events := make(chan whisper.EnvelopeEvent, 100) // must be buffered to prevent blocking whisper
|
||||
go func() {
|
||||
for e := range events {
|
||||
eventsProxy <- *NewGethEnvelopeEventWrapper(&e)
|
||||
eventsProxy <- *NewWhisperEnvelopeEventWrapper(&e)
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -121,17 +121,17 @@ func (w *gethWhisperWrapper) Subscribe(opts *types.SubscriptionOptions) (string,
|
|||
return "", err
|
||||
}
|
||||
|
||||
id, err := w.whisper.Subscribe(GetGethFilterFrom(f))
|
||||
id, err := w.whisper.Subscribe(GetWhisperFilterFrom(f))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
f.(*gethFilterWrapper).id = id
|
||||
f.(*whisperFilterWrapper).id = id
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (w *gethWhisperWrapper) GetFilter(id string) types.Filter {
|
||||
return NewGethFilterWrapper(w.whisper.GetFilter(id), id)
|
||||
return NewWhisperFilterWrapper(w.whisper.GetFilter(id), id)
|
||||
}
|
||||
|
||||
func (w *gethWhisperWrapper) Unsubscribe(id string) error {
|
||||
|
@ -139,7 +139,7 @@ func (w *gethWhisperWrapper) Unsubscribe(id string) error {
|
|||
}
|
||||
|
||||
func (w *gethWhisperWrapper) createFilterWrapper(id string, keyAsym *ecdsa.PrivateKey, keySym []byte, pow float64, topics [][]byte) (types.Filter, error) {
|
||||
return NewGethFilterWrapper(&whisper.Filter{
|
||||
return NewWhisperFilterWrapper(&whisper.Filter{
|
||||
KeyAsym: keyAsym,
|
||||
KeySym: keySym,
|
||||
PoW: pow,
|
||||
|
@ -173,3 +173,30 @@ func (w *gethWhisperWrapper) RequestHistoricMessagesWithTimeout(peerID []byte, e
|
|||
func (w *gethWhisperWrapper) SyncMessages(peerID []byte, req types.SyncMailRequest) error {
|
||||
return w.whisper.SyncMessages(peerID, *GetGethSyncMailRequestFrom(&req))
|
||||
}
|
||||
|
||||
type whisperFilterWrapper struct {
|
||||
filter *whisper.Filter
|
||||
id string
|
||||
}
|
||||
|
||||
// NewWhisperFilterWrapper returns an object that wraps Geth's Filter in a types interface
|
||||
func NewWhisperFilterWrapper(f *whisper.Filter, id string) types.Filter {
|
||||
if f.Messages == nil {
|
||||
panic("Messages should not be nil")
|
||||
}
|
||||
|
||||
return &whisperFilterWrapper{
|
||||
filter: f,
|
||||
id: id,
|
||||
}
|
||||
}
|
||||
|
||||
// GetWhisperFilterFrom retrieves the underlying whisper Filter struct from a wrapped Filter interface
|
||||
func GetWhisperFilterFrom(f types.Filter) *whisper.Filter {
|
||||
return f.(*whisperFilterWrapper).filter
|
||||
}
|
||||
|
||||
// ID returns the filter ID
|
||||
func (w *whisperFilterWrapper) ID() string {
|
||||
return w.id
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package types
|
||||
|
||||
const (
|
||||
// PubKeyLength represents the length (in bytes) of an uncompressed public key
|
||||
PubKeyLength = 512 / 8
|
||||
// AesKeyLength represents the length (in bytes) of an private key
|
||||
AesKeyLength = 256 / 8
|
||||
)
|
|
@ -19,6 +19,7 @@ func (n EnodeID) String() string {
|
|||
type Node interface {
|
||||
NewENSVerifier(logger *zap.Logger) enstypes.ENSVerifier
|
||||
GetWhisper(ctx interface{}) (Whisper, error)
|
||||
GetWaku(ctx interface{}) (Waku, error)
|
||||
AddPeer(url string) error
|
||||
RemovePeer(url string) error
|
||||
}
|
||||
|
|
|
@ -63,3 +63,25 @@ type PublicWhisperAPI interface {
|
|||
// are received between the last poll and now.
|
||||
GetFilterMessages(id string) ([]*Message, error)
|
||||
}
|
||||
|
||||
// PublicWakuAPI provides the waku RPC service that can be
|
||||
// use publicly without security implications.
|
||||
type PublicWakuAPI interface {
|
||||
// AddPrivateKey imports the given private key.
|
||||
AddPrivateKey(ctx context.Context, privateKey HexBytes) (string, error)
|
||||
// GenerateSymKeyFromPassword derives a key from the given password, stores it, and returns its ID.
|
||||
GenerateSymKeyFromPassword(ctx context.Context, passwd string) (string, error)
|
||||
// DeleteKeyPair removes the key with the given key if it exists.
|
||||
DeleteKeyPair(ctx context.Context, key string) (bool, error)
|
||||
|
||||
// Post posts a message on the Whisper network.
|
||||
// returns the hash of the message in case of success.
|
||||
Post(ctx context.Context, req NewMessage) ([]byte, error)
|
||||
|
||||
// NewMessageFilter creates a new filter that can be used to poll for
|
||||
// (new) messages that satisfy the given criteria.
|
||||
NewMessageFilter(req Criteria) (string, error)
|
||||
// GetFilterMessages returns the messages that match the filter criteria and
|
||||
// are received between the last poll and now.
|
||||
GetFilterMessages(id string) ([]*Message, error)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package types
|
||||
|
||||
// SubscriptionOptions represents the parameters passed to Subscribe()
|
||||
// to customize the subscription behavior.
|
||||
type SubscriptionOptions struct {
|
||||
PrivateKeyID string
|
||||
SymKeyID string
|
||||
PoW float64
|
||||
Topics [][]byte
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Whisper represents a dark communication interface through the Ethereum
|
||||
// network, using its very own P2P communication layer.
|
||||
type Waku interface {
|
||||
PublicWakuAPI() PublicWakuAPI
|
||||
|
||||
// MinPow returns the PoW value required by this node.
|
||||
MinPow() float64
|
||||
// BloomFilter returns the aggregated bloom filter for all the topics of interest.
|
||||
// The nodes are required to send only messages that match the advertised bloom filter.
|
||||
// If a message does not match the bloom, it will tantamount to spam, and the peer will
|
||||
// be disconnected.
|
||||
BloomFilter() []byte
|
||||
// SetTimeSource assigns a particular source of time to a whisper object.
|
||||
SetTimeSource(timesource func() time.Time)
|
||||
// GetCurrentTime returns current time.
|
||||
GetCurrentTime() time.Time
|
||||
|
||||
// GetPrivateKey retrieves the private key of the specified identity.
|
||||
GetPrivateKey(id string) (*ecdsa.PrivateKey, error)
|
||||
|
||||
SubscribeEnvelopeEvents(events chan<- EnvelopeEvent) Subscription
|
||||
|
||||
// AddKeyPair imports a asymmetric private key and returns a deterministic identifier.
|
||||
AddKeyPair(key *ecdsa.PrivateKey) (string, error)
|
||||
// DeleteKeyPair deletes the key with the specified ID if it exists.
|
||||
DeleteKeyPair(keyID string) bool
|
||||
AddSymKeyDirect(key []byte) (string, error)
|
||||
AddSymKeyFromPassword(password string) (string, error)
|
||||
DeleteSymKey(id string) bool
|
||||
GetSymKey(id string) ([]byte, error)
|
||||
|
||||
Subscribe(opts *SubscriptionOptions) (string, error)
|
||||
GetFilter(id string) Filter
|
||||
Unsubscribe(id string) error
|
||||
|
||||
// RequestHistoricMessages sends a message with p2pRequestCode to a specific peer,
|
||||
// which is known to implement MailServer interface, and is supposed to process this
|
||||
// request and respond with a number of peer-to-peer messages (possibly expired),
|
||||
// which are not supposed to be forwarded any further.
|
||||
// The whisper protocol is agnostic of the format and contents of envelope.
|
||||
// A timeout of 0 never expires.
|
||||
RequestHistoricMessagesWithTimeout(peerID []byte, envelope Envelope, timeout time.Duration) error
|
||||
// SendMessagesRequest sends a MessagesRequest. This is an equivalent to RequestHistoricMessages
|
||||
// in terms of the functionality.
|
||||
SendMessagesRequest(peerID []byte, request MessagesRequest) error
|
||||
}
|
|
@ -5,22 +5,6 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// PubKeyLength represents the length (in bytes) of an uncompressed public key
|
||||
PubKeyLength = 512 / 8
|
||||
// AesKeyLength represents the length (in bytes) of an private key
|
||||
AesKeyLength = 256 / 8
|
||||
)
|
||||
|
||||
// SubscriptionOptions represents the parameters passed to Whisper.Subscribe
|
||||
// to customize the subscription behavior
|
||||
type SubscriptionOptions struct {
|
||||
PrivateKeyID string
|
||||
SymKeyID string
|
||||
PoW float64
|
||||
Topics [][]byte
|
||||
}
|
||||
|
||||
// Whisper represents a dark communication interface through the Ethereum
|
||||
// network, using its very own P2P communication layer.
|
||||
type Whisper interface {
|
||||
|
|
|
@ -86,7 +86,7 @@ func _1557732988_initialize_dbDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1557732988_initialize_db.down.sql", size: 72, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
|
||||
info := bindataFileInfo{name: "1557732988_initialize_db.down.sql", size: 72, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x77, 0x40, 0x78, 0xb7, 0x71, 0x3c, 0x20, 0x3b, 0xc9, 0xb, 0x2f, 0x49, 0xe4, 0xff, 0x1c, 0x84, 0x54, 0xa1, 0x30, 0xe3, 0x90, 0xf8, 0x73, 0xda, 0xb0, 0x2a, 0xea, 0x8e, 0xf1, 0x82, 0xe7, 0xd2}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ func _1557732988_initialize_dbUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1557732988_initialize_db.up.sql", size: 234, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
|
||||
info := bindataFileInfo{name: "1557732988_initialize_db.up.sql", size: 234, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8f, 0xa, 0x31, 0xf, 0x94, 0xe, 0xd7, 0xd6, 0xaa, 0x22, 0xd6, 0x6c, 0x7a, 0xbc, 0xad, 0x6a, 0xed, 0x2e, 0x7a, 0xf0, 0x24, 0x81, 0x87, 0x14, 0xe, 0x1c, 0x8a, 0xf1, 0x45, 0xaf, 0x9e, 0x85}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func staticGo() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "static.go", size: 178, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
|
||||
info := bindataFileInfo{name: "static.go", size: 178, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xab, 0x8a, 0xf4, 0x27, 0x24, 0x9d, 0x2a, 0x1, 0x7b, 0x54, 0xea, 0xae, 0x4a, 0x35, 0x40, 0x92, 0xb5, 0xf9, 0xb3, 0x54, 0x3e, 0x3a, 0x1a, 0x2b, 0xae, 0xfb, 0x9e, 0x82, 0xeb, 0x4c, 0xf, 0x6}}
|
||||
return a, nil
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ func _0001_accountsDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "0001_accounts.down.sql", size: 21, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
|
||||
info := bindataFileInfo{name: "0001_accounts.down.sql", size: 21, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd2, 0x61, 0x4c, 0x18, 0xfc, 0xc, 0xdf, 0x5c, 0x1f, 0x5e, 0xd3, 0xbd, 0xfa, 0x12, 0x5e, 0x8d, 0x8d, 0x8b, 0xb9, 0x5f, 0x99, 0x46, 0x63, 0xa5, 0xe3, 0xa6, 0x8a, 0x4, 0xf1, 0x73, 0x8a, 0xe9}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ func _0001_accountsUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "0001_accounts.up.sql", size: 163, mode: os.FileMode(0644), modTime: time.Unix(1575903446, 0)}
|
||||
info := bindataFileInfo{name: "0001_accounts.up.sql", size: 163, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf2, 0xfa, 0x99, 0x8e, 0x96, 0xb3, 0x13, 0x6c, 0x1f, 0x6, 0x27, 0xc5, 0xd2, 0xd4, 0xe0, 0xa5, 0x26, 0x82, 0xa7, 0x26, 0xf2, 0x68, 0x9d, 0xed, 0x9c, 0x3d, 0xbb, 0xdc, 0x37, 0x28, 0xbc, 0x1}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func docGo() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "doc.go", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
|
||||
info := bindataFileInfo{name: "doc.go", size: 74, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xde, 0x7c, 0x28, 0xcd, 0x47, 0xf2, 0xfa, 0x7c, 0x51, 0x2d, 0xd8, 0x38, 0xb, 0xb0, 0x34, 0x9d, 0x4c, 0x62, 0xa, 0x9e, 0x28, 0xc3, 0x31, 0x23, 0xd9, 0xbb, 0x89, 0x9f, 0xa0, 0x89, 0x1f, 0xe8}}
|
||||
return a, nil
|
||||
}
|
||||
|
|
13
node/node.go
13
node/node.go
|
@ -363,7 +363,7 @@ func activateShhService(stack *node.Node, config *params.NodeConfig, db *leveldb
|
|||
if err := ctx.Service(ðnode); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return shhext.New(ethnode.Node, ctx, shhext.EnvelopeSignalHandler{}, db, config.ShhextConfig), nil
|
||||
return shhext.New(ethnode.Node, ctx, "shhext", shhext.EnvelopeSignalHandler{}, db, config.ShhextConfig), nil
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -381,9 +381,14 @@ func activateWakuService(stack *node.Node, config *params.NodeConfig, db *leveld
|
|||
return
|
||||
}
|
||||
|
||||
// TODO: what to do with shhext?
|
||||
|
||||
return nil
|
||||
// TODO(dshulyak) add a config option to enable it by default, but disable if app is started from statusd
|
||||
return stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
|
||||
var ethnode *nodebridge.NodeService
|
||||
if err := ctx.Service(ðnode); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return shhext.New(ethnode.Node, ctx, "wakuext", shhext.EnvelopeSignalHandler{}, db, config.ShhextConfig), nil
|
||||
})
|
||||
}
|
||||
|
||||
func createShhService(ctx *node.ServiceContext, whisperConfig *params.WhisperConfig, clusterConfig *params.ClusterConfig) (*whisper.Whisper, error) {
|
||||
|
|
|
@ -5,9 +5,8 @@ package applicationmetadata
|
|||
|
||||
import (
|
||||
fmt "fmt"
|
||||
math "math"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
|
@ -100,7 +100,7 @@ func _1536754952_initial_schemaDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1536754952_initial_schema.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1536754952_initial_schema.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x44, 0xcf, 0x76, 0x71, 0x1f, 0x5e, 0x9a, 0x43, 0xd8, 0xcd, 0xb8, 0xc3, 0x70, 0xc3, 0x7f, 0xfc, 0x90, 0xb4, 0x25, 0x1e, 0xf4, 0x66, 0x20, 0xb8, 0x33, 0x7e, 0xb0, 0x76, 0x1f, 0xc, 0xc0, 0x75}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ func _1536754952_initial_schemaUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1536754952_initial_schema.up.sql", size: 962, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1536754952_initial_schema.up.sql", size: 962, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xea, 0x90, 0x5a, 0x59, 0x3e, 0x3, 0xe2, 0x3c, 0x81, 0x42, 0xcd, 0x4c, 0x9a, 0xe8, 0xda, 0x93, 0x2b, 0x70, 0xa4, 0xd5, 0x29, 0x3e, 0xd5, 0xc9, 0x27, 0xb6, 0xb7, 0x65, 0xff, 0x0, 0xcb, 0xde}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ func _1539249977_update_ratchet_infoDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1539249977_update_ratchet_info.down.sql", size: 311, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1539249977_update_ratchet_info.down.sql", size: 311, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1, 0xa4, 0xeb, 0xa0, 0xe6, 0xa0, 0xd4, 0x48, 0xbb, 0xad, 0x6f, 0x7d, 0x67, 0x8c, 0xbd, 0x25, 0xde, 0x1f, 0x73, 0x9a, 0xbb, 0xa8, 0xc9, 0x30, 0xb7, 0xa9, 0x7c, 0xaf, 0xb5, 0x1, 0x61, 0xdd}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ func _1539249977_update_ratchet_infoUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1539249977_update_ratchet_info.up.sql", size: 368, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1539249977_update_ratchet_info.up.sql", size: 368, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc, 0x8e, 0xbf, 0x6f, 0xa, 0xc0, 0xe1, 0x3c, 0x42, 0x28, 0x88, 0x1d, 0xdb, 0xba, 0x1c, 0x83, 0xec, 0xba, 0xd3, 0x5f, 0x5c, 0x77, 0x5e, 0xa7, 0x46, 0x36, 0xec, 0x69, 0xa, 0x4b, 0x17, 0x79}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ func _1540715431_add_versionDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1540715431_add_version.down.sql", size: 127, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1540715431_add_version.down.sql", size: 127, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0x9, 0x4, 0xe3, 0x76, 0x2e, 0xb8, 0x9, 0x23, 0xf0, 0x70, 0x93, 0xc4, 0x50, 0xe, 0x9d, 0x84, 0x22, 0x8c, 0x94, 0xd3, 0x24, 0x9, 0x9a, 0xc1, 0xa1, 0x48, 0x45, 0xfd, 0x40, 0x6e, 0xe6}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ func _1540715431_add_versionUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1540715431_add_version.up.sql", size: 265, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1540715431_add_version.up.sql", size: 265, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc7, 0x4c, 0x36, 0x96, 0xdf, 0x16, 0x10, 0xa6, 0x27, 0x1a, 0x79, 0x8b, 0x42, 0x83, 0x23, 0xc, 0x7e, 0xb6, 0x3d, 0x2, 0xda, 0xa4, 0xb4, 0xd, 0x27, 0x55, 0xba, 0xdc, 0xb2, 0x88, 0x8f, 0xa6}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ func _1541164797_add_installationsDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1541164797_add_installations.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1541164797_add_installations.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0xfd, 0xe6, 0xd8, 0xca, 0x3b, 0x38, 0x18, 0xee, 0x0, 0x5f, 0x36, 0x9e, 0x1e, 0xd, 0x19, 0x3e, 0xb4, 0x73, 0x53, 0xe9, 0xa5, 0xac, 0xdd, 0xa1, 0x2f, 0xc7, 0x6c, 0xa8, 0xd9, 0xa, 0x88}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ func _1541164797_add_installationsUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1541164797_add_installations.up.sql", size: 216, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1541164797_add_installations.up.sql", size: 216, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2d, 0x18, 0x26, 0xb8, 0x88, 0x47, 0xdb, 0x83, 0xcc, 0xb6, 0x9d, 0x1c, 0x1, 0xae, 0x2f, 0xde, 0x97, 0x82, 0x3, 0x30, 0xa8, 0x63, 0xa1, 0x78, 0x4b, 0xa5, 0x9, 0x8, 0x75, 0xa2, 0x57, 0x81}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ func _1558084410_add_secretDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1558084410_add_secret.down.sql", size: 56, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1558084410_add_secret.down.sql", size: 56, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x49, 0xb, 0x65, 0xdf, 0x59, 0xbf, 0xe9, 0x5, 0x5b, 0x6f, 0xd5, 0x3a, 0xb7, 0x57, 0xe8, 0x78, 0x38, 0x73, 0x53, 0x57, 0xf7, 0x24, 0x4, 0xe4, 0xa2, 0x49, 0x22, 0xa2, 0xc6, 0xfd, 0x80, 0xa4}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ func _1558084410_add_secretUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1558084410_add_secret.up.sql", size: 301, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1558084410_add_secret.up.sql", size: 301, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0x32, 0x36, 0x8e, 0x47, 0xb0, 0x8f, 0xc1, 0xc6, 0xf7, 0xc6, 0x9f, 0x2d, 0x44, 0x75, 0x2b, 0x26, 0xec, 0x6, 0xa0, 0x7b, 0xa5, 0xbd, 0xc8, 0x76, 0x8a, 0x82, 0x68, 0x2, 0x42, 0xb5, 0xf4}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -300,7 +300,7 @@ func _1558588866_add_versionDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1558588866_add_version.down.sql", size: 47, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1558588866_add_version.down.sql", size: 47, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xde, 0x52, 0x34, 0x3c, 0x46, 0x4a, 0xf0, 0x72, 0x47, 0x6f, 0x49, 0x5c, 0xc7, 0xf9, 0x32, 0xce, 0xc4, 0x3d, 0xfd, 0x61, 0xa1, 0x8b, 0x8f, 0xf2, 0x31, 0x34, 0xde, 0x15, 0x49, 0xa6, 0xde, 0xb9}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ func _1558588866_add_versionUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1558588866_add_version.up.sql", size: 57, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1558588866_add_version.up.sql", size: 57, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2a, 0xea, 0x64, 0x39, 0x61, 0x20, 0x83, 0x83, 0xb, 0x2e, 0x79, 0x64, 0xb, 0x53, 0xfa, 0xfe, 0xc6, 0xf7, 0x67, 0x42, 0xd3, 0x4f, 0xdc, 0x7e, 0x30, 0x32, 0xe8, 0x14, 0x41, 0xe9, 0xe7, 0x3b}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -340,7 +340,7 @@ func _1559627659_add_contact_codeDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1559627659_add_contact_code.down.sql", size: 32, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1559627659_add_contact_code.down.sql", size: 32, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5d, 0x64, 0x6d, 0xce, 0x24, 0x42, 0x20, 0x8d, 0x4f, 0x37, 0xaa, 0x9d, 0xc, 0x57, 0x98, 0xc1, 0xd1, 0x1a, 0x34, 0xcd, 0x9f, 0x8f, 0x34, 0x86, 0xb3, 0xd3, 0xdc, 0xf1, 0x7d, 0xe5, 0x1b, 0x6e}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -360,7 +360,7 @@ func _1559627659_add_contact_codeUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1559627659_add_contact_code.up.sql", size: 198, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1559627659_add_contact_code.up.sql", size: 198, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x16, 0xf6, 0xc2, 0x62, 0x9c, 0xd2, 0xc9, 0x1e, 0xd8, 0xea, 0xaa, 0xea, 0x95, 0x8f, 0x89, 0x6a, 0x85, 0x5d, 0x9d, 0x99, 0x78, 0x3c, 0x90, 0x66, 0x99, 0x3e, 0x4b, 0x19, 0x62, 0xfb, 0x31, 0x4d}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -380,7 +380,7 @@ func _1561368210_add_installation_metadataDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561368210_add_installation_metadata.down.sql", size: 35, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1561368210_add_installation_metadata.down.sql", size: 35, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa8, 0xde, 0x3f, 0xd2, 0x4a, 0x50, 0x98, 0x56, 0xe3, 0xc0, 0xcd, 0x9d, 0xb0, 0x34, 0x3b, 0xe5, 0x62, 0x18, 0xb5, 0x20, 0xc9, 0x3e, 0xdc, 0x6a, 0x40, 0x36, 0x66, 0xea, 0x51, 0x8c, 0x71, 0xf5}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -400,7 +400,7 @@ func _1561368210_add_installation_metadataUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561368210_add_installation_metadata.up.sql", size: 267, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1561368210_add_installation_metadata.up.sql", size: 267, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb4, 0x71, 0x8f, 0x29, 0xb1, 0xaa, 0xd6, 0xd1, 0x8c, 0x17, 0xef, 0x6c, 0xd5, 0x80, 0xb8, 0x2c, 0xc3, 0xfe, 0xec, 0x24, 0x4d, 0xc8, 0x25, 0xd3, 0xb4, 0xcd, 0xa9, 0xac, 0x63, 0x61, 0xb2, 0x9c}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -420,7 +420,7 @@ func docGo() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xef, 0xaf, 0xdf, 0xcf, 0x65, 0xae, 0x19, 0xfc, 0x9d, 0x29, 0xc1, 0x91, 0xaf, 0xb5, 0xd5, 0xb1, 0x56, 0xf3, 0xee, 0xa8, 0xba, 0x13, 0x65, 0xdb, 0xab, 0xcf, 0x4e, 0xac, 0x92, 0xe9, 0x60, 0xf1}}
|
||||
return a, nil
|
||||
}
|
||||
|
|
|
@ -5,9 +5,8 @@ package encryption
|
|||
|
||||
import (
|
||||
fmt "fmt"
|
||||
math "math"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
|
@ -697,6 +697,7 @@ golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2 h1:4dVFTC832rPn4pomLSz1vA+are2+dU19w1H8OngV7nc=
|
||||
golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 h1:6KET3Sqa7fkVfD63QnAM81ZeYg5n4HwApOJkufONnHA=
|
||||
golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
"github.com/status-im/status-go/protocol/encryption"
|
||||
"github.com/status-im/status-go/protocol/encryption/multidevice"
|
||||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
transport "github.com/status-im/status-go/protocol/transport/whisper"
|
||||
"github.com/status-im/status-go/protocol/transport"
|
||||
v1protocol "github.com/status-im/status-go/protocol/v1"
|
||||
)
|
||||
|
||||
|
@ -34,7 +34,7 @@ type messageProcessor struct {
|
|||
identity *ecdsa.PrivateKey
|
||||
datasync *datasync.DataSync
|
||||
protocol *encryption.Protocol
|
||||
transport *transport.WhisperServiceTransport
|
||||
transport transport.Transport
|
||||
logger *zap.Logger
|
||||
|
||||
featureFlags featureFlags
|
||||
|
@ -44,7 +44,7 @@ func newMessageProcessor(
|
|||
identity *ecdsa.PrivateKey,
|
||||
database *sql.DB,
|
||||
enc *encryption.Protocol,
|
||||
transport *transport.WhisperServiceTransport,
|
||||
transport transport.Transport,
|
||||
logger *zap.Logger,
|
||||
features featureFlags,
|
||||
) (*messageProcessor, error) {
|
||||
|
|
|
@ -23,7 +23,9 @@ import (
|
|||
"github.com/status-im/status-go/protocol/identity/identicon"
|
||||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
"github.com/status-im/status-go/protocol/sqlite"
|
||||
transport "github.com/status-im/status-go/protocol/transport/whisper"
|
||||
"github.com/status-im/status-go/protocol/transport"
|
||||
wakutransp "github.com/status-im/status-go/protocol/transport/waku"
|
||||
shhtransp "github.com/status-im/status-go/protocol/transport/whisper"
|
||||
v1protocol "github.com/status-im/status-go/protocol/v1"
|
||||
)
|
||||
|
||||
|
@ -47,7 +49,7 @@ type Messenger struct {
|
|||
node types.Node
|
||||
identity *ecdsa.PrivateKey
|
||||
persistence *sqlitePersistence
|
||||
transport *transport.WhisperServiceTransport
|
||||
transport transport.Transport
|
||||
encryptor *encryption.Protocol
|
||||
processor *messageProcessor
|
||||
handler *MessageHandler
|
||||
|
@ -195,11 +197,6 @@ func NewMessenger(
|
|||
) (*Messenger, error) {
|
||||
var messenger *Messenger
|
||||
|
||||
shh, err := node.GetWhisper(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := config{}
|
||||
|
||||
for _, opt := range opts {
|
||||
|
@ -279,22 +276,42 @@ func NewMessenger(
|
|||
}
|
||||
|
||||
// Apply migrations for all components.
|
||||
err = sqlite.Migrate(database)
|
||||
err := sqlite.Migrate(database)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to apply migrations")
|
||||
}
|
||||
|
||||
// Initialize transport layer.
|
||||
t, err := transport.NewWhisperServiceTransport(
|
||||
shh,
|
||||
identity,
|
||||
database,
|
||||
nil,
|
||||
c.envelopesMonitorConfig,
|
||||
logger,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create a WhisperServiceTransport")
|
||||
var transp transport.Transport
|
||||
if shh, err := node.GetWhisper(nil); err == nil {
|
||||
transp, err = shhtransp.NewWhisperServiceTransport(
|
||||
shh,
|
||||
identity,
|
||||
database,
|
||||
nil,
|
||||
c.envelopesMonitorConfig,
|
||||
logger,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create WhisperServiceTransport")
|
||||
}
|
||||
} else if err != nil {
|
||||
logger.Info("failed to find Whisper service; trying Waku", zap.Error(err))
|
||||
waku, err := node.GetWaku(nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to find Whisper and Waku services")
|
||||
}
|
||||
transp, err = wakutransp.NewWakuServiceTransport(
|
||||
waku,
|
||||
identity,
|
||||
database,
|
||||
nil,
|
||||
c.envelopesMonitorConfig,
|
||||
logger,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create WakuServiceTransport")
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize encryption layer.
|
||||
|
@ -311,7 +328,7 @@ func NewMessenger(
|
|||
identity,
|
||||
database,
|
||||
encryptionProtocol,
|
||||
t,
|
||||
transp,
|
||||
logger,
|
||||
c.featureFlags,
|
||||
)
|
||||
|
@ -325,7 +342,7 @@ func NewMessenger(
|
|||
node: node,
|
||||
identity: identity,
|
||||
persistence: &sqlitePersistence{db: database},
|
||||
transport: t,
|
||||
transport: transp,
|
||||
encryptor: encryptionProtocol,
|
||||
processor: processor,
|
||||
handler: handler,
|
||||
|
@ -340,8 +357,8 @@ func NewMessenger(
|
|||
verifyTransactionClient: c.verifyTransactionClient,
|
||||
shutdownTasks: []func() error{
|
||||
database.Close,
|
||||
t.Reset,
|
||||
t.Stop,
|
||||
transp.ResetFilters,
|
||||
transp.Stop,
|
||||
func() error { processor.Stop(); return nil },
|
||||
// Currently this often fails, seems like it's safe to ignore them
|
||||
// https://github.com/uber-go/zap/issues/328
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
package protocol
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
encryptmigrations "github.com/status-im/status-go/protocol/encryption/migrations"
|
||||
appmigrations "github.com/status-im/status-go/protocol/migrations"
|
||||
transpmigrations "github.com/status-im/status-go/protocol/transport/whisper/migrations"
|
||||
)
|
||||
|
||||
type getter func(string) ([]byte, error)
|
||||
|
||||
type migrationsWithGetter struct {
|
||||
Names []string
|
||||
Getter getter
|
||||
}
|
||||
|
||||
var defaultMigrations = []migrationsWithGetter{
|
||||
{
|
||||
Names: transpmigrations.AssetNames(),
|
||||
Getter: transpmigrations.Asset,
|
||||
},
|
||||
{
|
||||
Names: encryptmigrations.AssetNames(),
|
||||
Getter: encryptmigrations.Asset,
|
||||
},
|
||||
{
|
||||
Names: appmigrations.AssetNames(),
|
||||
Getter: appmigrations.Asset,
|
||||
},
|
||||
}
|
||||
|
||||
func prepareMigrations(migrations []migrationsWithGetter) ([]string, getter, error) {
|
||||
var allNames []string
|
||||
nameToGetter := make(map[string]getter)
|
||||
|
||||
for _, m := range migrations {
|
||||
for _, name := range m.Names {
|
||||
if !validateName(name) {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := nameToGetter[name]; ok {
|
||||
return nil, nil, errors.Errorf("migration with name %s already exists", name)
|
||||
}
|
||||
allNames = append(allNames, name)
|
||||
nameToGetter[name] = m.Getter
|
||||
}
|
||||
}
|
||||
|
||||
return allNames, func(name string) ([]byte, error) {
|
||||
getter, ok := nameToGetter[name]
|
||||
if !ok {
|
||||
return nil, errors.Errorf("no migration for name %s", name)
|
||||
}
|
||||
return getter(name)
|
||||
}, nil
|
||||
}
|
||||
|
||||
// validateName verifies that only *.sql files are taken into consideration.
|
||||
func validateName(name string) bool {
|
||||
return strings.HasSuffix(name, ".sql")
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
// Code generated by go-bindata. DO NOT EDIT.
|
||||
// sources:
|
||||
// 000001_init.down.db.sql (65B)
|
||||
// 000001_init.up.db.sql (2.693kB)
|
||||
// 000001_init.up.db.sql (2.719kB)
|
||||
// doc.go (377B)
|
||||
|
||||
package migrations
|
||||
|
@ -86,12 +86,12 @@ func _000001_initDownDbSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000001_init.down.db.sql", size: 65, mode: os.FileMode(0644), modTime: time.Unix(1577718673, 0)}
|
||||
info := bindataFileInfo{name: "000001_init.down.db.sql", size: 65, mode: os.FileMode(0644), modTime: time.Unix(1578756765, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5e, 0xbb, 0x3f, 0x1, 0x75, 0x19, 0x70, 0x86, 0xa7, 0x34, 0x40, 0x17, 0x34, 0x3e, 0x18, 0x51, 0x79, 0xd4, 0x22, 0xad, 0x8f, 0x80, 0xcc, 0xa6, 0xcc, 0x6, 0x2b, 0x62, 0x2, 0x47, 0xba, 0xf9}}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var __000001_initUpDbSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x56\x51\x6f\xe3\x36\x0c\x7e\xf7\xaf\x20\xb0\x87\xb6\x80\x3b\xdc\x80\xdb\x6d\x40\x9f\xd2\x9e\xbb\x05\xcb\x92\x43\xea\x0e\xbd\x27\x81\x91\xd8\x58\x88\x2d\x19\x12\x9d\x5c\x80\xfb\xf1\x83\x9c\x38\xb1\x12\xa7\xbd\x61\x7d\x28\x5a\x52\x24\xc5\x8f\xfc\x3e\xf9\x61\x9e\x8d\xf2\x0c\xf2\xd1\xfd\x24\x83\xf1\x23\x4c\x67\x39\x64\x2f\xe3\xa7\xfc\x09\x64\x81\xec\xe1\x3a\xd1\x0a\xfe\x19\xcd\x1f\xfe\x1c\xcd\xe1\xcb\x7c\xfc\xf7\x68\xfe\x15\xfe\xca\xbe\xc2\x6c\x0a\x0f\xb3\xe9\xe3\x64\xfc\x90\xc3\x3c\xfb\x32\x19\x3d\x64\x69\x62\xb0\xa2\xc3\xe9\x90\x6b\xfa\x3c\x99\xa4\x89\xb4\xa5\x75\x67\x76\xf8\x9c\x3d\x8e\x9e\x27\x39\x5c\xfd\x84\xbf\xfc\xfe\x9b\xfa\xf5\x2a\x4d\x78\x5b\x13\x8c\xa7\x79\x2f\x18\x25\xeb\x35\xc1\xfd\x6c\x36\xc9\x46\xd3\xf3\xe8\x7c\xfe\x9c\xa5\x09\xeb\x8a\x3c\x63\x55\x9f\x44\x2b\x2a\x89\x49\x09\x64\x21\x4b\x2b\x57\x62\x8d\x65\x13\x97\x38\x64\xfa\x90\x26\x75\xb3\x28\xb5\x14\x2b\xda\xc2\xfd\x64\x76\x9f\x26\x8d\x59\x6b\xda\x90\x12\x15\x79\x8f\x4b\x12\xd2\x36\x86\x2f\xc6\x97\xe8\x7f\xac\x50\x7b\x70\x9f\x73\x5f\xaa\xa2\x6a\x41\xce\xc7\xff\x15\xba\x16\x4d\xad\x90\x69\xe7\x48\x6e\xee\x92\x24\x9a\x9a\xb4\x86\x51\xb6\xa3\x02\xd0\x0a\xf2\xec\x25\x7f\x7f\x52\x00\xa8\x94\x23\xef\x77\xe7\x8f\x80\x01\xb4\x43\x3c\xb3\x92\xf1\x62\x4d\x4e\xbf\x6a\x52\x87\x61\x74\x0d\x3d\x8e\x26\x4f\xd9\xe9\x29\x81\x97\x71\x02\xc0\x52\xe3\x40\x71\xad\xc8\xb0\x96\xd6\x9c\xbb\xea\xc2\xb2\x3d\x37\xb7\x48\xee\x20\x52\x6f\xd4\xf3\x5b\xcf\x54\x09\xc6\x65\x87\x30\x80\xa2\xb5\x96\x24\xb4\x79\xb5\x07\x1b\x3b\xbd\x68\x98\x04\x5b\xc1\x58\xae\xe2\x7a\x2d\xfa\xb7\xb7\x30\xe6\x2b\x0f\xba\xaa\xad\x63\x34\x0c\x5c\x60\xf8\xa5\x3d\x30\x2e\x4a\x82\x02\x3d\x38\xbb\xd1\x0a\xd0\xc3\x86\xc0\x51\xb9\x05\x6b\x40\x73\x08\xde\x14\x64\x42\x70\x49\x55\xe8\xd5\x2c\x41\x9b\x57\x6d\x34\xd3\xad\x97\xce\x96\xe5\xcf\xc9\x1b\xb4\x6c\x3c\xb9\x6e\x71\x76\x33\x6f\xa7\xfe\xc3\x14\x0d\xe7\x37\x85\xf6\x35\x39\x11\x91\x26\xfb\x23\x9b\x47\xc0\x02\x78\xdb\x38\x39\xb0\x0b\x01\x39\xcf\xda\x20\x6b\x6b\x0e\xc8\x01\x30\x7d\xe3\x01\xfa\x07\x57\xd8\x52\x32\x2c\x06\x08\x1e\xdc\xa1\xab\xbe\x78\xec\xf3\x5d\x20\x75\x9b\xb0\x40\x16\xbd\xc6\x63\x6f\x69\x25\x96\xe2\xed\x33\x85\x56\x74\x79\x93\x01\x1c\xf9\xda\x1a\x1f\x56\x21\xbe\x56\x27\x05\x5d\x2f\xfb\x0b\x5d\x60\xfd\x1e\x4a\x22\x73\x59\xc3\x7a\x55\x6d\xc3\x4b\xab\xcd\x52\x78\x46\x6e\x7c\x5c\xb9\x46\xe7\x49\x89\x16\xe7\x23\xec\x0e\x37\xa2\xc6\x6d\x69\x51\xf5\xac\x9e\xb5\x5c\x91\x13\x35\xca\xd5\xf1\x96\x9d\xb5\x40\x5f\xc4\xb9\xa5\xad\x2a\x34\xaa\x87\x57\x6c\xdf\x75\x36\xe8\xea\xa4\x64\xd0\xf9\xea\x6c\x35\xec\x09\x3b\xe1\x50\xf2\xb0\x97\x1d\x1a\x1f\xc4\xdf\x9a\x37\x6e\xeb\xf5\xd2\x20\x37\x8e\x7a\x9d\x1f\x7c\x8c\xdc\xce\xa2\x2f\x9a\xe3\xe9\xe7\xec\x05\xb4\xfa\x26\xf6\xdb\x3d\x9b\xc6\x9c\xba\xde\xd9\x6f\xee\x06\x22\x08\x9d\x2c\xc4\x62\x7b\xd8\xac\xd9\x14\x4e\xa2\x77\x28\x37\x0b\xcf\xee\xfa\xea\xc3\xff\xfc\xb9\x82\xef\xdf\xfb\x8b\x95\xc2\xed\xa7\x8f\x29\x7c\xfa\x78\x13\x1c\x5a\xa5\x1d\x0d\xd2\x76\x9b\xcf\x1f\x87\x58\x3b\xc2\xa2\x44\xd2\xf1\xdf\x84\xe3\x7d\x52\xb5\x5a\xec\xe9\xe4\x81\x6c\xe5\x97\xda\x81\x9f\xbe\x9d\x7b\x17\x5f\xe6\xa1\xa3\x36\x14\x1b\xb6\x15\xb2\x96\x58\x96\xdb\xcb\xa7\x87\xa8\xe9\x48\xea\x5a\x93\xe1\xa3\xf0\xf7\xd9\xf2\x0e\x66\x21\x23\x99\x65\x50\xcb\xe3\x42\xfa\xf0\x3c\xac\xb1\xd4\xe1\xd5\x69\x91\xec\x0a\xc7\xec\x39\xe7\x54\xd4\xf9\xa5\x15\xef\x0f\x63\xd7\x01\xbb\xed\x11\xbd\x60\x7a\xd5\xae\x85\x9a\x4c\x67\x89\x99\x10\xd7\xe9\x5d\xf6\x14\xba\xdd\xe7\x13\xc0\xc9\x97\xcf\x20\x63\x06\xb1\x88\xa0\x08\x7c\x78\x1f\xb1\xeb\xde\xdf\x37\x77\xc9\xbf\x01\x00\x00\xff\xff\xc7\x20\x3e\x09\x85\x0a\x00\x00")
|
||||
var __000001_initUpDbSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x56\xd1\x6f\xe2\xb8\x13\x7e\xe7\xaf\x18\xe9\xf7\x40\x2b\xd1\x9f\xf6\xa4\xbd\xbd\x93\xfa\x44\xd9\xf4\x0e\x1d\x07\x2b\x9a\x9e\xba\x4f\xd6\xe0\x0c\xc4\xc2\xb1\x23\x7b\x02\x8b\xb4\x7f\xfc\xc9\x81\x40\x0c\x81\xee\xea\xfa\x50\xb5\x33\xe3\x19\xcf\x37\xf3\x7d\xce\x68\x9e\x0c\xd3\x04\xd2\xe1\xd3\x24\x81\xf1\x33\x4c\x67\x29\x24\x6f\xe3\x97\xf4\x05\x64\x8e\xec\xe1\xae\x07\xa0\x32\xf8\x67\x38\x1f\xfd\x39\x9c\xc3\x97\xf9\xf8\xef\xe1\xfc\x2b\xfc\x95\x7c\x85\xd9\x14\x46\xb3\xe9\xf3\x64\x3c\x4a\x61\x9e\x7c\x99\x0c\x47\xc9\xa0\x07\x60\xb0\xa0\x63\x7c\xc8\x37\x7d\x9d\x4c\x82\x43\x5a\x6d\xdd\x85\x07\x3e\x27\xcf\xc3\xd7\x49\x0a\xfd\xff\xe1\x2f\xbf\xff\x96\xfd\xda\x0f\xb1\xbc\x2b\x09\xc6\xd3\x34\x4a\x80\x92\xd5\x86\xe0\x69\x36\x9b\x24\xc3\xe9\x65\x86\x74\xfe\x5a\xdf\x80\x55\x41\x9e\xb1\x28\x2f\x32\x64\xa4\x89\x29\x13\xc8\x42\x6a\x2b\xd7\x62\x83\xba\x8a\x0b\x1d\xb3\x7d\x08\x07\xca\x6a\xa1\x95\x14\x6b\xda\xc1\xd3\x64\xf6\x14\x4c\x95\xd9\x28\xda\x52\x26\x0a\xf2\x1e\x57\x24\xa4\xad\x0c\xdf\xc8\xa1\xd1\xff\x68\xb9\x3a\xf4\x90\xf7\x58\xb0\xa0\x62\x41\xce\x9f\xff\x9f\xab\x52\x54\x65\x86\x4c\x7b\x57\xef\xfe\xb1\xd7\x8b\xe6\x29\xad\x61\x94\xa7\x21\xa6\xc9\x5b\xfa\x23\x13\xc4\x2c\x73\xe4\xfd\x3e\xbe\x0d\x5f\x3d\xda\x0b\x2b\x19\x2f\x36\xe4\xd4\x52\x51\x76\x1c\x4e\xd3\xd6\xf3\x70\xf2\x92\x9c\x47\x09\xbc\x85\x17\x6a\x85\x1d\xc5\x55\x46\x86\x95\xb4\xe6\xd2\x55\xe6\x96\xed\xa5\xb9\x46\x73\x0f\x51\x76\xa3\x9e\xdf\x79\xa6\x42\x30\xae\x4e\x18\x67\xb4\x51\x92\x84\x32\x4b\x7b\xb4\xb1\x53\x8b\x8a\x49\xb0\x15\x8c\x7a\x1d\xd7\xab\xd1\x7f\x78\x80\x31\xf7\x3d\xa8\xa2\xb4\x8e\xd1\x30\x70\x8e\xe1\x97\xf2\xc0\xb8\xd0\x04\x39\x7a\x70\x76\xab\x32\x40\x0f\x5b\x02\x47\x7a\x07\xd6\x80\xe2\x70\x78\x9b\x93\x09\x87\x35\x15\xa1\x57\xb3\x02\x65\x96\xca\x28\xa6\x07\x2f\x9d\xd5\xfa\xff\xbd\x1b\x84\xad\x3c\xb9\x66\x79\xf6\x33\xff\x59\xea\x02\x6c\x73\xe5\x4b\x72\x22\xa2\x50\xf2\x47\x12\x33\x19\xc0\xdb\xca\xc9\x8e\x5d\x08\xc8\x79\x56\x06\x59\x59\x73\x44\x0e\x80\xe9\x1b\x77\x8a\x02\xd4\x5b\x4a\x86\x45\x27\xe5\xa1\xee\xaa\x2d\x29\x87\x7c\x57\x29\x0e\xb5\x70\x89\x56\xe3\xb1\x57\x5b\x89\x5a\xdc\x8e\xc9\x55\x46\xd7\x37\x19\xc0\x91\x2f\xad\xf1\x61\x15\xe2\x6b\x35\x92\xd0\xf4\x72\xb8\xd0\x15\xee\x1f\xa0\x24\x32\xd7\x35\xad\x55\xd5\x56\xbc\xb2\xca\xac\x84\x67\xe4\xca\xc7\x95\x4b\x74\x9e\x32\x51\xe3\x7c\x82\xdd\xe1\x56\x94\xb8\xd3\x16\xb3\x96\xd5\xb3\x92\x6b\x72\xa2\x44\xb9\x3e\xdd\xb2\xb1\xe6\xe8\xf3\x38\xb7\xb4\x45\x81\x26\x6b\xe1\x15\xdb\xf7\x9d\x75\xba\x1a\x29\xe9\x74\x2e\x9d\x2d\xba\x3d\x61\x27\x1c\x4a\xee\xf6\xb2\x43\xe3\xc3\x63\x60\xcd\x8d\xdb\x7a\xb5\x32\xc8\x95\xa3\x56\xe7\x47\x1f\x23\xd7\xb3\x68\x8b\xe6\x78\xfa\x39\x79\x03\x95\x7d\x13\x87\xed\x9e\x4d\x63\x4e\xdd\xed\xed\xf7\x8f\x1d\x27\x08\x9d\xcc\xc5\x62\x77\xdc\xac\xd9\x14\xce\x4e\xef\x51\xae\x16\x9e\xdd\x5d\xff\xc3\x7f\xfc\xe9\xc3\xf7\xef\xed\xc5\x1a\xc0\xc3\xa7\x8f\x03\xf8\xf4\xf1\x3e\x38\x54\x36\x68\x68\x30\xa8\xb7\xf9\xf2\x71\x88\xb5\x23\x2c\x4a\x24\x1d\x3f\x27\x1c\xef\x93\xaa\xd6\x62\x4f\x67\x0f\x65\x2d\xbf\x54\x0f\xfc\xfc\x0d\x3d\xb8\xf8\x3a\x0f\x1d\xd5\x47\xb1\x62\x5b\x20\x2b\x89\x5a\xef\xae\x47\x77\x51\xd3\x91\x54\xa5\x22\xc3\x27\xe1\x6f\xb3\xe5\x1d\xcc\x42\x46\x32\xab\xa0\x96\xa7\x85\xf4\xe1\x79\xd8\xa0\x56\xe1\xd5\xa9\x91\x6c\x0a\xc7\xec\xb9\xe4\x54\xd4\xf9\xb5\x15\x6f\x0f\x63\xdf\x01\xbb\xdd\x09\xbd\x60\x5a\x2a\x57\x43\x4d\xa6\xb1\xc4\x4c\x88\xeb\xb4\x2e\x7b\x0e\x5d\xf3\x39\x75\xf6\x0d\xd4\xc9\x98\x4e\x2c\x22\x28\x02\x1f\xde\x47\xec\xae\xf5\xf7\xfd\x63\xef\xdf\x00\x00\x00\xff\xff\xd7\x95\x8b\x6b\x9f\x0a\x00\x00")
|
||||
|
||||
func _000001_initUpDbSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
|
@ -106,8 +106,8 @@ func _000001_initUpDbSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000001_init.up.db.sql", size: 2693, mode: os.FileMode(0644), modTime: time.Unix(1577718868, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x34, 0x9f, 0x6, 0x64, 0xcf, 0x97, 0xbe, 0xa8, 0xa2, 0x2f, 0xda, 0xc5, 0x9d, 0x26, 0x3, 0x65, 0x98, 0x8a, 0x7a, 0x6a, 0xc3, 0xd, 0x3f, 0x25, 0xfe, 0x4c, 0x5, 0xdb, 0x98, 0xa9, 0xf9, 0xf}}
|
||||
info := bindataFileInfo{name: "000001_init.up.db.sql", size: 2719, mode: os.FileMode(0644), modTime: time.Unix(1578756765, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x60, 0xdc, 0xeb, 0xe, 0xc2, 0x4f, 0x75, 0xa, 0xf6, 0x3e, 0xc7, 0xc4, 0x4, 0xe2, 0xe1, 0xa4, 0x73, 0x2f, 0x4a, 0xad, 0x1a, 0x0, 0xc3, 0x93, 0x9d, 0x77, 0x3e, 0x31, 0x91, 0x77, 0x2e, 0xc8}}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
|
@ -126,7 +126,7 @@ func docGo() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xef, 0xaf, 0xdf, 0xcf, 0x65, 0xae, 0x19, 0xfc, 0x9d, 0x29, 0xc1, 0x91, 0xaf, 0xb5, 0xd5, 0xb1, 0x56, 0xf3, 0xee, 0xa8, 0xba, 0x13, 0x65, 0xdb, 0xab, 0xcf, 0x4e, 0xac, 0x92, 0xe9, 0x60, 0xf1}}
|
||||
return a, nil
|
||||
}
|
||||
|
|
|
@ -5,9 +5,8 @@ package protobuf
|
|||
|
||||
import (
|
||||
fmt "fmt"
|
||||
math "math"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
|
@ -5,9 +5,8 @@ package protobuf
|
|||
|
||||
import (
|
||||
fmt "fmt"
|
||||
math "math"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
|
@ -5,9 +5,8 @@ package protobuf
|
|||
|
||||
import (
|
||||
fmt "fmt"
|
||||
math "math"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
|
@ -7,7 +7,8 @@ import (
|
|||
|
||||
encryptmigrations "github.com/status-im/status-go/protocol/encryption/migrations"
|
||||
appmigrations "github.com/status-im/status-go/protocol/migrations"
|
||||
transpmigrations "github.com/status-im/status-go/protocol/transport/whisper/migrations"
|
||||
wakumigrations "github.com/status-im/status-go/protocol/transport/waku/migrations"
|
||||
whispermigrations "github.com/status-im/status-go/protocol/transport/whisper/migrations"
|
||||
)
|
||||
|
||||
type getter func(string) ([]byte, error)
|
||||
|
@ -19,8 +20,12 @@ type migrationsWithGetter struct {
|
|||
|
||||
var defaultMigrations = []migrationsWithGetter{
|
||||
{
|
||||
Names: transpmigrations.AssetNames(),
|
||||
Getter: transpmigrations.Asset,
|
||||
Names: whispermigrations.AssetNames(),
|
||||
Getter: whispermigrations.Asset,
|
||||
},
|
||||
{
|
||||
Names: wakumigrations.AssetNames(),
|
||||
Getter: wakumigrations.Asset,
|
||||
},
|
||||
{
|
||||
Names: encryptmigrations.AssetNames(),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package protocol
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"testing"
|
|
@ -0,0 +1,22 @@
|
|||
package transport
|
||||
|
||||
import (
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type EnvelopesMonitorConfig struct {
|
||||
EnvelopeEventsHandler EnvelopeEventsHandler
|
||||
MaxAttempts int
|
||||
MailserverConfirmationsEnabled bool
|
||||
IsMailserver func(types.EnodeID) bool
|
||||
Logger *zap.Logger
|
||||
}
|
||||
|
||||
// EnvelopeEventsHandler used for two different event types.
|
||||
type EnvelopeEventsHandler interface {
|
||||
EnvelopeSent([][]byte)
|
||||
EnvelopeExpired([][]byte, error)
|
||||
MailServerRequestCompleted(types.Hash, types.Hash, []byte, error)
|
||||
MailServerRequestExpired(types.Hash)
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package transport
|
||||
|
||||
import "github.com/status-im/status-go/eth-node/types"
|
||||
|
||||
// TODO: revise fields encoding/decoding. Some are encoded using hexutil and some using encoding/hex.
|
||||
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 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 filters.
|
||||
// It's encoded using encoding/hex.
|
||||
Identity string `json:"identity"`
|
||||
// Topic is the whisper topic
|
||||
Topic types.TopicType `json:"topic"`
|
||||
// Discovery is whether this is a discovery topic
|
||||
Discovery bool `json:"discovery"`
|
||||
// Negotiated tells us whether is a negotiated topic
|
||||
Negotiated bool `json:"negotiated"`
|
||||
// Listen is whether we are actually listening for messages on this chat, or the filter is only created in order to be able to post on the topic
|
||||
Listen bool `json:"listen"`
|
||||
}
|
||||
|
||||
func (c *Filter) IsPublic() bool {
|
||||
return !c.OneToOne
|
||||
}
|
|
@ -1,66 +1,47 @@
|
|||
package whisper
|
||||
package transport
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"database/sql"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
)
|
||||
|
||||
const (
|
||||
discoveryTopic = "contact-discovery"
|
||||
minPow = 0.0
|
||||
)
|
||||
|
||||
var (
|
||||
// The number of partitions.
|
||||
nPartitions = big.NewInt(5000)
|
||||
minPow = 0.0
|
||||
)
|
||||
|
||||
type whisperFilter struct {
|
||||
type RawFilter struct {
|
||||
FilterID string
|
||||
Topic types.TopicType
|
||||
SymKeyID string
|
||||
}
|
||||
|
||||
// TODO: revise fields encoding/decoding. Some are encoded using hexutil and some using encoding/hex.
|
||||
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 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 filters.
|
||||
// It's encoded using encoding/hex.
|
||||
Identity string `json:"identity"`
|
||||
// Topic is the whisper topic
|
||||
Topic types.TopicType `json:"topic"`
|
||||
// Discovery is whether this is a discovery topic
|
||||
Discovery bool `json:"discovery"`
|
||||
// Negotiated tells us whether is a negotiated topic
|
||||
Negotiated bool `json:"negotiated"`
|
||||
// Listen is whether we are actually listening for messages on this chat, or the filter is only created in order to be able to post on the topic
|
||||
Listen bool `json:"listen"`
|
||||
type KeysPersistence interface {
|
||||
All() (map[string][]byte, error)
|
||||
Add(chatID string, key []byte) error
|
||||
}
|
||||
|
||||
func (c *Filter) IsPublic() bool {
|
||||
return !c.OneToOne
|
||||
type FiltersService interface {
|
||||
AddKeyPair(key *ecdsa.PrivateKey) (string, error)
|
||||
DeleteKeyPair(keyID string) bool
|
||||
|
||||
AddSymKeyDirect(key []byte) (string, error)
|
||||
AddSymKeyFromPassword(password string) (string, error)
|
||||
GetSymKey(id string) ([]byte, error)
|
||||
DeleteSymKey(id string) bool
|
||||
|
||||
Subscribe(opts *types.SubscriptionOptions) (string, error)
|
||||
Unsubscribe(id string) error
|
||||
}
|
||||
|
||||
type filtersManager struct {
|
||||
whisper types.Whisper
|
||||
persistence *sqlitePersistence
|
||||
type FiltersManager struct {
|
||||
service FiltersService
|
||||
persistence KeysPersistence
|
||||
privateKey *ecdsa.PrivateKey
|
||||
keys map[string][]byte // a cache of symmetric manager derived from passwords
|
||||
logger *zap.Logger
|
||||
|
@ -71,22 +52,20 @@ type filtersManager struct {
|
|||
filters map[string]*Filter
|
||||
}
|
||||
|
||||
// newFiltersManager returns a new filtersManager.
|
||||
func newFiltersManager(db *sql.DB, w types.Whisper, privateKey *ecdsa.PrivateKey, logger *zap.Logger) (*filtersManager, error) {
|
||||
// NewFiltersManager returns a new filtersManager.
|
||||
func NewFiltersManager(persistence KeysPersistence, service FiltersService, privateKey *ecdsa.PrivateKey, logger *zap.Logger) (*FiltersManager, error) {
|
||||
if logger == nil {
|
||||
logger = zap.NewNop()
|
||||
}
|
||||
|
||||
persistence := newSQLitePersistence(db)
|
||||
|
||||
keys, err := persistence.All()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &filtersManager{
|
||||
return &FiltersManager{
|
||||
privateKey: privateKey,
|
||||
whisper: w,
|
||||
service: service,
|
||||
persistence: persistence,
|
||||
keys: keys,
|
||||
filters: make(map[string]*Filter),
|
||||
|
@ -94,7 +73,7 @@ func newFiltersManager(db *sql.DB, w types.Whisper, privateKey *ecdsa.PrivateKey
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (s *filtersManager) Init(
|
||||
func (s *FiltersManager) Init(
|
||||
chatIDs []string,
|
||||
publicKeys []*ecdsa.PublicKey,
|
||||
) ([]*Filter, error) {
|
||||
|
@ -146,7 +125,7 @@ func (s *filtersManager) Init(
|
|||
}
|
||||
|
||||
// DEPRECATED
|
||||
func (s *filtersManager) InitWithFilters(filters []*Filter) ([]*Filter, error) {
|
||||
func (s *FiltersManager) InitWithFilters(filters []*Filter) ([]*Filter, error) {
|
||||
var (
|
||||
chatIDs []string
|
||||
publicKeys []*ecdsa.PublicKey
|
||||
|
@ -154,7 +133,7 @@ func (s *filtersManager) InitWithFilters(filters []*Filter) ([]*Filter, error) {
|
|||
|
||||
for _, filter := range filters {
|
||||
if filter.Identity != "" && filter.OneToOne {
|
||||
publicKey, err := strToPublicKey(filter.Identity)
|
||||
publicKey, err := StrToPublicKey(filter.Identity)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -167,7 +146,7 @@ func (s *filtersManager) InitWithFilters(filters []*Filter) ([]*Filter, error) {
|
|||
return s.Init(chatIDs, publicKeys)
|
||||
}
|
||||
|
||||
func (s *filtersManager) Reset() error {
|
||||
func (s *FiltersManager) Reset() error {
|
||||
var filters []*Filter
|
||||
|
||||
s.mutex.Lock()
|
||||
|
@ -179,7 +158,7 @@ func (s *filtersManager) Reset() error {
|
|||
return s.Remove(filters...)
|
||||
}
|
||||
|
||||
func (s *filtersManager) Filters() (result []*Filter) {
|
||||
func (s *FiltersManager) Filters() (result []*Filter) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
|
@ -190,14 +169,14 @@ func (s *filtersManager) Filters() (result []*Filter) {
|
|||
return
|
||||
}
|
||||
|
||||
func (s *filtersManager) Filter(chatID string) *Filter {
|
||||
func (s *FiltersManager) Filter(chatID string) *Filter {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
return s.filters[chatID]
|
||||
}
|
||||
|
||||
// FilterByFilterID returns a Filter with a given Whisper filter ID.
|
||||
func (s *filtersManager) FilterByFilterID(filterID string) *Filter {
|
||||
func (s *FiltersManager) FilterByFilterID(filterID string) *Filter {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
for _, f := range s.filters {
|
||||
|
@ -208,11 +187,11 @@ func (s *filtersManager) FilterByFilterID(filterID string) *Filter {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *filtersManager) FiltersByPublicKey(publicKey *ecdsa.PublicKey) (result []*Filter) {
|
||||
func (s *FiltersManager) FiltersByPublicKey(publicKey *ecdsa.PublicKey) (result []*Filter) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
identityStr := publicKeyToStr(publicKey)
|
||||
identityStr := PublicKeyToStr(publicKey)
|
||||
|
||||
for _, f := range s.filters {
|
||||
if f.Identity == identityStr {
|
||||
|
@ -224,16 +203,16 @@ func (s *filtersManager) FiltersByPublicKey(publicKey *ecdsa.PublicKey) (result
|
|||
}
|
||||
|
||||
// Remove remove all the filters associated with a chat/identity
|
||||
func (s *filtersManager) Remove(filters ...*Filter) error {
|
||||
func (s *FiltersManager) Remove(filters ...*Filter) error {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
for _, f := range filters {
|
||||
if err := s.whisper.Unsubscribe(f.FilterID); err != nil {
|
||||
if err := s.service.Unsubscribe(f.FilterID); err != nil {
|
||||
return err
|
||||
}
|
||||
if f.SymKeyID != "" {
|
||||
s.whisper.DeleteSymKey(f.SymKeyID)
|
||||
s.service.DeleteSymKey(f.SymKeyID)
|
||||
}
|
||||
delete(s.filters, f.ChatID)
|
||||
}
|
||||
|
@ -242,19 +221,19 @@ func (s *filtersManager) Remove(filters ...*Filter) error {
|
|||
}
|
||||
|
||||
// LoadPartitioned creates a filter for a partitioned topic.
|
||||
func (s *filtersManager) LoadPartitioned(publicKey *ecdsa.PublicKey) (*Filter, error) {
|
||||
func (s *FiltersManager) LoadPartitioned(publicKey *ecdsa.PublicKey) (*Filter, error) {
|
||||
return s.loadPartitioned(publicKey, false)
|
||||
}
|
||||
|
||||
func (s *filtersManager) loadMyPartitioned() (*Filter, error) {
|
||||
func (s *FiltersManager) loadMyPartitioned() (*Filter, error) {
|
||||
return s.loadPartitioned(&s.privateKey.PublicKey, true)
|
||||
}
|
||||
|
||||
func (s *filtersManager) loadPartitioned(publicKey *ecdsa.PublicKey, listen bool) (*Filter, error) {
|
||||
func (s *FiltersManager) loadPartitioned(publicKey *ecdsa.PublicKey, listen bool) (*Filter, error) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
chatID := partitionedTopic(publicKey)
|
||||
chatID := PartitionedTopic(publicKey)
|
||||
if _, ok := s.filters[chatID]; ok {
|
||||
return s.filters[chatID], nil
|
||||
}
|
||||
|
@ -270,7 +249,7 @@ func (s *filtersManager) loadPartitioned(publicKey *ecdsa.PublicKey, listen bool
|
|||
ChatID: chatID,
|
||||
FilterID: filter.FilterID,
|
||||
Topic: filter.Topic,
|
||||
Identity: publicKeyToStr(publicKey),
|
||||
Identity: PublicKeyToStr(publicKey),
|
||||
Listen: listen,
|
||||
OneToOne: true,
|
||||
}
|
||||
|
@ -281,11 +260,11 @@ func (s *filtersManager) loadPartitioned(publicKey *ecdsa.PublicKey, listen bool
|
|||
}
|
||||
|
||||
// LoadNegotiated loads a negotiated secret as a filter.
|
||||
func (s *filtersManager) LoadNegotiated(secret types.NegotiatedSecret) (*Filter, error) {
|
||||
func (s *FiltersManager) LoadNegotiated(secret types.NegotiatedSecret) (*Filter, error) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
chatID := negotiatedTopic(secret.PublicKey)
|
||||
chatID := NegotiatedTopic(secret.PublicKey)
|
||||
|
||||
if _, ok := s.filters[chatID]; ok {
|
||||
return s.filters[chatID], nil
|
||||
|
@ -302,7 +281,7 @@ func (s *filtersManager) LoadNegotiated(secret types.NegotiatedSecret) (*Filter,
|
|||
Topic: filter.Topic,
|
||||
SymKeyID: filter.SymKeyID,
|
||||
FilterID: filter.FilterID,
|
||||
Identity: publicKeyToStr(secret.PublicKey),
|
||||
Identity: PublicKeyToStr(secret.PublicKey),
|
||||
Negotiated: true,
|
||||
Listen: true,
|
||||
OneToOne: true,
|
||||
|
@ -315,11 +294,11 @@ func (s *filtersManager) LoadNegotiated(secret types.NegotiatedSecret) (*Filter,
|
|||
|
||||
// LoadDiscovery adds 1 discovery filter
|
||||
// for the personal discovery topic.
|
||||
func (s *filtersManager) LoadDiscovery() ([]*Filter, error) {
|
||||
func (s *FiltersManager) LoadDiscovery() ([]*Filter, error) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
personalDiscoveryTopic := personalDiscoveryTopic(&s.privateKey.PublicKey)
|
||||
personalDiscoveryTopic := PersonalDiscoveryTopic(&s.privateKey.PublicKey)
|
||||
|
||||
// Check if filters are already loaded.
|
||||
var result []*Filter
|
||||
|
@ -334,9 +313,7 @@ func (s *filtersManager) LoadDiscovery() ([]*Filter, error) {
|
|||
return result, nil
|
||||
}
|
||||
|
||||
var discoveryResponse *whisperFilter
|
||||
var err error
|
||||
identityStr := publicKeyToStr(&s.privateKey.PublicKey)
|
||||
identityStr := PublicKeyToStr(&s.privateKey.PublicKey)
|
||||
|
||||
// Load personal discovery
|
||||
personalDiscoveryChat := &Filter{
|
||||
|
@ -347,7 +324,7 @@ func (s *filtersManager) LoadDiscovery() ([]*Filter, error) {
|
|||
OneToOne: true,
|
||||
}
|
||||
|
||||
discoveryResponse, err = s.addAsymmetric(personalDiscoveryChat.ChatID, true)
|
||||
discoveryResponse, err := s.addAsymmetric(personalDiscoveryChat.ChatID, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -361,7 +338,7 @@ func (s *filtersManager) LoadDiscovery() ([]*Filter, error) {
|
|||
}
|
||||
|
||||
// LoadPublic adds a filter for a public chat.
|
||||
func (s *filtersManager) LoadPublic(chatID string) (*Filter, error) {
|
||||
func (s *FiltersManager) LoadPublic(chatID string) (*Filter, error) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
|
@ -389,11 +366,11 @@ func (s *filtersManager) LoadPublic(chatID string) (*Filter, error) {
|
|||
}
|
||||
|
||||
// LoadContactCode creates a filter for the advertise topic for a given public key.
|
||||
func (s *filtersManager) LoadContactCode(pubKey *ecdsa.PublicKey) (*Filter, error) {
|
||||
func (s *FiltersManager) LoadContactCode(pubKey *ecdsa.PublicKey) (*Filter, error) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
chatID := contactCodeTopic(pubKey)
|
||||
chatID := ContactCodeTopic(pubKey)
|
||||
|
||||
if _, ok := s.filters[chatID]; ok {
|
||||
return s.filters[chatID], nil
|
||||
|
@ -409,7 +386,7 @@ func (s *filtersManager) LoadContactCode(pubKey *ecdsa.PublicKey) (*Filter, erro
|
|||
FilterID: contactCodeFilter.FilterID,
|
||||
Topic: contactCodeFilter.Topic,
|
||||
SymKeyID: contactCodeFilter.SymKeyID,
|
||||
Identity: publicKeyToStr(pubKey),
|
||||
Identity: PublicKeyToStr(pubKey),
|
||||
Listen: true,
|
||||
}
|
||||
|
||||
|
@ -418,25 +395,25 @@ func (s *filtersManager) LoadContactCode(pubKey *ecdsa.PublicKey) (*Filter, erro
|
|||
}
|
||||
|
||||
// addSymmetric adds a symmetric key filter
|
||||
func (s *filtersManager) addSymmetric(chatID string) (*whisperFilter, error) {
|
||||
func (s *FiltersManager) addSymmetric(chatID string) (*RawFilter, error) {
|
||||
var symKeyID string
|
||||
var err error
|
||||
|
||||
topic := toTopic(chatID)
|
||||
topic := ToTopic(chatID)
|
||||
topics := [][]byte{topic}
|
||||
|
||||
symKey, ok := s.keys[chatID]
|
||||
if ok {
|
||||
symKeyID, err = s.whisper.AddSymKeyDirect(symKey)
|
||||
symKeyID, err = s.service.AddSymKeyDirect(symKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
symKeyID, err = s.whisper.AddSymKeyFromPassword(chatID)
|
||||
symKeyID, err = s.service.AddSymKeyFromPassword(chatID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if symKey, err = s.whisper.GetSymKey(symKeyID); err != nil {
|
||||
if symKey, err = s.service.GetSymKey(symKeyID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.keys[chatID] = symKey
|
||||
|
@ -447,7 +424,7 @@ func (s *filtersManager) addSymmetric(chatID string) (*whisperFilter, error) {
|
|||
}
|
||||
}
|
||||
|
||||
id, err := s.whisper.Subscribe(&types.SubscriptionOptions{
|
||||
id, err := s.service.Subscribe(&types.SubscriptionOptions{
|
||||
SymKeyID: symKeyID,
|
||||
PoW: minPow,
|
||||
Topics: topics,
|
||||
|
@ -456,7 +433,7 @@ func (s *filtersManager) addSymmetric(chatID string) (*whisperFilter, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &whisperFilter{
|
||||
return &RawFilter{
|
||||
FilterID: id,
|
||||
SymKeyID: symKeyID,
|
||||
Topic: types.BytesToTopic(topic),
|
||||
|
@ -465,7 +442,7 @@ func (s *filtersManager) addSymmetric(chatID string) (*whisperFilter, error) {
|
|||
|
||||
// addAsymmetricFilter adds a filter with our private key
|
||||
// and set minPow according to the listen parameter.
|
||||
func (s *filtersManager) addAsymmetric(chatID string, listen bool) (*whisperFilter, error) {
|
||||
func (s *FiltersManager) addAsymmetric(chatID string, listen bool) (*RawFilter, error) {
|
||||
var (
|
||||
err error
|
||||
pow = 1.0 // use PoW high enough to discard all messages for the filter
|
||||
|
@ -475,15 +452,15 @@ func (s *filtersManager) addAsymmetric(chatID string, listen bool) (*whisperFilt
|
|||
pow = minPow
|
||||
}
|
||||
|
||||
topic := toTopic(chatID)
|
||||
topic := ToTopic(chatID)
|
||||
topics := [][]byte{topic}
|
||||
|
||||
privateKeyID, err := s.whisper.AddKeyPair(s.privateKey)
|
||||
privateKeyID, err := s.service.AddKeyPair(s.privateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
id, err := s.whisper.Subscribe(&types.SubscriptionOptions{
|
||||
id, err := s.service.Subscribe(&types.SubscriptionOptions{
|
||||
PrivateKeyID: privateKeyID,
|
||||
PoW: pow,
|
||||
Topics: topics,
|
||||
|
@ -491,58 +468,13 @@ func (s *filtersManager) addAsymmetric(chatID string, listen bool) (*whisperFilt
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &whisperFilter{FilterID: id, Topic: types.BytesToTopic(topic)}, nil
|
||||
return &RawFilter{FilterID: id, Topic: types.BytesToTopic(topic)}, nil
|
||||
}
|
||||
|
||||
// GetNegotiated returns a negotiated chat given an identity
|
||||
func (s *filtersManager) GetNegotiated(identity *ecdsa.PublicKey) *Filter {
|
||||
func (s *FiltersManager) GetNegotiated(identity *ecdsa.PublicKey) *Filter {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
return s.filters[negotiatedTopic(identity)]
|
||||
}
|
||||
|
||||
func toTopic(s string) []byte {
|
||||
return crypto.Keccak256([]byte(s))[:types.TopicLength]
|
||||
}
|
||||
|
||||
// ToTopic converts a string to a whisper topic.
|
||||
func ToTopic(s string) []byte {
|
||||
return toTopic(s)
|
||||
}
|
||||
|
||||
func strToPublicKey(str string) (*ecdsa.PublicKey, error) {
|
||||
publicKeyBytes, err := hex.DecodeString(str)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return crypto.UnmarshalPubkey(publicKeyBytes)
|
||||
}
|
||||
|
||||
func publicKeyToStr(publicKey *ecdsa.PublicKey) string {
|
||||
return hex.EncodeToString(crypto.FromECDSAPub(publicKey))
|
||||
}
|
||||
|
||||
func personalDiscoveryTopic(publicKey *ecdsa.PublicKey) string {
|
||||
return "contact-discovery-" + publicKeyToStr(publicKey)
|
||||
}
|
||||
|
||||
// partitionedTopic returns the associated partitioned topic string
|
||||
// with the given public key.
|
||||
func partitionedTopic(publicKey *ecdsa.PublicKey) string {
|
||||
partition := big.NewInt(0)
|
||||
partition.Mod(publicKey.X, nPartitions)
|
||||
return "contact-discovery-" + strconv.FormatInt(partition.Int64(), 10)
|
||||
}
|
||||
|
||||
func ContactCodeTopic(publicKey *ecdsa.PublicKey) string {
|
||||
return contactCodeTopic(publicKey)
|
||||
}
|
||||
|
||||
func contactCodeTopic(publicKey *ecdsa.PublicKey) string {
|
||||
return "0x" + publicKeyToStr(publicKey) + "-contact-code"
|
||||
}
|
||||
|
||||
func negotiatedTopic(publicKey *ecdsa.PublicKey) string {
|
||||
return "0x" + publicKeyToStr(publicKey) + "-negotiated"
|
||||
return s.filters[NegotiatedTopic(identity)]
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package whisper
|
||||
package transport
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
|
@ -26,7 +26,7 @@ func TestFiltersManagerSuite(t *testing.T) {
|
|||
|
||||
type FiltersManagerSuite struct {
|
||||
suite.Suite
|
||||
chats *filtersManager
|
||||
chats *FiltersManager
|
||||
dbPath string
|
||||
manager []*testKey
|
||||
logger *zap.Logger
|
||||
|
@ -77,7 +77,7 @@ func (s *FiltersManagerSuite) SetupTest() {
|
|||
|
||||
whisper := gethbridge.NewGethWhisperWrapper(whisper.New(nil))
|
||||
|
||||
s.chats, err = newFiltersManager(db, whisper, s.manager[0].privateKey, s.logger)
|
||||
s.chats, err = NewFiltersManager(db, whisper, s.manager[0].privateKey, s.logger)
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package transport
|
||||
|
||||
import "github.com/status-im/status-go/eth-node/types"
|
||||
|
||||
func DefaultMessage() types.NewMessage {
|
||||
msg := types.NewMessage{}
|
||||
|
||||
msg.TTL = 10
|
||||
msg.PowTarget = 0.002
|
||||
msg.PowTime = 1
|
||||
|
||||
return msg
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package transport
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
)
|
||||
|
||||
const discoveryTopic = "contact-discovery"
|
||||
|
||||
var (
|
||||
// The number of partitions.
|
||||
nPartitions = big.NewInt(5000)
|
||||
)
|
||||
|
||||
// ToTopic converts a string to a whisper topic.
|
||||
func ToTopic(s string) []byte {
|
||||
return crypto.Keccak256([]byte(s))[:types.TopicLength]
|
||||
}
|
||||
|
||||
func StrToPublicKey(str string) (*ecdsa.PublicKey, error) {
|
||||
publicKeyBytes, err := hex.DecodeString(str)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return crypto.UnmarshalPubkey(publicKeyBytes)
|
||||
}
|
||||
|
||||
func PublicKeyToStr(publicKey *ecdsa.PublicKey) string {
|
||||
return hex.EncodeToString(crypto.FromECDSAPub(publicKey))
|
||||
}
|
||||
|
||||
func PersonalDiscoveryTopic(publicKey *ecdsa.PublicKey) string {
|
||||
return "contact-discovery-" + PublicKeyToStr(publicKey)
|
||||
}
|
||||
|
||||
// PartitionedTopic returns the associated partitioned topic string
|
||||
// with the given public key.
|
||||
func PartitionedTopic(publicKey *ecdsa.PublicKey) string {
|
||||
partition := big.NewInt(0)
|
||||
partition.Mod(publicKey.X, nPartitions)
|
||||
return "contact-discovery-" + strconv.FormatInt(partition.Int64(), 10)
|
||||
}
|
||||
|
||||
func ContactCodeTopic(publicKey *ecdsa.PublicKey) string {
|
||||
return "0x" + PublicKeyToStr(publicKey) + "-contact-code"
|
||||
}
|
||||
|
||||
func NegotiatedTopic(publicKey *ecdsa.PublicKey) string {
|
||||
return "0x" + PublicKeyToStr(publicKey) + "-negotiated"
|
||||
}
|
||||
|
||||
func DiscoveryTopic() string {
|
||||
return discoveryTopic
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package transport
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
)
|
||||
|
||||
type Transport interface {
|
||||
Stop() error
|
||||
|
||||
JoinPrivate(publicKey *ecdsa.PublicKey) error
|
||||
LeavePrivate(publicKey *ecdsa.PublicKey) error
|
||||
JoinGroup(publicKeys []*ecdsa.PublicKey) error
|
||||
LeaveGroup(publicKeys []*ecdsa.PublicKey) error
|
||||
JoinPublic(chatID string) error
|
||||
LeavePublic(chatID string) error
|
||||
|
||||
SendPublic(ctx context.Context, newMessage *types.NewMessage, chatName string) ([]byte, error)
|
||||
SendPrivateWithSharedSecret(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey, secret []byte) ([]byte, error)
|
||||
SendPrivateWithPartitioned(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error)
|
||||
SendMessagesRequest(
|
||||
ctx context.Context,
|
||||
peerID []byte,
|
||||
from, to uint32,
|
||||
previousCursor []byte,
|
||||
) (cursor []byte, err error)
|
||||
|
||||
Track(identifiers [][]byte, hash []byte, newMessage *types.NewMessage)
|
||||
|
||||
InitFilters(chatIDs []string, publicKeys []*ecdsa.PublicKey) ([]*Filter, error)
|
||||
LoadFilters(filters []*Filter) ([]*Filter, error)
|
||||
RemoveFilters(filters []*Filter) error
|
||||
ResetFilters() error
|
||||
ProcessNegotiatedSecret(secret types.NegotiatedSecret) (*Filter, error)
|
||||
RetrieveRawAll() (map[Filter][]*types.Message, error)
|
||||
}
|
|
@ -0,0 +1,310 @@
|
|||
package waku
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/protocol/transport"
|
||||
)
|
||||
|
||||
// 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 waku queue.
|
||||
EnvelopePosted EnvelopeState = iota
|
||||
// EnvelopeSent is set when envelope is sent to at least one peer.
|
||||
EnvelopeSent
|
||||
)
|
||||
|
||||
// EnvelopeEventsHandler used for two different event types.
|
||||
type EnvelopeEventsHandler interface {
|
||||
EnvelopeSent([][]byte)
|
||||
EnvelopeExpired([][]byte, error)
|
||||
MailServerRequestCompleted(types.Hash, types.Hash, []byte, error)
|
||||
MailServerRequestExpired(types.Hash)
|
||||
}
|
||||
|
||||
// NewEnvelopesMonitor returns a pointer to an instance of the EnvelopesMonitor.
|
||||
func NewEnvelopesMonitor(w types.Waku, config transport.EnvelopesMonitorConfig) *EnvelopesMonitor {
|
||||
logger := config.Logger
|
||||
|
||||
if logger == nil {
|
||||
logger = zap.NewNop()
|
||||
}
|
||||
|
||||
var api types.PublicWakuAPI
|
||||
if w != nil {
|
||||
api = w.PublicWakuAPI()
|
||||
}
|
||||
|
||||
return &EnvelopesMonitor{
|
||||
w: w,
|
||||
api: api,
|
||||
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[types.Hash]EnvelopeState{},
|
||||
messages: map[types.Hash]*types.NewMessage{},
|
||||
attempts: map[types.Hash]int{},
|
||||
identifiers: make(map[types.Hash][][]byte),
|
||||
|
||||
// key is hash of the batch (event.Batch)
|
||||
batches: map[types.Hash]map[types.Hash]struct{}{},
|
||||
}
|
||||
}
|
||||
|
||||
// EnvelopesMonitor is responsible for monitoring waku envelopes state.
|
||||
type EnvelopesMonitor struct {
|
||||
w types.Waku
|
||||
api types.PublicWakuAPI
|
||||
handler EnvelopeEventsHandler
|
||||
mailServerConfirmation bool
|
||||
maxAttempts int
|
||||
|
||||
mu sync.Mutex
|
||||
envelopes map[types.Hash]EnvelopeState
|
||||
batches map[types.Hash]map[types.Hash]struct{}
|
||||
|
||||
messages map[types.Hash]*types.NewMessage
|
||||
attempts map[types.Hash]int
|
||||
identifiers map[types.Hash][][]byte
|
||||
|
||||
wg sync.WaitGroup
|
||||
quit chan struct{}
|
||||
isMailserver func(peer types.EnodeID) bool
|
||||
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// Start processing events.
|
||||
func (m *EnvelopesMonitor) Start() {
|
||||
m.quit = make(chan struct{})
|
||||
m.wg.Add(1)
|
||||
go func() {
|
||||
m.handleEnvelopeEvents()
|
||||
m.wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
// Stop process events.
|
||||
func (m *EnvelopesMonitor) Stop() {
|
||||
close(m.quit)
|
||||
m.wg.Wait()
|
||||
}
|
||||
|
||||
// Add hash to a tracker.
|
||||
func (m *EnvelopesMonitor) Add(identifiers [][]byte, envelopeHash types.Hash, message types.NewMessage) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.envelopes[envelopeHash] = EnvelopePosted
|
||||
m.identifiers[envelopeHash] = identifiers
|
||||
m.messages[envelopeHash] = &message
|
||||
m.attempts[envelopeHash] = 1
|
||||
}
|
||||
|
||||
func (m *EnvelopesMonitor) GetState(hash types.Hash) EnvelopeState {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
state, exist := m.envelopes[hash]
|
||||
if !exist {
|
||||
return NotRegistered
|
||||
}
|
||||
return state
|
||||
}
|
||||
|
||||
// handleEnvelopeEvents processes waku envelope events
|
||||
func (m *EnvelopesMonitor) handleEnvelopeEvents() {
|
||||
events := make(chan types.EnvelopeEvent, 100) // must be buffered to prevent blocking waku
|
||||
sub := m.w.SubscribeEnvelopeEvents(events)
|
||||
defer func() {
|
||||
close(events)
|
||||
sub.Unsubscribe()
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-m.quit:
|
||||
return
|
||||
case event := <-events:
|
||||
m.handleEvent(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handleEvent based on type of the event either triggers
|
||||
// confirmation handler or removes hash from tracker
|
||||
func (m *EnvelopesMonitor) handleEvent(event types.EnvelopeEvent) {
|
||||
handlers := map[types.EventType]func(types.EnvelopeEvent){
|
||||
types.EventEnvelopeSent: m.handleEventEnvelopeSent,
|
||||
types.EventEnvelopeExpired: m.handleEventEnvelopeExpired,
|
||||
types.EventBatchAcknowledged: m.handleAcknowledgedBatch,
|
||||
types.EventEnvelopeReceived: m.handleEventEnvelopeReceived,
|
||||
}
|
||||
if handler, ok := handlers[event.Event]; ok {
|
||||
handler(event)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *EnvelopesMonitor) handleEventEnvelopeSent(event types.EnvelopeEvent) {
|
||||
if m.mailServerConfirmation {
|
||||
if !m.isMailserver(event.Peer) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
state, ok := m.envelopes[event.Hash]
|
||||
// if we didn't send a message using extension - skip it
|
||||
// if message was already confirmed - skip it
|
||||
if !ok || state == EnvelopeSent {
|
||||
return
|
||||
}
|
||||
m.logger.Debug("envelope is sent", zap.String("hash", event.Hash.String()), zap.String("peer", event.Peer.String()))
|
||||
if event.Batch != (types.Hash{}) {
|
||||
if _, ok := m.batches[event.Batch]; !ok {
|
||||
m.batches[event.Batch] = map[types.Hash]struct{}{}
|
||||
}
|
||||
m.batches[event.Batch][event.Hash] = struct{}{}
|
||||
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(m.identifiers[event.Hash])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *EnvelopesMonitor) handleAcknowledgedBatch(event types.EnvelopeEvent) {
|
||||
if m.mailServerConfirmation {
|
||||
if !m.isMailserver(event.Peer) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
envelopes, ok := m.batches[event.Batch]
|
||||
if !ok {
|
||||
m.logger.Debug("batch is not found", zap.String("batch", event.Batch.String()))
|
||||
}
|
||||
m.logger.Debug("received a confirmation", zap.String("batch", event.Batch.String()), zap.String("peer", event.Peer.String()))
|
||||
envelopeErrors, ok := event.Data.([]types.EnvelopeError)
|
||||
if event.Data != nil && !ok {
|
||||
m.logger.Error("received unexpected data in the the confirmation event", zap.String("batch", event.Batch.String()))
|
||||
}
|
||||
failedEnvelopes := map[types.Hash]struct{}{}
|
||||
for i := range envelopeErrors {
|
||||
envelopeError := envelopeErrors[i]
|
||||
_, exist := m.envelopes[envelopeError.Hash]
|
||||
if exist {
|
||||
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 types.EnvelopeTimeNotSynced:
|
||||
err = errors.New("envelope wasn't delivered due to time sync issues")
|
||||
}
|
||||
m.handleEnvelopeFailure(envelopeError.Hash, err)
|
||||
}
|
||||
failedEnvelopes[envelopeError.Hash] = struct{}{}
|
||||
}
|
||||
|
||||
for hash := range envelopes {
|
||||
if _, exist := failedEnvelopes[hash]; exist {
|
||||
continue
|
||||
}
|
||||
state, ok := m.envelopes[hash]
|
||||
if !ok || state == EnvelopeSent {
|
||||
continue
|
||||
}
|
||||
m.envelopes[hash] = EnvelopeSent
|
||||
if m.handler != nil {
|
||||
m.handler.EnvelopeSent(m.identifiers[hash])
|
||||
}
|
||||
}
|
||||
delete(m.batches, event.Batch)
|
||||
}
|
||||
|
||||
func (m *EnvelopesMonitor) handleEventEnvelopeExpired(event types.EnvelopeEvent) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.handleEnvelopeFailure(event.Hash, errors.New("envelope expired due to connectivity issues"))
|
||||
}
|
||||
|
||||
// handleEnvelopeFailure is a common code path for processing envelopes failures. not thread safe, lock
|
||||
// must be used on a higher level.
|
||||
func (m *EnvelopesMonitor) handleEnvelopeFailure(hash types.Hash, err error) {
|
||||
if state, ok := m.envelopes[hash]; ok {
|
||||
message, exist := m.messages[hash]
|
||||
if !exist {
|
||||
m.logger.Error("message was deleted erroneously", zap.String("envelope hash", hash.String()))
|
||||
}
|
||||
attempt := m.attempts[hash]
|
||||
identifiers := m.identifiers[hash]
|
||||
m.clearMessageState(hash)
|
||||
if state == EnvelopeSent {
|
||||
return
|
||||
}
|
||||
if attempt < m.maxAttempts {
|
||||
m.logger.Debug("retrying to send a message", zap.String("hash", hash.String()), zap.Int("attempt", attempt+1))
|
||||
hex, err := m.api.Post(context.TODO(), *message)
|
||||
if err != nil {
|
||||
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 := types.BytesToHash(hex)
|
||||
m.envelopes[envelopeID] = EnvelopePosted
|
||||
m.messages[envelopeID] = message
|
||||
m.attempts[envelopeID] = attempt + 1
|
||||
m.identifiers[envelopeID] = identifiers
|
||||
} else {
|
||||
m.logger.Debug("envelope expired", zap.String("hash", hash.String()))
|
||||
if m.handler != nil {
|
||||
m.handler.EnvelopeExpired(identifiers, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *EnvelopesMonitor) handleEventEnvelopeReceived(event types.EnvelopeEvent) {
|
||||
if m.mailServerConfirmation {
|
||||
if !m.isMailserver(event.Peer) {
|
||||
return
|
||||
}
|
||||
}
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
state, ok := m.envelopes[event.Hash]
|
||||
if !ok || state != EnvelopePosted {
|
||||
return
|
||||
}
|
||||
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(m.identifiers[event.Hash])
|
||||
}
|
||||
}
|
||||
|
||||
// clearMessageState removes all message and envelope state.
|
||||
// not thread-safe, should be protected on a higher level.
|
||||
func (m *EnvelopesMonitor) clearMessageState(envelopeID types.Hash) {
|
||||
delete(m.envelopes, envelopeID)
|
||||
delete(m.messages, envelopeID)
|
||||
delete(m.attempts, envelopeID)
|
||||
delete(m.identifiers, envelopeID)
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
package waku
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
)
|
||||
|
||||
var (
|
||||
testHash = types.Hash{0x01}
|
||||
testIDs = [][]byte{[]byte("id")}
|
||||
)
|
||||
|
||||
type EnvelopesMonitorSuite struct {
|
||||
suite.Suite
|
||||
|
||||
monitor *EnvelopesMonitor
|
||||
}
|
||||
|
||||
func TestEnvelopesMonitorSuite(t *testing.T) {
|
||||
suite.Run(t, new(EnvelopesMonitorSuite))
|
||||
}
|
||||
|
||||
func (s *EnvelopesMonitorSuite) SetupTest() {
|
||||
s.monitor = NewEnvelopesMonitor(
|
||||
nil,
|
||||
EnvelopesMonitorConfig{
|
||||
EnvelopeEventsHandler: nil,
|
||||
MaxAttempts: 0,
|
||||
MailserverConfirmationsEnabled: false,
|
||||
IsMailserver: func(types.EnodeID) bool { return false },
|
||||
Logger: zap.NewNop(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (s *EnvelopesMonitorSuite) TestConfirmed() {
|
||||
s.monitor.Add(testIDs, testHash, types.NewMessage{})
|
||||
s.Contains(s.monitor.envelopes, testHash)
|
||||
s.Equal(EnvelopePosted, s.monitor.envelopes[testHash])
|
||||
s.monitor.handleEvent(types.EnvelopeEvent{
|
||||
Event: types.EventEnvelopeSent,
|
||||
Hash: testHash,
|
||||
})
|
||||
s.Contains(s.monitor.envelopes, testHash)
|
||||
s.Equal(EnvelopeSent, s.monitor.envelopes[testHash])
|
||||
}
|
||||
|
||||
func (s *EnvelopesMonitorSuite) TestConfirmedWithAcknowledge() {
|
||||
testBatch := types.Hash{1}
|
||||
pkey, err := crypto.GenerateKey()
|
||||
s.Require().NoError(err)
|
||||
node := enode.NewV4(&pkey.PublicKey, nil, 0, 0)
|
||||
s.monitor.Add(testIDs, testHash, types.NewMessage{})
|
||||
s.Contains(s.monitor.envelopes, testHash)
|
||||
s.Equal(EnvelopePosted, s.monitor.envelopes[testHash])
|
||||
s.monitor.handleEvent(types.EnvelopeEvent{
|
||||
Event: types.EventEnvelopeSent,
|
||||
Hash: testHash,
|
||||
Batch: testBatch,
|
||||
})
|
||||
s.Equal(EnvelopePosted, s.monitor.envelopes[testHash])
|
||||
s.monitor.handleEvent(types.EnvelopeEvent{
|
||||
Event: types.EventBatchAcknowledged,
|
||||
Batch: testBatch,
|
||||
Peer: types.EnodeID(node.ID()),
|
||||
})
|
||||
s.Contains(s.monitor.envelopes, testHash)
|
||||
s.Equal(EnvelopeSent, s.monitor.envelopes[testHash])
|
||||
}
|
||||
|
||||
func (s *EnvelopesMonitorSuite) TestIgnored() {
|
||||
s.monitor.handleEvent(types.EnvelopeEvent{
|
||||
Event: types.EventEnvelopeSent,
|
||||
Hash: testHash,
|
||||
})
|
||||
s.NotContains(s.monitor.envelopes, testHash)
|
||||
}
|
||||
|
||||
func (s *EnvelopesMonitorSuite) TestRemoved() {
|
||||
s.monitor.Add(testIDs, testHash, types.NewMessage{})
|
||||
s.Contains(s.monitor.envelopes, testHash)
|
||||
s.monitor.handleEvent(types.EnvelopeEvent{
|
||||
Event: types.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(testIDs, testHash, types.NewMessage{})
|
||||
s.monitor.handleEvent(types.EnvelopeEvent{
|
||||
Event: types.EventEnvelopeSent,
|
||||
Hash: testHash,
|
||||
Peer: types.EnodeID{1}, // could be empty, doesn't impact test behaviour
|
||||
})
|
||||
s.Require().Equal(EnvelopePosted, s.monitor.GetState(testHash))
|
||||
}
|
||||
|
||||
func (s *EnvelopesMonitorSuite) TestReceived() {
|
||||
s.monitor.isMailserver = func(peer types.EnodeID) bool {
|
||||
return true
|
||||
}
|
||||
s.monitor.Add(testIDs, testHash, types.NewMessage{})
|
||||
s.Contains(s.monitor.envelopes, testHash)
|
||||
s.monitor.handleEvent(types.EnvelopeEvent{
|
||||
Event: types.EventEnvelopeReceived,
|
||||
Hash: testHash,
|
||||
})
|
||||
s.Require().Equal(EnvelopeSent, s.monitor.GetState(testHash))
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package waku
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
)
|
||||
|
||||
func createMessagesRequest(from, to uint32, cursor []byte, topics []types.TopicType) types.MessagesRequest {
|
||||
aUUID := uuid.New()
|
||||
// uuid is 16 bytes, converted to hex it's 32 bytes as expected by types.MessagesRequest
|
||||
id := []byte(hex.EncodeToString(aUUID[:]))
|
||||
return types.MessagesRequest{
|
||||
ID: id,
|
||||
From: from,
|
||||
To: to,
|
||||
Limit: 100,
|
||||
Cursor: cursor,
|
||||
Bloom: topicsToBloom(topics...),
|
||||
}
|
||||
}
|
||||
|
||||
func topicsToBloom(topics ...types.TopicType) []byte {
|
||||
i := new(big.Int)
|
||||
for _, topic := range topics {
|
||||
bloom := types.TopicToBloom(topic)
|
||||
i.Or(i, new(big.Int).SetBytes(bloom[:]))
|
||||
}
|
||||
|
||||
combined := make([]byte, types.BloomFilterSize)
|
||||
data := i.Bytes()
|
||||
copy(combined[types.BloomFilterSize-len(data):], data[:])
|
||||
|
||||
return combined
|
||||
}
|
|
@ -0,0 +1,319 @@
|
|||
// Code generated by go-bindata. DO NOT EDIT.
|
||||
// sources:
|
||||
// 1561059284_add_waku_keys.down.sql (22B)
|
||||
// 1561059284_add_waku_keys.up.sql (109B)
|
||||
// doc.go (373B)
|
||||
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func bindataRead(data []byte, name string) ([]byte, error) {
|
||||
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read %q: %v", name, err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
_, err = io.Copy(&buf, gz)
|
||||
clErr := gz.Close()
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read %q: %v", name, err)
|
||||
}
|
||||
if clErr != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
type asset struct {
|
||||
bytes []byte
|
||||
info os.FileInfo
|
||||
digest [sha256.Size]byte
|
||||
}
|
||||
|
||||
type bindataFileInfo struct {
|
||||
name string
|
||||
size int64
|
||||
mode os.FileMode
|
||||
modTime time.Time
|
||||
}
|
||||
|
||||
func (fi bindataFileInfo) Name() string {
|
||||
return fi.name
|
||||
}
|
||||
func (fi bindataFileInfo) Size() int64 {
|
||||
return fi.size
|
||||
}
|
||||
func (fi bindataFileInfo) Mode() os.FileMode {
|
||||
return fi.mode
|
||||
}
|
||||
func (fi bindataFileInfo) ModTime() time.Time {
|
||||
return fi.modTime
|
||||
}
|
||||
func (fi bindataFileInfo) IsDir() bool {
|
||||
return false
|
||||
}
|
||||
func (fi bindataFileInfo) Sys() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
var __1561059284_add_waku_keysDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\x09\xf2\x0f\x50\x08\x71\x74\xf2\x71\x55\x28\x4f\xcc\x2e\x8d\xcf\x4e\xad\x2c\xb6\xe6\x02\x04\x00\x00\xff\xff\x4f\x00\xe6\x8e\x16\x00\x00\x00")
|
||||
|
||||
func _1561059284_add_waku_keysDownSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
__1561059284_add_waku_keysDownSql,
|
||||
"1561059284_add_waku_keys.down.sql",
|
||||
)
|
||||
}
|
||||
|
||||
func _1561059284_add_waku_keysDownSql() (*asset, error) {
|
||||
bytes, err := _1561059284_add_waku_keysDownSqlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561059284_add_waku_keys.down.sql", size: 22, mode: os.FileMode(0644), modTime: time.Unix(1578604329, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe5, 0x2a, 0x7e, 0x9, 0xa3, 0xdd, 0xc6, 0x3, 0xfa, 0xaa, 0x98, 0xa0, 0x26, 0x5e, 0x67, 0x43, 0xe6, 0x20, 0xfd, 0x10, 0xfd, 0x60, 0x89, 0x17, 0x13, 0x87, 0x1b, 0x44, 0x36, 0x79, 0xb6, 0x60}}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var __1561059284_add_waku_keysUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x04\xc0\xb1\x0a\xc2\x40\x0c\x06\xe0\xfd\x9e\xe2\x1f\x15\x7c\x03\xa7\xbb\x33\x6a\x30\x26\x12\x52\x6a\xa7\x52\xb4\xa0\xdc\xa8\x22\x7d\xfb\x7e\xd5\x29\x07\x21\x72\x11\xc2\x7f\x6a\xbf\xb1\xcd\xcb\x07\x9b\x04\x3c\x5e\xd3\x77\x7c\x3f\x11\x74\x0f\xdc\x9c\xaf\xd9\x07\x5c\x68\x80\x29\xaa\xe9\x51\xb8\x06\xf8\xa4\xe6\xb4\x4b\x40\x9b\x17\x14\xb1\x02\xb5\x80\x76\x22\x69\x8b\x9e\xe3\x6c\x5d\xc0\xad\xe7\xc3\x3e\xad\x01\x00\x00\xff\xff\xbc\x45\x31\x54\x6d\x00\x00\x00")
|
||||
|
||||
func _1561059284_add_waku_keysUpSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
__1561059284_add_waku_keysUpSql,
|
||||
"1561059284_add_waku_keys.up.sql",
|
||||
)
|
||||
}
|
||||
|
||||
func _1561059284_add_waku_keysUpSql() (*asset, error) {
|
||||
bytes, err := _1561059284_add_waku_keysUpSqlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561059284_add_waku_keys.up.sql", size: 109, mode: os.FileMode(0644), modTime: time.Unix(1578604337, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa9, 0x5c, 0x8, 0x32, 0xef, 0x12, 0x88, 0x21, 0xd, 0x7a, 0x42, 0x4d, 0xe7, 0x2d, 0x6c, 0x99, 0xb6, 0x1, 0xf1, 0xba, 0x2c, 0x40, 0x8d, 0xa9, 0x4b, 0xe6, 0xc4, 0x21, 0xec, 0x47, 0x6b, 0xf7}}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _docGo = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x8f\x3d\x72\xeb\x30\x0c\x84\x7b\x9d\x62\xc7\x8d\x9b\x27\xb2\x79\x55\xba\x94\xe9\x73\x01\x98\x5a\x91\x18\x4b\xa4\x42\xc0\x7f\xb7\xcf\xc8\xe3\xc2\x5d\xda\x1d\x7c\x1f\x76\x63\xc4\x77\x51\xc3\xac\x0b\xa1\x86\xca\x44\x33\xe9\x0f\x9c\x98\xe4\x62\xc4\x21\xab\x97\xcb\x29\xa4\xb6\x46\x73\xf1\x8b\x8d\xba\xc6\x55\x73\x17\x67\xbc\xfe\x3f\x0c\x31\x22\x49\x3d\x3a\x8a\xd4\x69\xe1\xd3\x65\x30\x97\xee\x5a\x33\x6e\xea\x05\x82\xad\x73\xd6\x7b\xc0\xa7\x63\xa1\x98\xc3\x8b\xf8\xd1\xe0\x85\x48\x62\xdc\x35\x73\xeb\xc8\x6d\x3c\x69\x9d\xc4\x25\xec\xd1\xd7\xfc\x96\xec\x0d\x93\x2c\x0b\x27\xcc\xbd\xad\x4f\xd6\x64\x25\x26\xed\x4c\xde\xfa\xe3\x1f\xc4\x8c\x8e\x2a\x2b\x6d\xe7\x8b\x5c\x89\xda\x5e\xef\x21\x75\xfa\x7b\x11\x6e\xad\x9f\x0d\x62\xe0\x7d\x63\x72\x4e\x61\x18\x36\x49\x67\xc9\x84\xfd\x2c\xea\x1c\x86\x18\x73\xfb\xc8\xac\xdc\xa9\xf7\x8e\xe3\x76\xce\xaf\x2b\x8c\x0d\x21\xbc\xd4\xda\xaa\x85\xdc\x10\x86\xdf\x00\x00\x00\xff\xff\x21\xa5\x75\x05\x75\x01\x00\x00")
|
||||
|
||||
func docGoBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_docGo,
|
||||
"doc.go",
|
||||
)
|
||||
}
|
||||
|
||||
func docGo() (*asset, error) {
|
||||
bytes, err := docGoBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "doc.go", size: 373, mode: os.FileMode(0644), modTime: time.Unix(1578604293, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x23, 0x6a, 0xc1, 0xce, 0x94, 0xf6, 0xef, 0xf1, 0x97, 0x95, 0xb, 0x35, 0xaf, 0x5f, 0xe7, 0x5f, 0xac, 0x6e, 0xb8, 0xab, 0xba, 0xb5, 0x35, 0x97, 0x22, 0x36, 0x11, 0xce, 0x44, 0xfc, 0xfa, 0xac}}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// Asset loads and returns the asset for the given name.
|
||||
// It returns an error if the asset could not be found or
|
||||
// could not be loaded.
|
||||
func Asset(name string) ([]byte, error) {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[canonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
|
||||
}
|
||||
return a.bytes, nil
|
||||
}
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
|
||||
// AssetString returns the asset contents as a string (instead of a []byte).
|
||||
func AssetString(name string) (string, error) {
|
||||
data, err := Asset(name)
|
||||
return string(data), err
|
||||
}
|
||||
|
||||
// MustAsset is like Asset but panics when Asset would return an error.
|
||||
// It simplifies safe initialization of global variables.
|
||||
func MustAsset(name string) []byte {
|
||||
a, err := Asset(name)
|
||||
if err != nil {
|
||||
panic("asset: Asset(" + name + "): " + err.Error())
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// MustAssetString is like AssetString but panics when Asset would return an
|
||||
// error. It simplifies safe initialization of global variables.
|
||||
func MustAssetString(name string) string {
|
||||
return string(MustAsset(name))
|
||||
}
|
||||
|
||||
// AssetInfo loads and returns the asset info for the given name.
|
||||
// It returns an error if the asset could not be found or
|
||||
// could not be loaded.
|
||||
func AssetInfo(name string) (os.FileInfo, error) {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[canonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
|
||||
}
|
||||
return a.info, nil
|
||||
}
|
||||
return nil, fmt.Errorf("AssetInfo %s not found", name)
|
||||
}
|
||||
|
||||
// AssetDigest returns the digest of the file with the given name. It returns an
|
||||
// error if the asset could not be found or the digest could not be loaded.
|
||||
func AssetDigest(name string) ([sha256.Size]byte, error) {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[canonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err)
|
||||
}
|
||||
return a.digest, nil
|
||||
}
|
||||
return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name)
|
||||
}
|
||||
|
||||
// Digests returns a map of all known files and their checksums.
|
||||
func Digests() (map[string][sha256.Size]byte, error) {
|
||||
mp := make(map[string][sha256.Size]byte, len(_bindata))
|
||||
for name := range _bindata {
|
||||
a, err := _bindata[name]()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mp[name] = a.digest
|
||||
}
|
||||
return mp, nil
|
||||
}
|
||||
|
||||
// AssetNames returns the names of the assets.
|
||||
func AssetNames() []string {
|
||||
names := make([]string, 0, len(_bindata))
|
||||
for name := range _bindata {
|
||||
names = append(names, name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||
var _bindata = map[string]func() (*asset, error){
|
||||
"1561059284_add_waku_keys.down.sql": _1561059284_add_waku_keysDownSql,
|
||||
|
||||
"1561059284_add_waku_keys.up.sql": _1561059284_add_waku_keysUpSql,
|
||||
|
||||
"doc.go": docGo,
|
||||
}
|
||||
|
||||
// AssetDir returns the file names below a certain
|
||||
// directory embedded in the file by go-bindata.
|
||||
// For example if you run go-bindata on data/... and data contains the
|
||||
// following hierarchy:
|
||||
// data/
|
||||
// foo.txt
|
||||
// img/
|
||||
// a.png
|
||||
// b.png
|
||||
// then AssetDir("data") would return []string{"foo.txt", "img"},
|
||||
// AssetDir("data/img") would return []string{"a.png", "b.png"},
|
||||
// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and
|
||||
// AssetDir("") will return []string{"data"}.
|
||||
func AssetDir(name string) ([]string, error) {
|
||||
node := _bintree
|
||||
if len(name) != 0 {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
pathList := strings.Split(canonicalName, "/")
|
||||
for _, p := range pathList {
|
||||
node = node.Children[p]
|
||||
if node == nil {
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
if node.Func != nil {
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
rv := make([]string, 0, len(node.Children))
|
||||
for childName := range node.Children {
|
||||
rv = append(rv, childName)
|
||||
}
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
type bintree struct {
|
||||
Func func() (*asset, error)
|
||||
Children map[string]*bintree
|
||||
}
|
||||
|
||||
var _bintree = &bintree{nil, map[string]*bintree{
|
||||
"1561059284_add_waku_keys.down.sql": &bintree{_1561059284_add_waku_keysDownSql, map[string]*bintree{}},
|
||||
"1561059284_add_waku_keys.up.sql": &bintree{_1561059284_add_waku_keysUpSql, map[string]*bintree{}},
|
||||
"doc.go": &bintree{docGo, map[string]*bintree{}},
|
||||
}}
|
||||
|
||||
// RestoreAsset restores an asset under the given directory.
|
||||
func RestoreAsset(dir, name string) error {
|
||||
data, err := Asset(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info, err := AssetInfo(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
|
||||
}
|
||||
|
||||
// RestoreAssets restores an asset under the given directory recursively.
|
||||
func RestoreAssets(dir, name string) error {
|
||||
children, err := AssetDir(name)
|
||||
// File
|
||||
if err != nil {
|
||||
return RestoreAsset(dir, name)
|
||||
}
|
||||
// Dir
|
||||
for _, child := range children {
|
||||
err = RestoreAssets(dir, filepath.Join(name, child))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func _filePath(dir, name string) string {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...)
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
DROP TABLE waku_keys;
|
|
@ -0,0 +1,4 @@
|
|||
CREATE TABLE waku_keys (
|
||||
chat_id TEXT PRIMARY KEY ON CONFLICT IGNORE,
|
||||
key BLOB NOT NULL
|
||||
) WITHOUT ROWID;
|
|
@ -0,0 +1,9 @@
|
|||
// This file is necessary because "github.com/status-im/migrate/v4"
|
||||
// can't handle files starting with a prefix. At least that's the case
|
||||
// for go-bindata.
|
||||
// If go-bindata is called from the same directory, asset names
|
||||
// have no prefix and "github.com/status-im/migrate/v4" works as expected.
|
||||
|
||||
package sqlite
|
||||
|
||||
//go:generate go-bindata -pkg sqlite -o ../migrations.go .
|
|
@ -0,0 +1,57 @@
|
|||
package waku
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
type sqlitePersistence struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func newSQLitePersistence(db *sql.DB) *sqlitePersistence {
|
||||
return &sqlitePersistence{db: db}
|
||||
}
|
||||
|
||||
func (s *sqlitePersistence) Add(chatID string, key []byte) error {
|
||||
statement := "INSERT INTO waku_keys(chat_id, key) VALUES(?, ?)"
|
||||
stmt, err := s.db.Prepare(statement)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
_, err = stmt.Exec(chatID, key)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *sqlitePersistence) All() (map[string][]byte, error) {
|
||||
keys := make(map[string][]byte)
|
||||
|
||||
statement := "SELECT chat_id, key FROM waku_keys"
|
||||
|
||||
stmt, err := s.db.Prepare(statement)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
rows, err := stmt.Query()
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for rows.Next() {
|
||||
var (
|
||||
chatID string
|
||||
key []byte
|
||||
)
|
||||
|
||||
err := rows.Scan(&chatID, &key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keys[chatID] = key
|
||||
}
|
||||
|
||||
return keys, nil
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package waku
|
||||
|
||||
import (
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
)
|
||||
|
||||
type RequestOptions struct {
|
||||
Topics []types.TopicType
|
||||
Password string
|
||||
Limit int
|
||||
From int64 // in seconds
|
||||
To int64 // in seconds
|
||||
}
|
|
@ -0,0 +1,426 @@
|
|||
package waku
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"database/sql"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/protocol/transport"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNoMailservers returned if there is no configured mailservers that can be used.
|
||||
ErrNoMailservers = errors.New("no configured mailservers")
|
||||
)
|
||||
|
||||
type wakuServiceKeysManager struct {
|
||||
waku types.Waku
|
||||
|
||||
// Identity of the current user.
|
||||
privateKey *ecdsa.PrivateKey
|
||||
|
||||
passToSymKeyMutex sync.RWMutex
|
||||
passToSymKeyCache map[string]string
|
||||
}
|
||||
|
||||
func (m *wakuServiceKeysManager) AddOrGetKeyPair(priv *ecdsa.PrivateKey) (string, error) {
|
||||
// caching is handled in waku
|
||||
return m.waku.AddKeyPair(priv)
|
||||
}
|
||||
|
||||
func (m *wakuServiceKeysManager) AddOrGetSymKeyFromPassword(password string) (string, error) {
|
||||
m.passToSymKeyMutex.Lock()
|
||||
defer m.passToSymKeyMutex.Unlock()
|
||||
|
||||
if val, ok := m.passToSymKeyCache[password]; ok {
|
||||
return val, nil
|
||||
}
|
||||
|
||||
id, err := m.waku.AddSymKeyFromPassword(password)
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
|
||||
m.passToSymKeyCache[password] = id
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (m *wakuServiceKeysManager) RawSymKey(id string) ([]byte, error) {
|
||||
return m.waku.GetSymKey(id)
|
||||
}
|
||||
|
||||
type Option func(*WakuServiceTransport) error
|
||||
|
||||
// WakuServiceTransport is a transport based on Whisper service.
|
||||
type WakuServiceTransport struct {
|
||||
waku types.Waku
|
||||
api types.PublicWakuAPI // only PublicWakuAPI implements logic to send messages
|
||||
keysManager *wakuServiceKeysManager
|
||||
filters *transport.FiltersManager
|
||||
logger *zap.Logger
|
||||
|
||||
mailservers []string
|
||||
envelopesMonitor *EnvelopesMonitor
|
||||
}
|
||||
|
||||
// NewWakuServiceTransport returns a new WakuServiceTransport.
|
||||
// TODO: leaving a chat should verify that for a given public key
|
||||
// there are no other chats. It may happen that we leave a private chat
|
||||
// but still have a public chat for a given public key.
|
||||
func NewWakuServiceTransport(
|
||||
waku types.Waku,
|
||||
privateKey *ecdsa.PrivateKey,
|
||||
db *sql.DB,
|
||||
mailservers []string,
|
||||
envelopesMonitorConfig *transport.EnvelopesMonitorConfig,
|
||||
logger *zap.Logger,
|
||||
opts ...Option,
|
||||
) (*WakuServiceTransport, error) {
|
||||
filtersManager, err := transport.NewFiltersManager(newSQLitePersistence(db), waku, privateKey, logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var envelopesMonitor *EnvelopesMonitor
|
||||
if envelopesMonitorConfig != nil {
|
||||
envelopesMonitor = NewEnvelopesMonitor(waku, *envelopesMonitorConfig)
|
||||
envelopesMonitor.Start()
|
||||
}
|
||||
|
||||
var api types.PublicWhisperAPI
|
||||
if waku != nil {
|
||||
api = waku.PublicWakuAPI()
|
||||
}
|
||||
t := &WakuServiceTransport{
|
||||
waku: waku,
|
||||
api: api,
|
||||
envelopesMonitor: envelopesMonitor,
|
||||
keysManager: &wakuServiceKeysManager{
|
||||
waku: waku,
|
||||
privateKey: privateKey,
|
||||
passToSymKeyCache: make(map[string]string),
|
||||
},
|
||||
filters: filtersManager,
|
||||
mailservers: mailservers,
|
||||
logger: logger.With(zap.Namespace("WakuServiceTransport")),
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
if err := opt(t); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) InitFilters(chatIDs []string, publicKeys []*ecdsa.PublicKey) ([]*transport.Filter, error) {
|
||||
return a.filters.Init(chatIDs, publicKeys)
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) Filters() []*transport.Filter {
|
||||
return a.filters.Filters()
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
func (a *WakuServiceTransport) LoadFilters(filters []*transport.Filter) ([]*transport.Filter, error) {
|
||||
return a.filters.InitWithFilters(filters)
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
func (a *WakuServiceTransport) RemoveFilters(filters []*transport.Filter) error {
|
||||
return a.filters.Remove(filters...)
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) ResetFilters() error {
|
||||
return a.filters.Reset()
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) ProcessNegotiatedSecret(secret types.NegotiatedSecret) (*transport.Filter, error) {
|
||||
filter, err := a.filters.LoadNegotiated(secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return filter, nil
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) JoinPublic(chatID string) error {
|
||||
_, err := a.filters.LoadPublic(chatID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) LeavePublic(chatID string) error {
|
||||
chat := a.filters.Filter(chatID)
|
||||
if chat != nil {
|
||||
return nil
|
||||
}
|
||||
return a.filters.Remove(chat)
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) JoinPrivate(publicKey *ecdsa.PublicKey) error {
|
||||
_, err := a.filters.LoadDiscovery()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = a.filters.LoadContactCode(publicKey)
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) LeavePrivate(publicKey *ecdsa.PublicKey) error {
|
||||
filters := a.filters.FiltersByPublicKey(publicKey)
|
||||
return a.filters.Remove(filters...)
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) JoinGroup(publicKeys []*ecdsa.PublicKey) error {
|
||||
_, err := a.filters.LoadDiscovery()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, pk := range publicKeys {
|
||||
_, err = a.filters.LoadContactCode(pk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) LeaveGroup(publicKeys []*ecdsa.PublicKey) error {
|
||||
for _, publicKey := range publicKeys {
|
||||
filters := a.filters.FiltersByPublicKey(publicKey)
|
||||
if err := a.filters.Remove(filters...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
Message *types.Message
|
||||
Public bool
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) RetrieveAllMessages() ([]Message, error) {
|
||||
var messages []Message
|
||||
|
||||
for _, filter := range a.filters.Filters() {
|
||||
filterMsgs, err := a.api.GetFilterMessages(filter.FilterID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, m := range filterMsgs {
|
||||
messages = append(messages, Message{
|
||||
Message: m,
|
||||
Public: filter.IsPublic(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) RetrievePublicMessages(chatID string) ([]*types.Message, error) {
|
||||
filter, err := a.filters.LoadPublic(chatID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return a.api.GetFilterMessages(filter.FilterID)
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) RetrievePrivateMessages(publicKey *ecdsa.PublicKey) ([]*types.Message, error) {
|
||||
chats := a.filters.FiltersByPublicKey(publicKey)
|
||||
discoveryChats, err := a.filters.Init(nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []*types.Message
|
||||
|
||||
for _, chat := range append(chats, discoveryChats...) {
|
||||
filterMsgs, err := a.api.GetFilterMessages(chat.FilterID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result = append(result, filterMsgs...)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) RetrieveRawAll() (map[transport.Filter][]*types.Message, error) {
|
||||
result := make(map[transport.Filter][]*types.Message)
|
||||
|
||||
allFilters := a.filters.Filters()
|
||||
for _, filter := range allFilters {
|
||||
msgs, err := a.api.GetFilterMessages(filter.FilterID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
result[*filter] = append(result[*filter], msgs...)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SendPublic sends a new message using the Whisper service.
|
||||
// For public filters, chat name is used as an ID as well as
|
||||
// a topic.
|
||||
func (a *WakuServiceTransport) SendPublic(ctx context.Context, newMessage *types.NewMessage, chatName string) ([]byte, error) {
|
||||
if err := a.addSig(newMessage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
filter, err := a.filters.LoadPublic(chatName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newMessage.SymKeyID = filter.SymKeyID
|
||||
newMessage.Topic = filter.Topic
|
||||
|
||||
return a.api.Post(ctx, *newMessage)
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) SendPrivateWithSharedSecret(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey, secret []byte) ([]byte, error) {
|
||||
if err := a.addSig(newMessage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
filter, err := a.filters.LoadNegotiated(types.NegotiatedSecret{
|
||||
PublicKey: publicKey,
|
||||
Key: secret,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newMessage.SymKeyID = filter.SymKeyID
|
||||
newMessage.Topic = filter.Topic
|
||||
newMessage.PublicKey = nil
|
||||
|
||||
return a.api.Post(ctx, *newMessage)
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) SendPrivateWithPartitioned(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error) {
|
||||
if err := a.addSig(newMessage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
filter, err := a.filters.LoadPartitioned(publicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newMessage.Topic = filter.Topic
|
||||
newMessage.PublicKey = crypto.FromECDSAPub(publicKey)
|
||||
|
||||
return a.api.Post(ctx, *newMessage)
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) SendPrivateOnDiscovery(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error) {
|
||||
if err := a.addSig(newMessage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// There is no need to load any chat
|
||||
// because listening on the discovery topic
|
||||
// is done automatically.
|
||||
// TODO: change this anyway, it should be explicit
|
||||
// and idempotent.
|
||||
|
||||
newMessage.Topic = types.BytesToTopic(transport.ToTopic(transport.DiscoveryTopic()))
|
||||
newMessage.PublicKey = crypto.FromECDSAPub(publicKey)
|
||||
|
||||
return a.api.Post(ctx, *newMessage)
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) addSig(newMessage *types.NewMessage) error {
|
||||
sigID, err := a.keysManager.AddOrGetKeyPair(a.keysManager.privateKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newMessage.SigID = sigID
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) Track(identifiers [][]byte, hash []byte, newMessage *types.NewMessage) {
|
||||
if a.envelopesMonitor != nil {
|
||||
a.envelopesMonitor.Add(identifiers, types.BytesToHash(hash), *newMessage)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) Stop() error {
|
||||
if a.envelopesMonitor != nil {
|
||||
a.envelopesMonitor.Stop()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RequestHistoricMessages requests historic messages for all registered filters.
|
||||
func (a *WakuServiceTransport) SendMessagesRequest(
|
||||
ctx context.Context,
|
||||
peerID []byte,
|
||||
from, to uint32,
|
||||
previousCursor []byte,
|
||||
) (cursor []byte, err error) {
|
||||
topics := make([]types.TopicType, len(a.Filters()))
|
||||
for _, f := range a.Filters() {
|
||||
topics = append(topics, f.Topic)
|
||||
}
|
||||
|
||||
r := createMessagesRequest(from, to, previousCursor, topics)
|
||||
r.SetDefaults(a.waku.GetCurrentTime())
|
||||
|
||||
events := make(chan types.EnvelopeEvent, 10)
|
||||
sub := a.waku.SubscribeEnvelopeEvents(events)
|
||||
defer sub.Unsubscribe()
|
||||
|
||||
err = a.waku.SendMessagesRequest(peerID, r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := a.waitForRequestCompleted(ctx, r.ID, events)
|
||||
if err == nil && resp != nil && resp.Error != nil {
|
||||
err = resp.Error
|
||||
} else if err == nil && resp != nil {
|
||||
cursor = resp.Cursor
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) waitForRequestCompleted(ctx context.Context, requestID []byte, events chan types.EnvelopeEvent) (*types.MailServerResponse, error) {
|
||||
for {
|
||||
select {
|
||||
case ev := <-events:
|
||||
a.logger.Debug(
|
||||
"waiting for request completed and received an event",
|
||||
zap.Binary("requestID", requestID),
|
||||
zap.Any("event", ev),
|
||||
)
|
||||
if !bytes.Equal(ev.Hash.Bytes(), requestID) {
|
||||
continue
|
||||
}
|
||||
if ev.Event != types.EventMailServerRequestCompleted {
|
||||
continue
|
||||
}
|
||||
data, ok := ev.Data.(*types.MailServerResponse)
|
||||
if ok {
|
||||
return data, nil
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package waku
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/status-im/status-go/protocol/sqlite"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/status-im/status-go/protocol/tt"
|
||||
)
|
||||
|
||||
func TestNewWakuServiceTransport(t *testing.T) {
|
||||
dbPath, err := ioutil.TempFile("", "transport.sql")
|
||||
require.NoError(t, err)
|
||||
defer os.Remove(dbPath.Name())
|
||||
db, err := sqlite.Open(dbPath.Name(), "some-key")
|
||||
require.NoError(t, err)
|
||||
|
||||
logger := tt.MustCreateTestLogger()
|
||||
require.NoError(t, err)
|
||||
defer func() { _ = logger.Sync() }()
|
||||
|
||||
_, err = NewWakuServiceTransport(nil, nil, db, nil, nil, logger)
|
||||
require.NoError(t, err)
|
||||
}
|
|
@ -5,6 +5,8 @@ import (
|
|||
"errors"
|
||||
"sync"
|
||||
|
||||
"github.com/status-im/status-go/protocol/transport"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
|
@ -18,18 +20,10 @@ const (
|
|||
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 is set when envelope is sent to at least one peer.
|
||||
EnvelopeSent
|
||||
)
|
||||
|
||||
type EnvelopesMonitorConfig struct {
|
||||
EnvelopeEventsHandler EnvelopeEventsHandler
|
||||
MaxAttempts int
|
||||
MailserverConfirmationsEnabled bool
|
||||
IsMailserver func(types.EnodeID) bool
|
||||
Logger *zap.Logger
|
||||
}
|
||||
|
||||
// EnvelopeEventsHandler used for two different event types.
|
||||
type EnvelopeEventsHandler interface {
|
||||
EnvelopeSent([][]byte)
|
||||
|
@ -39,7 +33,7 @@ type EnvelopeEventsHandler interface {
|
|||
}
|
||||
|
||||
// NewEnvelopesMonitor returns a pointer to an instance of the EnvelopesMonitor.
|
||||
func NewEnvelopesMonitor(w types.Whisper, config EnvelopesMonitorConfig) *EnvelopesMonitor {
|
||||
func NewEnvelopesMonitor(w types.Whisper, config transport.EnvelopesMonitorConfig) *EnvelopesMonitor {
|
||||
logger := config.Logger
|
||||
|
||||
if logger == nil {
|
||||
|
|
|
@ -9,8 +9,6 @@ import (
|
|||
"github.com/status-im/status-go/eth-node/types"
|
||||
)
|
||||
|
||||
const defaultMessagesRequestLimit = 100
|
||||
|
||||
func createMessagesRequest(from, to uint32, cursor []byte, topics []types.TopicType) types.MessagesRequest {
|
||||
aUUID := uuid.New()
|
||||
// uuid is 16 bytes, converted to hex it's 32 bytes as expected by types.MessagesRequest
|
||||
|
@ -19,7 +17,7 @@ func createMessagesRequest(from, to uint32, cursor []byte, topics []types.TopicT
|
|||
ID: id,
|
||||
From: from,
|
||||
To: to,
|
||||
Limit: defaultMessagesRequestLimit,
|
||||
Limit: 100,
|
||||
Cursor: cursor,
|
||||
Bloom: topicsToBloom(topics...),
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ func _1561059285_add_whisper_keysDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561059285_add_whisper_keys.down.sql", size: 25, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1561059285_add_whisper_keys.down.sql", size: 25, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb9, 0x31, 0x3f, 0xce, 0xfa, 0x44, 0x36, 0x1b, 0xb0, 0xec, 0x5d, 0xb, 0x90, 0xb, 0x21, 0x4f, 0xd5, 0xe5, 0x50, 0xed, 0xc7, 0x43, 0xdf, 0x83, 0xb4, 0x3a, 0xc1, 0x55, 0x2e, 0x53, 0x7c, 0x67}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ func _1561059285_add_whisper_keysUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561059285_add_whisper_keys.up.sql", size: 112, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1561059285_add_whisper_keys.up.sql", size: 112, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x25, 0x41, 0xc, 0x92, 0xdd, 0x9e, 0xff, 0x5d, 0xd0, 0x93, 0xe4, 0x24, 0x50, 0x29, 0xcf, 0xc6, 0xf7, 0x49, 0x3c, 0x73, 0xd9, 0x8c, 0xfa, 0xf2, 0xcf, 0xf6, 0x6f, 0xbc, 0x31, 0xe6, 0xf7, 0xe2}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func docGo() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "doc.go", size: 373, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "doc.go", size: 373, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x23, 0x6a, 0xc1, 0xce, 0x94, 0xf6, 0xef, 0xf1, 0x97, 0x95, 0xb, 0x35, 0xaf, 0x5f, 0xe7, 0x5f, 0xac, 0x6e, 0xb8, 0xab, 0xba, 0xb5, 0x35, 0x97, 0x22, 0x36, 0x11, 0xce, 0x44, 0xfc, 0xfa, 0xac}}
|
||||
return a, nil
|
||||
}
|
||||
|
|
|
@ -11,17 +11,3 @@ type RequestOptions struct {
|
|||
From int64 // in seconds
|
||||
To int64 // in seconds
|
||||
}
|
||||
|
||||
const (
|
||||
defaultPowTime = 1
|
||||
)
|
||||
|
||||
func DefaultWhisperMessage() types.NewMessage {
|
||||
msg := types.NewMessage{}
|
||||
|
||||
msg.TTL = 10
|
||||
msg.PowTarget = 0.002
|
||||
msg.PowTime = defaultPowTime
|
||||
|
||||
return msg
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/protocol/transport"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -63,7 +64,7 @@ type WhisperServiceTransport struct {
|
|||
shh types.Whisper
|
||||
shhAPI types.PublicWhisperAPI // only PublicWhisperAPI implements logic to send messages
|
||||
keysManager *whisperServiceKeysManager
|
||||
filters *filtersManager
|
||||
filters *transport.FiltersManager
|
||||
logger *zap.Logger
|
||||
|
||||
mailservers []string
|
||||
|
@ -79,11 +80,11 @@ func NewWhisperServiceTransport(
|
|||
privateKey *ecdsa.PrivateKey,
|
||||
db *sql.DB,
|
||||
mailservers []string,
|
||||
envelopesMonitorConfig *EnvelopesMonitorConfig,
|
||||
envelopesMonitorConfig *transport.EnvelopesMonitorConfig,
|
||||
logger *zap.Logger,
|
||||
opts ...Option,
|
||||
) (*WhisperServiceTransport, error) {
|
||||
filtersManager, err := newFiltersManager(db, shh, privateKey, logger)
|
||||
filtersManager, err := transport.NewFiltersManager(newSQLitePersistence(db), shh, privateKey, logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -121,29 +122,29 @@ func NewWhisperServiceTransport(
|
|||
return t, nil
|
||||
}
|
||||
|
||||
func (a *WhisperServiceTransport) InitFilters(chatIDs []string, publicKeys []*ecdsa.PublicKey) ([]*Filter, error) {
|
||||
func (a *WhisperServiceTransport) InitFilters(chatIDs []string, publicKeys []*ecdsa.PublicKey) ([]*transport.Filter, error) {
|
||||
return a.filters.Init(chatIDs, publicKeys)
|
||||
}
|
||||
|
||||
func (a *WhisperServiceTransport) Filters() []*Filter {
|
||||
func (a *WhisperServiceTransport) Filters() []*transport.Filter {
|
||||
return a.filters.Filters()
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
func (a *WhisperServiceTransport) LoadFilters(filters []*Filter) ([]*Filter, error) {
|
||||
func (a *WhisperServiceTransport) LoadFilters(filters []*transport.Filter) ([]*transport.Filter, error) {
|
||||
return a.filters.InitWithFilters(filters)
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
func (a *WhisperServiceTransport) RemoveFilters(filters []*Filter) error {
|
||||
func (a *WhisperServiceTransport) RemoveFilters(filters []*transport.Filter) error {
|
||||
return a.filters.Remove(filters...)
|
||||
}
|
||||
|
||||
func (a *WhisperServiceTransport) Reset() error {
|
||||
func (a *WhisperServiceTransport) ResetFilters() error {
|
||||
return a.filters.Reset()
|
||||
}
|
||||
|
||||
func (a *WhisperServiceTransport) ProcessNegotiatedSecret(secret types.NegotiatedSecret) (*Filter, error) {
|
||||
func (a *WhisperServiceTransport) ProcessNegotiatedSecret(secret types.NegotiatedSecret) (*transport.Filter, error) {
|
||||
filter, err := a.filters.LoadNegotiated(secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -257,8 +258,8 @@ func (a *WhisperServiceTransport) RetrievePrivateMessages(publicKey *ecdsa.Publi
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (a *WhisperServiceTransport) RetrieveRawAll() (map[Filter][]*types.Message, error) {
|
||||
result := make(map[Filter][]*types.Message)
|
||||
func (a *WhisperServiceTransport) RetrieveRawAll() (map[transport.Filter][]*types.Message, error) {
|
||||
result := make(map[transport.Filter][]*types.Message)
|
||||
|
||||
allFilters := a.filters.Filters()
|
||||
for _, filter := range allFilters {
|
||||
|
@ -338,9 +339,7 @@ func (a *WhisperServiceTransport) SendPrivateOnDiscovery(ctx context.Context, ne
|
|||
// TODO: change this anyway, it should be explicit
|
||||
// and idempotent.
|
||||
|
||||
newMessage.Topic = types.BytesToTopic(
|
||||
ToTopic(discoveryTopic),
|
||||
)
|
||||
newMessage.Topic = types.BytesToTopic(transport.ToTopic(transport.DiscoveryTopic()))
|
||||
newMessage.PublicKey = crypto.FromECDSAPub(publicKey)
|
||||
|
||||
return a.shhAPI.Post(ctx, *newMessage)
|
||||
|
|
|
@ -21,7 +21,7 @@ import (
|
|||
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
statustransp "github.com/status-im/status-go/protocol/transport/whisper"
|
||||
"github.com/status-im/status-go/protocol/transport"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -429,7 +429,7 @@ func (s *Service) addressString() string {
|
|||
|
||||
// postPing publishes a whisper message
|
||||
func (s *Service) postPing() (types.HexBytes, error) {
|
||||
msg := statustransp.DefaultWhisperMessage()
|
||||
msg := transport.DefaultMessage()
|
||||
|
||||
msg.Topic = toWhisperTopic(defaultTopic)
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ import (
|
|||
enstypes "github.com/status-im/status-go/eth-node/types/ens"
|
||||
"github.com/status-im/status-go/protocol"
|
||||
"github.com/status-im/status-go/protocol/encryption/multidevice"
|
||||
statustransp "github.com/status-im/status-go/protocol/transport/whisper"
|
||||
"github.com/status-im/status-go/protocol/transport"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -601,7 +601,7 @@ func (api *PublicAPI) CompleteRequest(parent context.Context, hex string) (err e
|
|||
return err
|
||||
}
|
||||
|
||||
func (api *PublicAPI) LoadFilters(parent context.Context, chats []*statustransp.Filter) ([]*statustransp.Filter, error) {
|
||||
func (api *PublicAPI) LoadFilters(parent context.Context, chats []*transport.Filter) ([]*transport.Filter, error) {
|
||||
return api.service.messenger.LoadFilters(chats)
|
||||
}
|
||||
|
||||
|
@ -631,7 +631,7 @@ func (api *PublicAPI) Contacts(parent context.Context) []*protocol.Contact {
|
|||
return api.service.messenger.Contacts()
|
||||
}
|
||||
|
||||
func (api *PublicAPI) RemoveFilters(parent context.Context, chats []*statustransp.Filter) error {
|
||||
func (api *PublicAPI) RemoveFilters(parent context.Context, chats []*transport.Filter) error {
|
||||
return api.service.messenger.RemoveFilters(chats)
|
||||
}
|
||||
|
||||
|
@ -752,6 +752,7 @@ func makeEnvelop(
|
|||
pow float64,
|
||||
now time.Time,
|
||||
) (types.Envelope, error) {
|
||||
// TODO: replace with an types.Envelope creator passed to the API struct
|
||||
params := whisper.MessageParams{
|
||||
PoW: pow,
|
||||
Payload: payload,
|
||||
|
|
|
@ -32,8 +32,8 @@ import (
|
|||
|
||||
coretypes "github.com/status-im/status-go/eth-node/core/types"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
protocol "github.com/status-im/status-go/protocol"
|
||||
protocolwhisper "github.com/status-im/status-go/protocol/transport/whisper"
|
||||
"github.com/status-im/status-go/protocol"
|
||||
"github.com/status-im/status-go/protocol/transport"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -53,10 +53,10 @@ type EnvelopeEventsHandler interface {
|
|||
|
||||
// Service is a service that provides some additional Whisper API.
|
||||
type Service struct {
|
||||
messenger *protocol.Messenger
|
||||
identity *ecdsa.PrivateKey
|
||||
cancelMessenger chan struct{}
|
||||
|
||||
apiName string
|
||||
messenger *protocol.Messenger
|
||||
identity *ecdsa.PrivateKey
|
||||
cancelMessenger chan struct{}
|
||||
storage db.TransactionalStorage
|
||||
n types.Node
|
||||
w types.Whisper
|
||||
|
@ -77,7 +77,7 @@ type Service struct {
|
|||
var _ node.Service = (*Service)(nil)
|
||||
|
||||
// New returns a new shhext Service.
|
||||
func New(n types.Node, ctx interface{}, handler EnvelopeEventsHandler, ldb *leveldb.DB, config params.ShhextConfig) *Service {
|
||||
func New(n types.Node, ctx interface{}, apiName string, handler EnvelopeEventsHandler, ldb *leveldb.DB, config params.ShhextConfig) *Service {
|
||||
w, err := n.GetWhisper(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -97,6 +97,7 @@ func New(n types.Node, ctx interface{}, handler EnvelopeEventsHandler, ldb *leve
|
|||
requestsRegistry: requestsRegistry,
|
||||
}
|
||||
return &Service{
|
||||
apiName: apiName,
|
||||
storage: db.NewLevelDBStorage(ldb),
|
||||
n: n,
|
||||
w: w,
|
||||
|
@ -137,7 +138,7 @@ func (s *Service) InitProtocol(identity *ecdsa.PrivateKey, db *sql.DB) error { /
|
|||
return err
|
||||
}
|
||||
|
||||
envelopesMonitorConfig := &protocolwhisper.EnvelopesMonitorConfig{
|
||||
envelopesMonitorConfig := &transport.EnvelopesMonitorConfig{
|
||||
MaxAttempts: s.config.MaxMessageDeliveryAttempts,
|
||||
MailserverConfirmationsEnabled: s.config.MailServerConfirmations,
|
||||
IsMailserver: func(peer types.EnodeID) bool {
|
||||
|
@ -297,7 +298,7 @@ func (s *Service) Protocols() []p2p.Protocol {
|
|||
func (s *Service) APIs() []rpc.API {
|
||||
apis := []rpc.API{
|
||||
{
|
||||
Namespace: "shhext",
|
||||
Namespace: s.apiName,
|
||||
Version: "1.0",
|
||||
Service: NewPublicAPI(s),
|
||||
Public: true,
|
||||
|
@ -409,7 +410,7 @@ func (s *Service) syncMessages(ctx context.Context, mailServerID []byte, r types
|
|||
}
|
||||
}
|
||||
|
||||
func onNegotiatedFilters(filters []*protocolwhisper.Filter) {
|
||||
func onNegotiatedFilters(filters []*transport.Filter) {
|
||||
var signalFilters []*signal.Filter
|
||||
for _, filter := range filters {
|
||||
|
||||
|
@ -430,8 +431,12 @@ func onNegotiatedFilters(filters []*protocolwhisper.Filter) {
|
|||
}
|
||||
}
|
||||
|
||||
func buildMessengerOptions(config params.ShhextConfig, db *sql.DB, envelopesMonitorConfig *protocolwhisper.EnvelopesMonitorConfig, logger *zap.Logger) []protocol.Option {
|
||||
|
||||
func buildMessengerOptions(
|
||||
config params.ShhextConfig,
|
||||
db *sql.DB,
|
||||
envelopesMonitorConfig *transport.EnvelopesMonitorConfig,
|
||||
logger *zap.Logger,
|
||||
) []protocol.Option {
|
||||
options := []protocol.Option{
|
||||
protocol.WithCustomLogger(logger),
|
||||
protocol.WithDatabase(db),
|
||||
|
|
|
@ -139,7 +139,7 @@ func (s *ShhExtSuite) SetupTest() {
|
|||
db, err := leveldb.Open(storage.NewMemStorage(), nil)
|
||||
s.Require().NoError(err)
|
||||
nodeWrapper := &testNodeWrapper{w: s.whisperWrapper[i]}
|
||||
s.services[i] = New(nodeWrapper, nil, nil, db, config)
|
||||
s.services[i] = New(nodeWrapper, nil, "shhext", nil, db, config)
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "test-shhext-service")
|
||||
s.Require().NoError(err)
|
||||
|
@ -175,7 +175,7 @@ func (s *ShhExtSuite) TestInitProtocol() {
|
|||
s.Require().NoError(err)
|
||||
|
||||
nodeWrapper := &testNodeWrapper{w: shh}
|
||||
service := New(nodeWrapper, nil, nil, db, config)
|
||||
service := New(nodeWrapper, nil, "shhext", nil, db, config)
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "test-shhext-service-init-protocol")
|
||||
s.Require().NoError(err)
|
||||
|
@ -215,7 +215,7 @@ func (s *ShhExtSuite) TestRequestMessagesErrors() {
|
|||
PFSEnabled: true,
|
||||
}
|
||||
nodeWrapper := &testNodeWrapper{w: shh}
|
||||
service := New(nodeWrapper, nil, mock, nil, config)
|
||||
service := New(nodeWrapper, nil, "shhext", mock, nil, config)
|
||||
api := NewPublicAPI(service)
|
||||
|
||||
const (
|
||||
|
@ -321,7 +321,7 @@ func (s *ShhExtSuite) TestRequestMessagesSuccess() {
|
|||
PFSEnabled: true,
|
||||
}
|
||||
nodeWrapper := &testNodeWrapper{w: shh}
|
||||
service := New(nodeWrapper, nil, mock, nil, config)
|
||||
service := New(nodeWrapper, nil, "shhext", mock, nil, config)
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "test-shhext-service-request-messages")
|
||||
s.Require().NoError(err)
|
||||
|
@ -397,6 +397,10 @@ func (w *testNodeWrapper) GetWhisper(_ interface{}) (types.Whisper, error) {
|
|||
return w.w, nil
|
||||
}
|
||||
|
||||
func (w *testNodeWrapper) GetWaku(_ interface{}) (types.Waku, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (w *testNodeWrapper) AddPeer(url string) error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
@ -457,7 +461,14 @@ func (s *WhisperNodeMockSuite) SetupTest() {
|
|||
))
|
||||
|
||||
nodeWrapper := &testNodeWrapper{w: whisperWrapper}
|
||||
s.localService = New(nodeWrapper, nil, nil, db, params.ShhextConfig{MailServerConfirmations: true, MaxMessageDeliveryAttempts: 3})
|
||||
s.localService = New(
|
||||
nodeWrapper,
|
||||
nil,
|
||||
"shhext",
|
||||
nil,
|
||||
db,
|
||||
params.ShhextConfig{MailServerConfirmations: true, MaxMessageDeliveryAttempts: 3},
|
||||
)
|
||||
s.Require().NoError(s.localService.UpdateMailservers([]*enode.Node{node}))
|
||||
|
||||
s.localWhisperAPI = whisper.NewPublicWhisperAPI(w)
|
||||
|
@ -584,7 +595,7 @@ func (s *RequestWithTrackingHistorySuite) SetupTest() {
|
|||
|
||||
s.localWhisperAPI = local.PublicWhisperAPI()
|
||||
nodeWrapper := &testNodeWrapper{w: local}
|
||||
s.localService = New(nodeWrapper, nil, nil, db, params.ShhextConfig{})
|
||||
s.localService = New(nodeWrapper, nil, "shhext", nil, db, params.ShhextConfig{})
|
||||
s.localContext = NewContextFromService(context.Background(), s.localService, s.localService.storage)
|
||||
localPkey, err := crypto.GenerateKey()
|
||||
s.Require().NoError(err)
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -86,7 +86,7 @@ func configPublicChainAccountsJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "config/public-chain-accounts.json", size: 307, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
|
||||
info := bindataFileInfo{name: "config/public-chain-accounts.json", size: 307, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x76, 0x5d, 0xc0, 0xfe, 0x57, 0x50, 0x18, 0xec, 0x2d, 0x61, 0x1b, 0xa9, 0x81, 0x11, 0x5f, 0x77, 0xf7, 0xb6, 0x67, 0x82, 0x1, 0x40, 0x68, 0x9d, 0xc5, 0x41, 0xaf, 0xce, 0x43, 0x81, 0x92, 0x96}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ func configStatusChainAccountsJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "config/status-chain-accounts.json", size: 543, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
|
||||
info := bindataFileInfo{name: "config/status-chain-accounts.json", size: 543, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8e, 0xb3, 0x61, 0x51, 0x70, 0x3c, 0x12, 0x3e, 0xf1, 0x1c, 0x81, 0xfb, 0x9a, 0x7c, 0xe3, 0x63, 0xd0, 0x8f, 0x12, 0xc5, 0x2d, 0xf4, 0xea, 0x27, 0x33, 0xef, 0xca, 0xf9, 0x3f, 0x72, 0x44, 0xbf}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func configTestDataJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "config/test-data.json", size: 84, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)}
|
||||
info := bindataFileInfo{name: "config/test-data.json", size: 84, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xce, 0x9d, 0x80, 0xf5, 0x87, 0xfa, 0x57, 0x1d, 0xa1, 0xd5, 0x7a, 0x10, 0x3, 0xac, 0xd7, 0xf4, 0x64, 0x32, 0x96, 0x2b, 0xb7, 0x21, 0xb7, 0xa6, 0x80, 0x40, 0xe9, 0x65, 0xe3, 0xd6, 0xbd, 0x40}}
|
||||
return a, nil
|
||||
}
|
||||
|
|
|
@ -2,11 +2,25 @@ package gethbridge
|
|||
|
||||
import (
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/waku"
|
||||
"github.com/status-im/status-go/whisper/v6"
|
||||
)
|
||||
|
||||
// NewGethEnvelopeErrorWrapper returns a types.EnvelopeError object that mimics Geth's EnvelopeError
|
||||
func NewGethEnvelopeErrorWrapper(envelopeError *whisper.EnvelopeError) *types.EnvelopeError {
|
||||
// NewWhisperEnvelopeErrorWrapper returns a types.EnvelopeError object that mimics Geth's EnvelopeError
|
||||
func NewWhisperEnvelopeErrorWrapper(envelopeError *whisper.EnvelopeError) *types.EnvelopeError {
|
||||
if envelopeError == nil {
|
||||
panic("envelopeError should not be nil")
|
||||
}
|
||||
|
||||
return &types.EnvelopeError{
|
||||
Hash: types.Hash(envelopeError.Hash),
|
||||
Code: mapGethErrorCode(envelopeError.Code),
|
||||
Description: envelopeError.Description,
|
||||
}
|
||||
}
|
||||
|
||||
// NewWakuEnvelopeErrorWrapper returns a types.EnvelopeError object that mimics Geth's EnvelopeError
|
||||
func NewWakuEnvelopeErrorWrapper(envelopeError *waku.EnvelopeError) *types.EnvelopeError {
|
||||
if envelopeError == nil {
|
||||
panic("envelopeError should not be nil")
|
||||
}
|
||||
|
@ -21,8 +35,10 @@ func NewGethEnvelopeErrorWrapper(envelopeError *whisper.EnvelopeError) *types.En
|
|||
func mapGethErrorCode(code uint) uint {
|
||||
switch code {
|
||||
case whisper.EnvelopeTimeNotSynced:
|
||||
case waku.EnvelopeTimeNotSynced:
|
||||
return types.EnvelopeTimeNotSynced
|
||||
case whisper.EnvelopeOtherError:
|
||||
case waku.EnvelopeOtherError:
|
||||
return types.EnvelopeOtherError
|
||||
}
|
||||
return types.EnvelopeOtherError
|
||||
|
|
|
@ -2,11 +2,12 @@ package gethbridge
|
|||
|
||||
import (
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/waku"
|
||||
"github.com/status-im/status-go/whisper/v6"
|
||||
)
|
||||
|
||||
// NewGethEnvelopeEventWrapper returns a types.EnvelopeEvent object that mimics Geth's EnvelopeEvent
|
||||
func NewGethEnvelopeEventWrapper(envelopeEvent *whisper.EnvelopeEvent) *types.EnvelopeEvent {
|
||||
// NewWhisperEnvelopeEventWrapper returns a types.EnvelopeEvent object that mimics Geth's EnvelopeEvent
|
||||
func NewWhisperEnvelopeEventWrapper(envelopeEvent *whisper.EnvelopeEvent) *types.EnvelopeEvent {
|
||||
if envelopeEvent == nil {
|
||||
panic("envelopeEvent should not be nil")
|
||||
}
|
||||
|
@ -16,10 +17,10 @@ func NewGethEnvelopeEventWrapper(envelopeEvent *whisper.EnvelopeEvent) *types.En
|
|||
case []whisper.EnvelopeError:
|
||||
wrappedData := make([]types.EnvelopeError, len(data))
|
||||
for index, envError := range data {
|
||||
wrappedData[index] = *NewGethEnvelopeErrorWrapper(&envError)
|
||||
wrappedData[index] = *NewWhisperEnvelopeErrorWrapper(&envError)
|
||||
}
|
||||
case *whisper.MailServerResponse:
|
||||
wrappedData = NewGethMailServerResponseWrapper(data)
|
||||
wrappedData = NewWhisperMailServerResponseWrapper(data)
|
||||
case whisper.SyncEventResponse:
|
||||
wrappedData = NewGethSyncEventResponseWrapper(data)
|
||||
}
|
||||
|
@ -31,3 +32,28 @@ func NewGethEnvelopeEventWrapper(envelopeEvent *whisper.EnvelopeEvent) *types.En
|
|||
Data: wrappedData,
|
||||
}
|
||||
}
|
||||
|
||||
// NewWakuEnvelopeEventWrapper returns a types.EnvelopeEvent object that mimics Geth's EnvelopeEvent
|
||||
func NewWakuEnvelopeEventWrapper(envelopeEvent *waku.EnvelopeEvent) *types.EnvelopeEvent {
|
||||
if envelopeEvent == nil {
|
||||
panic("envelopeEvent should not be nil")
|
||||
}
|
||||
|
||||
wrappedData := envelopeEvent.Data
|
||||
switch data := envelopeEvent.Data.(type) {
|
||||
case []waku.EnvelopeError:
|
||||
wrappedData := make([]types.EnvelopeError, len(data))
|
||||
for index, envError := range data {
|
||||
wrappedData[index] = *NewWakuEnvelopeErrorWrapper(&envError)
|
||||
}
|
||||
case *waku.MailServerResponse:
|
||||
wrappedData = NewWakuMailServerResponseWrapper(data)
|
||||
}
|
||||
return &types.EnvelopeEvent{
|
||||
Event: types.EventType(envelopeEvent.Event),
|
||||
Hash: types.Hash(envelopeEvent.Hash),
|
||||
Batch: types.Hash(envelopeEvent.Batch),
|
||||
Peer: types.EnodeID(envelopeEvent.Peer),
|
||||
Data: wrappedData,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
package gethbridge
|
||||
|
||||
import (
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/whisper/v6"
|
||||
)
|
||||
|
||||
type gethFilterWrapper struct {
|
||||
filter *whisper.Filter
|
||||
id string
|
||||
}
|
||||
|
||||
// NewGethFilterWrapper returns an object that wraps Geth's Filter in a types interface
|
||||
func NewGethFilterWrapper(f *whisper.Filter, id string) types.Filter {
|
||||
if f.Messages == nil {
|
||||
panic("Messages should not be nil")
|
||||
}
|
||||
|
||||
return &gethFilterWrapper{
|
||||
filter: f,
|
||||
id: id,
|
||||
}
|
||||
}
|
||||
|
||||
// GetGethFilterFrom retrieves the underlying whisper Filter struct from a wrapped Filter interface
|
||||
func GetGethFilterFrom(f types.Filter) *whisper.Filter {
|
||||
return f.(*gethFilterWrapper).filter
|
||||
}
|
||||
|
||||
// ID returns the filter ID
|
||||
func (w *gethFilterWrapper) ID() string {
|
||||
return w.id
|
||||
}
|
18
vendor/github.com/status-im/status-go/eth-node/bridge/geth/mailserver_response.go
generated
vendored
18
vendor/github.com/status-im/status-go/eth-node/bridge/geth/mailserver_response.go
generated
vendored
|
@ -2,11 +2,25 @@ package gethbridge
|
|||
|
||||
import (
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/waku"
|
||||
"github.com/status-im/status-go/whisper/v6"
|
||||
)
|
||||
|
||||
// NewGethMailServerResponseWrapper returns a types.MailServerResponse object that mimics Geth's MailServerResponse
|
||||
func NewGethMailServerResponseWrapper(mailServerResponse *whisper.MailServerResponse) *types.MailServerResponse {
|
||||
// NewWhisperMailServerResponseWrapper returns a types.MailServerResponse object that mimics Geth's MailServerResponse
|
||||
func NewWhisperMailServerResponseWrapper(mailServerResponse *whisper.MailServerResponse) *types.MailServerResponse {
|
||||
if mailServerResponse == nil {
|
||||
panic("mailServerResponse should not be nil")
|
||||
}
|
||||
|
||||
return &types.MailServerResponse{
|
||||
LastEnvelopeHash: types.Hash(mailServerResponse.LastEnvelopeHash),
|
||||
Cursor: mailServerResponse.Cursor,
|
||||
Error: mailServerResponse.Error,
|
||||
}
|
||||
}
|
||||
|
||||
// NewWakuMailServerResponseWrapper returns a types.MailServerResponse object that mimics Geth's MailServerResponse
|
||||
func NewWakuMailServerResponseWrapper(mailServerResponse *waku.MailServerResponse) *types.MailServerResponse {
|
||||
if mailServerResponse == nil {
|
||||
panic("mailServerResponse should not be nil")
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package gethbridge
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/status-im/status-go/waku"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
|
@ -41,12 +44,35 @@ func (w *gethNodeWrapper) GetWhisper(ctx interface{}) (types.Whisper, error) {
|
|||
}
|
||||
}
|
||||
if nativeWhisper == nil {
|
||||
panic("Whisper service is not available")
|
||||
return nil, errors.New("whisper service is not available")
|
||||
}
|
||||
|
||||
return NewGethWhisperWrapper(nativeWhisper), nil
|
||||
}
|
||||
|
||||
func (w *gethNodeWrapper) GetWaku(ctx interface{}) (types.Waku, error) {
|
||||
var nativeWaku *waku.Waku
|
||||
if ctx == nil || ctx == w {
|
||||
err := w.stack.Service(&nativeWaku)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
switch serviceProvider := ctx.(type) {
|
||||
case *node.ServiceContext:
|
||||
err := serviceProvider.Service(&nativeWaku)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
if nativeWaku == nil {
|
||||
return nil, errors.New("waku service is not available")
|
||||
}
|
||||
|
||||
return NewGethWakuWrapper(nativeWaku), nil
|
||||
}
|
||||
|
||||
func (w *gethNodeWrapper) AddPeer(url string) error {
|
||||
parsedNode, err := enode.ParseV4(url)
|
||||
if err != nil {
|
||||
|
|
103
vendor/github.com/status-im/status-go/eth-node/bridge/geth/public_waku_api.go
generated
vendored
Normal file
103
vendor/github.com/status-im/status-go/eth-node/bridge/geth/public_waku_api.go
generated
vendored
Normal file
|
@ -0,0 +1,103 @@
|
|||
package gethbridge
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/waku"
|
||||
)
|
||||
|
||||
type gethPublicWakuAPIWrapper struct {
|
||||
api *waku.PublicWakuAPI
|
||||
}
|
||||
|
||||
// NewGethPublicWakuAPIWrapper returns an object that wraps Geth's PublicWakuAPI in a types interface
|
||||
func NewGethPublicWakuAPIWrapper(api *waku.PublicWakuAPI) types.PublicWakuAPI {
|
||||
if api == nil {
|
||||
panic("PublicWakuAPI cannot be nil")
|
||||
}
|
||||
|
||||
return &gethPublicWakuAPIWrapper{
|
||||
api: api,
|
||||
}
|
||||
}
|
||||
|
||||
// AddPrivateKey imports the given private key.
|
||||
func (w *gethPublicWakuAPIWrapper) AddPrivateKey(ctx context.Context, privateKey types.HexBytes) (string, error) {
|
||||
return w.api.AddPrivateKey(ctx, hexutil.Bytes(privateKey))
|
||||
}
|
||||
|
||||
// GenerateSymKeyFromPassword derives a key from the given password, stores it, and returns its ID.
|
||||
func (w *gethPublicWakuAPIWrapper) GenerateSymKeyFromPassword(ctx context.Context, passwd string) (string, error) {
|
||||
return w.api.GenerateSymKeyFromPassword(ctx, passwd)
|
||||
}
|
||||
|
||||
// DeleteKeyPair removes the key with the given key if it exists.
|
||||
func (w *gethPublicWakuAPIWrapper) DeleteKeyPair(ctx context.Context, key string) (bool, error) {
|
||||
return w.api.DeleteKeyPair(ctx, key)
|
||||
}
|
||||
|
||||
// NewMessageFilter creates a new filter that can be used to poll for
|
||||
// (new) messages that satisfy the given criteria.
|
||||
func (w *gethPublicWakuAPIWrapper) NewMessageFilter(req types.Criteria) (string, error) {
|
||||
topics := make([]waku.TopicType, len(req.Topics))
|
||||
for index, tt := range req.Topics {
|
||||
topics[index] = waku.TopicType(tt)
|
||||
}
|
||||
|
||||
criteria := waku.Criteria{
|
||||
SymKeyID: req.SymKeyID,
|
||||
PrivateKeyID: req.PrivateKeyID,
|
||||
Sig: req.Sig,
|
||||
MinPow: req.MinPow,
|
||||
Topics: topics,
|
||||
AllowP2P: req.AllowP2P,
|
||||
}
|
||||
return w.api.NewMessageFilter(criteria)
|
||||
}
|
||||
|
||||
// GetFilterMessages returns the messages that match the filter criteria and
|
||||
// are received between the last poll and now.
|
||||
func (w *gethPublicWakuAPIWrapper) GetFilterMessages(id string) ([]*types.Message, error) {
|
||||
msgs, err := w.api.GetFilterMessages(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wrappedMsgs := make([]*types.Message, len(msgs))
|
||||
for index, msg := range msgs {
|
||||
wrappedMsgs[index] = &types.Message{
|
||||
Sig: msg.Sig,
|
||||
TTL: msg.TTL,
|
||||
Timestamp: msg.Timestamp,
|
||||
Topic: types.TopicType(msg.Topic),
|
||||
Payload: msg.Payload,
|
||||
Padding: msg.Padding,
|
||||
PoW: msg.PoW,
|
||||
Hash: msg.Hash,
|
||||
Dst: msg.Dst,
|
||||
P2P: msg.P2P,
|
||||
}
|
||||
}
|
||||
return wrappedMsgs, nil
|
||||
}
|
||||
|
||||
// Post posts a message on the network.
|
||||
// returns the hash of the message in case of success.
|
||||
func (w *gethPublicWakuAPIWrapper) Post(ctx context.Context, req types.NewMessage) ([]byte, error) {
|
||||
msg := waku.NewMessage{
|
||||
SymKeyID: req.SymKeyID,
|
||||
PublicKey: req.PublicKey,
|
||||
Sig: req.SigID, // Sig is really a SigID
|
||||
TTL: req.TTL,
|
||||
Topic: waku.TopicType(req.Topic),
|
||||
Payload: req.Payload,
|
||||
Padding: req.Padding,
|
||||
PowTime: req.PowTime,
|
||||
PowTarget: req.PowTarget,
|
||||
TargetPeer: req.TargetPeer,
|
||||
}
|
||||
return w.api.Post(ctx, msg)
|
||||
}
|
197
vendor/github.com/status-im/status-go/eth-node/bridge/geth/waku.go
generated
vendored
Normal file
197
vendor/github.com/status-im/status-go/eth-node/bridge/geth/waku.go
generated
vendored
Normal file
|
@ -0,0 +1,197 @@
|
|||
package gethbridge
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"time"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/waku"
|
||||
)
|
||||
|
||||
type gethWakuWrapper struct {
|
||||
waku *waku.Waku
|
||||
}
|
||||
|
||||
// NewGethWakuWrapper returns an object that wraps Geth's Waku in a types interface
|
||||
func NewGethWakuWrapper(w *waku.Waku) types.Waku {
|
||||
if w == nil {
|
||||
panic("waku cannot be nil")
|
||||
}
|
||||
|
||||
return &gethWakuWrapper{
|
||||
waku: w,
|
||||
}
|
||||
}
|
||||
|
||||
// GetGethWhisperFrom retrieves the underlying whisper Whisper struct from a wrapped Whisper interface
|
||||
func GetGethWakuFrom(m types.Waku) *waku.Waku {
|
||||
return m.(*gethWakuWrapper).waku
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) PublicWakuAPI() types.PublicWakuAPI {
|
||||
return NewGethPublicWakuAPIWrapper(waku.NewPublicWakuAPI(w.waku))
|
||||
}
|
||||
|
||||
// MinPow returns the PoW value required by this node.
|
||||
func (w *gethWakuWrapper) MinPow() float64 {
|
||||
return w.waku.MinPow()
|
||||
}
|
||||
|
||||
// BloomFilter returns the aggregated bloom filter for all the topics of interest.
|
||||
// The nodes are required to send only messages that match the advertised bloom filter.
|
||||
// If a message does not match the bloom, it will tantamount to spam, and the peer will
|
||||
// be disconnected.
|
||||
func (w *gethWakuWrapper) BloomFilter() []byte {
|
||||
return w.waku.BloomFilter()
|
||||
}
|
||||
|
||||
// GetCurrentTime returns current time.
|
||||
func (w *gethWakuWrapper) GetCurrentTime() time.Time {
|
||||
return w.waku.CurrentTime()
|
||||
}
|
||||
|
||||
// SetTimeSource assigns a particular source of time to a whisper object.
|
||||
func (w *gethWakuWrapper) SetTimeSource(timesource func() time.Time) {
|
||||
w.waku.SetTimeSource(timesource)
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) SubscribeEnvelopeEvents(eventsProxy chan<- types.EnvelopeEvent) types.Subscription {
|
||||
events := make(chan waku.EnvelopeEvent, 100) // must be buffered to prevent blocking whisper
|
||||
go func() {
|
||||
for e := range events {
|
||||
eventsProxy <- *NewWakuEnvelopeEventWrapper(&e)
|
||||
}
|
||||
}()
|
||||
|
||||
return NewGethSubscriptionWrapper(w.waku.SubscribeEnvelopeEvents(events))
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) {
|
||||
return w.waku.GetPrivateKey(id)
|
||||
}
|
||||
|
||||
// AddKeyPair imports a asymmetric private key and returns a deterministic identifier.
|
||||
func (w *gethWakuWrapper) AddKeyPair(key *ecdsa.PrivateKey) (string, error) {
|
||||
return w.waku.AddKeyPair(key)
|
||||
}
|
||||
|
||||
// DeleteKeyPair deletes the key with the specified ID if it exists.
|
||||
func (w *gethWakuWrapper) DeleteKeyPair(keyID string) bool {
|
||||
return w.waku.DeleteKeyPair(keyID)
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) AddSymKeyDirect(key []byte) (string, error) {
|
||||
return w.waku.AddSymKeyDirect(key)
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) AddSymKeyFromPassword(password string) (string, error) {
|
||||
return w.waku.AddSymKeyFromPassword(password)
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) DeleteSymKey(id string) bool {
|
||||
return w.waku.DeleteSymKey(id)
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) GetSymKey(id string) ([]byte, error) {
|
||||
return w.waku.GetSymKey(id)
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) Subscribe(opts *types.SubscriptionOptions) (string, error) {
|
||||
var (
|
||||
err error
|
||||
keyAsym *ecdsa.PrivateKey
|
||||
keySym []byte
|
||||
)
|
||||
|
||||
if opts.SymKeyID != "" {
|
||||
keySym, err = w.GetSymKey(opts.SymKeyID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
if opts.PrivateKeyID != "" {
|
||||
keyAsym, err = w.GetPrivateKey(opts.PrivateKeyID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
f, err := w.createFilterWrapper("", keyAsym, keySym, opts.PoW, opts.Topics)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
id, err := w.waku.Subscribe(GetWakuFilterFrom(f))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
f.(*wakuFilterWrapper).id = id
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) GetFilter(id string) types.Filter {
|
||||
return NewWakuFilterWrapper(w.waku.GetFilter(id), id)
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) Unsubscribe(id string) error {
|
||||
return w.waku.Unsubscribe(id)
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) createFilterWrapper(id string, keyAsym *ecdsa.PrivateKey, keySym []byte, pow float64, topics [][]byte) (types.Filter, error) {
|
||||
return NewWakuFilterWrapper(&waku.Filter{
|
||||
KeyAsym: keyAsym,
|
||||
KeySym: keySym,
|
||||
PoW: pow,
|
||||
AllowP2P: true,
|
||||
Topics: topics,
|
||||
Messages: waku.NewMemoryMessageStore(),
|
||||
}, id), nil
|
||||
}
|
||||
|
||||
func (w *gethWakuWrapper) SendMessagesRequest(peerID []byte, r types.MessagesRequest) error {
|
||||
return w.waku.SendMessagesRequest(peerID, waku.MessagesRequest{
|
||||
ID: r.ID,
|
||||
From: r.From,
|
||||
To: r.To,
|
||||
Limit: r.Limit,
|
||||
Cursor: r.Cursor,
|
||||
Bloom: r.Bloom,
|
||||
})
|
||||
}
|
||||
|
||||
// RequestHistoricMessages sends a message with p2pRequestCode to a specific peer,
|
||||
// which is known to implement MailServer interface, and is supposed to process this
|
||||
// request and respond with a number of peer-to-peer messages (possibly expired),
|
||||
// which are not supposed to be forwarded any further.
|
||||
// The whisper protocol is agnostic of the format and contents of envelope.
|
||||
func (w *gethWakuWrapper) RequestHistoricMessagesWithTimeout(peerID []byte, envelope types.Envelope, timeout time.Duration) error {
|
||||
return w.waku.RequestHistoricMessagesWithTimeout(peerID, MustUnwrapWakuEnvelope(envelope), timeout)
|
||||
}
|
||||
|
||||
type wakuFilterWrapper struct {
|
||||
filter *waku.Filter
|
||||
id string
|
||||
}
|
||||
|
||||
// NewWakuFilterWrapper returns an object that wraps Geth's Filter in a types interface
|
||||
func NewWakuFilterWrapper(f *waku.Filter, id string) types.Filter {
|
||||
if f.Messages == nil {
|
||||
panic("Messages should not be nil")
|
||||
}
|
||||
|
||||
return &wakuFilterWrapper{
|
||||
filter: f,
|
||||
id: id,
|
||||
}
|
||||
}
|
||||
|
||||
// GetWakuFilterFrom retrieves the underlying whisper Filter struct from a wrapped Filter interface
|
||||
func GetWakuFilterFrom(f types.Filter) *waku.Filter {
|
||||
return f.(*wakuFilterWrapper).filter
|
||||
}
|
||||
|
||||
// ID returns the filter ID
|
||||
func (w *wakuFilterWrapper) ID() string {
|
||||
return w.id
|
||||
}
|
|
@ -59,7 +59,7 @@ func (w *gethWhisperWrapper) SubscribeEnvelopeEvents(eventsProxy chan<- types.En
|
|||
events := make(chan whisper.EnvelopeEvent, 100) // must be buffered to prevent blocking whisper
|
||||
go func() {
|
||||
for e := range events {
|
||||
eventsProxy <- *NewGethEnvelopeEventWrapper(&e)
|
||||
eventsProxy <- *NewWhisperEnvelopeEventWrapper(&e)
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -121,17 +121,17 @@ func (w *gethWhisperWrapper) Subscribe(opts *types.SubscriptionOptions) (string,
|
|||
return "", err
|
||||
}
|
||||
|
||||
id, err := w.whisper.Subscribe(GetGethFilterFrom(f))
|
||||
id, err := w.whisper.Subscribe(GetWhisperFilterFrom(f))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
f.(*gethFilterWrapper).id = id
|
||||
f.(*whisperFilterWrapper).id = id
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (w *gethWhisperWrapper) GetFilter(id string) types.Filter {
|
||||
return NewGethFilterWrapper(w.whisper.GetFilter(id), id)
|
||||
return NewWhisperFilterWrapper(w.whisper.GetFilter(id), id)
|
||||
}
|
||||
|
||||
func (w *gethWhisperWrapper) Unsubscribe(id string) error {
|
||||
|
@ -139,7 +139,7 @@ func (w *gethWhisperWrapper) Unsubscribe(id string) error {
|
|||
}
|
||||
|
||||
func (w *gethWhisperWrapper) createFilterWrapper(id string, keyAsym *ecdsa.PrivateKey, keySym []byte, pow float64, topics [][]byte) (types.Filter, error) {
|
||||
return NewGethFilterWrapper(&whisper.Filter{
|
||||
return NewWhisperFilterWrapper(&whisper.Filter{
|
||||
KeyAsym: keyAsym,
|
||||
KeySym: keySym,
|
||||
PoW: pow,
|
||||
|
@ -173,3 +173,30 @@ func (w *gethWhisperWrapper) RequestHistoricMessagesWithTimeout(peerID []byte, e
|
|||
func (w *gethWhisperWrapper) SyncMessages(peerID []byte, req types.SyncMailRequest) error {
|
||||
return w.whisper.SyncMessages(peerID, *GetGethSyncMailRequestFrom(&req))
|
||||
}
|
||||
|
||||
type whisperFilterWrapper struct {
|
||||
filter *whisper.Filter
|
||||
id string
|
||||
}
|
||||
|
||||
// NewWhisperFilterWrapper returns an object that wraps Geth's Filter in a types interface
|
||||
func NewWhisperFilterWrapper(f *whisper.Filter, id string) types.Filter {
|
||||
if f.Messages == nil {
|
||||
panic("Messages should not be nil")
|
||||
}
|
||||
|
||||
return &whisperFilterWrapper{
|
||||
filter: f,
|
||||
id: id,
|
||||
}
|
||||
}
|
||||
|
||||
// GetWhisperFilterFrom retrieves the underlying whisper Filter struct from a wrapped Filter interface
|
||||
func GetWhisperFilterFrom(f types.Filter) *whisper.Filter {
|
||||
return f.(*whisperFilterWrapper).filter
|
||||
}
|
||||
|
||||
// ID returns the filter ID
|
||||
func (w *whisperFilterWrapper) ID() string {
|
||||
return w.id
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package types
|
||||
|
||||
const (
|
||||
// PubKeyLength represents the length (in bytes) of an uncompressed public key
|
||||
PubKeyLength = 512 / 8
|
||||
// AesKeyLength represents the length (in bytes) of an private key
|
||||
AesKeyLength = 256 / 8
|
||||
)
|
|
@ -19,6 +19,7 @@ func (n EnodeID) String() string {
|
|||
type Node interface {
|
||||
NewENSVerifier(logger *zap.Logger) enstypes.ENSVerifier
|
||||
GetWhisper(ctx interface{}) (Whisper, error)
|
||||
GetWaku(ctx interface{}) (Waku, error)
|
||||
AddPeer(url string) error
|
||||
RemovePeer(url string) error
|
||||
}
|
||||
|
|
|
@ -63,3 +63,25 @@ type PublicWhisperAPI interface {
|
|||
// are received between the last poll and now.
|
||||
GetFilterMessages(id string) ([]*Message, error)
|
||||
}
|
||||
|
||||
// PublicWakuAPI provides the waku RPC service that can be
|
||||
// use publicly without security implications.
|
||||
type PublicWakuAPI interface {
|
||||
// AddPrivateKey imports the given private key.
|
||||
AddPrivateKey(ctx context.Context, privateKey HexBytes) (string, error)
|
||||
// GenerateSymKeyFromPassword derives a key from the given password, stores it, and returns its ID.
|
||||
GenerateSymKeyFromPassword(ctx context.Context, passwd string) (string, error)
|
||||
// DeleteKeyPair removes the key with the given key if it exists.
|
||||
DeleteKeyPair(ctx context.Context, key string) (bool, error)
|
||||
|
||||
// Post posts a message on the Whisper network.
|
||||
// returns the hash of the message in case of success.
|
||||
Post(ctx context.Context, req NewMessage) ([]byte, error)
|
||||
|
||||
// NewMessageFilter creates a new filter that can be used to poll for
|
||||
// (new) messages that satisfy the given criteria.
|
||||
NewMessageFilter(req Criteria) (string, error)
|
||||
// GetFilterMessages returns the messages that match the filter criteria and
|
||||
// are received between the last poll and now.
|
||||
GetFilterMessages(id string) ([]*Message, error)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package types
|
||||
|
||||
// SubscriptionOptions represents the parameters passed to Subscribe()
|
||||
// to customize the subscription behavior.
|
||||
type SubscriptionOptions struct {
|
||||
PrivateKeyID string
|
||||
SymKeyID string
|
||||
PoW float64
|
||||
Topics [][]byte
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Whisper represents a dark communication interface through the Ethereum
|
||||
// network, using its very own P2P communication layer.
|
||||
type Waku interface {
|
||||
PublicWakuAPI() PublicWakuAPI
|
||||
|
||||
// MinPow returns the PoW value required by this node.
|
||||
MinPow() float64
|
||||
// BloomFilter returns the aggregated bloom filter for all the topics of interest.
|
||||
// The nodes are required to send only messages that match the advertised bloom filter.
|
||||
// If a message does not match the bloom, it will tantamount to spam, and the peer will
|
||||
// be disconnected.
|
||||
BloomFilter() []byte
|
||||
// SetTimeSource assigns a particular source of time to a whisper object.
|
||||
SetTimeSource(timesource func() time.Time)
|
||||
// GetCurrentTime returns current time.
|
||||
GetCurrentTime() time.Time
|
||||
|
||||
// GetPrivateKey retrieves the private key of the specified identity.
|
||||
GetPrivateKey(id string) (*ecdsa.PrivateKey, error)
|
||||
|
||||
SubscribeEnvelopeEvents(events chan<- EnvelopeEvent) Subscription
|
||||
|
||||
// AddKeyPair imports a asymmetric private key and returns a deterministic identifier.
|
||||
AddKeyPair(key *ecdsa.PrivateKey) (string, error)
|
||||
// DeleteKeyPair deletes the key with the specified ID if it exists.
|
||||
DeleteKeyPair(keyID string) bool
|
||||
AddSymKeyDirect(key []byte) (string, error)
|
||||
AddSymKeyFromPassword(password string) (string, error)
|
||||
DeleteSymKey(id string) bool
|
||||
GetSymKey(id string) ([]byte, error)
|
||||
|
||||
Subscribe(opts *SubscriptionOptions) (string, error)
|
||||
GetFilter(id string) Filter
|
||||
Unsubscribe(id string) error
|
||||
|
||||
// RequestHistoricMessages sends a message with p2pRequestCode to a specific peer,
|
||||
// which is known to implement MailServer interface, and is supposed to process this
|
||||
// request and respond with a number of peer-to-peer messages (possibly expired),
|
||||
// which are not supposed to be forwarded any further.
|
||||
// The whisper protocol is agnostic of the format and contents of envelope.
|
||||
// A timeout of 0 never expires.
|
||||
RequestHistoricMessagesWithTimeout(peerID []byte, envelope Envelope, timeout time.Duration) error
|
||||
// SendMessagesRequest sends a MessagesRequest. This is an equivalent to RequestHistoricMessages
|
||||
// in terms of the functionality.
|
||||
SendMessagesRequest(peerID []byte, request MessagesRequest) error
|
||||
}
|
|
@ -5,22 +5,6 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// PubKeyLength represents the length (in bytes) of an uncompressed public key
|
||||
PubKeyLength = 512 / 8
|
||||
// AesKeyLength represents the length (in bytes) of an private key
|
||||
AesKeyLength = 256 / 8
|
||||
)
|
||||
|
||||
// SubscriptionOptions represents the parameters passed to Whisper.Subscribe
|
||||
// to customize the subscription behavior
|
||||
type SubscriptionOptions struct {
|
||||
PrivateKeyID string
|
||||
SymKeyID string
|
||||
PoW float64
|
||||
Topics [][]byte
|
||||
}
|
||||
|
||||
// Whisper represents a dark communication interface through the Ethereum
|
||||
// network, using its very own P2P communication layer.
|
||||
type Whisper interface {
|
||||
|
|
34
vendor/github.com/status-im/status-go/protocol/encryption/migrations/migrations.go
generated
vendored
34
vendor/github.com/status-im/status-go/protocol/encryption/migrations/migrations.go
generated
vendored
|
@ -100,7 +100,7 @@ func _1536754952_initial_schemaDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1536754952_initial_schema.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1536754952_initial_schema.down.sql", size: 83, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x44, 0xcf, 0x76, 0x71, 0x1f, 0x5e, 0x9a, 0x43, 0xd8, 0xcd, 0xb8, 0xc3, 0x70, 0xc3, 0x7f, 0xfc, 0x90, 0xb4, 0x25, 0x1e, 0xf4, 0x66, 0x20, 0xb8, 0x33, 0x7e, 0xb0, 0x76, 0x1f, 0xc, 0xc0, 0x75}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ func _1536754952_initial_schemaUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1536754952_initial_schema.up.sql", size: 962, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1536754952_initial_schema.up.sql", size: 962, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xea, 0x90, 0x5a, 0x59, 0x3e, 0x3, 0xe2, 0x3c, 0x81, 0x42, 0xcd, 0x4c, 0x9a, 0xe8, 0xda, 0x93, 0x2b, 0x70, 0xa4, 0xd5, 0x29, 0x3e, 0xd5, 0xc9, 0x27, 0xb6, 0xb7, 0x65, 0xff, 0x0, 0xcb, 0xde}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ func _1539249977_update_ratchet_infoDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1539249977_update_ratchet_info.down.sql", size: 311, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1539249977_update_ratchet_info.down.sql", size: 311, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x1, 0xa4, 0xeb, 0xa0, 0xe6, 0xa0, 0xd4, 0x48, 0xbb, 0xad, 0x6f, 0x7d, 0x67, 0x8c, 0xbd, 0x25, 0xde, 0x1f, 0x73, 0x9a, 0xbb, 0xa8, 0xc9, 0x30, 0xb7, 0xa9, 0x7c, 0xaf, 0xb5, 0x1, 0x61, 0xdd}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ func _1539249977_update_ratchet_infoUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1539249977_update_ratchet_info.up.sql", size: 368, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1539249977_update_ratchet_info.up.sql", size: 368, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc, 0x8e, 0xbf, 0x6f, 0xa, 0xc0, 0xe1, 0x3c, 0x42, 0x28, 0x88, 0x1d, 0xdb, 0xba, 0x1c, 0x83, 0xec, 0xba, 0xd3, 0x5f, 0x5c, 0x77, 0x5e, 0xa7, 0x46, 0x36, 0xec, 0x69, 0xa, 0x4b, 0x17, 0x79}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ func _1540715431_add_versionDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1540715431_add_version.down.sql", size: 127, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1540715431_add_version.down.sql", size: 127, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0x9, 0x4, 0xe3, 0x76, 0x2e, 0xb8, 0x9, 0x23, 0xf0, 0x70, 0x93, 0xc4, 0x50, 0xe, 0x9d, 0x84, 0x22, 0x8c, 0x94, 0xd3, 0x24, 0x9, 0x9a, 0xc1, 0xa1, 0x48, 0x45, 0xfd, 0x40, 0x6e, 0xe6}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ func _1540715431_add_versionUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1540715431_add_version.up.sql", size: 265, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1540715431_add_version.up.sql", size: 265, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc7, 0x4c, 0x36, 0x96, 0xdf, 0x16, 0x10, 0xa6, 0x27, 0x1a, 0x79, 0x8b, 0x42, 0x83, 0x23, 0xc, 0x7e, 0xb6, 0x3d, 0x2, 0xda, 0xa4, 0xb4, 0xd, 0x27, 0x55, 0xba, 0xdc, 0xb2, 0x88, 0x8f, 0xa6}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ func _1541164797_add_installationsDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1541164797_add_installations.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1541164797_add_installations.down.sql", size: 26, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0xfd, 0xe6, 0xd8, 0xca, 0x3b, 0x38, 0x18, 0xee, 0x0, 0x5f, 0x36, 0x9e, 0x1e, 0xd, 0x19, 0x3e, 0xb4, 0x73, 0x53, 0xe9, 0xa5, 0xac, 0xdd, 0xa1, 0x2f, 0xc7, 0x6c, 0xa8, 0xd9, 0xa, 0x88}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ func _1541164797_add_installationsUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1541164797_add_installations.up.sql", size: 216, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1541164797_add_installations.up.sql", size: 216, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2d, 0x18, 0x26, 0xb8, 0x88, 0x47, 0xdb, 0x83, 0xcc, 0xb6, 0x9d, 0x1c, 0x1, 0xae, 0x2f, 0xde, 0x97, 0x82, 0x3, 0x30, 0xa8, 0x63, 0xa1, 0x78, 0x4b, 0xa5, 0x9, 0x8, 0x75, 0xa2, 0x57, 0x81}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ func _1558084410_add_secretDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1558084410_add_secret.down.sql", size: 56, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1558084410_add_secret.down.sql", size: 56, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x49, 0xb, 0x65, 0xdf, 0x59, 0xbf, 0xe9, 0x5, 0x5b, 0x6f, 0xd5, 0x3a, 0xb7, 0x57, 0xe8, 0x78, 0x38, 0x73, 0x53, 0x57, 0xf7, 0x24, 0x4, 0xe4, 0xa2, 0x49, 0x22, 0xa2, 0xc6, 0xfd, 0x80, 0xa4}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ func _1558084410_add_secretUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1558084410_add_secret.up.sql", size: 301, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1558084410_add_secret.up.sql", size: 301, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf5, 0x32, 0x36, 0x8e, 0x47, 0xb0, 0x8f, 0xc1, 0xc6, 0xf7, 0xc6, 0x9f, 0x2d, 0x44, 0x75, 0x2b, 0x26, 0xec, 0x6, 0xa0, 0x7b, 0xa5, 0xbd, 0xc8, 0x76, 0x8a, 0x82, 0x68, 0x2, 0x42, 0xb5, 0xf4}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -300,7 +300,7 @@ func _1558588866_add_versionDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1558588866_add_version.down.sql", size: 47, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1558588866_add_version.down.sql", size: 47, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xde, 0x52, 0x34, 0x3c, 0x46, 0x4a, 0xf0, 0x72, 0x47, 0x6f, 0x49, 0x5c, 0xc7, 0xf9, 0x32, 0xce, 0xc4, 0x3d, 0xfd, 0x61, 0xa1, 0x8b, 0x8f, 0xf2, 0x31, 0x34, 0xde, 0x15, 0x49, 0xa6, 0xde, 0xb9}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ func _1558588866_add_versionUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1558588866_add_version.up.sql", size: 57, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1558588866_add_version.up.sql", size: 57, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2a, 0xea, 0x64, 0x39, 0x61, 0x20, 0x83, 0x83, 0xb, 0x2e, 0x79, 0x64, 0xb, 0x53, 0xfa, 0xfe, 0xc6, 0xf7, 0x67, 0x42, 0xd3, 0x4f, 0xdc, 0x7e, 0x30, 0x32, 0xe8, 0x14, 0x41, 0xe9, 0xe7, 0x3b}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -340,7 +340,7 @@ func _1559627659_add_contact_codeDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1559627659_add_contact_code.down.sql", size: 32, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1559627659_add_contact_code.down.sql", size: 32, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5d, 0x64, 0x6d, 0xce, 0x24, 0x42, 0x20, 0x8d, 0x4f, 0x37, 0xaa, 0x9d, 0xc, 0x57, 0x98, 0xc1, 0xd1, 0x1a, 0x34, 0xcd, 0x9f, 0x8f, 0x34, 0x86, 0xb3, 0xd3, 0xdc, 0xf1, 0x7d, 0xe5, 0x1b, 0x6e}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -360,7 +360,7 @@ func _1559627659_add_contact_codeUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1559627659_add_contact_code.up.sql", size: 198, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1559627659_add_contact_code.up.sql", size: 198, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x16, 0xf6, 0xc2, 0x62, 0x9c, 0xd2, 0xc9, 0x1e, 0xd8, 0xea, 0xaa, 0xea, 0x95, 0x8f, 0x89, 0x6a, 0x85, 0x5d, 0x9d, 0x99, 0x78, 0x3c, 0x90, 0x66, 0x99, 0x3e, 0x4b, 0x19, 0x62, 0xfb, 0x31, 0x4d}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -380,7 +380,7 @@ func _1561368210_add_installation_metadataDownSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561368210_add_installation_metadata.down.sql", size: 35, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1561368210_add_installation_metadata.down.sql", size: 35, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa8, 0xde, 0x3f, 0xd2, 0x4a, 0x50, 0x98, 0x56, 0xe3, 0xc0, 0xcd, 0x9d, 0xb0, 0x34, 0x3b, 0xe5, 0x62, 0x18, 0xb5, 0x20, 0xc9, 0x3e, 0xdc, 0x6a, 0x40, 0x36, 0x66, 0xea, 0x51, 0x8c, 0x71, 0xf5}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -400,7 +400,7 @@ func _1561368210_add_installation_metadataUpSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561368210_add_installation_metadata.up.sql", size: 267, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "1561368210_add_installation_metadata.up.sql", size: 267, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb4, 0x71, 0x8f, 0x29, 0xb1, 0xaa, 0xd6, 0xd1, 0x8c, 0x17, 0xef, 0x6c, 0xd5, 0x80, 0xb8, 0x2c, 0xc3, 0xfe, 0xec, 0x24, 0x4d, 0xc8, 0x25, 0xd3, 0xb4, 0xcd, 0xa9, 0xac, 0x63, 0x61, 0xb2, 0x9c}}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -420,7 +420,7 @@ func docGo() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1575625435, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xef, 0xaf, 0xdf, 0xcf, 0x65, 0xae, 0x19, 0xfc, 0x9d, 0x29, 0xc1, 0x91, 0xaf, 0xb5, 0xd5, 0xb1, 0x56, 0xf3, 0xee, 0xa8, 0xba, 0x13, 0x65, 0xdb, 0xab, 0xcf, 0x4e, 0xac, 0x92, 0xe9, 0x60, 0xf1}}
|
||||
return a, nil
|
||||
}
|
||||
|
|
3
vendor/github.com/status-im/status-go/protocol/encryption/protocol_message.pb.go
generated
vendored
3
vendor/github.com/status-im/status-go/protocol/encryption/protocol_message.pb.go
generated
vendored
|
@ -5,9 +5,8 @@ package encryption
|
|||
|
||||
import (
|
||||
fmt "fmt"
|
||||
math "math"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
|
@ -697,6 +697,7 @@ golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2 h1:4dVFTC832rPn4pomLSz1vA+are2+dU19w1H8OngV7nc=
|
||||
golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3 h1:6KET3Sqa7fkVfD63QnAM81ZeYg5n4HwApOJkufONnHA=
|
||||
golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
"github.com/status-im/status-go/protocol/encryption"
|
||||
"github.com/status-im/status-go/protocol/encryption/multidevice"
|
||||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
transport "github.com/status-im/status-go/protocol/transport/whisper"
|
||||
"github.com/status-im/status-go/protocol/transport"
|
||||
v1protocol "github.com/status-im/status-go/protocol/v1"
|
||||
)
|
||||
|
||||
|
@ -34,7 +34,7 @@ type messageProcessor struct {
|
|||
identity *ecdsa.PrivateKey
|
||||
datasync *datasync.DataSync
|
||||
protocol *encryption.Protocol
|
||||
transport *transport.WhisperServiceTransport
|
||||
transport transport.Transport
|
||||
logger *zap.Logger
|
||||
|
||||
featureFlags featureFlags
|
||||
|
@ -44,7 +44,7 @@ func newMessageProcessor(
|
|||
identity *ecdsa.PrivateKey,
|
||||
database *sql.DB,
|
||||
enc *encryption.Protocol,
|
||||
transport *transport.WhisperServiceTransport,
|
||||
transport transport.Transport,
|
||||
logger *zap.Logger,
|
||||
features featureFlags,
|
||||
) (*messageProcessor, error) {
|
||||
|
|
|
@ -23,7 +23,9 @@ import (
|
|||
"github.com/status-im/status-go/protocol/identity/identicon"
|
||||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
"github.com/status-im/status-go/protocol/sqlite"
|
||||
transport "github.com/status-im/status-go/protocol/transport/whisper"
|
||||
"github.com/status-im/status-go/protocol/transport"
|
||||
wakutransp "github.com/status-im/status-go/protocol/transport/waku"
|
||||
shhtransp "github.com/status-im/status-go/protocol/transport/whisper"
|
||||
v1protocol "github.com/status-im/status-go/protocol/v1"
|
||||
)
|
||||
|
||||
|
@ -47,7 +49,7 @@ type Messenger struct {
|
|||
node types.Node
|
||||
identity *ecdsa.PrivateKey
|
||||
persistence *sqlitePersistence
|
||||
transport *transport.WhisperServiceTransport
|
||||
transport transport.Transport
|
||||
encryptor *encryption.Protocol
|
||||
processor *messageProcessor
|
||||
handler *MessageHandler
|
||||
|
@ -195,11 +197,6 @@ func NewMessenger(
|
|||
) (*Messenger, error) {
|
||||
var messenger *Messenger
|
||||
|
||||
shh, err := node.GetWhisper(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := config{}
|
||||
|
||||
for _, opt := range opts {
|
||||
|
@ -279,22 +276,42 @@ func NewMessenger(
|
|||
}
|
||||
|
||||
// Apply migrations for all components.
|
||||
err = sqlite.Migrate(database)
|
||||
err := sqlite.Migrate(database)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to apply migrations")
|
||||
}
|
||||
|
||||
// Initialize transport layer.
|
||||
t, err := transport.NewWhisperServiceTransport(
|
||||
shh,
|
||||
identity,
|
||||
database,
|
||||
nil,
|
||||
c.envelopesMonitorConfig,
|
||||
logger,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create a WhisperServiceTransport")
|
||||
var transp transport.Transport
|
||||
if shh, err := node.GetWhisper(nil); err == nil {
|
||||
transp, err = shhtransp.NewWhisperServiceTransport(
|
||||
shh,
|
||||
identity,
|
||||
database,
|
||||
nil,
|
||||
c.envelopesMonitorConfig,
|
||||
logger,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create WhisperServiceTransport")
|
||||
}
|
||||
} else if err != nil {
|
||||
logger.Info("failed to find Whisper service; trying Waku", zap.Error(err))
|
||||
waku, err := node.GetWaku(nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to find Whisper and Waku services")
|
||||
}
|
||||
transp, err = wakutransp.NewWakuServiceTransport(
|
||||
waku,
|
||||
identity,
|
||||
database,
|
||||
nil,
|
||||
c.envelopesMonitorConfig,
|
||||
logger,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create WakuServiceTransport")
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize encryption layer.
|
||||
|
@ -311,7 +328,7 @@ func NewMessenger(
|
|||
identity,
|
||||
database,
|
||||
encryptionProtocol,
|
||||
t,
|
||||
transp,
|
||||
logger,
|
||||
c.featureFlags,
|
||||
)
|
||||
|
@ -325,7 +342,7 @@ func NewMessenger(
|
|||
node: node,
|
||||
identity: identity,
|
||||
persistence: &sqlitePersistence{db: database},
|
||||
transport: t,
|
||||
transport: transp,
|
||||
encryptor: encryptionProtocol,
|
||||
processor: processor,
|
||||
handler: handler,
|
||||
|
@ -340,8 +357,8 @@ func NewMessenger(
|
|||
verifyTransactionClient: c.verifyTransactionClient,
|
||||
shutdownTasks: []func() error{
|
||||
database.Close,
|
||||
t.Reset,
|
||||
t.Stop,
|
||||
transp.ResetFilters,
|
||||
transp.Stop,
|
||||
func() error { processor.Stop(); return nil },
|
||||
// Currently this often fails, seems like it's safe to ignore them
|
||||
// https://github.com/uber-go/zap/issues/328
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
package protocol
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
encryptmigrations "github.com/status-im/status-go/protocol/encryption/migrations"
|
||||
appmigrations "github.com/status-im/status-go/protocol/migrations"
|
||||
transpmigrations "github.com/status-im/status-go/protocol/transport/whisper/migrations"
|
||||
)
|
||||
|
||||
type getter func(string) ([]byte, error)
|
||||
|
||||
type migrationsWithGetter struct {
|
||||
Names []string
|
||||
Getter getter
|
||||
}
|
||||
|
||||
var defaultMigrations = []migrationsWithGetter{
|
||||
{
|
||||
Names: transpmigrations.AssetNames(),
|
||||
Getter: transpmigrations.Asset,
|
||||
},
|
||||
{
|
||||
Names: encryptmigrations.AssetNames(),
|
||||
Getter: encryptmigrations.Asset,
|
||||
},
|
||||
{
|
||||
Names: appmigrations.AssetNames(),
|
||||
Getter: appmigrations.Asset,
|
||||
},
|
||||
}
|
||||
|
||||
func prepareMigrations(migrations []migrationsWithGetter) ([]string, getter, error) {
|
||||
var allNames []string
|
||||
nameToGetter := make(map[string]getter)
|
||||
|
||||
for _, m := range migrations {
|
||||
for _, name := range m.Names {
|
||||
if !validateName(name) {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := nameToGetter[name]; ok {
|
||||
return nil, nil, errors.Errorf("migration with name %s already exists", name)
|
||||
}
|
||||
allNames = append(allNames, name)
|
||||
nameToGetter[name] = m.Getter
|
||||
}
|
||||
}
|
||||
|
||||
return allNames, func(name string) ([]byte, error) {
|
||||
getter, ok := nameToGetter[name]
|
||||
if !ok {
|
||||
return nil, errors.Errorf("no migration for name %s", name)
|
||||
}
|
||||
return getter(name)
|
||||
}, nil
|
||||
}
|
||||
|
||||
// validateName verifies that only *.sql files are taken into consideration.
|
||||
func validateName(name string) bool {
|
||||
return strings.HasSuffix(name, ".sql")
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
// Code generated by go-bindata. DO NOT EDIT.
|
||||
// sources:
|
||||
// 000001_init.down.db.sql (65B)
|
||||
// 000001_init.up.db.sql (2.693kB)
|
||||
// 000001_init.up.db.sql (2.719kB)
|
||||
// doc.go (377B)
|
||||
|
||||
package migrations
|
||||
|
@ -86,12 +86,12 @@ func _000001_initDownDbSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000001_init.down.db.sql", size: 65, mode: os.FileMode(0644), modTime: time.Unix(1577718673, 0)}
|
||||
info := bindataFileInfo{name: "000001_init.down.db.sql", size: 65, mode: os.FileMode(0644), modTime: time.Unix(1578756765, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5e, 0xbb, 0x3f, 0x1, 0x75, 0x19, 0x70, 0x86, 0xa7, 0x34, 0x40, 0x17, 0x34, 0x3e, 0x18, 0x51, 0x79, 0xd4, 0x22, 0xad, 0x8f, 0x80, 0xcc, 0xa6, 0xcc, 0x6, 0x2b, 0x62, 0x2, 0x47, 0xba, 0xf9}}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var __000001_initUpDbSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x56\x51\x6f\xe3\x36\x0c\x7e\xf7\xaf\x20\xb0\x87\xb6\x80\x3b\xdc\x80\xdb\x6d\x40\x9f\xd2\x9e\xbb\x05\xcb\x92\x43\xea\x0e\xbd\x27\x81\x91\xd8\x58\x88\x2d\x19\x12\x9d\x5c\x80\xfb\xf1\x83\x9c\x38\xb1\x12\xa7\xbd\x61\x7d\x28\x5a\x52\x24\xc5\x8f\xfc\x3e\xf9\x61\x9e\x8d\xf2\x0c\xf2\xd1\xfd\x24\x83\xf1\x23\x4c\x67\x39\x64\x2f\xe3\xa7\xfc\x09\x64\x81\xec\xe1\x3a\xd1\x0a\xfe\x19\xcd\x1f\xfe\x1c\xcd\xe1\xcb\x7c\xfc\xf7\x68\xfe\x15\xfe\xca\xbe\xc2\x6c\x0a\x0f\xb3\xe9\xe3\x64\xfc\x90\xc3\x3c\xfb\x32\x19\x3d\x64\x69\x62\xb0\xa2\xc3\xe9\x90\x6b\xfa\x3c\x99\xa4\x89\xb4\xa5\x75\x67\x76\xf8\x9c\x3d\x8e\x9e\x27\x39\x5c\xfd\x84\xbf\xfc\xfe\x9b\xfa\xf5\x2a\x4d\x78\x5b\x13\x8c\xa7\x79\x2f\x18\x25\xeb\x35\xc1\xfd\x6c\x36\xc9\x46\xd3\xf3\xe8\x7c\xfe\x9c\xa5\x09\xeb\x8a\x3c\x63\x55\x9f\x44\x2b\x2a\x89\x49\x09\x64\x21\x4b\x2b\x57\x62\x8d\x65\x13\x97\x38\x64\xfa\x90\x26\x75\xb3\x28\xb5\x14\x2b\xda\xc2\xfd\x64\x76\x9f\x26\x8d\x59\x6b\xda\x90\x12\x15\x79\x8f\x4b\x12\xd2\x36\x86\x2f\xc6\x97\xe8\x7f\xac\x50\x7b\x70\x9f\x73\x5f\xaa\xa2\x6a\x41\xce\xc7\xff\x15\xba\x16\x4d\xad\x90\x69\xe7\x48\x6e\xee\x92\x24\x9a\x9a\xb4\x86\x51\xb6\xa3\x02\xd0\x0a\xf2\xec\x25\x7f\x7f\x52\x00\xa8\x94\x23\xef\x77\xe7\x8f\x80\x01\xb4\x43\x3c\xb3\x92\xf1\x62\x4d\x4e\xbf\x6a\x52\x87\x61\x74\x0d\x3d\x8e\x26\x4f\xd9\xe9\x29\x81\x97\x71\x02\xc0\x52\xe3\x40\x71\xad\xc8\xb0\x96\xd6\x9c\xbb\xea\xc2\xb2\x3d\x37\xb7\x48\xee\x20\x52\x6f\xd4\xf3\x5b\xcf\x54\x09\xc6\x65\x87\x30\x80\xa2\xb5\x96\x24\xb4\x79\xb5\x07\x1b\x3b\xbd\x68\x98\x04\x5b\xc1\x58\xae\xe2\x7a\x2d\xfa\xb7\xb7\x30\xe6\x2b\x0f\xba\xaa\xad\x63\x34\x0c\x5c\x60\xf8\xa5\x3d\x30\x2e\x4a\x82\x02\x3d\x38\xbb\xd1\x0a\xd0\xc3\x86\xc0\x51\xb9\x05\x6b\x40\x73\x08\xde\x14\x64\x42\x70\x49\x55\xe8\xd5\x2c\x41\x9b\x57\x6d\x34\xd3\xad\x97\xce\x96\xe5\xcf\xc9\x1b\xb4\x6c\x3c\xb9\x6e\x71\x76\x33\x6f\xa7\xfe\xc3\x14\x0d\xe7\x37\x85\xf6\x35\x39\x11\x91\x26\xfb\x23\x9b\x47\xc0\x02\x78\xdb\x38\x39\xb0\x0b\x01\x39\xcf\xda\x20\x6b\x6b\x0e\xc8\x01\x30\x7d\xe3\x01\xfa\x07\x57\xd8\x52\x32\x2c\x06\x08\x1e\xdc\xa1\xab\xbe\x78\xec\xf3\x5d\x20\x75\x9b\xb0\x40\x16\xbd\xc6\x63\x6f\x69\x25\x96\xe2\xed\x33\x85\x56\x74\x79\x93\x01\x1c\xf9\xda\x1a\x1f\x56\x21\xbe\x56\x27\x05\x5d\x2f\xfb\x0b\x5d\x60\xfd\x1e\x4a\x22\x73\x59\xc3\x7a\x55\x6d\xc3\x4b\xab\xcd\x52\x78\x46\x6e\x7c\x5c\xb9\x46\xe7\x49\x89\x16\xe7\x23\xec\x0e\x37\xa2\xc6\x6d\x69\x51\xf5\xac\x9e\xb5\x5c\x91\x13\x35\xca\xd5\xf1\x96\x9d\xb5\x40\x5f\xc4\xb9\xa5\xad\x2a\x34\xaa\x87\x57\x6c\xdf\x75\x36\xe8\xea\xa4\x64\xd0\xf9\xea\x6c\x35\xec\x09\x3b\xe1\x50\xf2\xb0\x97\x1d\x1a\x1f\xc4\xdf\x9a\x37\x6e\xeb\xf5\xd2\x20\x37\x8e\x7a\x9d\x1f\x7c\x8c\xdc\xce\xa2\x2f\x9a\xe3\xe9\xe7\xec\x05\xb4\xfa\x26\xf6\xdb\x3d\x9b\xc6\x9c\xba\xde\xd9\x6f\xee\x06\x22\x08\x9d\x2c\xc4\x62\x7b\xd8\xac\xd9\x14\x4e\xa2\x77\x28\x37\x0b\xcf\xee\xfa\xea\xc3\xff\xfc\xb9\x82\xef\xdf\xfb\x8b\x95\xc2\xed\xa7\x8f\x29\x7c\xfa\x78\x13\x1c\x5a\xa5\x1d\x0d\xd2\x76\x9b\xcf\x1f\x87\x58\x3b\xc2\xa2\x44\xd2\xf1\xdf\x84\xe3\x7d\x52\xb5\x5a\xec\xe9\xe4\x81\x6c\xe5\x97\xda\x81\x9f\xbe\x9d\x7b\x17\x5f\xe6\xa1\xa3\x36\x14\x1b\xb6\x15\xb2\x96\x58\x96\xdb\xcb\xa7\x87\xa8\xe9\x48\xea\x5a\x93\xe1\xa3\xf0\xf7\xd9\xf2\x0e\x66\x21\x23\x99\x65\x50\xcb\xe3\x42\xfa\xf0\x3c\xac\xb1\xd4\xe1\xd5\x69\x91\xec\x0a\xc7\xec\x39\xe7\x54\xd4\xf9\xa5\x15\xef\x0f\x63\xd7\x01\xbb\xed\x11\xbd\x60\x7a\xd5\xae\x85\x9a\x4c\x67\x89\x99\x10\xd7\xe9\x5d\xf6\x14\xba\xdd\xe7\x13\xc0\xc9\x97\xcf\x20\x63\x06\xb1\x88\xa0\x08\x7c\x78\x1f\xb1\xeb\xde\xdf\x37\x77\xc9\xbf\x01\x00\x00\xff\xff\xc7\x20\x3e\x09\x85\x0a\x00\x00")
|
||||
var __000001_initUpDbSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x56\xd1\x6f\xe2\xb8\x13\x7e\xe7\xaf\x18\xe9\xf7\x40\x2b\xd1\x9f\xf6\xa4\xbd\xbd\x93\xfa\x44\xd9\xf4\x0e\x1d\x07\x2b\x9a\x9e\xba\x4f\xd6\xe0\x0c\xc4\xc2\xb1\x23\x7b\x02\x8b\xb4\x7f\xfc\xc9\x81\x40\x0c\x81\xee\xea\xfa\x50\xb5\x33\xe3\x19\xcf\x37\xf3\x7d\xce\x68\x9e\x0c\xd3\x04\xd2\xe1\xd3\x24\x81\xf1\x33\x4c\x67\x29\x24\x6f\xe3\x97\xf4\x05\x64\x8e\xec\xe1\xae\x07\xa0\x32\xf8\x67\x38\x1f\xfd\x39\x9c\xc3\x97\xf9\xf8\xef\xe1\xfc\x2b\xfc\x95\x7c\x85\xd9\x14\x46\xb3\xe9\xf3\x64\x3c\x4a\x61\x9e\x7c\x99\x0c\x47\xc9\xa0\x07\x60\xb0\xa0\x63\x7c\xc8\x37\x7d\x9d\x4c\x82\x43\x5a\x6d\xdd\x85\x07\x3e\x27\xcf\xc3\xd7\x49\x0a\xfd\xff\xe1\x2f\xbf\xff\x96\xfd\xda\x0f\xb1\xbc\x2b\x09\xc6\xd3\x34\x4a\x80\x92\xd5\x86\xe0\x69\x36\x9b\x24\xc3\xe9\x65\x86\x74\xfe\x5a\xdf\x80\x55\x41\x9e\xb1\x28\x2f\x32\x64\xa4\x89\x29\x13\xc8\x42\x6a\x2b\xd7\x62\x83\xba\x8a\x0b\x1d\xb3\x7d\x08\x07\xca\x6a\xa1\x95\x14\x6b\xda\xc1\xd3\x64\xf6\x14\x4c\x95\xd9\x28\xda\x52\x26\x0a\xf2\x1e\x57\x24\xa4\xad\x0c\xdf\xc8\xa1\xd1\xff\x68\xb9\x3a\xf4\x90\xf7\x58\xb0\xa0\x62\x41\xce\x9f\xff\x9f\xab\x52\x54\x65\x86\x4c\x7b\x57\xef\xfe\xb1\xd7\x8b\xe6\x29\xad\x61\x94\xa7\x21\xa6\xc9\x5b\xfa\x23\x13\xc4\x2c\x73\xe4\xfd\x3e\xbe\x0d\x5f\x3d\xda\x0b\x2b\x19\x2f\x36\xe4\xd4\x52\x51\x76\x1c\x4e\xd3\xd6\xf3\x70\xf2\x92\x9c\x47\x09\xbc\x85\x17\x6a\x85\x1d\xc5\x55\x46\x86\x95\xb4\xe6\xd2\x55\xe6\x96\xed\xa5\xb9\x46\x73\x0f\x51\x76\xa3\x9e\xdf\x79\xa6\x42\x30\xae\x4e\x18\x67\xb4\x51\x92\x84\x32\x4b\x7b\xb4\xb1\x53\x8b\x8a\x49\xb0\x15\x8c\x7a\x1d\xd7\xab\xd1\x7f\x78\x80\x31\xf7\x3d\xa8\xa2\xb4\x8e\xd1\x30\x70\x8e\xe1\x97\xf2\xc0\xb8\xd0\x04\x39\x7a\x70\x76\xab\x32\x40\x0f\x5b\x02\x47\x7a\x07\xd6\x80\xe2\x70\x78\x9b\x93\x09\x87\x35\x15\xa1\x57\xb3\x02\x65\x96\xca\x28\xa6\x07\x2f\x9d\xd5\xfa\xff\xbd\x1b\x84\xad\x3c\xb9\x66\x79\xf6\x33\xff\x59\xea\x02\x6c\x73\xe5\x4b\x72\x22\xa2\x50\xf2\x47\x12\x33\x19\xc0\xdb\xca\xc9\x8e\x5d\x08\xc8\x79\x56\x06\x59\x59\x73\x44\x0e\x80\xe9\x1b\x77\x8a\x02\xd4\x5b\x4a\x86\x45\x27\xe5\xa1\xee\xaa\x2d\x29\x87\x7c\x57\x29\x0e\xb5\x70\x89\x56\xe3\xb1\x57\x5b\x89\x5a\xdc\x8e\xc9\x55\x46\xd7\x37\x19\xc0\x91\x2f\xad\xf1\x61\x15\xe2\x6b\x35\x92\xd0\xf4\x72\xb8\xd0\x15\xee\x1f\xa0\x24\x32\xd7\x35\xad\x55\xd5\x56\xbc\xb2\xca\xac\x84\x67\xe4\xca\xc7\x95\x4b\x74\x9e\x32\x51\xe3\x7c\x82\xdd\xe1\x56\x94\xb8\xd3\x16\xb3\x96\xd5\xb3\x92\x6b\x72\xa2\x44\xb9\x3e\xdd\xb2\xb1\xe6\xe8\xf3\x38\xb7\xb4\x45\x81\x26\x6b\xe1\x15\xdb\xf7\x9d\x75\xba\x1a\x29\xe9\x74\x2e\x9d\x2d\xba\x3d\x61\x27\x1c\x4a\xee\xf6\xb2\x43\xe3\xc3\x63\x60\xcd\x8d\xdb\x7a\xb5\x32\xc8\x95\xa3\x56\xe7\x47\x1f\x23\xd7\xb3\x68\x8b\xe6\x78\xfa\x39\x79\x03\x95\x7d\x13\x87\xed\x9e\x4d\x63\x4e\xdd\xed\xed\xf7\x8f\x1d\x27\x08\x9d\xcc\xc5\x62\x77\xdc\xac\xd9\x14\xce\x4e\xef\x51\xae\x16\x9e\xdd\x5d\xff\xc3\x7f\xfc\xe9\xc3\xf7\xef\xed\xc5\x1a\xc0\xc3\xa7\x8f\x03\xf8\xf4\xf1\x3e\x38\x54\x36\x68\x68\x30\xa8\xb7\xf9\xf2\x71\x88\xb5\x23\x2c\x4a\x24\x1d\x3f\x27\x1c\xef\x93\xaa\xd6\x62\x4f\x67\x0f\x65\x2d\xbf\x54\x0f\xfc\xfc\x0d\x3d\xb8\xf8\x3a\x0f\x1d\xd5\x47\xb1\x62\x5b\x20\x2b\x89\x5a\xef\xae\x47\x77\x51\xd3\x91\x54\xa5\x22\xc3\x27\xe1\x6f\xb3\xe5\x1d\xcc\x42\x46\x32\xab\xa0\x96\xa7\x85\xf4\xe1\x79\xd8\xa0\x56\xe1\xd5\xa9\x91\x6c\x0a\xc7\xec\xb9\xe4\x54\xd4\xf9\xb5\x15\x6f\x0f\x63\xdf\x01\xbb\xdd\x09\xbd\x60\x5a\x2a\x57\x43\x4d\xa6\xb1\xc4\x4c\x88\xeb\xb4\x2e\x7b\x0e\x5d\xf3\x39\x75\xf6\x0d\xd4\xc9\x98\x4e\x2c\x22\x28\x02\x1f\xde\x47\xec\xae\xf5\xf7\xfd\x63\xef\xdf\x00\x00\x00\xff\xff\xd7\x95\x8b\x6b\x9f\x0a\x00\x00")
|
||||
|
||||
func _000001_initUpDbSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
|
@ -106,8 +106,8 @@ func _000001_initUpDbSql() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000001_init.up.db.sql", size: 2693, mode: os.FileMode(0644), modTime: time.Unix(1577718868, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x34, 0x9f, 0x6, 0x64, 0xcf, 0x97, 0xbe, 0xa8, 0xa2, 0x2f, 0xda, 0xc5, 0x9d, 0x26, 0x3, 0x65, 0x98, 0x8a, 0x7a, 0x6a, 0xc3, 0xd, 0x3f, 0x25, 0xfe, 0x4c, 0x5, 0xdb, 0x98, 0xa9, 0xf9, 0xf}}
|
||||
info := bindataFileInfo{name: "000001_init.up.db.sql", size: 2719, mode: os.FileMode(0644), modTime: time.Unix(1578756765, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x60, 0xdc, 0xeb, 0xe, 0xc2, 0x4f, 0x75, 0xa, 0xf6, 0x3e, 0xc7, 0xc4, 0x4, 0xe2, 0xe1, 0xa4, 0x73, 0x2f, 0x4a, 0xad, 0x1a, 0x0, 0xc3, 0x93, 0x9d, 0x77, 0x3e, 0x31, 0x91, 0x77, 0x2e, 0xc8}}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
|
@ -126,7 +126,7 @@ func docGo() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1574354941, 0)}
|
||||
info := bindataFileInfo{name: "doc.go", size: 377, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xef, 0xaf, 0xdf, 0xcf, 0x65, 0xae, 0x19, 0xfc, 0x9d, 0x29, 0xc1, 0x91, 0xaf, 0xb5, 0xd5, 0xb1, 0x56, 0xf3, 0xee, 0xa8, 0xba, 0x13, 0x65, 0xdb, 0xab, 0xcf, 0x4e, 0xac, 0x92, 0xe9, 0x60, 0xf1}}
|
||||
return a, nil
|
||||
}
|
||||
|
|
|
@ -5,9 +5,8 @@ package protobuf
|
|||
|
||||
import (
|
||||
fmt "fmt"
|
||||
math "math"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
|
@ -5,9 +5,8 @@ package protobuf
|
|||
|
||||
import (
|
||||
fmt "fmt"
|
||||
math "math"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
|
@ -5,9 +5,8 @@ package protobuf
|
|||
|
||||
import (
|
||||
fmt "fmt"
|
||||
math "math"
|
||||
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
|
@ -7,7 +7,8 @@ import (
|
|||
|
||||
encryptmigrations "github.com/status-im/status-go/protocol/encryption/migrations"
|
||||
appmigrations "github.com/status-im/status-go/protocol/migrations"
|
||||
transpmigrations "github.com/status-im/status-go/protocol/transport/whisper/migrations"
|
||||
wakumigrations "github.com/status-im/status-go/protocol/transport/waku/migrations"
|
||||
whispermigrations "github.com/status-im/status-go/protocol/transport/whisper/migrations"
|
||||
)
|
||||
|
||||
type getter func(string) ([]byte, error)
|
||||
|
@ -19,8 +20,12 @@ type migrationsWithGetter struct {
|
|||
|
||||
var defaultMigrations = []migrationsWithGetter{
|
||||
{
|
||||
Names: transpmigrations.AssetNames(),
|
||||
Getter: transpmigrations.Asset,
|
||||
Names: whispermigrations.AssetNames(),
|
||||
Getter: whispermigrations.Asset,
|
||||
},
|
||||
{
|
||||
Names: wakumigrations.AssetNames(),
|
||||
Getter: wakumigrations.Asset,
|
||||
},
|
||||
{
|
||||
Names: encryptmigrations.AssetNames(),
|
||||
|
|
22
vendor/github.com/status-im/status-go/protocol/transport/envelopes_monitor.go
generated
vendored
Normal file
22
vendor/github.com/status-im/status-go/protocol/transport/envelopes_monitor.go
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
package transport
|
||||
|
||||
import (
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type EnvelopesMonitorConfig struct {
|
||||
EnvelopeEventsHandler EnvelopeEventsHandler
|
||||
MaxAttempts int
|
||||
MailserverConfirmationsEnabled bool
|
||||
IsMailserver func(types.EnodeID) bool
|
||||
Logger *zap.Logger
|
||||
}
|
||||
|
||||
// EnvelopeEventsHandler used for two different event types.
|
||||
type EnvelopeEventsHandler interface {
|
||||
EnvelopeSent([][]byte)
|
||||
EnvelopeExpired([][]byte, error)
|
||||
MailServerRequestCompleted(types.Hash, types.Hash, []byte, error)
|
||||
MailServerRequestExpired(types.Hash)
|
||||
}
|
30
vendor/github.com/status-im/status-go/protocol/transport/filter.go
generated
vendored
Normal file
30
vendor/github.com/status-im/status-go/protocol/transport/filter.go
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
package transport
|
||||
|
||||
import "github.com/status-im/status-go/eth-node/types"
|
||||
|
||||
// TODO: revise fields encoding/decoding. Some are encoded using hexutil and some using encoding/hex.
|
||||
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 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 filters.
|
||||
// It's encoded using encoding/hex.
|
||||
Identity string `json:"identity"`
|
||||
// Topic is the whisper topic
|
||||
Topic types.TopicType `json:"topic"`
|
||||
// Discovery is whether this is a discovery topic
|
||||
Discovery bool `json:"discovery"`
|
||||
// Negotiated tells us whether is a negotiated topic
|
||||
Negotiated bool `json:"negotiated"`
|
||||
// Listen is whether we are actually listening for messages on this chat, or the filter is only created in order to be able to post on the topic
|
||||
Listen bool `json:"listen"`
|
||||
}
|
||||
|
||||
func (c *Filter) IsPublic() bool {
|
||||
return !c.OneToOne
|
||||
}
|
|
@ -1,66 +1,47 @@
|
|||
package whisper
|
||||
package transport
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"database/sql"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
)
|
||||
|
||||
const (
|
||||
discoveryTopic = "contact-discovery"
|
||||
minPow = 0.0
|
||||
)
|
||||
|
||||
var (
|
||||
// The number of partitions.
|
||||
nPartitions = big.NewInt(5000)
|
||||
minPow = 0.0
|
||||
)
|
||||
|
||||
type whisperFilter struct {
|
||||
type RawFilter struct {
|
||||
FilterID string
|
||||
Topic types.TopicType
|
||||
SymKeyID string
|
||||
}
|
||||
|
||||
// TODO: revise fields encoding/decoding. Some are encoded using hexutil and some using encoding/hex.
|
||||
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 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 filters.
|
||||
// It's encoded using encoding/hex.
|
||||
Identity string `json:"identity"`
|
||||
// Topic is the whisper topic
|
||||
Topic types.TopicType `json:"topic"`
|
||||
// Discovery is whether this is a discovery topic
|
||||
Discovery bool `json:"discovery"`
|
||||
// Negotiated tells us whether is a negotiated topic
|
||||
Negotiated bool `json:"negotiated"`
|
||||
// Listen is whether we are actually listening for messages on this chat, or the filter is only created in order to be able to post on the topic
|
||||
Listen bool `json:"listen"`
|
||||
type KeysPersistence interface {
|
||||
All() (map[string][]byte, error)
|
||||
Add(chatID string, key []byte) error
|
||||
}
|
||||
|
||||
func (c *Filter) IsPublic() bool {
|
||||
return !c.OneToOne
|
||||
type FiltersService interface {
|
||||
AddKeyPair(key *ecdsa.PrivateKey) (string, error)
|
||||
DeleteKeyPair(keyID string) bool
|
||||
|
||||
AddSymKeyDirect(key []byte) (string, error)
|
||||
AddSymKeyFromPassword(password string) (string, error)
|
||||
GetSymKey(id string) ([]byte, error)
|
||||
DeleteSymKey(id string) bool
|
||||
|
||||
Subscribe(opts *types.SubscriptionOptions) (string, error)
|
||||
Unsubscribe(id string) error
|
||||
}
|
||||
|
||||
type filtersManager struct {
|
||||
whisper types.Whisper
|
||||
persistence *sqlitePersistence
|
||||
type FiltersManager struct {
|
||||
service FiltersService
|
||||
persistence KeysPersistence
|
||||
privateKey *ecdsa.PrivateKey
|
||||
keys map[string][]byte // a cache of symmetric manager derived from passwords
|
||||
logger *zap.Logger
|
||||
|
@ -71,22 +52,20 @@ type filtersManager struct {
|
|||
filters map[string]*Filter
|
||||
}
|
||||
|
||||
// newFiltersManager returns a new filtersManager.
|
||||
func newFiltersManager(db *sql.DB, w types.Whisper, privateKey *ecdsa.PrivateKey, logger *zap.Logger) (*filtersManager, error) {
|
||||
// NewFiltersManager returns a new filtersManager.
|
||||
func NewFiltersManager(persistence KeysPersistence, service FiltersService, privateKey *ecdsa.PrivateKey, logger *zap.Logger) (*FiltersManager, error) {
|
||||
if logger == nil {
|
||||
logger = zap.NewNop()
|
||||
}
|
||||
|
||||
persistence := newSQLitePersistence(db)
|
||||
|
||||
keys, err := persistence.All()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &filtersManager{
|
||||
return &FiltersManager{
|
||||
privateKey: privateKey,
|
||||
whisper: w,
|
||||
service: service,
|
||||
persistence: persistence,
|
||||
keys: keys,
|
||||
filters: make(map[string]*Filter),
|
||||
|
@ -94,7 +73,7 @@ func newFiltersManager(db *sql.DB, w types.Whisper, privateKey *ecdsa.PrivateKey
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (s *filtersManager) Init(
|
||||
func (s *FiltersManager) Init(
|
||||
chatIDs []string,
|
||||
publicKeys []*ecdsa.PublicKey,
|
||||
) ([]*Filter, error) {
|
||||
|
@ -146,7 +125,7 @@ func (s *filtersManager) Init(
|
|||
}
|
||||
|
||||
// DEPRECATED
|
||||
func (s *filtersManager) InitWithFilters(filters []*Filter) ([]*Filter, error) {
|
||||
func (s *FiltersManager) InitWithFilters(filters []*Filter) ([]*Filter, error) {
|
||||
var (
|
||||
chatIDs []string
|
||||
publicKeys []*ecdsa.PublicKey
|
||||
|
@ -154,7 +133,7 @@ func (s *filtersManager) InitWithFilters(filters []*Filter) ([]*Filter, error) {
|
|||
|
||||
for _, filter := range filters {
|
||||
if filter.Identity != "" && filter.OneToOne {
|
||||
publicKey, err := strToPublicKey(filter.Identity)
|
||||
publicKey, err := StrToPublicKey(filter.Identity)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -167,7 +146,7 @@ func (s *filtersManager) InitWithFilters(filters []*Filter) ([]*Filter, error) {
|
|||
return s.Init(chatIDs, publicKeys)
|
||||
}
|
||||
|
||||
func (s *filtersManager) Reset() error {
|
||||
func (s *FiltersManager) Reset() error {
|
||||
var filters []*Filter
|
||||
|
||||
s.mutex.Lock()
|
||||
|
@ -179,7 +158,7 @@ func (s *filtersManager) Reset() error {
|
|||
return s.Remove(filters...)
|
||||
}
|
||||
|
||||
func (s *filtersManager) Filters() (result []*Filter) {
|
||||
func (s *FiltersManager) Filters() (result []*Filter) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
|
@ -190,14 +169,14 @@ func (s *filtersManager) Filters() (result []*Filter) {
|
|||
return
|
||||
}
|
||||
|
||||
func (s *filtersManager) Filter(chatID string) *Filter {
|
||||
func (s *FiltersManager) Filter(chatID string) *Filter {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
return s.filters[chatID]
|
||||
}
|
||||
|
||||
// FilterByFilterID returns a Filter with a given Whisper filter ID.
|
||||
func (s *filtersManager) FilterByFilterID(filterID string) *Filter {
|
||||
func (s *FiltersManager) FilterByFilterID(filterID string) *Filter {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
for _, f := range s.filters {
|
||||
|
@ -208,11 +187,11 @@ func (s *filtersManager) FilterByFilterID(filterID string) *Filter {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *filtersManager) FiltersByPublicKey(publicKey *ecdsa.PublicKey) (result []*Filter) {
|
||||
func (s *FiltersManager) FiltersByPublicKey(publicKey *ecdsa.PublicKey) (result []*Filter) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
identityStr := publicKeyToStr(publicKey)
|
||||
identityStr := PublicKeyToStr(publicKey)
|
||||
|
||||
for _, f := range s.filters {
|
||||
if f.Identity == identityStr {
|
||||
|
@ -224,16 +203,16 @@ func (s *filtersManager) FiltersByPublicKey(publicKey *ecdsa.PublicKey) (result
|
|||
}
|
||||
|
||||
// Remove remove all the filters associated with a chat/identity
|
||||
func (s *filtersManager) Remove(filters ...*Filter) error {
|
||||
func (s *FiltersManager) Remove(filters ...*Filter) error {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
for _, f := range filters {
|
||||
if err := s.whisper.Unsubscribe(f.FilterID); err != nil {
|
||||
if err := s.service.Unsubscribe(f.FilterID); err != nil {
|
||||
return err
|
||||
}
|
||||
if f.SymKeyID != "" {
|
||||
s.whisper.DeleteSymKey(f.SymKeyID)
|
||||
s.service.DeleteSymKey(f.SymKeyID)
|
||||
}
|
||||
delete(s.filters, f.ChatID)
|
||||
}
|
||||
|
@ -242,19 +221,19 @@ func (s *filtersManager) Remove(filters ...*Filter) error {
|
|||
}
|
||||
|
||||
// LoadPartitioned creates a filter for a partitioned topic.
|
||||
func (s *filtersManager) LoadPartitioned(publicKey *ecdsa.PublicKey) (*Filter, error) {
|
||||
func (s *FiltersManager) LoadPartitioned(publicKey *ecdsa.PublicKey) (*Filter, error) {
|
||||
return s.loadPartitioned(publicKey, false)
|
||||
}
|
||||
|
||||
func (s *filtersManager) loadMyPartitioned() (*Filter, error) {
|
||||
func (s *FiltersManager) loadMyPartitioned() (*Filter, error) {
|
||||
return s.loadPartitioned(&s.privateKey.PublicKey, true)
|
||||
}
|
||||
|
||||
func (s *filtersManager) loadPartitioned(publicKey *ecdsa.PublicKey, listen bool) (*Filter, error) {
|
||||
func (s *FiltersManager) loadPartitioned(publicKey *ecdsa.PublicKey, listen bool) (*Filter, error) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
chatID := partitionedTopic(publicKey)
|
||||
chatID := PartitionedTopic(publicKey)
|
||||
if _, ok := s.filters[chatID]; ok {
|
||||
return s.filters[chatID], nil
|
||||
}
|
||||
|
@ -270,7 +249,7 @@ func (s *filtersManager) loadPartitioned(publicKey *ecdsa.PublicKey, listen bool
|
|||
ChatID: chatID,
|
||||
FilterID: filter.FilterID,
|
||||
Topic: filter.Topic,
|
||||
Identity: publicKeyToStr(publicKey),
|
||||
Identity: PublicKeyToStr(publicKey),
|
||||
Listen: listen,
|
||||
OneToOne: true,
|
||||
}
|
||||
|
@ -281,11 +260,11 @@ func (s *filtersManager) loadPartitioned(publicKey *ecdsa.PublicKey, listen bool
|
|||
}
|
||||
|
||||
// LoadNegotiated loads a negotiated secret as a filter.
|
||||
func (s *filtersManager) LoadNegotiated(secret types.NegotiatedSecret) (*Filter, error) {
|
||||
func (s *FiltersManager) LoadNegotiated(secret types.NegotiatedSecret) (*Filter, error) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
chatID := negotiatedTopic(secret.PublicKey)
|
||||
chatID := NegotiatedTopic(secret.PublicKey)
|
||||
|
||||
if _, ok := s.filters[chatID]; ok {
|
||||
return s.filters[chatID], nil
|
||||
|
@ -302,7 +281,7 @@ func (s *filtersManager) LoadNegotiated(secret types.NegotiatedSecret) (*Filter,
|
|||
Topic: filter.Topic,
|
||||
SymKeyID: filter.SymKeyID,
|
||||
FilterID: filter.FilterID,
|
||||
Identity: publicKeyToStr(secret.PublicKey),
|
||||
Identity: PublicKeyToStr(secret.PublicKey),
|
||||
Negotiated: true,
|
||||
Listen: true,
|
||||
OneToOne: true,
|
||||
|
@ -315,11 +294,11 @@ func (s *filtersManager) LoadNegotiated(secret types.NegotiatedSecret) (*Filter,
|
|||
|
||||
// LoadDiscovery adds 1 discovery filter
|
||||
// for the personal discovery topic.
|
||||
func (s *filtersManager) LoadDiscovery() ([]*Filter, error) {
|
||||
func (s *FiltersManager) LoadDiscovery() ([]*Filter, error) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
personalDiscoveryTopic := personalDiscoveryTopic(&s.privateKey.PublicKey)
|
||||
personalDiscoveryTopic := PersonalDiscoveryTopic(&s.privateKey.PublicKey)
|
||||
|
||||
// Check if filters are already loaded.
|
||||
var result []*Filter
|
||||
|
@ -334,9 +313,7 @@ func (s *filtersManager) LoadDiscovery() ([]*Filter, error) {
|
|||
return result, nil
|
||||
}
|
||||
|
||||
var discoveryResponse *whisperFilter
|
||||
var err error
|
||||
identityStr := publicKeyToStr(&s.privateKey.PublicKey)
|
||||
identityStr := PublicKeyToStr(&s.privateKey.PublicKey)
|
||||
|
||||
// Load personal discovery
|
||||
personalDiscoveryChat := &Filter{
|
||||
|
@ -347,7 +324,7 @@ func (s *filtersManager) LoadDiscovery() ([]*Filter, error) {
|
|||
OneToOne: true,
|
||||
}
|
||||
|
||||
discoveryResponse, err = s.addAsymmetric(personalDiscoveryChat.ChatID, true)
|
||||
discoveryResponse, err := s.addAsymmetric(personalDiscoveryChat.ChatID, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -361,7 +338,7 @@ func (s *filtersManager) LoadDiscovery() ([]*Filter, error) {
|
|||
}
|
||||
|
||||
// LoadPublic adds a filter for a public chat.
|
||||
func (s *filtersManager) LoadPublic(chatID string) (*Filter, error) {
|
||||
func (s *FiltersManager) LoadPublic(chatID string) (*Filter, error) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
|
@ -389,11 +366,11 @@ func (s *filtersManager) LoadPublic(chatID string) (*Filter, error) {
|
|||
}
|
||||
|
||||
// LoadContactCode creates a filter for the advertise topic for a given public key.
|
||||
func (s *filtersManager) LoadContactCode(pubKey *ecdsa.PublicKey) (*Filter, error) {
|
||||
func (s *FiltersManager) LoadContactCode(pubKey *ecdsa.PublicKey) (*Filter, error) {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
chatID := contactCodeTopic(pubKey)
|
||||
chatID := ContactCodeTopic(pubKey)
|
||||
|
||||
if _, ok := s.filters[chatID]; ok {
|
||||
return s.filters[chatID], nil
|
||||
|
@ -409,7 +386,7 @@ func (s *filtersManager) LoadContactCode(pubKey *ecdsa.PublicKey) (*Filter, erro
|
|||
FilterID: contactCodeFilter.FilterID,
|
||||
Topic: contactCodeFilter.Topic,
|
||||
SymKeyID: contactCodeFilter.SymKeyID,
|
||||
Identity: publicKeyToStr(pubKey),
|
||||
Identity: PublicKeyToStr(pubKey),
|
||||
Listen: true,
|
||||
}
|
||||
|
||||
|
@ -418,25 +395,25 @@ func (s *filtersManager) LoadContactCode(pubKey *ecdsa.PublicKey) (*Filter, erro
|
|||
}
|
||||
|
||||
// addSymmetric adds a symmetric key filter
|
||||
func (s *filtersManager) addSymmetric(chatID string) (*whisperFilter, error) {
|
||||
func (s *FiltersManager) addSymmetric(chatID string) (*RawFilter, error) {
|
||||
var symKeyID string
|
||||
var err error
|
||||
|
||||
topic := toTopic(chatID)
|
||||
topic := ToTopic(chatID)
|
||||
topics := [][]byte{topic}
|
||||
|
||||
symKey, ok := s.keys[chatID]
|
||||
if ok {
|
||||
symKeyID, err = s.whisper.AddSymKeyDirect(symKey)
|
||||
symKeyID, err = s.service.AddSymKeyDirect(symKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
symKeyID, err = s.whisper.AddSymKeyFromPassword(chatID)
|
||||
symKeyID, err = s.service.AddSymKeyFromPassword(chatID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if symKey, err = s.whisper.GetSymKey(symKeyID); err != nil {
|
||||
if symKey, err = s.service.GetSymKey(symKeyID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.keys[chatID] = symKey
|
||||
|
@ -447,7 +424,7 @@ func (s *filtersManager) addSymmetric(chatID string) (*whisperFilter, error) {
|
|||
}
|
||||
}
|
||||
|
||||
id, err := s.whisper.Subscribe(&types.SubscriptionOptions{
|
||||
id, err := s.service.Subscribe(&types.SubscriptionOptions{
|
||||
SymKeyID: symKeyID,
|
||||
PoW: minPow,
|
||||
Topics: topics,
|
||||
|
@ -456,7 +433,7 @@ func (s *filtersManager) addSymmetric(chatID string) (*whisperFilter, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &whisperFilter{
|
||||
return &RawFilter{
|
||||
FilterID: id,
|
||||
SymKeyID: symKeyID,
|
||||
Topic: types.BytesToTopic(topic),
|
||||
|
@ -465,7 +442,7 @@ func (s *filtersManager) addSymmetric(chatID string) (*whisperFilter, error) {
|
|||
|
||||
// addAsymmetricFilter adds a filter with our private key
|
||||
// and set minPow according to the listen parameter.
|
||||
func (s *filtersManager) addAsymmetric(chatID string, listen bool) (*whisperFilter, error) {
|
||||
func (s *FiltersManager) addAsymmetric(chatID string, listen bool) (*RawFilter, error) {
|
||||
var (
|
||||
err error
|
||||
pow = 1.0 // use PoW high enough to discard all messages for the filter
|
||||
|
@ -475,15 +452,15 @@ func (s *filtersManager) addAsymmetric(chatID string, listen bool) (*whisperFilt
|
|||
pow = minPow
|
||||
}
|
||||
|
||||
topic := toTopic(chatID)
|
||||
topic := ToTopic(chatID)
|
||||
topics := [][]byte{topic}
|
||||
|
||||
privateKeyID, err := s.whisper.AddKeyPair(s.privateKey)
|
||||
privateKeyID, err := s.service.AddKeyPair(s.privateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
id, err := s.whisper.Subscribe(&types.SubscriptionOptions{
|
||||
id, err := s.service.Subscribe(&types.SubscriptionOptions{
|
||||
PrivateKeyID: privateKeyID,
|
||||
PoW: pow,
|
||||
Topics: topics,
|
||||
|
@ -491,58 +468,13 @@ func (s *filtersManager) addAsymmetric(chatID string, listen bool) (*whisperFilt
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &whisperFilter{FilterID: id, Topic: types.BytesToTopic(topic)}, nil
|
||||
return &RawFilter{FilterID: id, Topic: types.BytesToTopic(topic)}, nil
|
||||
}
|
||||
|
||||
// GetNegotiated returns a negotiated chat given an identity
|
||||
func (s *filtersManager) GetNegotiated(identity *ecdsa.PublicKey) *Filter {
|
||||
func (s *FiltersManager) GetNegotiated(identity *ecdsa.PublicKey) *Filter {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
return s.filters[negotiatedTopic(identity)]
|
||||
}
|
||||
|
||||
func toTopic(s string) []byte {
|
||||
return crypto.Keccak256([]byte(s))[:types.TopicLength]
|
||||
}
|
||||
|
||||
// ToTopic converts a string to a whisper topic.
|
||||
func ToTopic(s string) []byte {
|
||||
return toTopic(s)
|
||||
}
|
||||
|
||||
func strToPublicKey(str string) (*ecdsa.PublicKey, error) {
|
||||
publicKeyBytes, err := hex.DecodeString(str)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return crypto.UnmarshalPubkey(publicKeyBytes)
|
||||
}
|
||||
|
||||
func publicKeyToStr(publicKey *ecdsa.PublicKey) string {
|
||||
return hex.EncodeToString(crypto.FromECDSAPub(publicKey))
|
||||
}
|
||||
|
||||
func personalDiscoveryTopic(publicKey *ecdsa.PublicKey) string {
|
||||
return "contact-discovery-" + publicKeyToStr(publicKey)
|
||||
}
|
||||
|
||||
// partitionedTopic returns the associated partitioned topic string
|
||||
// with the given public key.
|
||||
func partitionedTopic(publicKey *ecdsa.PublicKey) string {
|
||||
partition := big.NewInt(0)
|
||||
partition.Mod(publicKey.X, nPartitions)
|
||||
return "contact-discovery-" + strconv.FormatInt(partition.Int64(), 10)
|
||||
}
|
||||
|
||||
func ContactCodeTopic(publicKey *ecdsa.PublicKey) string {
|
||||
return contactCodeTopic(publicKey)
|
||||
}
|
||||
|
||||
func contactCodeTopic(publicKey *ecdsa.PublicKey) string {
|
||||
return "0x" + publicKeyToStr(publicKey) + "-contact-code"
|
||||
}
|
||||
|
||||
func negotiatedTopic(publicKey *ecdsa.PublicKey) string {
|
||||
return "0x" + publicKeyToStr(publicKey) + "-negotiated"
|
||||
return s.filters[NegotiatedTopic(identity)]
|
||||
}
|
13
vendor/github.com/status-im/status-go/protocol/transport/message.go
generated
vendored
Normal file
13
vendor/github.com/status-im/status-go/protocol/transport/message.go
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
package transport
|
||||
|
||||
import "github.com/status-im/status-go/eth-node/types"
|
||||
|
||||
func DefaultMessage() types.NewMessage {
|
||||
msg := types.NewMessage{}
|
||||
|
||||
msg.TTL = 10
|
||||
msg.PowTarget = 0.002
|
||||
msg.PowTime = 1
|
||||
|
||||
return msg
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package transport
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
)
|
||||
|
||||
const discoveryTopic = "contact-discovery"
|
||||
|
||||
var (
|
||||
// The number of partitions.
|
||||
nPartitions = big.NewInt(5000)
|
||||
)
|
||||
|
||||
// ToTopic converts a string to a whisper topic.
|
||||
func ToTopic(s string) []byte {
|
||||
return crypto.Keccak256([]byte(s))[:types.TopicLength]
|
||||
}
|
||||
|
||||
func StrToPublicKey(str string) (*ecdsa.PublicKey, error) {
|
||||
publicKeyBytes, err := hex.DecodeString(str)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return crypto.UnmarshalPubkey(publicKeyBytes)
|
||||
}
|
||||
|
||||
func PublicKeyToStr(publicKey *ecdsa.PublicKey) string {
|
||||
return hex.EncodeToString(crypto.FromECDSAPub(publicKey))
|
||||
}
|
||||
|
||||
func PersonalDiscoveryTopic(publicKey *ecdsa.PublicKey) string {
|
||||
return "contact-discovery-" + PublicKeyToStr(publicKey)
|
||||
}
|
||||
|
||||
// PartitionedTopic returns the associated partitioned topic string
|
||||
// with the given public key.
|
||||
func PartitionedTopic(publicKey *ecdsa.PublicKey) string {
|
||||
partition := big.NewInt(0)
|
||||
partition.Mod(publicKey.X, nPartitions)
|
||||
return "contact-discovery-" + strconv.FormatInt(partition.Int64(), 10)
|
||||
}
|
||||
|
||||
func ContactCodeTopic(publicKey *ecdsa.PublicKey) string {
|
||||
return "0x" + PublicKeyToStr(publicKey) + "-contact-code"
|
||||
}
|
||||
|
||||
func NegotiatedTopic(publicKey *ecdsa.PublicKey) string {
|
||||
return "0x" + PublicKeyToStr(publicKey) + "-negotiated"
|
||||
}
|
||||
|
||||
func DiscoveryTopic() string {
|
||||
return discoveryTopic
|
||||
}
|
38
vendor/github.com/status-im/status-go/protocol/transport/transport.go
generated
vendored
Normal file
38
vendor/github.com/status-im/status-go/protocol/transport/transport.go
generated
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
package transport
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
)
|
||||
|
||||
type Transport interface {
|
||||
Stop() error
|
||||
|
||||
JoinPrivate(publicKey *ecdsa.PublicKey) error
|
||||
LeavePrivate(publicKey *ecdsa.PublicKey) error
|
||||
JoinGroup(publicKeys []*ecdsa.PublicKey) error
|
||||
LeaveGroup(publicKeys []*ecdsa.PublicKey) error
|
||||
JoinPublic(chatID string) error
|
||||
LeavePublic(chatID string) error
|
||||
|
||||
SendPublic(ctx context.Context, newMessage *types.NewMessage, chatName string) ([]byte, error)
|
||||
SendPrivateWithSharedSecret(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey, secret []byte) ([]byte, error)
|
||||
SendPrivateWithPartitioned(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error)
|
||||
SendMessagesRequest(
|
||||
ctx context.Context,
|
||||
peerID []byte,
|
||||
from, to uint32,
|
||||
previousCursor []byte,
|
||||
) (cursor []byte, err error)
|
||||
|
||||
Track(identifiers [][]byte, hash []byte, newMessage *types.NewMessage)
|
||||
|
||||
InitFilters(chatIDs []string, publicKeys []*ecdsa.PublicKey) ([]*Filter, error)
|
||||
LoadFilters(filters []*Filter) ([]*Filter, error)
|
||||
RemoveFilters(filters []*Filter) error
|
||||
ResetFilters() error
|
||||
ProcessNegotiatedSecret(secret types.NegotiatedSecret) (*Filter, error)
|
||||
RetrieveRawAll() (map[Filter][]*types.Message, error)
|
||||
}
|
310
vendor/github.com/status-im/status-go/protocol/transport/waku/envelopes.go
generated
vendored
Normal file
310
vendor/github.com/status-im/status-go/protocol/transport/waku/envelopes.go
generated
vendored
Normal file
|
@ -0,0 +1,310 @@
|
|||
package waku
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/protocol/transport"
|
||||
)
|
||||
|
||||
// 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 waku queue.
|
||||
EnvelopePosted EnvelopeState = iota
|
||||
// EnvelopeSent is set when envelope is sent to at least one peer.
|
||||
EnvelopeSent
|
||||
)
|
||||
|
||||
// EnvelopeEventsHandler used for two different event types.
|
||||
type EnvelopeEventsHandler interface {
|
||||
EnvelopeSent([][]byte)
|
||||
EnvelopeExpired([][]byte, error)
|
||||
MailServerRequestCompleted(types.Hash, types.Hash, []byte, error)
|
||||
MailServerRequestExpired(types.Hash)
|
||||
}
|
||||
|
||||
// NewEnvelopesMonitor returns a pointer to an instance of the EnvelopesMonitor.
|
||||
func NewEnvelopesMonitor(w types.Waku, config transport.EnvelopesMonitorConfig) *EnvelopesMonitor {
|
||||
logger := config.Logger
|
||||
|
||||
if logger == nil {
|
||||
logger = zap.NewNop()
|
||||
}
|
||||
|
||||
var api types.PublicWakuAPI
|
||||
if w != nil {
|
||||
api = w.PublicWakuAPI()
|
||||
}
|
||||
|
||||
return &EnvelopesMonitor{
|
||||
w: w,
|
||||
api: api,
|
||||
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[types.Hash]EnvelopeState{},
|
||||
messages: map[types.Hash]*types.NewMessage{},
|
||||
attempts: map[types.Hash]int{},
|
||||
identifiers: make(map[types.Hash][][]byte),
|
||||
|
||||
// key is hash of the batch (event.Batch)
|
||||
batches: map[types.Hash]map[types.Hash]struct{}{},
|
||||
}
|
||||
}
|
||||
|
||||
// EnvelopesMonitor is responsible for monitoring waku envelopes state.
|
||||
type EnvelopesMonitor struct {
|
||||
w types.Waku
|
||||
api types.PublicWakuAPI
|
||||
handler EnvelopeEventsHandler
|
||||
mailServerConfirmation bool
|
||||
maxAttempts int
|
||||
|
||||
mu sync.Mutex
|
||||
envelopes map[types.Hash]EnvelopeState
|
||||
batches map[types.Hash]map[types.Hash]struct{}
|
||||
|
||||
messages map[types.Hash]*types.NewMessage
|
||||
attempts map[types.Hash]int
|
||||
identifiers map[types.Hash][][]byte
|
||||
|
||||
wg sync.WaitGroup
|
||||
quit chan struct{}
|
||||
isMailserver func(peer types.EnodeID) bool
|
||||
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// Start processing events.
|
||||
func (m *EnvelopesMonitor) Start() {
|
||||
m.quit = make(chan struct{})
|
||||
m.wg.Add(1)
|
||||
go func() {
|
||||
m.handleEnvelopeEvents()
|
||||
m.wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
// Stop process events.
|
||||
func (m *EnvelopesMonitor) Stop() {
|
||||
close(m.quit)
|
||||
m.wg.Wait()
|
||||
}
|
||||
|
||||
// Add hash to a tracker.
|
||||
func (m *EnvelopesMonitor) Add(identifiers [][]byte, envelopeHash types.Hash, message types.NewMessage) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.envelopes[envelopeHash] = EnvelopePosted
|
||||
m.identifiers[envelopeHash] = identifiers
|
||||
m.messages[envelopeHash] = &message
|
||||
m.attempts[envelopeHash] = 1
|
||||
}
|
||||
|
||||
func (m *EnvelopesMonitor) GetState(hash types.Hash) EnvelopeState {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
state, exist := m.envelopes[hash]
|
||||
if !exist {
|
||||
return NotRegistered
|
||||
}
|
||||
return state
|
||||
}
|
||||
|
||||
// handleEnvelopeEvents processes waku envelope events
|
||||
func (m *EnvelopesMonitor) handleEnvelopeEvents() {
|
||||
events := make(chan types.EnvelopeEvent, 100) // must be buffered to prevent blocking waku
|
||||
sub := m.w.SubscribeEnvelopeEvents(events)
|
||||
defer func() {
|
||||
close(events)
|
||||
sub.Unsubscribe()
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case <-m.quit:
|
||||
return
|
||||
case event := <-events:
|
||||
m.handleEvent(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handleEvent based on type of the event either triggers
|
||||
// confirmation handler or removes hash from tracker
|
||||
func (m *EnvelopesMonitor) handleEvent(event types.EnvelopeEvent) {
|
||||
handlers := map[types.EventType]func(types.EnvelopeEvent){
|
||||
types.EventEnvelopeSent: m.handleEventEnvelopeSent,
|
||||
types.EventEnvelopeExpired: m.handleEventEnvelopeExpired,
|
||||
types.EventBatchAcknowledged: m.handleAcknowledgedBatch,
|
||||
types.EventEnvelopeReceived: m.handleEventEnvelopeReceived,
|
||||
}
|
||||
if handler, ok := handlers[event.Event]; ok {
|
||||
handler(event)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *EnvelopesMonitor) handleEventEnvelopeSent(event types.EnvelopeEvent) {
|
||||
if m.mailServerConfirmation {
|
||||
if !m.isMailserver(event.Peer) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
state, ok := m.envelopes[event.Hash]
|
||||
// if we didn't send a message using extension - skip it
|
||||
// if message was already confirmed - skip it
|
||||
if !ok || state == EnvelopeSent {
|
||||
return
|
||||
}
|
||||
m.logger.Debug("envelope is sent", zap.String("hash", event.Hash.String()), zap.String("peer", event.Peer.String()))
|
||||
if event.Batch != (types.Hash{}) {
|
||||
if _, ok := m.batches[event.Batch]; !ok {
|
||||
m.batches[event.Batch] = map[types.Hash]struct{}{}
|
||||
}
|
||||
m.batches[event.Batch][event.Hash] = struct{}{}
|
||||
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(m.identifiers[event.Hash])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *EnvelopesMonitor) handleAcknowledgedBatch(event types.EnvelopeEvent) {
|
||||
if m.mailServerConfirmation {
|
||||
if !m.isMailserver(event.Peer) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
envelopes, ok := m.batches[event.Batch]
|
||||
if !ok {
|
||||
m.logger.Debug("batch is not found", zap.String("batch", event.Batch.String()))
|
||||
}
|
||||
m.logger.Debug("received a confirmation", zap.String("batch", event.Batch.String()), zap.String("peer", event.Peer.String()))
|
||||
envelopeErrors, ok := event.Data.([]types.EnvelopeError)
|
||||
if event.Data != nil && !ok {
|
||||
m.logger.Error("received unexpected data in the the confirmation event", zap.String("batch", event.Batch.String()))
|
||||
}
|
||||
failedEnvelopes := map[types.Hash]struct{}{}
|
||||
for i := range envelopeErrors {
|
||||
envelopeError := envelopeErrors[i]
|
||||
_, exist := m.envelopes[envelopeError.Hash]
|
||||
if exist {
|
||||
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 types.EnvelopeTimeNotSynced:
|
||||
err = errors.New("envelope wasn't delivered due to time sync issues")
|
||||
}
|
||||
m.handleEnvelopeFailure(envelopeError.Hash, err)
|
||||
}
|
||||
failedEnvelopes[envelopeError.Hash] = struct{}{}
|
||||
}
|
||||
|
||||
for hash := range envelopes {
|
||||
if _, exist := failedEnvelopes[hash]; exist {
|
||||
continue
|
||||
}
|
||||
state, ok := m.envelopes[hash]
|
||||
if !ok || state == EnvelopeSent {
|
||||
continue
|
||||
}
|
||||
m.envelopes[hash] = EnvelopeSent
|
||||
if m.handler != nil {
|
||||
m.handler.EnvelopeSent(m.identifiers[hash])
|
||||
}
|
||||
}
|
||||
delete(m.batches, event.Batch)
|
||||
}
|
||||
|
||||
func (m *EnvelopesMonitor) handleEventEnvelopeExpired(event types.EnvelopeEvent) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.handleEnvelopeFailure(event.Hash, errors.New("envelope expired due to connectivity issues"))
|
||||
}
|
||||
|
||||
// handleEnvelopeFailure is a common code path for processing envelopes failures. not thread safe, lock
|
||||
// must be used on a higher level.
|
||||
func (m *EnvelopesMonitor) handleEnvelopeFailure(hash types.Hash, err error) {
|
||||
if state, ok := m.envelopes[hash]; ok {
|
||||
message, exist := m.messages[hash]
|
||||
if !exist {
|
||||
m.logger.Error("message was deleted erroneously", zap.String("envelope hash", hash.String()))
|
||||
}
|
||||
attempt := m.attempts[hash]
|
||||
identifiers := m.identifiers[hash]
|
||||
m.clearMessageState(hash)
|
||||
if state == EnvelopeSent {
|
||||
return
|
||||
}
|
||||
if attempt < m.maxAttempts {
|
||||
m.logger.Debug("retrying to send a message", zap.String("hash", hash.String()), zap.Int("attempt", attempt+1))
|
||||
hex, err := m.api.Post(context.TODO(), *message)
|
||||
if err != nil {
|
||||
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 := types.BytesToHash(hex)
|
||||
m.envelopes[envelopeID] = EnvelopePosted
|
||||
m.messages[envelopeID] = message
|
||||
m.attempts[envelopeID] = attempt + 1
|
||||
m.identifiers[envelopeID] = identifiers
|
||||
} else {
|
||||
m.logger.Debug("envelope expired", zap.String("hash", hash.String()))
|
||||
if m.handler != nil {
|
||||
m.handler.EnvelopeExpired(identifiers, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *EnvelopesMonitor) handleEventEnvelopeReceived(event types.EnvelopeEvent) {
|
||||
if m.mailServerConfirmation {
|
||||
if !m.isMailserver(event.Peer) {
|
||||
return
|
||||
}
|
||||
}
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
state, ok := m.envelopes[event.Hash]
|
||||
if !ok || state != EnvelopePosted {
|
||||
return
|
||||
}
|
||||
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(m.identifiers[event.Hash])
|
||||
}
|
||||
}
|
||||
|
||||
// clearMessageState removes all message and envelope state.
|
||||
// not thread-safe, should be protected on a higher level.
|
||||
func (m *EnvelopesMonitor) clearMessageState(envelopeID types.Hash) {
|
||||
delete(m.envelopes, envelopeID)
|
||||
delete(m.messages, envelopeID)
|
||||
delete(m.attempts, envelopeID)
|
||||
delete(m.identifiers, envelopeID)
|
||||
}
|
38
vendor/github.com/status-im/status-go/protocol/transport/waku/mailserver.go
generated
vendored
Normal file
38
vendor/github.com/status-im/status-go/protocol/transport/waku/mailserver.go
generated
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
package waku
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
)
|
||||
|
||||
func createMessagesRequest(from, to uint32, cursor []byte, topics []types.TopicType) types.MessagesRequest {
|
||||
aUUID := uuid.New()
|
||||
// uuid is 16 bytes, converted to hex it's 32 bytes as expected by types.MessagesRequest
|
||||
id := []byte(hex.EncodeToString(aUUID[:]))
|
||||
return types.MessagesRequest{
|
||||
ID: id,
|
||||
From: from,
|
||||
To: to,
|
||||
Limit: 100,
|
||||
Cursor: cursor,
|
||||
Bloom: topicsToBloom(topics...),
|
||||
}
|
||||
}
|
||||
|
||||
func topicsToBloom(topics ...types.TopicType) []byte {
|
||||
i := new(big.Int)
|
||||
for _, topic := range topics {
|
||||
bloom := types.TopicToBloom(topic)
|
||||
i.Or(i, new(big.Int).SetBytes(bloom[:]))
|
||||
}
|
||||
|
||||
combined := make([]byte, types.BloomFilterSize)
|
||||
data := i.Bytes()
|
||||
copy(combined[types.BloomFilterSize-len(data):], data[:])
|
||||
|
||||
return combined
|
||||
}
|
319
vendor/github.com/status-im/status-go/protocol/transport/waku/migrations/migrations.go
generated
vendored
Normal file
319
vendor/github.com/status-im/status-go/protocol/transport/waku/migrations/migrations.go
generated
vendored
Normal file
|
@ -0,0 +1,319 @@
|
|||
// Code generated by go-bindata. DO NOT EDIT.
|
||||
// sources:
|
||||
// 1561059284_add_waku_keys.down.sql (22B)
|
||||
// 1561059284_add_waku_keys.up.sql (109B)
|
||||
// doc.go (373B)
|
||||
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func bindataRead(data []byte, name string) ([]byte, error) {
|
||||
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read %q: %v", name, err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
_, err = io.Copy(&buf, gz)
|
||||
clErr := gz.Close()
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read %q: %v", name, err)
|
||||
}
|
||||
if clErr != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
type asset struct {
|
||||
bytes []byte
|
||||
info os.FileInfo
|
||||
digest [sha256.Size]byte
|
||||
}
|
||||
|
||||
type bindataFileInfo struct {
|
||||
name string
|
||||
size int64
|
||||
mode os.FileMode
|
||||
modTime time.Time
|
||||
}
|
||||
|
||||
func (fi bindataFileInfo) Name() string {
|
||||
return fi.name
|
||||
}
|
||||
func (fi bindataFileInfo) Size() int64 {
|
||||
return fi.size
|
||||
}
|
||||
func (fi bindataFileInfo) Mode() os.FileMode {
|
||||
return fi.mode
|
||||
}
|
||||
func (fi bindataFileInfo) ModTime() time.Time {
|
||||
return fi.modTime
|
||||
}
|
||||
func (fi bindataFileInfo) IsDir() bool {
|
||||
return false
|
||||
}
|
||||
func (fi bindataFileInfo) Sys() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
var __1561059284_add_waku_keysDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\x09\xf2\x0f\x50\x08\x71\x74\xf2\x71\x55\x28\x4f\xcc\x2e\x8d\xcf\x4e\xad\x2c\xb6\xe6\x02\x04\x00\x00\xff\xff\x4f\x00\xe6\x8e\x16\x00\x00\x00")
|
||||
|
||||
func _1561059284_add_waku_keysDownSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
__1561059284_add_waku_keysDownSql,
|
||||
"1561059284_add_waku_keys.down.sql",
|
||||
)
|
||||
}
|
||||
|
||||
func _1561059284_add_waku_keysDownSql() (*asset, error) {
|
||||
bytes, err := _1561059284_add_waku_keysDownSqlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561059284_add_waku_keys.down.sql", size: 22, mode: os.FileMode(0644), modTime: time.Unix(1578604329, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe5, 0x2a, 0x7e, 0x9, 0xa3, 0xdd, 0xc6, 0x3, 0xfa, 0xaa, 0x98, 0xa0, 0x26, 0x5e, 0x67, 0x43, 0xe6, 0x20, 0xfd, 0x10, 0xfd, 0x60, 0x89, 0x17, 0x13, 0x87, 0x1b, 0x44, 0x36, 0x79, 0xb6, 0x60}}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var __1561059284_add_waku_keysUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x04\xc0\xb1\x0a\xc2\x40\x0c\x06\xe0\xfd\x9e\xe2\x1f\x15\x7c\x03\xa7\xbb\x33\x6a\x30\x26\x12\x52\x6a\xa7\x52\xb4\xa0\xdc\xa8\x22\x7d\xfb\x7e\xd5\x29\x07\x21\x72\x11\xc2\x7f\x6a\xbf\xb1\xcd\xcb\x07\x9b\x04\x3c\x5e\xd3\x77\x7c\x3f\x11\x74\x0f\xdc\x9c\xaf\xd9\x07\x5c\x68\x80\x29\xaa\xe9\x51\xb8\x06\xf8\xa4\xe6\xb4\x4b\x40\x9b\x17\x14\xb1\x02\xb5\x80\x76\x22\x69\x8b\x9e\xe3\x6c\x5d\xc0\xad\xe7\xc3\x3e\xad\x01\x00\x00\xff\xff\xbc\x45\x31\x54\x6d\x00\x00\x00")
|
||||
|
||||
func _1561059284_add_waku_keysUpSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
__1561059284_add_waku_keysUpSql,
|
||||
"1561059284_add_waku_keys.up.sql",
|
||||
)
|
||||
}
|
||||
|
||||
func _1561059284_add_waku_keysUpSql() (*asset, error) {
|
||||
bytes, err := _1561059284_add_waku_keysUpSqlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "1561059284_add_waku_keys.up.sql", size: 109, mode: os.FileMode(0644), modTime: time.Unix(1578604337, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa9, 0x5c, 0x8, 0x32, 0xef, 0x12, 0x88, 0x21, 0xd, 0x7a, 0x42, 0x4d, 0xe7, 0x2d, 0x6c, 0x99, 0xb6, 0x1, 0xf1, 0xba, 0x2c, 0x40, 0x8d, 0xa9, 0x4b, 0xe6, 0xc4, 0x21, 0xec, 0x47, 0x6b, 0xf7}}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var _docGo = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x8f\x3d\x72\xeb\x30\x0c\x84\x7b\x9d\x62\xc7\x8d\x9b\x27\xb2\x79\x55\xba\x94\xe9\x73\x01\x98\x5a\x91\x18\x4b\xa4\x42\xc0\x7f\xb7\xcf\xc8\xe3\xc2\x5d\xda\x1d\x7c\x1f\x76\x63\xc4\x77\x51\xc3\xac\x0b\xa1\x86\xca\x44\x33\xe9\x0f\x9c\x98\xe4\x62\xc4\x21\xab\x97\xcb\x29\xa4\xb6\x46\x73\xf1\x8b\x8d\xba\xc6\x55\x73\x17\x67\xbc\xfe\x3f\x0c\x31\x22\x49\x3d\x3a\x8a\xd4\x69\xe1\xd3\x65\x30\x97\xee\x5a\x33\x6e\xea\x05\x82\xad\x73\xd6\x7b\xc0\xa7\x63\xa1\x98\xc3\x8b\xf8\xd1\xe0\x85\x48\x62\xdc\x35\x73\xeb\xc8\x6d\x3c\x69\x9d\xc4\x25\xec\xd1\xd7\xfc\x96\xec\x0d\x93\x2c\x0b\x27\xcc\xbd\xad\x4f\xd6\x64\x25\x26\xed\x4c\xde\xfa\xe3\x1f\xc4\x8c\x8e\x2a\x2b\x6d\xe7\x8b\x5c\x89\xda\x5e\xef\x21\x75\xfa\x7b\x11\x6e\xad\x9f\x0d\x62\xe0\x7d\x63\x72\x4e\x61\x18\x36\x49\x67\xc9\x84\xfd\x2c\xea\x1c\x86\x18\x73\xfb\xc8\xac\xdc\xa9\xf7\x8e\xe3\x76\xce\xaf\x2b\x8c\x0d\x21\xbc\xd4\xda\xaa\x85\xdc\x10\x86\xdf\x00\x00\x00\xff\xff\x21\xa5\x75\x05\x75\x01\x00\x00")
|
||||
|
||||
func docGoBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_docGo,
|
||||
"doc.go",
|
||||
)
|
||||
}
|
||||
|
||||
func docGo() (*asset, error) {
|
||||
bytes, err := docGoBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "doc.go", size: 373, mode: os.FileMode(0644), modTime: time.Unix(1578604293, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x23, 0x6a, 0xc1, 0xce, 0x94, 0xf6, 0xef, 0xf1, 0x97, 0x95, 0xb, 0x35, 0xaf, 0x5f, 0xe7, 0x5f, 0xac, 0x6e, 0xb8, 0xab, 0xba, 0xb5, 0x35, 0x97, 0x22, 0x36, 0x11, 0xce, 0x44, 0xfc, 0xfa, 0xac}}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// Asset loads and returns the asset for the given name.
|
||||
// It returns an error if the asset could not be found or
|
||||
// could not be loaded.
|
||||
func Asset(name string) ([]byte, error) {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[canonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
|
||||
}
|
||||
return a.bytes, nil
|
||||
}
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
|
||||
// AssetString returns the asset contents as a string (instead of a []byte).
|
||||
func AssetString(name string) (string, error) {
|
||||
data, err := Asset(name)
|
||||
return string(data), err
|
||||
}
|
||||
|
||||
// MustAsset is like Asset but panics when Asset would return an error.
|
||||
// It simplifies safe initialization of global variables.
|
||||
func MustAsset(name string) []byte {
|
||||
a, err := Asset(name)
|
||||
if err != nil {
|
||||
panic("asset: Asset(" + name + "): " + err.Error())
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// MustAssetString is like AssetString but panics when Asset would return an
|
||||
// error. It simplifies safe initialization of global variables.
|
||||
func MustAssetString(name string) string {
|
||||
return string(MustAsset(name))
|
||||
}
|
||||
|
||||
// AssetInfo loads and returns the asset info for the given name.
|
||||
// It returns an error if the asset could not be found or
|
||||
// could not be loaded.
|
||||
func AssetInfo(name string) (os.FileInfo, error) {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[canonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
|
||||
}
|
||||
return a.info, nil
|
||||
}
|
||||
return nil, fmt.Errorf("AssetInfo %s not found", name)
|
||||
}
|
||||
|
||||
// AssetDigest returns the digest of the file with the given name. It returns an
|
||||
// error if the asset could not be found or the digest could not be loaded.
|
||||
func AssetDigest(name string) ([sha256.Size]byte, error) {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[canonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err)
|
||||
}
|
||||
return a.digest, nil
|
||||
}
|
||||
return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name)
|
||||
}
|
||||
|
||||
// Digests returns a map of all known files and their checksums.
|
||||
func Digests() (map[string][sha256.Size]byte, error) {
|
||||
mp := make(map[string][sha256.Size]byte, len(_bindata))
|
||||
for name := range _bindata {
|
||||
a, err := _bindata[name]()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mp[name] = a.digest
|
||||
}
|
||||
return mp, nil
|
||||
}
|
||||
|
||||
// AssetNames returns the names of the assets.
|
||||
func AssetNames() []string {
|
||||
names := make([]string, 0, len(_bindata))
|
||||
for name := range _bindata {
|
||||
names = append(names, name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||
var _bindata = map[string]func() (*asset, error){
|
||||
"1561059284_add_waku_keys.down.sql": _1561059284_add_waku_keysDownSql,
|
||||
|
||||
"1561059284_add_waku_keys.up.sql": _1561059284_add_waku_keysUpSql,
|
||||
|
||||
"doc.go": docGo,
|
||||
}
|
||||
|
||||
// AssetDir returns the file names below a certain
|
||||
// directory embedded in the file by go-bindata.
|
||||
// For example if you run go-bindata on data/... and data contains the
|
||||
// following hierarchy:
|
||||
// data/
|
||||
// foo.txt
|
||||
// img/
|
||||
// a.png
|
||||
// b.png
|
||||
// then AssetDir("data") would return []string{"foo.txt", "img"},
|
||||
// AssetDir("data/img") would return []string{"a.png", "b.png"},
|
||||
// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and
|
||||
// AssetDir("") will return []string{"data"}.
|
||||
func AssetDir(name string) ([]string, error) {
|
||||
node := _bintree
|
||||
if len(name) != 0 {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
pathList := strings.Split(canonicalName, "/")
|
||||
for _, p := range pathList {
|
||||
node = node.Children[p]
|
||||
if node == nil {
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
if node.Func != nil {
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
rv := make([]string, 0, len(node.Children))
|
||||
for childName := range node.Children {
|
||||
rv = append(rv, childName)
|
||||
}
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
type bintree struct {
|
||||
Func func() (*asset, error)
|
||||
Children map[string]*bintree
|
||||
}
|
||||
|
||||
var _bintree = &bintree{nil, map[string]*bintree{
|
||||
"1561059284_add_waku_keys.down.sql": &bintree{_1561059284_add_waku_keysDownSql, map[string]*bintree{}},
|
||||
"1561059284_add_waku_keys.up.sql": &bintree{_1561059284_add_waku_keysUpSql, map[string]*bintree{}},
|
||||
"doc.go": &bintree{docGo, map[string]*bintree{}},
|
||||
}}
|
||||
|
||||
// RestoreAsset restores an asset under the given directory.
|
||||
func RestoreAsset(dir, name string) error {
|
||||
data, err := Asset(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info, err := AssetInfo(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
|
||||
}
|
||||
|
||||
// RestoreAssets restores an asset under the given directory recursively.
|
||||
func RestoreAssets(dir, name string) error {
|
||||
children, err := AssetDir(name)
|
||||
// File
|
||||
if err != nil {
|
||||
return RestoreAsset(dir, name)
|
||||
}
|
||||
// Dir
|
||||
for _, child := range children {
|
||||
err = RestoreAssets(dir, filepath.Join(name, child))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func _filePath(dir, name string) string {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...)
|
||||
}
|
57
vendor/github.com/status-im/status-go/protocol/transport/waku/persistence.go
generated
vendored
Normal file
57
vendor/github.com/status-im/status-go/protocol/transport/waku/persistence.go
generated
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
package waku
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
type sqlitePersistence struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func newSQLitePersistence(db *sql.DB) *sqlitePersistence {
|
||||
return &sqlitePersistence{db: db}
|
||||
}
|
||||
|
||||
func (s *sqlitePersistence) Add(chatID string, key []byte) error {
|
||||
statement := "INSERT INTO waku_keys(chat_id, key) VALUES(?, ?)"
|
||||
stmt, err := s.db.Prepare(statement)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
_, err = stmt.Exec(chatID, key)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *sqlitePersistence) All() (map[string][]byte, error) {
|
||||
keys := make(map[string][]byte)
|
||||
|
||||
statement := "SELECT chat_id, key FROM waku_keys"
|
||||
|
||||
stmt, err := s.db.Prepare(statement)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
rows, err := stmt.Query()
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for rows.Next() {
|
||||
var (
|
||||
chatID string
|
||||
key []byte
|
||||
)
|
||||
|
||||
err := rows.Scan(&chatID, &key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keys[chatID] = key
|
||||
}
|
||||
|
||||
return keys, nil
|
||||
}
|
13
vendor/github.com/status-im/status-go/protocol/transport/waku/waku.go
generated
vendored
Normal file
13
vendor/github.com/status-im/status-go/protocol/transport/waku/waku.go
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
package waku
|
||||
|
||||
import (
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
)
|
||||
|
||||
type RequestOptions struct {
|
||||
Topics []types.TopicType
|
||||
Password string
|
||||
Limit int
|
||||
From int64 // in seconds
|
||||
To int64 // in seconds
|
||||
}
|
426
vendor/github.com/status-im/status-go/protocol/transport/waku/waku_service.go
generated
vendored
Normal file
426
vendor/github.com/status-im/status-go/protocol/transport/waku/waku_service.go
generated
vendored
Normal file
|
@ -0,0 +1,426 @@
|
|||
package waku
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"database/sql"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/crypto"
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
"github.com/status-im/status-go/protocol/transport"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNoMailservers returned if there is no configured mailservers that can be used.
|
||||
ErrNoMailservers = errors.New("no configured mailservers")
|
||||
)
|
||||
|
||||
type wakuServiceKeysManager struct {
|
||||
waku types.Waku
|
||||
|
||||
// Identity of the current user.
|
||||
privateKey *ecdsa.PrivateKey
|
||||
|
||||
passToSymKeyMutex sync.RWMutex
|
||||
passToSymKeyCache map[string]string
|
||||
}
|
||||
|
||||
func (m *wakuServiceKeysManager) AddOrGetKeyPair(priv *ecdsa.PrivateKey) (string, error) {
|
||||
// caching is handled in waku
|
||||
return m.waku.AddKeyPair(priv)
|
||||
}
|
||||
|
||||
func (m *wakuServiceKeysManager) AddOrGetSymKeyFromPassword(password string) (string, error) {
|
||||
m.passToSymKeyMutex.Lock()
|
||||
defer m.passToSymKeyMutex.Unlock()
|
||||
|
||||
if val, ok := m.passToSymKeyCache[password]; ok {
|
||||
return val, nil
|
||||
}
|
||||
|
||||
id, err := m.waku.AddSymKeyFromPassword(password)
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
|
||||
m.passToSymKeyCache[password] = id
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (m *wakuServiceKeysManager) RawSymKey(id string) ([]byte, error) {
|
||||
return m.waku.GetSymKey(id)
|
||||
}
|
||||
|
||||
type Option func(*WakuServiceTransport) error
|
||||
|
||||
// WakuServiceTransport is a transport based on Whisper service.
|
||||
type WakuServiceTransport struct {
|
||||
waku types.Waku
|
||||
api types.PublicWakuAPI // only PublicWakuAPI implements logic to send messages
|
||||
keysManager *wakuServiceKeysManager
|
||||
filters *transport.FiltersManager
|
||||
logger *zap.Logger
|
||||
|
||||
mailservers []string
|
||||
envelopesMonitor *EnvelopesMonitor
|
||||
}
|
||||
|
||||
// NewWakuServiceTransport returns a new WakuServiceTransport.
|
||||
// TODO: leaving a chat should verify that for a given public key
|
||||
// there are no other chats. It may happen that we leave a private chat
|
||||
// but still have a public chat for a given public key.
|
||||
func NewWakuServiceTransport(
|
||||
waku types.Waku,
|
||||
privateKey *ecdsa.PrivateKey,
|
||||
db *sql.DB,
|
||||
mailservers []string,
|
||||
envelopesMonitorConfig *transport.EnvelopesMonitorConfig,
|
||||
logger *zap.Logger,
|
||||
opts ...Option,
|
||||
) (*WakuServiceTransport, error) {
|
||||
filtersManager, err := transport.NewFiltersManager(newSQLitePersistence(db), waku, privateKey, logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var envelopesMonitor *EnvelopesMonitor
|
||||
if envelopesMonitorConfig != nil {
|
||||
envelopesMonitor = NewEnvelopesMonitor(waku, *envelopesMonitorConfig)
|
||||
envelopesMonitor.Start()
|
||||
}
|
||||
|
||||
var api types.PublicWhisperAPI
|
||||
if waku != nil {
|
||||
api = waku.PublicWakuAPI()
|
||||
}
|
||||
t := &WakuServiceTransport{
|
||||
waku: waku,
|
||||
api: api,
|
||||
envelopesMonitor: envelopesMonitor,
|
||||
keysManager: &wakuServiceKeysManager{
|
||||
waku: waku,
|
||||
privateKey: privateKey,
|
||||
passToSymKeyCache: make(map[string]string),
|
||||
},
|
||||
filters: filtersManager,
|
||||
mailservers: mailservers,
|
||||
logger: logger.With(zap.Namespace("WakuServiceTransport")),
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
if err := opt(t); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) InitFilters(chatIDs []string, publicKeys []*ecdsa.PublicKey) ([]*transport.Filter, error) {
|
||||
return a.filters.Init(chatIDs, publicKeys)
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) Filters() []*transport.Filter {
|
||||
return a.filters.Filters()
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
func (a *WakuServiceTransport) LoadFilters(filters []*transport.Filter) ([]*transport.Filter, error) {
|
||||
return a.filters.InitWithFilters(filters)
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
func (a *WakuServiceTransport) RemoveFilters(filters []*transport.Filter) error {
|
||||
return a.filters.Remove(filters...)
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) ResetFilters() error {
|
||||
return a.filters.Reset()
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) ProcessNegotiatedSecret(secret types.NegotiatedSecret) (*transport.Filter, error) {
|
||||
filter, err := a.filters.LoadNegotiated(secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return filter, nil
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) JoinPublic(chatID string) error {
|
||||
_, err := a.filters.LoadPublic(chatID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) LeavePublic(chatID string) error {
|
||||
chat := a.filters.Filter(chatID)
|
||||
if chat != nil {
|
||||
return nil
|
||||
}
|
||||
return a.filters.Remove(chat)
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) JoinPrivate(publicKey *ecdsa.PublicKey) error {
|
||||
_, err := a.filters.LoadDiscovery()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = a.filters.LoadContactCode(publicKey)
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) LeavePrivate(publicKey *ecdsa.PublicKey) error {
|
||||
filters := a.filters.FiltersByPublicKey(publicKey)
|
||||
return a.filters.Remove(filters...)
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) JoinGroup(publicKeys []*ecdsa.PublicKey) error {
|
||||
_, err := a.filters.LoadDiscovery()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, pk := range publicKeys {
|
||||
_, err = a.filters.LoadContactCode(pk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) LeaveGroup(publicKeys []*ecdsa.PublicKey) error {
|
||||
for _, publicKey := range publicKeys {
|
||||
filters := a.filters.FiltersByPublicKey(publicKey)
|
||||
if err := a.filters.Remove(filters...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
Message *types.Message
|
||||
Public bool
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) RetrieveAllMessages() ([]Message, error) {
|
||||
var messages []Message
|
||||
|
||||
for _, filter := range a.filters.Filters() {
|
||||
filterMsgs, err := a.api.GetFilterMessages(filter.FilterID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, m := range filterMsgs {
|
||||
messages = append(messages, Message{
|
||||
Message: m,
|
||||
Public: filter.IsPublic(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) RetrievePublicMessages(chatID string) ([]*types.Message, error) {
|
||||
filter, err := a.filters.LoadPublic(chatID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return a.api.GetFilterMessages(filter.FilterID)
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) RetrievePrivateMessages(publicKey *ecdsa.PublicKey) ([]*types.Message, error) {
|
||||
chats := a.filters.FiltersByPublicKey(publicKey)
|
||||
discoveryChats, err := a.filters.Init(nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []*types.Message
|
||||
|
||||
for _, chat := range append(chats, discoveryChats...) {
|
||||
filterMsgs, err := a.api.GetFilterMessages(chat.FilterID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result = append(result, filterMsgs...)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) RetrieveRawAll() (map[transport.Filter][]*types.Message, error) {
|
||||
result := make(map[transport.Filter][]*types.Message)
|
||||
|
||||
allFilters := a.filters.Filters()
|
||||
for _, filter := range allFilters {
|
||||
msgs, err := a.api.GetFilterMessages(filter.FilterID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
result[*filter] = append(result[*filter], msgs...)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SendPublic sends a new message using the Whisper service.
|
||||
// For public filters, chat name is used as an ID as well as
|
||||
// a topic.
|
||||
func (a *WakuServiceTransport) SendPublic(ctx context.Context, newMessage *types.NewMessage, chatName string) ([]byte, error) {
|
||||
if err := a.addSig(newMessage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
filter, err := a.filters.LoadPublic(chatName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newMessage.SymKeyID = filter.SymKeyID
|
||||
newMessage.Topic = filter.Topic
|
||||
|
||||
return a.api.Post(ctx, *newMessage)
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) SendPrivateWithSharedSecret(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey, secret []byte) ([]byte, error) {
|
||||
if err := a.addSig(newMessage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
filter, err := a.filters.LoadNegotiated(types.NegotiatedSecret{
|
||||
PublicKey: publicKey,
|
||||
Key: secret,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newMessage.SymKeyID = filter.SymKeyID
|
||||
newMessage.Topic = filter.Topic
|
||||
newMessage.PublicKey = nil
|
||||
|
||||
return a.api.Post(ctx, *newMessage)
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) SendPrivateWithPartitioned(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error) {
|
||||
if err := a.addSig(newMessage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
filter, err := a.filters.LoadPartitioned(publicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newMessage.Topic = filter.Topic
|
||||
newMessage.PublicKey = crypto.FromECDSAPub(publicKey)
|
||||
|
||||
return a.api.Post(ctx, *newMessage)
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) SendPrivateOnDiscovery(ctx context.Context, newMessage *types.NewMessage, publicKey *ecdsa.PublicKey) ([]byte, error) {
|
||||
if err := a.addSig(newMessage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// There is no need to load any chat
|
||||
// because listening on the discovery topic
|
||||
// is done automatically.
|
||||
// TODO: change this anyway, it should be explicit
|
||||
// and idempotent.
|
||||
|
||||
newMessage.Topic = types.BytesToTopic(transport.ToTopic(transport.DiscoveryTopic()))
|
||||
newMessage.PublicKey = crypto.FromECDSAPub(publicKey)
|
||||
|
||||
return a.api.Post(ctx, *newMessage)
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) addSig(newMessage *types.NewMessage) error {
|
||||
sigID, err := a.keysManager.AddOrGetKeyPair(a.keysManager.privateKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newMessage.SigID = sigID
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) Track(identifiers [][]byte, hash []byte, newMessage *types.NewMessage) {
|
||||
if a.envelopesMonitor != nil {
|
||||
a.envelopesMonitor.Add(identifiers, types.BytesToHash(hash), *newMessage)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) Stop() error {
|
||||
if a.envelopesMonitor != nil {
|
||||
a.envelopesMonitor.Stop()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RequestHistoricMessages requests historic messages for all registered filters.
|
||||
func (a *WakuServiceTransport) SendMessagesRequest(
|
||||
ctx context.Context,
|
||||
peerID []byte,
|
||||
from, to uint32,
|
||||
previousCursor []byte,
|
||||
) (cursor []byte, err error) {
|
||||
topics := make([]types.TopicType, len(a.Filters()))
|
||||
for _, f := range a.Filters() {
|
||||
topics = append(topics, f.Topic)
|
||||
}
|
||||
|
||||
r := createMessagesRequest(from, to, previousCursor, topics)
|
||||
r.SetDefaults(a.waku.GetCurrentTime())
|
||||
|
||||
events := make(chan types.EnvelopeEvent, 10)
|
||||
sub := a.waku.SubscribeEnvelopeEvents(events)
|
||||
defer sub.Unsubscribe()
|
||||
|
||||
err = a.waku.SendMessagesRequest(peerID, r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := a.waitForRequestCompleted(ctx, r.ID, events)
|
||||
if err == nil && resp != nil && resp.Error != nil {
|
||||
err = resp.Error
|
||||
} else if err == nil && resp != nil {
|
||||
cursor = resp.Cursor
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a *WakuServiceTransport) waitForRequestCompleted(ctx context.Context, requestID []byte, events chan types.EnvelopeEvent) (*types.MailServerResponse, error) {
|
||||
for {
|
||||
select {
|
||||
case ev := <-events:
|
||||
a.logger.Debug(
|
||||
"waiting for request completed and received an event",
|
||||
zap.Binary("requestID", requestID),
|
||||
zap.Any("event", ev),
|
||||
)
|
||||
if !bytes.Equal(ev.Hash.Bytes(), requestID) {
|
||||
continue
|
||||
}
|
||||
if ev.Event != types.EventMailServerRequestCompleted {
|
||||
continue
|
||||
}
|
||||
data, ok := ev.Data.(*types.MailServerResponse)
|
||||
if ok {
|
||||
return data, nil
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,8 @@ import (
|
|||
"errors"
|
||||
"sync"
|
||||
|
||||
"github.com/status-im/status-go/protocol/transport"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/status-im/status-go/eth-node/types"
|
||||
|
@ -18,18 +20,10 @@ const (
|
|||
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 is set when envelope is sent to at least one peer.
|
||||
EnvelopeSent
|
||||
)
|
||||
|
||||
type EnvelopesMonitorConfig struct {
|
||||
EnvelopeEventsHandler EnvelopeEventsHandler
|
||||
MaxAttempts int
|
||||
MailserverConfirmationsEnabled bool
|
||||
IsMailserver func(types.EnodeID) bool
|
||||
Logger *zap.Logger
|
||||
}
|
||||
|
||||
// EnvelopeEventsHandler used for two different event types.
|
||||
type EnvelopeEventsHandler interface {
|
||||
EnvelopeSent([][]byte)
|
||||
|
@ -39,7 +33,7 @@ type EnvelopeEventsHandler interface {
|
|||
}
|
||||
|
||||
// NewEnvelopesMonitor returns a pointer to an instance of the EnvelopesMonitor.
|
||||
func NewEnvelopesMonitor(w types.Whisper, config EnvelopesMonitorConfig) *EnvelopesMonitor {
|
||||
func NewEnvelopesMonitor(w types.Whisper, config transport.EnvelopesMonitorConfig) *EnvelopesMonitor {
|
||||
logger := config.Logger
|
||||
|
||||
if logger == nil {
|
||||
|
|
|
@ -9,8 +9,6 @@ import (
|
|||
"github.com/status-im/status-go/eth-node/types"
|
||||
)
|
||||
|
||||
const defaultMessagesRequestLimit = 100
|
||||
|
||||
func createMessagesRequest(from, to uint32, cursor []byte, topics []types.TopicType) types.MessagesRequest {
|
||||
aUUID := uuid.New()
|
||||
// uuid is 16 bytes, converted to hex it's 32 bytes as expected by types.MessagesRequest
|
||||
|
@ -19,7 +17,7 @@ func createMessagesRequest(from, to uint32, cursor []byte, topics []types.TopicT
|
|||
ID: id,
|
||||
From: from,
|
||||
To: to,
|
||||
Limit: defaultMessagesRequestLimit,
|
||||
Limit: 100,
|
||||
Cursor: cursor,
|
||||
Bloom: topicsToBloom(topics...),
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue