diff --git a/Makefile b/Makefile index ff47d6822..4b030edf3 100644 --- a/Makefile +++ b/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) diff --git a/appdatabase/migrations/bindata.go b/appdatabase/migrations/bindata.go index 8464daa05..be99a5618 100644 --- a/appdatabase/migrations/bindata.go +++ b/appdatabase/migrations/bindata.go @@ -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 } diff --git a/eth-node/bridge/geth/envelope_error.go b/eth-node/bridge/geth/envelope_error.go index 5a8edf257..6d24b49fc 100644 --- a/eth-node/bridge/geth/envelope_error.go +++ b/eth-node/bridge/geth/envelope_error.go @@ -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 diff --git a/eth-node/bridge/geth/envelope_event.go b/eth-node/bridge/geth/envelope_event.go index 9836987a6..c31c509c1 100644 --- a/eth-node/bridge/geth/envelope_event.go +++ b/eth-node/bridge/geth/envelope_event.go @@ -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, + } +} diff --git a/eth-node/bridge/geth/filter.go b/eth-node/bridge/geth/filter.go deleted file mode 100644 index 914e17df8..000000000 --- a/eth-node/bridge/geth/filter.go +++ /dev/null @@ -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 -} diff --git a/eth-node/bridge/geth/mailserver_response.go b/eth-node/bridge/geth/mailserver_response.go index 01cbb30a2..10b796fb2 100644 --- a/eth-node/bridge/geth/mailserver_response.go +++ b/eth-node/bridge/geth/mailserver_response.go @@ -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") } diff --git a/eth-node/bridge/geth/node.go b/eth-node/bridge/geth/node.go index 7cfa42b71..7c691c189 100644 --- a/eth-node/bridge/geth/node.go +++ b/eth-node/bridge/geth/node.go @@ -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 { diff --git a/eth-node/bridge/geth/public_waku_api.go b/eth-node/bridge/geth/public_waku_api.go new file mode 100644 index 000000000..bfd9b76f6 --- /dev/null +++ b/eth-node/bridge/geth/public_waku_api.go @@ -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) +} diff --git a/eth-node/bridge/geth/waku.go b/eth-node/bridge/geth/waku.go new file mode 100644 index 000000000..143562513 --- /dev/null +++ b/eth-node/bridge/geth/waku.go @@ -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 +} diff --git a/eth-node/bridge/geth/whisper.go b/eth-node/bridge/geth/whisper.go index 8e64db81c..2423a3264 100644 --- a/eth-node/bridge/geth/whisper.go +++ b/eth-node/bridge/geth/whisper.go @@ -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 +} diff --git a/eth-node/types/const.go b/eth-node/types/const.go new file mode 100644 index 000000000..9e3148d0f --- /dev/null +++ b/eth-node/types/const.go @@ -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 +) diff --git a/eth-node/types/node.go b/eth-node/types/node.go index 20f3aead6..4c80c2cb8 100644 --- a/eth-node/types/node.go +++ b/eth-node/types/node.go @@ -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 } diff --git a/eth-node/types/rpc.go b/eth-node/types/rpc.go index c2c13de70..3ee868804 100644 --- a/eth-node/types/rpc.go +++ b/eth-node/types/rpc.go @@ -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) +} diff --git a/eth-node/types/subscribe.go b/eth-node/types/subscribe.go new file mode 100644 index 000000000..fbd347acc --- /dev/null +++ b/eth-node/types/subscribe.go @@ -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 +} diff --git a/eth-node/types/waku.go b/eth-node/types/waku.go new file mode 100644 index 000000000..ce81c2cf3 --- /dev/null +++ b/eth-node/types/waku.go @@ -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 +} diff --git a/eth-node/types/whisper.go b/eth-node/types/whisper.go index 55bd0d119..23529c4da 100644 --- a/eth-node/types/whisper.go +++ b/eth-node/types/whisper.go @@ -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 { diff --git a/mailserver/migrations/bindata.go b/mailserver/migrations/bindata.go index 684df9ce4..def9a0845 100644 --- a/mailserver/migrations/bindata.go +++ b/mailserver/migrations/bindata.go @@ -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 } diff --git a/multiaccounts/migrations/bindata.go b/multiaccounts/migrations/bindata.go index 2bbf13e53..5ceb19402 100644 --- a/multiaccounts/migrations/bindata.go +++ b/multiaccounts/migrations/bindata.go @@ -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 } diff --git a/node/node.go b/node/node.go index 153cb2dce..b1d742d42 100644 --- a/node/node.go +++ b/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) { diff --git a/protocol/applicationmetadata/message.pb.go b/protocol/applicationmetadata/message.pb.go index 646d27629..4e71857d8 100644 --- a/protocol/applicationmetadata/message.pb.go +++ b/protocol/applicationmetadata/message.pb.go @@ -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. diff --git a/protocol/encryption/migrations/migrations.go b/protocol/encryption/migrations/migrations.go index 3e93c617c..ea0a151ab 100644 --- a/protocol/encryption/migrations/migrations.go +++ b/protocol/encryption/migrations/migrations.go @@ -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 } diff --git a/protocol/encryption/protocol_message.pb.go b/protocol/encryption/protocol_message.pb.go index 81ce4a314..a682bdb61 100644 --- a/protocol/encryption/protocol_message.pb.go +++ b/protocol/encryption/protocol_message.pb.go @@ -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. diff --git a/protocol/go.sum b/protocol/go.sum index cca0d5f3e..050eb91f7 100644 --- a/protocol/go.sum +++ b/protocol/go.sum @@ -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= diff --git a/protocol/message_processor.go b/protocol/message_processor.go index f72f10880..1b05403f1 100644 --- a/protocol/message_processor.go +++ b/protocol/message_processor.go @@ -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) { diff --git a/protocol/messenger.go b/protocol/messenger.go index 95cbec002..111b5f58e 100644 --- a/protocol/messenger.go +++ b/protocol/messenger.go @@ -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 diff --git a/protocol/migrations.go b/protocol/migrations.go deleted file mode 100644 index c616440fe..000000000 --- a/protocol/migrations.go +++ /dev/null @@ -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") -} diff --git a/protocol/migrations/migrations.go b/protocol/migrations/migrations.go index 597b517f4..ff08e31f9 100644 --- a/protocol/migrations/migrations.go +++ b/protocol/migrations/migrations.go @@ -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 } diff --git a/protocol/protobuf/application_metadata_message.pb.go b/protocol/protobuf/application_metadata_message.pb.go index bd650fdd6..b166e283f 100644 --- a/protocol/protobuf/application_metadata_message.pb.go +++ b/protocol/protobuf/application_metadata_message.pb.go @@ -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. diff --git a/protocol/protobuf/chat_message.pb.go b/protocol/protobuf/chat_message.pb.go index 61db6ead5..49247f30c 100644 --- a/protocol/protobuf/chat_message.pb.go +++ b/protocol/protobuf/chat_message.pb.go @@ -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. diff --git a/protocol/protobuf/membership_update_message.pb.go b/protocol/protobuf/membership_update_message.pb.go index 1e923090d..30dd3d1f2 100644 --- a/protocol/protobuf/membership_update_message.pb.go +++ b/protocol/protobuf/membership_update_message.pb.go @@ -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. diff --git a/protocol/sqlite/migrations.go b/protocol/sqlite/migrations.go index a6a2cf862..387f7608d 100644 --- a/protocol/sqlite/migrations.go +++ b/protocol/sqlite/migrations.go @@ -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(), diff --git a/protocol/migrations_test.go b/protocol/sqlite/migrations_test.go similarity index 98% rename from protocol/migrations_test.go rename to protocol/sqlite/migrations_test.go index 98945a926..a15cfb01b 100644 --- a/protocol/migrations_test.go +++ b/protocol/sqlite/migrations_test.go @@ -1,4 +1,4 @@ -package protocol +package sqlite import ( "testing" diff --git a/protocol/transport/envelopes_monitor.go b/protocol/transport/envelopes_monitor.go new file mode 100644 index 000000000..523323203 --- /dev/null +++ b/protocol/transport/envelopes_monitor.go @@ -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) +} diff --git a/protocol/transport/filter.go b/protocol/transport/filter.go new file mode 100644 index 000000000..a1f7369a5 --- /dev/null +++ b/protocol/transport/filter.go @@ -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 +} diff --git a/vendor/github.com/status-im/status-go/protocol/transport/whisper/filter.go b/protocol/transport/filters_manager.go similarity index 57% rename from vendor/github.com/status-im/status-go/protocol/transport/whisper/filter.go rename to protocol/transport/filters_manager.go index e237d78f2..ad914e9d7 100644 --- a/vendor/github.com/status-im/status-go/protocol/transport/whisper/filter.go +++ b/protocol/transport/filters_manager.go @@ -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)] } diff --git a/protocol/transport/whisper/filter_test.go b/protocol/transport/filters_manager_test.go similarity index 96% rename from protocol/transport/whisper/filter_test.go rename to protocol/transport/filters_manager_test.go index 20fab84d4..881246cfe 100644 --- a/protocol/transport/whisper/filter_test.go +++ b/protocol/transport/filters_manager_test.go @@ -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) } diff --git a/protocol/transport/message.go b/protocol/transport/message.go new file mode 100644 index 000000000..3d7d9d499 --- /dev/null +++ b/protocol/transport/message.go @@ -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 +} diff --git a/protocol/transport/topic.go b/protocol/transport/topic.go new file mode 100644 index 000000000..876e6e39f --- /dev/null +++ b/protocol/transport/topic.go @@ -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 +} diff --git a/protocol/transport/transport.go b/protocol/transport/transport.go new file mode 100644 index 000000000..ea082f4ed --- /dev/null +++ b/protocol/transport/transport.go @@ -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) +} diff --git a/protocol/transport/waku/envelopes.go b/protocol/transport/waku/envelopes.go new file mode 100644 index 000000000..c06b086d6 --- /dev/null +++ b/protocol/transport/waku/envelopes.go @@ -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) +} diff --git a/protocol/transport/waku/envelopes_test.go b/protocol/transport/waku/envelopes_test.go new file mode 100644 index 000000000..14807f6e7 --- /dev/null +++ b/protocol/transport/waku/envelopes_test.go @@ -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)) +} diff --git a/protocol/transport/waku/mailserver.go b/protocol/transport/waku/mailserver.go new file mode 100644 index 000000000..b4419d10f --- /dev/null +++ b/protocol/transport/waku/mailserver.go @@ -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 +} diff --git a/protocol/transport/waku/migrations/migrations.go b/protocol/transport/waku/migrations/migrations.go new file mode 100644 index 000000000..8809b9b4c --- /dev/null +++ b/protocol/transport/waku/migrations/migrations.go @@ -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, "/")...)...) +} diff --git a/protocol/transport/waku/migrations/sqlite/1561059284_add_waku_keys.down.sql b/protocol/transport/waku/migrations/sqlite/1561059284_add_waku_keys.down.sql new file mode 100644 index 000000000..95d756b94 --- /dev/null +++ b/protocol/transport/waku/migrations/sqlite/1561059284_add_waku_keys.down.sql @@ -0,0 +1 @@ +DROP TABLE waku_keys; diff --git a/protocol/transport/waku/migrations/sqlite/1561059284_add_waku_keys.up.sql b/protocol/transport/waku/migrations/sqlite/1561059284_add_waku_keys.up.sql new file mode 100644 index 000000000..8746cabce --- /dev/null +++ b/protocol/transport/waku/migrations/sqlite/1561059284_add_waku_keys.up.sql @@ -0,0 +1,4 @@ +CREATE TABLE waku_keys ( + chat_id TEXT PRIMARY KEY ON CONFLICT IGNORE, + key BLOB NOT NULL +) WITHOUT ROWID; diff --git a/protocol/transport/waku/migrations/sqlite/doc.go b/protocol/transport/waku/migrations/sqlite/doc.go new file mode 100644 index 000000000..c3e0f561d --- /dev/null +++ b/protocol/transport/waku/migrations/sqlite/doc.go @@ -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 . diff --git a/protocol/transport/waku/persistence.go b/protocol/transport/waku/persistence.go new file mode 100644 index 000000000..df5e89e68 --- /dev/null +++ b/protocol/transport/waku/persistence.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 +} diff --git a/protocol/transport/waku/waku.go b/protocol/transport/waku/waku.go new file mode 100644 index 000000000..3a0eaa4ea --- /dev/null +++ b/protocol/transport/waku/waku.go @@ -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 +} diff --git a/protocol/transport/waku/waku_service.go b/protocol/transport/waku/waku_service.go new file mode 100644 index 000000000..57b319382 --- /dev/null +++ b/protocol/transport/waku/waku_service.go @@ -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() + } + } +} diff --git a/protocol/transport/waku/waku_service_test.go b/protocol/transport/waku/waku_service_test.go new file mode 100644 index 000000000..09f204189 --- /dev/null +++ b/protocol/transport/waku/waku_service_test.go @@ -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) +} diff --git a/protocol/transport/whisper/envelopes.go b/protocol/transport/whisper/envelopes.go index 21da4df38..886e19873 100644 --- a/protocol/transport/whisper/envelopes.go +++ b/protocol/transport/whisper/envelopes.go @@ -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 { diff --git a/protocol/transport/whisper/mailserver.go b/protocol/transport/whisper/mailserver.go index b25d3d751..d630b69ab 100644 --- a/protocol/transport/whisper/mailserver.go +++ b/protocol/transport/whisper/mailserver.go @@ -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...), } diff --git a/protocol/transport/whisper/migrations/migrations.go b/protocol/transport/whisper/migrations/migrations.go index 368797f1a..7fdff2a38 100644 --- a/protocol/transport/whisper/migrations/migrations.go +++ b/protocol/transport/whisper/migrations/migrations.go @@ -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 } diff --git a/protocol/transport/whisper/whisper.go b/protocol/transport/whisper/whisper.go index c9e118348..ef4970900 100644 --- a/protocol/transport/whisper/whisper.go +++ b/protocol/transport/whisper/whisper.go @@ -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 -} diff --git a/protocol/transport/whisper/whisper_service.go b/protocol/transport/whisper/whisper_service.go index b400561c3..38bc3a0a2 100644 --- a/protocol/transport/whisper/whisper_service.go +++ b/protocol/transport/whisper/whisper_service.go @@ -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) diff --git a/services/incentivisation/service.go b/services/incentivisation/service.go index c5a801433..5e6205908 100644 --- a/services/incentivisation/service.go +++ b/services/incentivisation/service.go @@ -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) diff --git a/services/shhext/api.go b/services/shhext/api.go index 91b5cabaa..9522a546a 100644 --- a/services/shhext/api.go +++ b/services/shhext/api.go @@ -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, diff --git a/services/shhext/service.go b/services/shhext/service.go index 5fb1b3113..f3dea0bf7 100644 --- a/services/shhext/service.go +++ b/services/shhext/service.go @@ -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), diff --git a/services/shhext/service_test.go b/services/shhext/service_test.go index 8c354c577..5446c8d8f 100644 --- a/services/shhext/service_test.go +++ b/services/shhext/service_test.go @@ -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) diff --git a/static/bindata.go b/static/bindata.go index a1d3b36cb..663f2dee5 100644 --- a/static/bindata.go +++ b/static/bindata.go @@ -1,9 +1,10 @@ // Code generated by go-bindata. DO NOT EDIT. // sources: -// ../config/README.md (3.33kB) -// ../config/cli/fleet-eth.beta.json (3.261kB) -// ../config/cli/fleet-eth.staging.json (1.862kB) -// ../config/cli/fleet-eth.test.json (1.543kB) +// ../config/README.md (3.132kB) +// ../config/cli/fleet-eth.beta.json (3.228kB) +// ../config/cli/fleet-eth.prod.json (3.234kB) +// ../config/cli/fleet-eth.staging.json (1.848kB) +// ../config/cli/fleet-eth.test.json (1.527kB) // ../config/cli/les-enabled.json (58B) // ../config/cli/mailserver-enabled.json (176B) // ../config/status-chain-genesis.json (612B) @@ -82,7 +83,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _ConfigReadmeMd = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd4\x57\x5f\x53\xdb\x48\x12\x7f\xd7\xa7\xe8\x52\x1e\x2e\x54\x11\xc9\x60\x1b\x58\xbf\x5c\x08\x90\x85\x3b\x42\x28\x43\x6e\x1f\x52\x29\x6b\xac\x69\x4b\xb3\x19\x4d\x6b\x67\x46\x76\xbc\x57\xf9\xee\x57\x3d\x92\xfc\x07\x7c\xfb\xbe\x05\x25\x89\x99\xfe\xfb\xfb\xf5\x74\x0f\x6f\xe0\xce\x78\x4b\xb2\xc9\xbd\x22\x13\x45\xcf\xa5\x72\x20\x29\x6f\x2a\x34\x1e\x24\xba\xdc\xaa\x39\x3a\xf0\x25\x82\x58\x0a\xa5\xc5\x5c\x23\x50\xcd\xd2\x0e\x94\x09\x1b\xff\x7a\xfa\xfc\x00\x39\x99\x85\x2a\x60\x41\x16\x32\xe7\x85\x6f\xdc\xbb\x82\xb2\x84\x4d\x22\x38\x6f\x9b\xdc\x37\x16\x81\x16\xaf\x54\xd8\x23\x2e\x94\x41\xd9\x1b\xfc\x9a\xd5\xc2\x8a\xca\xa5\xad\x44\x52\x50\xf6\xed\x6d\xfa\x72\xed\x08\x16\x4a\xe3\x31\xac\x4a\x95\x97\x20\xb4\x23\xb6\xe8\x85\x32\x6c\xd0\x0b\xa5\x51\x42\x4e\x15\xa7\xe2\x80\x0c\x54\x28\x8c\x32\x05\xc7\x80\x22\x2f\xbb\x34\x12\xe0\x08\xb3\x07\x92\x78\x15\x4c\x67\x5d\xb8\x5d\x54\x6d\xf2\x05\x1a\xb4\x42\x77\x31\x37\x56\xb0\x2a\x7c\xc7\xb5\x03\xe1\x83\xc4\x6c\x66\x89\xfc\x6c\xb6\x97\x22\x47\x98\x44\xd1\x5d\xbb\xd4\xe2\xd9\x81\x47\x0b\x10\x66\xbd\xc1\x52\x58\x04\x4f\x04\x4b\x51\x34\x08\x0b\x44\x0d\x0b\x8b\xbc\x06\x5f\xa9\x46\x03\xc2\x80\x72\xae\xc1\x6f\x6f\x4b\xef\x6b\x37\x49\xd3\x42\xf9\xb2\x99\x27\x39\x55\x69\x87\xb8\xda\x7c\x15\x94\x06\x69\x97\x1a\x5c\x1d\x25\x51\x74\xf3\x43\x54\xb5\xc6\x0d\x4f\x4a\xa3\x83\x5c\x18\x98\x23\x2c\x15\xae\x76\xd1\x6f\x65\xd2\x5c\x2b\xc6\x7d\xfb\xd7\x11\x2c\x48\x4b\xb4\x49\x14\xbd\x81\xbb\xaa\x26\xeb\x85\xf1\xf0\x84\xa1\x7a\x5c\xcb\xf5\x0b\x6a\x1d\x32\x6f\x3e\x98\xf7\x04\x0e\x97\x01\x47\xd7\xe9\xb4\xe8\x57\xe4\x3c\xa8\x8d\x41\x62\xd4\x19\x10\xad\x1c\x6b\xce\x51\xd3\x8a\x9d\xbe\xd9\xe3\xa9\xf5\xc7\xa8\x1f\x28\xab\x8e\xa2\x24\x8a\x2e\x0d\x60\x97\x3c\x2d\x5e\xba\x72\xe8\xbd\x32\x85\x83\x15\x35\x9a\x63\xcc\x75\x23\x71\x12\x65\x59\xf6\xbb\x23\x13\xfd\x37\x02\x00\x88\x1f\xd0\xaf\xc8\x7e\xbf\xbb\x8e\x27\x70\x72\xdc\xae\x5d\x0b\x2f\xae\x95\x8d\x27\x10\xa7\xbe\xaa\xb7\xc8\xbf\x93\xc2\x8b\xb8\x93\xe2\x78\xff\x8d\x6b\x96\x3a\x39\x1d\xfe\xb1\xc2\x17\xcf\x5e\x6e\x8a\x46\xe2\x9f\x4b\x6a\x5c\x3c\x01\x6f\x1b\xdc\xe8\x5f\x2b\x97\xd3\x12\x2d\xdb\x58\x08\xed\xfa\x9d\x7b\x06\xc7\x5c\x4a\x19\x42\x18\x24\xe1\x67\x32\x1c\x0c\x07\x1b\xa3\x97\x72\x89\xd6\x2b\x87\xbd\xd4\xc9\x69\x32\x1c\x25\xe3\xb3\xe4\xfc\x62\xeb\xb8\x60\x43\xf6\x99\x6a\x95\xb3\xf3\xaf\xf1\xaa\x54\xae\x46\x5b\x09\xa5\xe3\x6f\xd1\x4f\x06\x23\xd4\xf0\x9a\x9a\x7f\x48\x58\x31\x6e\x9e\x00\x4d\x68\x06\x01\xf3\xe9\xe3\x15\x30\xa4\x9d\x88\x41\x94\xaf\x30\xbc\x7d\x7e\x7e\xbc\x09\x3a\x72\x3f\x45\xde\xb8\x25\xe7\x77\xd2\x88\x77\xb6\x1e\xc9\xf2\xd6\xc5\x78\x34\xee\xd3\x7a\xbc\xfb\x44\xb2\xd1\xc8\xe1\xc6\xe8\xcb\x63\x83\xfe\x78\x85\xf3\xe1\xb1\x90\x95\x32\xf1\x26\x66\x03\x64\x25\x5a\x0e\x57\xc8\xdf\x1b\xe7\x41\x53\x51\x70\x13\xd8\x10\xff\x17\x11\xdf\x53\xf1\x51\x69\x0c\x0c\x2f\x85\x4d\x35\x15\x5b\x96\x13\x4d\x45\x1f\xe6\x3d\x15\xf7\xb8\x44\xcd\x92\x77\x0f\x1f\x3f\xef\xac\x7f\x12\x3f\x9e\xd4\x9f\x6c\xe3\x74\x30\xd8\x5b\xfe\x20\xf2\xef\x4d\xcd\x29\x8c\xb7\xeb\x57\x54\xd5\x16\x9d\x9b\x92\xe7\x43\xd3\x01\xd5\xe5\xf3\x1f\xa1\x95\x84\xac\xf7\x96\x6d\x93\x10\x16\x27\x90\xdd\x4c\xa7\x9f\xa7\xd9\x31\x64\xbf\x5d\x4e\x1f\xf8\xcd\xb1\xf0\xfb\xfa\xe6\xc3\x97\x5f\xf9\xe3\x79\x7a\x79\x75\x93\xb5\x27\xe9\xb7\x96\xe5\xbe\xe9\xf5\x0c\xb7\xfc\xae\xa9\xb1\x60\x48\x86\x06\x64\x51\x8b\x35\x74\xf2\x6f\x9f\x6e\x6f\x8f\xa0\xb6\xe4\x29\x27\x0d\x15\x3a\x27\x0a\x6c\x71\xd4\x7a\x53\x1d\xdd\x49\x02\x5f\x2a\xf7\x0a\xd8\x3d\xd7\xf1\x04\xda\xe5\xb0\x75\xa8\x42\x76\x36\x3e\x09\xa5\x9f\xd0\x2e\xd1\xbe\x96\xb8\x57\x45\xe9\xaf\xb4\x42\xe3\xf7\x8f\x4a\xd8\xdd\x6a\x3e\x0a\xe7\x56\x64\xd9\x47\xdc\xd1\x49\x8b\x85\x56\x06\xdf\x29\x33\xa7\x1f\x71\x50\xfa\xd9\x81\x1e\xa6\xc3\x6b\xe5\x8c\x9b\x5b\xe3\x50\x86\x91\xe7\xd6\x55\x85\xde\xaa\x1c\xd0\xe4\x76\x1d\x7a\x3a\x77\x9b\x52\x39\x4f\x76\x0d\x16\xff\x68\xd0\x79\x97\x44\xd1\x87\x35\x0f\x16\xd1\x68\x0f\xca\xc3\x4a\x69\xcd\x66\x20\xd3\x4c\xa9\x9c\x67\x80\xd5\x1c\xa5\x44\x09\xdc\x46\xe6\xc2\x61\x02\xcf\x14\x64\x6a\x72\xbe\xb0\xc8\x83\xd7\x79\x14\x32\xd0\xc5\x95\xcb\x80\x47\xb5\x70\x0e\x44\xdf\x7a\x43\x47\x54\x0e\xbe\x2b\x23\x27\xd1\xdf\x91\x80\x4d\x93\x65\x0c\x0e\x44\x0a\x10\x3f\xfe\x7a\x70\xfd\x2f\xb2\x08\x9b\x5f\xa6\x77\xec\xba\x87\x73\x92\xa6\x8d\x43\x3b\xa9\xbb\xb0\xde\x97\xe4\xfc\x84\xdb\xd9\x3f\xbb\xe9\x1c\xef\xe8\xff\x8c\xf6\xbf\xfa\x3a\x89\x66\xb3\x87\xcf\xcf\x37\x93\xd9\x2c\x8c\xb4\x9e\xe3\xde\x68\x5b\x2b\xf3\x35\x3c\x85\x84\xe1\xb2\xae\x41\x18\x09\x5f\xf9\xa0\x71\xa7\x75\x01\x1a\xb7\x1d\xef\x0b\x8d\xe8\x5d\xd2\x02\x94\xa8\x2a\x3d\xe2\x92\xcb\x0e\x01\x96\x75\xc3\xf1\x4a\x37\xdc\xca\x77\xe6\xa3\x72\x7d\x41\x54\xc2\x84\x73\xba\x2a\x85\x87\x1a\xd1\xba\xe0\x7f\x4e\xe4\x9d\xb7\xa2\x0e\xa7\xdd\xb5\x07\x7f\xe7\x06\x17\x6a\x4d\x98\x3c\xdc\x1c\x0c\xe6\x9e\x2d\xa0\xe1\xda\x75\x5e\x58\x2e\xe9\xdd\xda\x8a\xf7\x42\xd8\xf0\x72\x90\x8f\xf8\x23\x67\xd8\xb5\xf0\x64\x8e\xdb\xa1\xf9\x81\xc8\xf3\xe0\x0c\xe3\xa8\xc3\x3b\x46\x0e\x70\x92\xa6\xc3\xd1\x18\xad\x6f\x9f\xef\x4f\x87\xc9\x68\x9c\x9c\x9d\x27\x17\xbf\x4c\x86\x83\xd1\x60\xd4\x52\xf5\xad\x33\xf4\x6c\x39\x1a\xb9\x2d\xbd\x83\x16\x77\xe7\xf1\xfb\x5f\x2e\x92\xf3\xb3\x64\x3c\x4a\x86\xa7\x93\xe1\x60\xfc\xd2\x22\xd3\xa7\xf2\xff\x1b\xdc\xee\x74\x7f\xbf\x33\x6d\xc3\x5c\x1e\xef\x9b\xda\x8e\xfc\x57\xe6\x52\x55\x8f\xd2\x8b\xf3\xe4\x6c\x9c\x8c\x86\xc9\xe9\x49\xea\xf3\x3a\x1d\x0e\xce\x07\xc3\x14\x7d\xb9\x1c\xa5\x27\x67\x5f\x54\x73\x7a\x7b\x59\x0d\x4f\x4e\x0f\xfe\x76\xae\xa2\x6d\x81\x66\x1b\x54\x33\x28\x51\xd7\xe1\xc6\x74\x90\xe9\x85\x32\xb2\x2d\x91\x70\x3d\x5b\x87\xbb\x58\x45\x16\x77\x2e\x4e\x9e\xa0\x14\x4b\xee\xef\xc2\x40\xb6\x83\x4a\x06\xfc\x2f\xc0\x6b\xe0\xb3\xcd\x4d\xdd\x22\x84\x51\xec\x82\x92\xd0\x7a\x0d\x22\x34\xbc\xb6\x2a\xc9\xb4\x95\x95\x44\x51\xf6\x02\xa2\x2c\x28\x0b\x03\x42\x7b\xb4\x46\x78\xb5\xc4\xed\x28\xe2\x46\x2c\x89\x87\x3b\x67\xe6\x44\x85\xc1\x22\xc8\xfe\x02\x05\xc2\xc1\x2e\x0a\x92\x92\xe8\x7f\x01\x00\x00\xff\xff\xa7\x05\x7b\x66\x02\x0d\x00\x00") +var _ConfigReadmeMd = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x56\x5d\x6f\xdb\x3a\x12\x7d\xd7\xaf\x18\xa8\x0f\xdb\x00\xa9\xe4\xc4\x76\x92\xab\x97\x6d\x9a\xa4\x37\xd9\x4d\xd3\xc0\x49\xf7\x3e\x14\x85\x45\x8b\x63\x89\xb7\x14\x47\x97\xa4\xec\xba\x8b\xfe\xf7\xc5\x50\xf2\x57\x9c\x5d\x60\x91\xc0\xb6\xc8\x99\xc3\x99\x73\x46\x33\x7c\x03\x77\xc6\x5b\x92\x6d\xe1\x15\x99\x28\x7a\xae\x94\x03\x49\x45\x5b\xa3\xf1\x20\xd1\x15\x56\xcd\xd0\x81\xaf\x10\xc4\x42\x28\x2d\x66\x1a\x81\x1a\xb6\x76\xa0\x4c\xd8\xf8\xc7\xd3\xe7\x07\x28\xc8\xcc\x55\x09\x73\xb2\x90\x3b\x2f\x7c\xeb\xde\x95\x94\x27\x0c\x89\xe0\xbc\x6d\x0b\xdf\x5a\x04\x9a\x1f\xb8\xf0\x89\x38\x57\x06\xe5\x1a\xf0\x6b\xde\x08\x2b\x6a\x97\x76\x16\x49\x49\xf9\xb7\xb7\xe9\xcb\xb5\x23\x98\x2b\x8d\xc7\xb0\xac\x54\x51\x81\xd0\x8e\x18\xd1\x0b\x65\x18\xd0\x0b\xa5\x51\x42\x41\x35\xa7\xe2\x80\x0c\xd4\x28\x8c\x32\x25\xc7\x80\xa2\xa8\xfa\x34\x12\xe0\x08\xf3\x07\x92\x78\x15\xa0\xf3\x3e\xdc\x3e\xaa\x2e\xf9\x12\x0d\x5a\xa1\xfb\x98\x5b\x2b\xd8\x15\xbe\xe3\xca\x81\xf0\xc1\x62\x3a\xb5\x44\x7e\x3a\xdd\x4b\x91\x23\x4c\xa2\xe8\xae\x5b\xea\xf8\xec\xc9\xa3\x39\x08\xb3\xda\x70\x29\x2c\x82\x27\x82\x85\x28\x5b\x84\x39\xa2\x86\xb9\x45\x5e\x83\xaf\xd4\xa0\x01\x61\x40\x39\xd7\xe2\xb7\xb7\x95\xf7\x8d\xcb\xd2\xb4\x54\xbe\x6a\x67\x49\x41\x75\xda\x33\xae\x36\xbf\x4a\x4a\x83\xb5\x4b\x0d\x2e\x8f\x92\x28\xba\xf9\x21\xea\x46\xe3\x46\x27\xa5\xd1\x41\x21\x0c\xcc\x10\x16\x0a\x97\xbb\xec\x77\x36\x69\xa1\x15\xf3\xbe\x7d\x3a\x82\x39\x69\x89\x36\x89\xa2\x37\x70\x57\x37\x64\xbd\x30\x1e\x9e\x30\x54\x8f\xeb\xb4\x7e\x21\xad\x43\xd6\xcd\x07\x78\x4f\xe0\x70\x11\x78\x74\xbd\x4f\xc7\x7e\x4d\xce\x83\xda\x00\x12\xb3\xce\x84\x68\xe5\xd8\x73\x86\x9a\x96\x7c\xe8\x9b\x3d\x9d\xba\xf3\x98\xf5\x57\xca\xaa\x97\x28\x89\xa2\x4b\x03\xd8\x27\x4f\xf3\x97\x47\x39\xf4\x5e\x99\xd2\xc1\x92\x5a\xcd\x31\x16\xba\x95\x98\x45\x79\x9e\xff\xe9\xc8\x44\xff\x8e\x00\x00\xe2\x07\xf4\x4b\xb2\xdf\xef\xae\xe3\x0c\x4e\x8e\xbb\xb5\x6b\xe1\xc5\xb5\xb2\x71\x06\x71\xea\xeb\x66\xcb\xfc\x3b\x29\xbc\x88\x7b\x2b\x8e\xf7\x9f\xb8\x62\xab\x93\xd3\xe1\x5f\x4b\x7c\xf1\xb9\xb6\x9b\xa0\x91\xf8\x73\x41\xad\x8b\x33\xf0\xb6\xc5\x8d\xff\xb5\x72\x05\x2d\xd0\x32\xc6\x5c\x68\xb7\xde\xb9\x67\x72\xcc\xa5\x94\x21\x84\x41\x12\xfe\xb2\xe1\x60\x38\xd8\x80\x5e\xca\x05\x5a\xaf\x1c\xae\xad\x4e\x4e\x93\xe1\x28\x19\x9f\x25\xe7\x17\xdb\x83\x4b\x06\xb2\xcf\xd4\xa8\x82\x0f\xff\x1a\x2f\x2b\xe5\x1a\xb4\xb5\x50\x3a\xfe\x16\xfd\x62\x32\x42\x0d\xaf\xa8\xfd\x9b\x84\x25\xf3\xe6\x09\xd0\x84\x66\x10\x38\x9f\x3c\x5e\x01\x53\xda\x9b\x18\x44\x79\xc0\xe1\xed\xf3\xf3\xe3\x4d\xf0\x91\xfb\x29\xf2\xc6\x2d\x39\xbf\x93\x46\xbc\xb3\xf5\x48\x96\xb7\x2e\xc6\xa3\xf1\x3a\xad\xc7\xbb\x4f\x24\x5b\x8d\x1c\x6e\x8c\xbe\x3a\x36\xe8\x8f\x97\x38\x1b\x1e\x0b\x59\x2b\x13\x6f\x62\x36\x40\x56\xa2\xe5\x70\x85\xfc\xb3\x75\x1e\x34\x95\x25\x37\x81\x8d\xf0\xff\x23\xe2\x7b\x2a\x3f\x2a\x8d\x41\xe1\x85\xb0\xa9\xa6\x72\xab\x72\xa2\xa9\x5c\x87\x79\x4f\xe5\x3d\x2e\x50\xb3\xe5\xdd\xc3\xc7\xcf\x3b\xeb\x9f\xc4\x8f\x27\xf5\x93\x31\x4e\x07\x83\xbd\xe5\x0f\xa2\xf8\xde\x36\x9c\xc2\x78\xbb\x7e\x45\x75\x63\xd1\xb9\x09\x79\x7e\x69\x7a\xa2\xfa\x7c\xfe\x25\xb4\x92\x90\xaf\x4f\xcb\xb7\x49\x08\x8b\x19\xe4\x37\x93\xc9\xe7\x49\x7e\x0c\xf9\x1f\x97\x93\x07\xfe\xe6\x58\xf8\xfb\xfa\xe6\xc3\x97\xdf\xf9\xc7\xf3\xe4\xf2\xea\x26\xef\xde\xa4\x3f\x3a\x95\xd7\x4d\x6f\xad\x70\xa7\xef\x8a\x5a\x0b\x86\x64\x68\x40\x16\xb5\x58\x41\x6f\xff\xf6\xe9\xf6\xf6\x08\x1a\x4b\x9e\x0a\xd2\x50\xa3\x73\xa2\xc4\x8e\x47\xad\x37\xd5\xd1\xbf\x49\xe0\x2b\xe5\x0e\x88\xdd\x3b\x3a\xce\xa0\x5b\x0e\x5b\xaf\x55\xc8\xce\xc6\x27\xa1\xf4\x13\xda\x05\xda\x43\x8b\x7b\x55\x56\xfe\x4a\x2b\x34\x7e\xff\x55\x09\xbb\x5b\xcf\x47\xe1\xdc\x92\x2c\x9f\x11\xf7\x72\xd2\x7c\xae\x95\xc1\x77\xca\xcc\xe8\x47\x1c\x9c\x7e\xf5\xa4\x87\xe9\x70\xe8\x9c\x73\x73\x6b\x1d\xca\x30\xf2\xdc\xaa\xae\xd1\x5b\x55\x00\x9a\xc2\xae\x42\x4f\xe7\x6e\x53\x29\xe7\xc9\xae\xc0\xe2\x5f\x2d\x3a\xef\x92\x28\xfa\xb0\xe2\xc1\x22\x5a\xed\x41\x79\x58\x2a\xad\x19\x06\x72\xcd\x92\xca\x59\x0e\x58\xcf\x50\x4a\x94\xc0\x6d\x64\x26\x1c\x26\xf0\x4c\xc1\xa6\x21\xe7\x4b\x8b\x3c\x78\x9d\x47\x21\x83\x5c\x5c\xb9\x4c\x78\x24\xa4\x0c\x6c\xf3\x43\x90\xaf\x6b\x84\x59\xf4\x92\xfd\xeb\x1e\xf7\x80\xfe\xf8\xf1\xf7\xff\x4b\x92\x2f\x93\x3b\xe6\x70\x1d\x56\x96\xa6\xad\x43\x9b\x35\x3d\x45\xef\x2b\x72\x3e\xe3\xb6\xf0\xf7\x7e\xca\xc5\xbd\xef\xaf\x3d\x86\xa3\xe9\xf4\xe1\xf3\xf3\x4d\x36\x9d\x86\x61\xb0\x66\x67\x0d\xd3\xb1\x3c\x5b\xc1\x53\xd0\x0a\x2e\x9b\x06\x84\x91\xf0\x95\x73\xe4\x1e\xe5\x82\x30\x6e\x3b\x18\xe7\x1a\xd1\xbb\xa4\xd3\x36\x51\x75\x7a\xc4\x62\xe5\xaf\x69\x9d\xf7\x63\xe5\x4a\xb7\xdc\x04\x77\x26\x8b\x72\xeb\x29\x56\x0b\x13\x2a\x7c\x59\x09\x0f\x0d\xa2\x75\xe1\xfc\x19\x91\x77\xde\x8a\x26\xbc\x27\xae\xe3\x7c\xe7\xee\x13\x54\x12\xa6\x08\x33\xd7\x60\xe1\x19\x01\x0d\xab\xee\xbc\xb0\x5c\x0c\xbb\xc2\xc4\x7b\x21\x6c\x14\x78\x95\xfd\xf8\x23\x67\xd8\x37\xbf\x64\x86\xdb\x71\xf3\x81\xc8\xf3\xc8\x09\x8d\x7c\x2d\x2b\x72\x80\x59\x9a\x0e\x47\x63\xb4\xbe\xfb\x7c\x7f\x3a\x4c\x46\xe3\xe4\xec\x3c\xb9\xf8\x2d\x1b\x0e\x46\x83\x51\x27\xce\xb7\x1e\xe8\xd9\x72\x34\x72\x5b\xf8\xaf\x22\xee\x4e\xb2\xf7\xbf\x5d\x24\xe7\x67\xc9\x78\x94\x0c\x4f\xb3\xe1\x60\xfc\x12\x91\xe5\x53\xc5\x7f\x0d\x6e\x77\x2e\xbe\xdf\x99\x53\x61\xa2\x8d\xf7\xa1\xb6\xc3\xf2\x00\x2e\x55\xcd\x28\xbd\x38\x4f\xce\xc6\xc9\x68\x98\x9c\x9e\xa4\xbe\x68\xd2\xe1\xe0\x7c\x30\x4c\xd1\x57\x8b\x51\x7a\x72\xf6\x45\xb5\xa7\xb7\x97\xf5\xf0\xe4\xf4\xd5\xff\xfe\xa8\x68\x5b\xa0\xf9\x86\xd5\x1c\x2a\xd4\x4d\xb8\x6b\xbc\xaa\xf4\x5c\x19\xd9\x95\x48\xb8\xd8\xac\xc2\x2d\xa6\x26\x8b\x3b\x57\x0e\x4f\x50\x89\x05\x77\x46\x61\x20\xdf\x61\x25\x07\xbe\x3c\x1f\x12\x9f\x6f\xee\xb8\x16\x21\x0c\x31\x17\x9c\x84\xd6\x2b\x10\xa1\x55\x74\x55\x49\xa6\xab\xac\x24\x8a\xf2\x17\x14\xe5\xc1\x59\x18\x10\xda\xa3\x35\xc2\xab\x05\x6e\x9b\x38\xb7\x30\x49\x3c\x16\x39\x33\x27\x6a\x0c\x88\x20\xd7\x57\x0f\x10\x0e\x76\x59\x90\x94\x44\xff\x09\x00\x00\xff\xff\x0f\x9b\xca\x2d\x3c\x0c\x00\x00") func ConfigReadmeMdBytes() ([]byte, error) { return bindataRead( @@ -97,12 +98,12 @@ func ConfigReadmeMd() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "../config/README.md", size: 3330, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x65, 0xb9, 0xf5, 0x6, 0xbe, 0x7d, 0x85, 0x3b, 0x8, 0xbc, 0x5c, 0x71, 0x85, 0x19, 0xd1, 0xde, 0x38, 0xb5, 0xe9, 0x90, 0x5c, 0x45, 0xb2, 0xa5, 0x8a, 0x91, 0xee, 0xeb, 0x1e, 0xb4, 0xa9, 0x8f}} + info := bindataFileInfo{name: "../config/README.md", size: 3132, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3e, 0x6b, 0xc5, 0xa7, 0x25, 0x29, 0x76, 0x80, 0xd3, 0xc5, 0x5f, 0x31, 0xaa, 0x3f, 0x4a, 0xcb, 0xb0, 0x5, 0x5a, 0xfe, 0x28, 0x43, 0x80, 0xdd, 0xe8, 0x66, 0x2b, 0x8b, 0xa1, 0x76, 0x1a, 0x2d}} return a, nil } -var _ConfigCliFleetEthBetaJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x74\x56\x5b\x8f\x1e\xc5\xd1\xbe\xf7\xaf\x78\xb5\xd7\x9f\xde\xed\x3a\x77\xf9\xca\x1f\x04\x62\x41\x82\xcc\xc1\x04\x12\xe5\xa2\xba\xaa\xda\x76\x70\xbc\x64\xbd\xb6\x82\x23\xfe\x7b\x34\xcb\x46\x60\x60\x2f\x46\x1a\xf5\xcc\x74\x3d\x53\xcf\xa1\xeb\x3f\x0f\x4e\xa7\x8b\x2f\xfa\x55\xf5\xbb\xb7\x57\x6f\x5e\x5f\x3c\x3c\xdd\x5c\xbf\xe9\xff\x3b\x56\x3f\xbb\xfa\xc3\x8b\xd7\x79\xf5\xb6\xaf\x7f\xb8\x78\x78\xda\xf1\xf2\xf5\x4f\xeb\x1f\xbe\x7c\xf3\xfa\xa6\xaf\x3f\xbc\x7a\xb5\x5f\x3c\xbb\x78\x78\x3a\xb6\x38\x9d\x2e\x3e\x7a\x15\xeb\x65\xd7\x2f\x76\x38\x9d\x2e\x3e\x7e\xd9\x7d\x73\xf1\xf0\x74\xd1\x37\xcf\xcf\xab\x6f\xe2\xe2\xee\xc1\x07\x57\x57\x37\x9f\x5d\x55\x1f\x15\xff\x76\xbb\x74\x3a\x5d\xf4\xab\xab\xea\x87\x97\x97\x3d\xc3\x72\xd0\x92\xe9\x00\xed\x73\xad\x52\x8d\xcc\x85\x21\x52\x62\x3a\x69\x93\x2c\xa4\xb5\xbd\x76\xc6\xf4\x96\x46\xe6\x5e\x92\x49\x1b\x65\xc0\x5c\x0c\x80\xb5\x64\xd8\x8e\x0c\xe2\xbd\xd4\xf7\x5e\xcc\x8b\x14\xb7\x79\x57\xb8\x85\xaa\xc7\xac\x8d\x9e\x86\xad\xc2\x0c\x6a\x93\x1f\xb1\x9d\x1d\xce\x88\x7c\x26\x79\x48\x83\x07\xdf\xe1\xfe\x05\x48\x26\xcd\xd4\xad\xc6\x8e\x73\x57\x7a\xf8\x36\xf7\xb1\xd1\x99\xc7\xc0\xa5\x53\x0a\x92\x6c\x0f\x94\x84\xd5\x8c\x02\x53\x96\x2c\xd8\xc3\xc7\xd8\x1d\x1b\x32\x13\x43\x81\x06\xea\xdc\xee\xe3\x78\x2d\xac\x50\x70\x93\xd1\xc0\x9c\x44\x12\x98\x10\x8a\x46\xda\x8e\x84\xea\x90\x49\xf1\x08\x8c\xcf\x40\xf3\x0c\x43\xce\xc8\x74\x1f\x4e\x63\xb4\xda\x4d\x73\x15\xe7\xb6\x94\xb9\x96\x2b\x83\xcd\xa1\x3b\x16\x8a\x4d\xec\xa4\xd6\xc1\x1a\x73\x08\x91\x8d\x81\x98\x2b\x02\x27\x08\x69\xcf\x52\xee\x2c\x58\x03\x1b\xf6\xdc\x86\xa6\xb3\xd1\xa5\x86\xa2\xcc\x15\x4c\x35\x27\x0d\xae\x35\x74\xb6\x6e\x64\xb0\xe8\xb9\x72\x79\xe8\x23\x18\x7c\x06\xe1\xf3\x9c\x67\xc0\x7b\x61\x32\x39\xdb\x54\xca\x1d\x12\x51\x00\x36\x37\x4f\x8c\x24\x89\xd9\x6b\x39\x80\x66\x75\x41\x22\x6d\xdb\x1e\x1b\x82\x6d\x45\xed\x84\x6e\xdb\xa3\xca\x3b\x87\x30\x31\x58\x26\xb1\x21\x4a\x68\xb3\x35\x6b\xea\x34\xda\xca\x26\xe2\xcd\xc4\xc4\xe2\x9a\xc2\x0d\x16\x5c\x14\xd0\xb7\x9c\x0b\x9e\x8f\x9e\xf2\xb8\x0f\xa4\x90\x4b\xc4\xb2\x49\xb4\xa1\x73\xa9\xc1\x12\x5f\x7b\x08\x42\x6e\x1c\x88\xbc\x7b\x82\xe2\x4e\x2a\x54\x93\x6a\xee\xe6\x12\x25\x0d\x93\x4e\xc2\x02\x3a\xb8\x4e\x98\x5c\x7b\x16\x54\xed\x98\x83\x9c\xc9\x87\xce\x89\x15\x8a\xc1\xb5\x19\x8b\x77\xe6\xd6\x3a\x98\x9a\x20\x1a\xd3\x1e\xe1\xd0\x33\x4c\x3f\xf8\x3e\x8b\xdd\x07\xb3\x57\xef\x58\xe4\x4b\x7d\xad\xd5\xca\x35\xb3\xa6\xae\x36\x95\x45\xab\x49\xb4\x66\xf2\x42\x56\x1d\x5b\xa5\xd8\x09\x98\x62\x24\xf3\xa6\x99\x53\x02\xc5\x68\x8c\x83\x04\x9b\x2c\xe2\x18\xb0\x06\x11\x4e\x00\x61\x6c\x0f\x99\x38\x21\x27\xc9\x8a\x55\x65\x72\x7b\xb3\x94\x7b\x27\x3c\x22\x39\xe3\xc0\xb3\xfb\xe1\xa1\x3b\x94\xb7\x20\xff\x7e\x67\xff\xaf\xae\x8f\x0c\xa9\x3f\xc7\x8b\x97\x5f\xf6\xf5\xdb\xbe\xfe\xdd\x1c\xa8\x50\x68\xef\xbd\xa7\x86\xa8\x12\x2d\x25\xd9\x73\x5a\xcd\xe5\xd0\x63\x6f\x41\xd2\xb5\x72\xc8\x9a\xa0\x3e\x89\xd1\xb1\x1d\x63\x2f\x47\x47\xaf\xdc\xda\xbb\xd6\x61\xa6\x20\xf3\x41\x15\x73\xf7\xa0\xc9\x25\x31\x62\x22\x5b\x4f\xda\x90\x8d\x00\x11\xc7\xe7\x63\x2c\x2d\x9c\x29\x3c\xef\x72\x00\x44\xcf\x7e\x08\x57\x7e\xaf\xd9\xc9\xb8\x49\x67\x20\xed\xf0\xd9\x2d\xac\xbb\xf0\x90\xdf\x30\xf1\xa1\x48\x48\xc8\xde\x5b\xc5\x0a\xb5\x48\x2c\xcc\x8c\x99\xa2\xf3\xf0\x0c\x2c\xf4\xa0\x40\xec\x4d\x6d\x47\xdd\x86\xc9\x4e\x55\xb1\x05\x82\x60\x8d\xe8\xd2\x61\xbe\x4a\x7b\xb5\x44\x4f\x9a\x3b\x77\x6c\x0a\xf6\xf7\x34\x01\x8a\xf7\xe1\xb4\x6a\xf7\xe6\x5c\xb0\x48\x90\x56\xa1\x66\x20\x20\xa9\x0b\x0f\x3d\xa4\x60\x69\x08\x51\xbc\xa9\x25\x27\x42\x97\x03\x4f\x90\x91\xad\xd9\xd8\x86\x4a\x60\x48\x47\x3e\xc0\xd8\x91\xb0\x4b\xf0\x10\xf0\x5a\xb5\x49\x44\x7a\x08\x99\xc7\x36\x17\x90\x06\x30\xaf\xa0\xc3\x8e\xb5\x0e\x51\xc0\x91\x01\x7e\x46\x18\xf7\xa2\x64\x1e\x3e\x63\x69\x11\x8d\x19\x5b\xb2\x06\x39\x8e\xe8\xd0\x91\xac\x05\xba\x30\x8b\x8a\x68\x6d\x52\xcb\x15\x1b\x6a\x40\xe2\xce\x1a\xaa\xfb\x90\xc7\x14\xd3\x1a\xae\x36\xdd\xb2\xac\xd6\x1a\xad\xb4\xa7\x51\xe6\x58\xbc\xad\x79\x8d\x0d\x65\x88\xd8\xba\x88\x05\xc2\x66\xf9\xaa\x38\x28\x3f\x7a\x39\xce\x20\xf7\x62\x8c\x50\x9e\xa5\x3d\x45\x5c\xc6\xc2\xa6\xa2\xb5\x11\x47\xb2\x6b\x8f\x8c\xe6\xa8\x5d\x75\x10\x0a\xad\x43\x8f\x2a\x60\x16\x9d\x4e\x2b\x35\x2b\x37\xe0\xc4\x5c\x3c\x0a\x54\xd4\x09\x7b\xed\x2a\x51\x31\xf4\x0a\xe6\x41\x3a\xcb\x92\x2b\xac\x56\x71\x8d\xc1\x0b\x22\x07\xae\x3d\x7f\xc5\xb8\xdf\x87\x73\x80\x34\xe2\xd6\x2c\x5c\xcc\x39\x43\x60\x95\x05\xde\x12\x85\x06\x7d\x08\x34\xad\x6c\x0b\x32\xa1\x81\xab\x4a\x18\xbb\xea\xc6\x0a\x96\xc3\x07\x0d\xc2\x3d\x49\x57\xb7\x0e\xc7\xc5\xa5\x53\x77\xab\x35\x11\xa8\x88\x4c\x4d\xb1\x65\x30\x57\x93\xbb\x25\x28\x7a\xe1\x71\x90\xde\xc6\x00\xea\x19\xe1\x0c\xf7\x82\x34\x76\xb1\x26\x85\x58\xe8\xa3\x35\x36\x4b\x00\xb2\x90\xae\xf4\xa8\x6e\xf2\xbd\x0a\xb7\xbb\x84\x59\x64\x6b\x97\xd5\x90\xf2\x80\xb4\xf4\xb9\x6c\x2e\xac\x2d\x7b\x0e\x83\x64\xf2\xe5\x39\x62\x37\x87\xfa\x74\xea\x3a\xd8\x50\x22\x36\xda\xae\x2b\xc1\xa5\x6a\x13\x6d\xcd\x1e\xe3\x2e\xf7\x51\xe4\x0c\x7e\x2f\xe5\x33\x94\x17\x25\xb1\x07\xf6\xe8\xcd\x41\xd8\xc1\xae\xc3\xfb\x30\x25\x91\xf2\x6a\x00\x18\x28\x94\x38\xa2\x12\x2c\x28\x7b\xad\x24\x0f\x04\x6f\x29\x6a\xa0\x05\x02\x39\xba\x5b\x6a\xf6\xd8\x1e\x73\x05\x66\x0d\xd4\x01\xdc\x6a\x8b\x21\x38\x96\x15\x94\x54\xa9\x65\xe0\x71\x80\xff\x8a\xf2\x79\x1f\x4e\x21\x68\x14\xec\x74\xd5\x75\x1b\x6d\x22\x34\x13\x7c\x6d\xc8\x6a\xa3\x09\x99\xe6\xec\x03\xf5\x38\x1c\xdd\x97\xb6\xfb\x6c\x75\x31\x81\x88\xda\xa8\xc5\xe9\xb3\x24\xb8\x63\xed\x65\xd9\xbb\x08\x92\x72\xce\xd2\x31\xc2\x4c\x36\x70\x97\xd8\x04\xc1\x11\x73\x76\x16\x4a\x05\xa5\xfe\x44\xf9\x71\xd9\xd9\xfe\xc7\xf9\x7b\xc9\xff\xe5\x4d\xdc\xbc\xc8\x7b\x47\x3f\xf0\x69\xb8\x9d\x17\xb4\x99\x56\x50\x00\x35\x4a\xec\x30\x58\x6c\xb5\xc3\xbd\x55\x66\xec\x52\x46\xeb\x38\x7c\x38\x28\x11\xc3\x7d\x03\x89\x0f\x1c\x12\x73\xa2\x32\x53\xbb\x04\x59\x77\x43\x4d\x90\x9d\x4c\x14\xdb\x62\x66\x1c\x63\xdf\xa8\x6d\xce\x54\xb0\x45\x74\xf2\x60\x59\x3f\x69\x96\xe6\x59\xc7\x19\x49\x1f\xd2\xa0\x21\xbf\x6d\xb3\xeb\x30\xb3\x3d\x60\x59\x65\xc5\x31\x54\x11\x78\x53\x54\x17\x81\x05\xa0\x6d\x9d\xaa\x04\x0b\x6c\x60\x18\xe8\x8c\xe2\x31\xd7\xdc\x73\x99\x82\xa2\x61\xcd\x71\x08\x31\x96\x85\x84\xae\xe4\x55\xc3\xa2\x1d\x73\x50\x23\x2d\x5e\x33\x8b\xd7\x9e\x32\x6b\x6c\xbb\x9d\x22\x3a\x4d\xd3\xf7\x9d\x68\x65\x9e\x11\xe8\x0e\xe4\x7b\x5d\xfe\x79\xa2\xff\x4d\xa7\x2f\x5f\x7c\xcf\x97\xbf\x9a\x1d\x2f\x6f\xf2\xfb\x4b\x1a\x36\xe8\xb2\x6f\x9e\xbf\xe5\x4b\xd0\xa7\x2f\xde\xe0\xe3\xff\xff\xe7\x17\x8f\x9f\xbc\xfb\x98\xae\x3f\x7f\x26\xf2\xe4\xd9\xb7\x4f\xf2\xf3\xef\x7e\x78\xfb\xe4\xeb\xc7\xfe\x0a\x9f\xff\xe5\xf5\xb7\x4f\x9e\x3f\xfd\xe4\x83\xbf\xea\x77\x5f\xff\xe3\x93\x67\xf5\xf5\xcf\x7d\xba\xad\xf1\xfe\xac\x72\x7f\x89\x3f\xfd\xeb\xab\x6f\xde\x7c\xcb\x5f\x2e\xfd\x23\xce\xc7\x9f\x5d\x5d\xc5\xc7\x4f\xbf\x79\xfa\xe9\xbb\xef\xdf\x7d\xfa\xcd\x87\xf9\xec\x87\x4f\xfe\xfd\x2c\x3e\xfa\x08\x5f\xc8\xdb\x57\xfb\xee\x2f\x1f\x9c\x4e\x3f\x3e\xf8\xf1\xc1\x7f\x03\x00\x00\xff\xff\x10\xd9\x12\xac\xbd\x0c\x00\x00") +var _ConfigCliFleetEthBetaJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x74\x56\xcb\x8e\x5c\xc7\xcd\xde\xeb\x29\x1a\xb3\xfe\xd1\x53\xbc\x17\xb5\xd2\x6f\xc7\x8e\x60\x27\x86\x7c\x91\x63\x27\xc8\x82\x45\xb2\xa4\x89\x15\x8d\x33\x1a\x09\xb1\x02\xbf\x7b\x70\xc6\x42\x7c\xd3\x2c\x1a\x68\x54\xf7\x29\x7e\x87\xdf\x85\xfc\xcf\x83\xd3\xe9\xe2\x8b\x7e\x59\xfd\xf6\xcd\xf5\xeb\x57\x17\x0f\x4f\xb7\x37\xaf\xfb\xff\x8e\xd3\xcf\xae\xff\x70\xf5\x2a\xaf\xdf\xf4\xcd\x0f\x17\x0f\x4f\x3b\x5e\xbc\xfa\xe9\xfc\xc3\x17\xaf\x5f\xdd\xf6\xcd\x87\xd7\x2f\xf7\xd5\xb3\x8b\x87\xa7\xe3\x8a\xd3\xe9\xe2\xa3\x97\xb1\x5e\x74\xfd\xe2\x86\xd3\xe9\xe2\xe3\x17\xdd\xb7\x17\x0f\x4f\x17\x7d\xfb\xfc\xbc\xfa\x36\x2e\xde\xfd\xf0\xc1\xf5\xf5\xed\x67\xd7\xd5\x47\xc5\xbf\xdd\x1d\x9d\x4e\x17\xfd\xf2\xba\xfa\xe1\xe5\x65\xcf\xb0\x1c\xb4\x64\x3a\x40\xfb\x5c\xab\x54\x23\x73\x61\x88\x94\x98\x4e\xda\x24\x0b\x69\x6d\xaf\x9d\x31\xbd\xa5\x91\xb9\x97\x64\xd2\x46\x19\x30\x17\x03\x60\x2d\x19\xb6\x23\x83\x78\x2f\xf5\xbd\x17\xf3\x22\xc5\x6d\xde\x15\x6e\xa1\xea\x31\x6b\xa3\xa7\x61\xab\x30\x83\xda\xe4\x47\x6c\x67\x87\x33\x22\x9f\x49\x1e\x32\xd3\x3b\xd4\xbf\x80\xc8\xa4\x99\xba\xd5\xd8\x71\xee\x4a\x0f\xdf\xe6\x3e\x36\x3a\xf3\x18\xb8\x74\x4a\x41\x92\xed\x81\x92\xb0\x9a\x51\x60\xca\x92\x05\x7b\xf8\x18\xbb\x63\x43\x66\x62\x28\xd0\x40\x9d\xdb\x7d\x1c\x7f\x0b\x2b\x14\xdc\x64\x34\x30\x27\x91\x04\x26\x84\xa2\x91\xb6\x23\xa1\x3a\x64\x52\x3c\x02\xe3\x33\xd0\x3c\xc3\x90\x33\x32\xbd\x1f\xa5\x31\x5a\xed\xa6\xb9\x8a\x73\x5b\xca\x5c\xcb\x95\xc1\xe6\xd0\x1d\x0b\xc5\x26\x76\x52\xeb\x60\x8d\x39\x84\xc8\xc6\x40\xcc\x15\x81\x13\x84\xb4\x67\x29\x77\x16\xac\x81\x0d\x7b\x6e\x43\xd3\xd9\xe8\x52\x43\x51\xe6\x0a\xa6\x9a\x93\x06\xd7\x1a\x3a\x5b\x37\x32\x58\xf4\x5c\xb9\x3c\xf4\x11\x0c\x3e\x83\xf0\x79\xce\x33\xe0\x3d\x20\x99\x9c\x6d\x2a\xe5\x0e\x89\x28\x00\x9b\x9b\x27\x46\x92\xc4\xec\xb5\x1c\x40\xb3\xba\x20\x91\xb6\x6d\x8f\x0d\xc1\xb6\xa2\x76\x42\xb7\xed\x51\xe5\x9d\x43\x98\x18\x2c\x93\xd8\x10\x25\xb4\xd9\x9a\x35\x75\x1a\x6d\x65\x13\xf1\x66\x62\x62\x71\x4d\xe1\x06\x0b\x2e\x0a\xe8\x3b\xb6\x05\xcf\x47\x3f\x79\xbc\x1f\xa2\x90\x4b\xc4\xb2\x49\xb4\xa1\x73\xa9\xc1\x12\x5f\x7b\x08\x42\x6e\x1c\x88\xbc\x7b\x82\xe2\x4e\x2a\x54\x93\x6a\xee\xe6\x12\x25\x0d\x93\x4e\xc2\x02\x3a\x58\x4e\x98\x5c\x7b\x16\x54\xed\x98\x83\x9c\xc9\x87\xce\x89\x15\x8a\xc1\xb5\x19\x8b\x77\xe6\xd6\x3a\x58\x9a\x20\x1a\xd3\x1e\xe1\xd0\x33\x4c\x3f\x98\x3e\x8b\xbd\x1f\x64\xaf\xde\xb1\xc8\x97\xfa\x5a\xab\x95\x6b\x66\x4d\x5d\x6d\x2a\x8b\x56\x93\x68\xcd\xe4\x85\xac\x3a\xb6\x4a\xb1\x13\x30\xc5\x48\xe6\x4d\x33\xa7\x04\x8a\xd1\x18\x07\x01\x36\x59\xc4\x31\x60\x0d\x22\x9c\x00\xc2\xd8\x1e\x32\x71\x42\x4e\x92\x15\xab\xca\xe4\xee\xcb\x52\xee\x9d\xf0\x88\xe4\x8c\x03\xcf\xee\x87\x73\xee\x30\xde\x41\xfc\xfb\x3b\xcb\x7f\x75\x73\xe4\x46\xfd\x39\xae\x5e\x7c\xd9\x37\x6f\xfa\xe6\xbd\xde\xaf\x50\x68\xef\xbd\xa7\x86\xa8\x12\x2d\x25\xd9\x73\x5a\xcd\xe5\xd0\x63\x6f\x41\xd2\xb5\x72\xc8\x9a\xa0\x3e\x89\xd1\xb1\x1d\x63\x2f\x47\x47\xaf\xdc\xda\xbb\xd6\x61\xa1\x20\xf3\x41\x15\x73\xf7\xa0\xc9\x25\x31\x62\x22\x5b\x4f\xda\x90\x8d\x00\x11\xc7\xe3\x63\x2c\x2d\x9c\x29\x3c\xdf\x79\x1f\x44\xcf\x7e\x8f\x60\x93\x71\x93\xce\x40\xda\xe1\xb3\x5b\x58\x77\xe1\x21\xbb\x61\xe2\x43\x91\x90\x90\xbd\xb7\x8a\x15\x6a\x91\x58\x98\x19\x33\x45\xe7\xe1\x14\x58\xe8\x41\x81\xd8\x9b\xda\x8e\xaa\x0d\x93\x9d\xaa\x62\x0b\x04\xc1\x1a\xd1\xa5\xc3\x7c\x95\xf6\x6a\x89\x9e\x34\x77\xee\xd8\x14\xec\xbf\x52\x03\x28\xde\xe3\xfd\x6a\xf7\xe6\x5c\xb0\x48\x90\x56\xa1\x66\x20\x20\xa9\x0b\x0f\x3d\x44\x60\x69\x08\x51\xbc\xa9\x25\x27\x42\x97\x03\x4f\x90\x91\xad\xd9\xd8\x86\x4a\x60\x48\x47\x26\xc0\xd8\x91\xb0\x4b\xf0\x10\xee\x5a\xb5\x49\x44\x7a\x08\x99\xc7\x36\x17\x90\x06\x30\xaf\xa0\xc3\x84\xb5\x0e\x39\xc0\xe1\x7b\x3f\x23\xdc\xe3\x2b\x63\x1e\x3e\x63\x69\x11\x8d\x19\x5b\xb2\x06\x39\x8e\xe8\xd0\x91\xac\x05\xba\x30\x8b\x8a\x68\x6d\x52\xcb\x15\x1b\x6a\x40\xe2\xce\x1a\xaa\xfb\x10\xc6\x14\xd3\x1a\xae\x36\xdd\xb2\xac\xd6\x1a\xad\xb4\xa7\x51\xe6\x58\xbc\xad\x79\x8d\x0d\x65\x88\xd8\xba\x88\x05\xc2\x66\xf9\xaa\x38\xc8\x3e\xfa\x38\xce\x70\x4f\xce\x5b\x84\xf2\x2c\xed\x29\xe2\x32\x16\x36\x15\xad\x8d\x38\x92\x5d\x7b\x64\x34\x47\xed\xaa\x83\x4a\x68\x1d\x7a\xd4\x00\xb3\xe8\x74\x5a\xa9\x59\xb9\x01\x27\xe6\xe2\x51\xa0\xa2\x4e\xd8\x6b\x57\x89\x8a\xa1\x57\x30\x0f\xd2\x59\x96\x5c\x61\xb5\x8a\x6b\x0c\x5e\x10\x39\x70\xed\xf9\x1b\xae\xfd\xfd\x28\x07\x48\x23\x6e\xcd\xc2\xc5\x9c\x33\x04\x56\x59\xe0\x1d\x45\x68\xd0\x87\x30\xd3\xca\xb6\x20\x13\x1a\xb8\xaa\x84\xb1\xab\x6e\xac\x60\x39\xd4\xdf\x20\xdc\x93\x74\x75\xeb\x70\x5c\x5c\x3a\x75\xb7\x5a\x13\x81\x8a\xc8\xd4\x14\x5b\x06\x73\x35\xb9\x5b\x82\xa2\x17\x1e\x23\xf3\xce\xfa\xa8\x67\x84\x33\xdc\x03\xd1\xd8\xc5\x9a\x14\x62\xa1\x8f\xd6\xd8\x2c\x01\xc8\x42\xba\xd2\xa3\xba\xc9\xf7\x2a\xdc\xee\x12\x66\x91\xad\x5d\x56\x43\xca\x03\xd2\xd2\xe7\xb2\xb9\xb0\xb6\xec\x39\x0c\x92\xc9\x97\xe7\x88\xdd\x1c\xea\xd3\xa9\xeb\x60\x42\x89\xd8\x68\xbb\xae\x04\x97\xaa\x4d\xb4\x35\x7b\x8c\x77\x29\x8f\x22\x67\xf0\x7b\xc8\x9e\xa1\xbc\x28\x89\x3d\xb0\x47\x6f\x0e\xc2\x0e\x76\x1d\xde\x87\x11\x89\x94\x57\x03\xc0\x40\xa1\xc4\x11\x95\x60\x41\xd9\x6b\x25\x79\x20\x78\x4b\x51\x03\x2d\x10\xc8\xd1\xdd\x52\xb3\xc7\xf6\x98\x2b\x30\x6b\xa0\x0e\xe0\x56\x5b\x0c\xc1\xb1\xac\xa0\xa4\x4a\x2d\x03\x8f\x51\xfd\x1b\xb2\xe7\x7d\xc3\x08\x1a\x05\x3b\x5d\x75\xdd\x45\x99\x08\xcd\x04\x5f\x1b\xb2\xda\x68\x42\xa6\x39\xfb\x40\x3d\xc6\xa0\xfb\xd2\x76\x9f\xad\x2e\x26\x10\x51\x1b\xb5\x38\x7d\x96\x04\x77\xac\xbd\x2c\x7b\x17\x41\x52\xce\x59\x3a\x46\x98\xc9\x06\xee\x12\x9b\x20\x38\x62\xce\xce\x42\xa9\xa0\xd4\x9f\xc8\x3e\x3e\x76\x36\xff\x7d\xce\x7f\x79\x1b\xb7\x57\x79\xef\x72\x67\xda\x7d\xf8\x40\xf7\x62\xc9\x30\x3d\x04\x5b\x9d\x16\x69\x9c\x51\x2b\x68\xed\x18\xcb\x31\x45\x35\x6a\xd8\xca\x65\x84\x3e\xd7\xd8\xbb\x81\x40\x76\xd9\xb4\x63\x1d\x41\x6f\x1f\xb5\x42\xb2\x68\x73\x0f\x07\xed\xa1\x7e\x40\x97\xd1\x9e\xab\x13\x78\xae\x8e\x22\xb7\xc8\x09\x88\xf5\xbf\xe5\x4e\xcf\x76\x8f\x0e\x70\x0d\x70\x91\xb2\x06\xe8\x63\xa2\xf4\x30\x62\x5a\x2c\xda\xdc\xae\x39\x26\x98\x1e\xa9\x78\x38\x1a\x17\x24\x2f\x65\xe8\xd8\x84\xa3\xc9\xd8\xa6\xc1\xb4\xb1\x43\x27\xb6\xb7\xe7\x5e\xf3\x18\x57\x9e\xed\xdc\x85\xbb\x1b\x22\x59\xa6\x0f\x2e\xe1\x5d\x63\xb9\x1d\x21\x17\x98\x1c\xfc\x0b\x1d\x8c\xb3\x8d\xdf\xb7\xf8\xe7\x85\xfd\x77\x6d\xbe\xbc\xfa\x9e\x2f\x7f\xb3\x1c\x5e\xde\xe6\xf7\x97\x34\x6c\xd0\x65\xdf\x3e\x7f\xc3\x97\xa0\x4f\xaf\x5e\xe3\xe3\xff\xff\xe7\x17\x8f\x9f\xbc\xfd\x98\x6e\x3e\x7f\x26\xf2\xe4\xd9\xb7\x4f\xf2\xf3\xef\x7e\x78\xf3\xe4\xeb\xc7\xfe\x12\x9f\xff\xe5\xd5\xb7\x4f\x9e\x3f\xfd\xe4\x83\xbf\xea\x77\x5f\xff\xe3\x93\x67\xf5\xf5\xcf\x7d\xba\xab\xf1\xeb\x95\xe4\xfe\x12\x7f\xfa\xd7\x57\xdf\xbc\xfe\x96\xbf\x5c\xfa\x47\x9c\x8f\x3f\xbb\xbe\x8e\x8f\x9f\x7e\xf3\xf4\xd3\xb7\xdf\xbf\xfd\xf4\x9b\x0f\xf3\xd9\x0f\x9f\xfc\xfb\x59\x7c\xf4\x11\x5e\xc9\x9b\x97\xfb\xdd\x5b\x3e\x38\x9d\x7e\x7c\xf0\xe3\x83\xff\x06\x00\x00\xff\xff\x5a\xc4\x3b\x12\x9c\x0c\x00\x00") func ConfigCliFleetEthBetaJsonBytes() ([]byte, error) { return bindataRead( @@ -117,12 +118,32 @@ func ConfigCliFleetEthBetaJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "../config/cli/fleet-eth.beta.json", size: 3261, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x2b, 0xae, 0x42, 0x4b, 0xa4, 0xd9, 0x2, 0x69, 0x99, 0x29, 0x7e, 0x1, 0x4e, 0xd9, 0x58, 0x84, 0x28, 0x3a, 0x81, 0xc4, 0xde, 0x1d, 0xea, 0x51, 0xc8, 0x21, 0xff, 0x7b, 0xff, 0x23, 0x1c, 0x16}} + info := bindataFileInfo{name: "../config/cli/fleet-eth.beta.json", size: 3228, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd3, 0xff, 0x20, 0xed, 0x7a, 0xda, 0x82, 0x8a, 0x1f, 0x4, 0xb1, 0xbf, 0xa0, 0x25, 0x30, 0x1c, 0xba, 0x4f, 0x58, 0xdf, 0x63, 0x5f, 0x2, 0xb3, 0x9a, 0xb8, 0x2a, 0xdb, 0x98, 0xd0, 0xc7, 0xa6}} return a, nil } -var _ConfigCliFleetEthStagingJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x74\x94\x5d\x6f\x5c\xc7\x0d\x86\xef\xfd\x2b\x16\x7b\x5d\x1c\x91\x33\x1c\x0e\xa9\x2b\xd5\x8e\x64\x21\xad\x0d\x57\x8e\xdd\xc0\x45\x2f\x66\xf8\x21\xa9\x52\xb5\xce\xee\xca\xb1\x53\xe4\xbf\x17\xeb\x28\x88\x9d\x44\x77\x0b\x2e\x0e\xdf\xe7\x3c\x78\x0f\xff\xf7\x64\xb5\x5a\x5f\xc4\x9d\xc7\x4f\x1f\x36\xf7\xbb\xf5\xf1\x6a\xbf\xbd\x8f\xbf\x1c\xa6\x2f\x37\xdf\x5c\xef\x6c\xf3\x21\xb6\x9f\xd6\xc7\xab\x1c\xb7\xbb\x5f\xe6\xcf\x6e\xef\x77\xfb\xd8\x3e\xdb\xdc\xe5\xf5\xe5\xfa\x78\x75\x58\xb1\x5a\xad\x4f\xef\xc6\xbc\x0d\xff\x62\xc3\x6a\xb5\x3e\xbb\x8d\xd8\xaf\x8f\x57\xeb\xd8\x5f\x2d\xbb\xfd\xb8\xbc\xbe\xbb\x5c\x3f\xfc\xf7\x74\xb3\xd9\xbf\xdc\x78\x1c\x42\xff\xf5\x79\xb4\x5a\xad\xe3\x6e\xe3\x71\x7c\x74\xc4\x15\x26\x54\x2a\x36\x28\xb4\xb5\x92\x0d\x3a\xd2\x64\x93\x28\xe2\xac\xad\x4d\x83\x74\xa4\xe8\xda\x20\xb5\x4e\xab\xb3\x4c\x31\x13\xc3\xac\x93\x1d\xa1\x7a\x32\x67\xc3\x81\xd5\x7b\xaf\xb3\xf9\x84\xc4\x0a\xcc\x98\xb3\x59\x9f\x92\xa3\xa0\x91\x88\x82\x31\x59\xd7\x49\x38\x1a\x0f\x52\x38\xa1\xbe\x28\x2e\xa5\xe8\x42\x74\x5c\x81\x80\x1e\xb8\xbf\x80\xcc\xae\x39\xab\xa2\x66\x2f\x36\x1a\xc3\x70\xa0\x4a\x6e\x56\xa5\x8f\x99\x41\x18\xc0\xcc\x05\x30\xa6\x0f\x1f\x12\x1e\x40\x5c\xa8\xd1\x01\x2a\x26\x34\xf3\x81\x2d\x8b\x74\x2f\x46\xd3\xa5\xf9\x10\x4c\x88\x59\x9a\xc3\x20\xe1\x39\xa7\x89\x27\x95\x3e\xb5\xe3\xb0\x86\xad\xd6\xe9\x00\x19\x27\xd8\x69\xc1\x2a\x0b\x42\x5f\x4a\xd5\xc7\x38\x11\x46\x17\xc3\xae\x45\x47\x07\xd4\x48\x1a\xa3\x14\x52\xef\x15\x4a\x76\x1e\x21\x03\x38\x09\x66\x71\x13\x99\x7d\x56\x8c\x99\x49\x83\x4b\xcd\x39\x89\xe6\xe1\x67\x1f\x36\x47\x51\x36\xb4\xf0\xda\x7b\x73\xc5\x9c\x81\x42\x5c\x0d\x1b\x68\x1f\x3c\x2a\xa7\xcf\x62\x02\x94\x59\xd3\xda\xac\xed\xa4\xb6\xa5\x54\x59\xf4\x40\xf9\xab\xcd\xcf\x90\xff\x7e\xe8\xc2\x77\xdb\x43\xa7\xfc\xc5\xb8\xbe\x7d\x1d\xdb\x0f\xb1\xfd\xd3\x52\xcc\x4e\xd2\x14\x3b\x9b\xf6\x86\x5e\x91\x46\x44\xa6\x15\x0e\xd3\x14\xe6\x41\x58\x7a\x2b\xd1\xdd\xc3\x14\x27\x2a\xa0\x0c\x94\xe8\x66\x43\x9c\x6b\xb7\x8c\x62\xe1\x36\xb5\x97\x94\x98\x4c\x2e\xc8\x39\xbd\x4d\x0a\x51\xeb\x21\xd6\xd3\xbb\xa7\x0c\xac\x45\x73\x50\xf5\x29\x30\x61\x66\x1c\x4a\xd1\xca\xa2\xb0\x60\xe3\xe3\x0a\xed\xcf\x64\xf3\xa1\x0d\x73\x8c\x9e\xd8\x4b\x71\x44\x1c\x62\x6a\x2c\x56\x75\x54\xa4\x0a\xa1\xde\xb8\xb3\xb6\x64\x04\xc9\x8a\x66\x93\xcd\x25\x61\x78\x26\xa9\x62\xf4\x74\x1b\x92\xa3\x77\x88\xde\xa6\xc9\x68\x87\x3d\xdd\x0b\xb1\x82\x4d\x13\x08\x00\xc1\xde\x92\xc0\xb0\x75\xe7\xe4\x2e\xe2\x24\x27\x05\x78\x41\xd1\xa5\x10\x2c\xf8\x28\x66\x50\x1a\x82\x61\x72\x33\x19\xe1\x52\x87\x15\x9e\x86\x33\x67\xc1\x41\xcd\x0c\x87\xb4\x06\xa3\x09\xf4\x6e\xe2\xc5\xa3\x0c\x08\x30\x47\x09\x82\x74\x82\xec\xc1\xd9\x1d\x8a\x1b\x9b\x03\xab\x94\x09\x48\x16\x22\xce\x41\x2c\xbd\xb4\x3c\x18\xc7\x2a\xa1\x4d\x0e\x84\x00\x50\x46\xcf\x5f\x3a\xa1\x0b\x6a\x5d\x08\x1f\x28\xbf\xea\xc4\xeb\xfd\xd8\x5f\xdb\xa3\x17\x42\x91\x0c\x66\x85\x2c\x7d\x8e\x59\xc1\xd0\xd3\x2b\xfa\xf0\xce\xad\x0c\xe2\xf4\xa1\xb5\x43\xa3\x32\x22\x70\x02\x17\x52\x99\x58\xa9\x45\x80\x62\x65\xa4\x29\x53\xa3\x86\x10\x97\x12\x42\xa3\x17\xa8\xd6\xa4\xc9\x08\x74\x15\xd4\xe4\x3a\xc2\x02\x6b\x04\xb3\x04\x25\x33\x0b\x70\x55\xd1\x13\xe4\xbe\xe8\xe1\x05\x16\x24\x39\xae\x50\xa1\xfd\x51\x73\x71\xd1\x6e\x7c\x88\x50\xd2\x54\xb7\x44\x28\x5d\x13\x20\x74\x4a\x2d\xcd\x50\x32\x7a\x8e\x56\x9c\x9b\xb4\x02\xc3\xfb\x0c\x65\xe8\x26\x15\x40\x26\x95\x09\x3c\x22\x5d\x0f\xed\xc5\xf4\x31\x5b\xc7\xac\x75\x94\xa1\x55\x6a\xa6\x76\x6b\x0a\x1a\xde\x30\xb9\x1e\x1e\xaa\xa4\x58\x4b\xed\x71\xd0\x8c\x5a\x16\x58\x84\x1f\x18\xbf\x92\xfc\xdb\xe9\xff\x83\xe8\xa3\xeb\xf7\x74\xf4\xd5\x97\x7b\xb4\xb7\xf7\x47\x15\x3a\xd4\xa3\xd8\x5f\x7d\xa0\x23\xe4\x37\xd7\xf7\xe5\xfc\xaf\xff\xe5\xe7\xba\xfb\xe6\xc5\xcd\xf6\x29\x7d\x3f\xda\xe9\x79\x7d\xf7\xb1\xf8\xa7\xdd\xb3\x8f\x67\x97\x4f\xbf\x7b\x7d\xf1\xd3\xe5\xd5\xb5\xd5\x77\xba\xbf\x38\xbb\x78\x79\xfa\x9b\xa4\xcf\x09\xbf\xbb\x61\x8f\x67\xc8\x9b\x77\xdf\xbf\x39\x3f\x7d\xf5\x6e\xfb\xfe\xdb\x69\xff\xa8\x9f\xde\x9e\x9d\xf3\x9b\xfd\xdf\xb6\x3f\xee\x9e\xf3\x7f\xce\x69\x5c\xf7\xf2\x6a\x37\xff\x9e\x6f\xcf\xe6\xef\x32\xbe\x3c\xe6\x8f\x07\x5c\xdc\xed\xcb\xe9\xa7\xcd\xcd\xdd\x55\x1d\xf7\x1f\xaf\x28\xbf\xfd\xf1\xe6\xe2\xf2\x87\x9b\x73\xbc\xfc\x61\xfb\xcf\xe7\xb1\x93\x57\x37\x78\x53\x5f\xbc\xa5\x8f\xf7\x0f\x16\x9f\xac\x56\x3f\x3f\xf9\xf9\xc9\xff\x03\x00\x00\xff\xff\xb8\x10\xb5\xe1\x46\x07\x00\x00") +var _ConfigCliFleetEthProdJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x74\x56\x5f\xaf\xdd\x45\x72\x7c\xe7\x53\x5c\xdd\xe7\xe8\xb8\xbb\xa7\xbb\x67\xda\x4f\xce\x6e\x20\x88\x4d\x10\xbb\x2c\x04\x12\xe5\xa1\xff\x1a\x67\x89\x2f\x31\xb6\x15\x88\xf6\xbb\x47\x3f\xe3\x04\x56\x70\x9f\x8e\x34\xe7\xa7\x99\x9a\xaa\xae\x9a\xfa\x9f\x0f\xee\xee\xee\xff\xd4\x2f\xab\x7f\x7c\xfb\xf0\xe6\xfb\xfb\xa7\x77\xaf\x5f\xbd\xe9\xbf\xbb\x56\x3f\x7d\xf8\x87\x17\xdf\xe7\xc3\xdb\x7e\xf5\xc3\xfd\xd3\xbb\xf1\x6f\xbf\xff\x69\xfd\xf7\xdf\xbe\xf9\xfe\x75\xbf\xfa\xfd\xc3\xcb\x79\xf1\xfc\xfe\xe9\xdd\xb5\xc5\xdd\xdd\xfd\x87\x2f\x3d\xbe\xed\xfa\xc5\x0e\x77\x77\xf7\x1f\x7d\xdb\xfd\xfa\xfe\xe9\xdd\x7d\xbf\xfe\xe6\xf6\xdd\xab\x87\xba\x7f\xff\xc7\xef\x1e\x1e\x5e\x7f\xfa\x50\x7d\x9d\xf8\x6f\xef\x96\xee\xee\xee\xfb\xe5\x43\xf5\xd3\x27\x4f\xb4\x55\x84\x27\x16\x2c\x0e\x42\x5c\x76\x26\x0b\x06\xe0\x50\x46\x68\x14\x2e\x45\x6b\xf4\xdd\x5b\xc3\x55\x1b\x0f\x98\xbb\x43\xca\xa0\xa7\xac\x34\xef\x6d\x39\x34\xc5\xbe\xc3\x33\x10\x0a\x09\x10\x8e\x59\xac\x0d\xb9\x65\xba\xd0\xc2\x0c\xcb\x12\xb2\x0a\xe8\x18\x7a\x78\x3d\xe3\x7d\xdb\x72\x33\xbb\xa1\xda\x53\xe6\xf5\x1e\xf5\x2f\x20\xf2\xd2\x4c\x1d\xdd\x6c\x74\xa6\xd2\xdc\x66\x9b\xc1\x90\x31\x03\x50\xe8\x91\xc2\x5c\x7b\x80\x24\x31\x9a\x49\xf0\x48\x48\xe0\x80\x01\x4c\xfb\x60\x66\x92\x2b\x2e\x20\x3d\x63\x06\xd7\x67\xbe\x8b\x84\x66\xed\x05\x94\x67\x2d\x71\x4a\x74\xa5\xbd\xb4\x8d\x16\xa9\x61\xe6\xf2\x67\xb8\xcf\x0d\xe9\xdc\x70\xbd\xfb\xfd\x6d\x94\x8b\x66\xb4\xce\xd9\x0a\x01\xc6\xdb\x57\x75\x0b\x67\xcf\x70\x9d\xda\x03\xc1\x09\xb4\x52\xcb\x6b\xb1\xe8\x51\x94\x49\xef\x63\x4d\x9a\x49\x5b\xd6\xd0\x19\x24\x3e\xe2\x8c\xa8\x69\x7b\x47\xdb\xda\xbe\x49\x55\x10\x55\x4c\x49\xc5\x1d\xf6\xd2\x90\x55\xac\x41\x9b\x59\xc9\xd4\x9f\x2d\xbe\x6d\xb8\xb8\x24\x78\x04\x22\xad\x82\xcd\x10\x88\x86\xb6\xe4\x28\x49\x6d\x2b\x4e\xcf\x5d\x02\xbe\xb8\xb6\xb5\xa5\x5a\xa3\x9e\x85\x29\xb9\x41\xf6\xda\xb2\x1d\x47\x6a\xd7\x39\x2c\x08\x91\x62\x52\xbb\x9b\xcb\x57\xa2\xc0\xf1\x9a\xb3\x23\xd2\xda\x48\xa1\x0e\x70\x0f\xac\x39\x89\xbd\xf6\xd0\x04\x4d\xaa\x5d\x5a\x0b\xdd\x10\xf4\x86\xb0\x7f\x1b\xa3\x2c\x13\xf7\xd8\x67\xad\xc1\xce\xd0\x8d\x21\x16\x03\x42\x98\x43\x40\xc4\xd3\x07\x95\x26\x57\x91\x6e\xa9\xe6\x0b\x88\xe8\x52\xdf\xd2\xb9\xa8\x70\x5d\x22\x27\x1e\xae\x39\x85\x55\xe3\x07\x96\xf1\x32\xd0\x73\xa8\x5c\xc9\xb9\x86\xa9\x78\x32\x47\x0b\xf7\x81\x83\xa2\x7e\xf6\xcf\x62\x33\xdc\xf0\x3c\xc2\xa4\x30\x48\x0a\x58\x8d\x9e\x95\xa6\xd4\x3b\x8d\x37\x04\x09\x46\xe8\xb6\x2a\xb5\x7d\xe6\x50\x49\xb0\xda\xe0\x68\x2a\x17\x62\x09\x4c\x94\x54\xd9\xec\x03\x98\xea\x25\x38\x2b\x08\x5c\x46\x73\xcf\x34\xf1\xc9\x34\x0f\xa2\x35\x27\x32\xfc\x9a\x5f\x8e\xc0\x84\x1e\x32\x99\x82\x67\x4b\x6e\x44\xeb\x46\x28\x37\x14\x7d\x07\xf2\x1d\xc6\x7f\x7f\xef\xf9\x3f\xbf\xba\x82\xa3\xfe\xd9\x5f\x7c\xfb\x79\xbf\x7a\xdb\xaf\x7e\xdb\xfc\xa0\xde\xc0\xbe\xb1\xa5\xe2\xe8\xf1\x4d\x94\x7b\x3b\x61\x1e\x62\xf6\x5e\x67\x30\x4a\x2f\xc6\xcf\xce\xd4\x9c\x3e\xc7\x17\xe8\x1a\xc7\x24\x16\x35\xa2\x45\xa3\x3c\x2c\x51\xc2\x70\xa6\x4b\x70\xad\xf6\x38\x5d\xfb\x00\xdb\x5a\x14\xc0\x63\x89\x08\xed\xb9\x67\x63\x62\x30\xd9\x7b\xf3\x13\xef\x1b\x21\xff\x36\xd5\xc9\x34\x4b\x8f\xd3\x1a\xb7\x73\x59\x4a\xa7\x88\x37\x11\x6c\x31\x50\x5a\xb4\x88\xad\x47\x65\x17\x69\x2d\xd9\xbe\xf7\x66\x5e\xde\x09\x5c\x81\x41\xe6\xcb\x89\x7a\x56\xef\x14\x3e\x8d\x87\x6d\x55\xf9\x08\xfa\xc2\x00\xef\x52\xd8\x76\x5d\x34\x5a\xbc\xcf\x3a\x93\xe3\xb3\x9c\xed\x17\x03\x41\x37\x79\x04\x64\x37\x85\xac\x00\xcf\x36\x35\x42\xdd\xce\x08\x82\x1c\xe9\x0b\x88\xd5\xa4\x62\xa0\xd1\xf5\x34\xd6\x8c\x6d\xd4\x6b\x0e\xa1\x27\xd0\x64\x80\x9d\xc3\xfa\xec\x35\x61\xb1\xd9\xf3\x70\xf5\x01\x44\xd0\x64\x95\x38\x4d\xa1\xc9\x03\x65\x2b\xce\x66\x2b\x94\x7d\x62\xd2\x07\x56\x3f\x43\xe0\x1b\xda\xbe\xd1\x15\x51\xfc\x08\x4a\xca\x53\xbd\x32\x82\xae\x74\x5a\x90\x11\x12\xab\x01\x56\xe4\x26\x0a\x24\x1d\xf1\x9e\x43\x4d\x20\xe4\x7e\x99\x98\xd2\x8d\x1b\x72\x7b\x11\x5a\xcb\x5a\xe1\xe7\x5c\xc1\x70\xa4\xa3\x0e\x50\x35\x81\xaa\x2d\x12\x59\x4b\x02\x01\x16\x6c\x65\xf1\x10\xdc\xd0\xe7\x28\x41\x91\x1f\xbc\xe4\x26\xe6\x1b\x11\xde\x1e\x93\x7b\xbb\x2b\x9f\x6b\xe2\x44\x4c\x20\xa8\x57\xad\x18\x22\x48\x36\x6d\x48\x6f\xf6\x9a\xaa\x4b\x4d\x6c\x05\xa5\xd6\xc0\xbd\xbd\xd3\x56\xa4\x66\xe5\x20\x5d\x8f\x17\x43\xa1\xca\x05\xac\x63\xaa\x44\x65\x93\x95\x33\xc3\xd2\x53\x3b\xb9\x7c\x57\x14\x17\x00\x07\x7a\x02\xc5\x9c\xbf\x91\x9b\xf4\x91\xac\x07\x42\xcc\xa8\x83\x49\x32\xb0\x03\x96\x03\x9a\x96\x68\x6b\x36\x2b\x5c\x76\x5d\x15\x7b\xaf\x99\xcb\xb7\x4e\x24\x4b\x78\x8f\x4f\x69\x82\xb6\xb7\x7a\x2d\x59\xab\x29\x7c\x59\x89\x89\x72\x4e\x54\x84\x34\x65\xef\xc4\xb5\x5d\x3a\xe2\x48\x9b\x55\x4e\x6e\xdf\x32\x66\x23\xf2\xec\xb2\xfe\xd2\x9b\x9c\x9b\xd1\x23\x13\x79\x64\xb0\x98\xc0\x86\xc6\xac\xfc\x00\xfa\xe0\xa9\x38\x1b\xb5\xe5\xb0\xd3\xf1\x82\xa8\xe4\x3d\x51\x59\x67\x48\x7d\x36\x57\x94\xed\x49\xda\x86\xcc\x7a\x40\x64\x75\xee\x2c\x03\x23\x9f\xd6\xb3\xaa\xda\xb1\x61\x6c\x52\x36\x76\x64\x70\x60\x1d\xd9\x79\xf1\x70\xce\x91\x55\xff\xa7\x35\x92\xdd\xce\x23\x18\x8f\x2b\xc7\xca\xc5\xe6\xd4\xd0\xc3\xbe\xa8\x9d\x4d\xc1\xfa\xb2\xe2\x5a\xca\xd1\x88\x08\x24\x2b\x09\xbc\x12\xb7\xaf\xec\x88\x5c\xe6\xef\xc6\xb1\x56\xe3\x0a\x94\x8b\xe4\x6e\xa9\x73\xe1\xf2\x13\x4e\x59\x40\x0a\xc8\xad\x3b\x18\x9d\x3d\x76\xe1\x95\xbc\xba\xd3\x69\x33\xed\xbf\xd1\xda\x1e\x19\x48\x66\x54\x68\xa2\x3e\xc1\x14\xb5\xc8\x41\x13\x65\x11\xaa\x8c\x5b\x83\x69\x77\x74\xd5\x1e\xd7\xd2\x96\x39\x11\x3d\xc0\x0c\x91\xec\x2c\x86\xd3\x4b\x05\xa3\xf5\xa0\x2d\xdf\x9d\x40\x06\x84\x59\xc1\x76\x25\x2a\xd6\x1e\x1b\xac\xeb\xe1\x0d\x33\x22\x6d\x9d\x65\xbe\x5d\x8a\x7f\x8a\x7a\x79\x67\x1a\x62\xf9\x75\xd4\x7f\xfe\xda\x5f\xbf\xc8\x47\x0b\x1e\xae\xd2\xe5\x38\x47\x32\x2b\xa3\x68\xe2\xaa\x1e\x61\x51\x56\xb0\xc6\x38\x2a\xdc\xf6\x52\x38\x26\x38\x3b\x97\xb6\xd4\x08\x22\xa7\x61\x35\xc5\x41\xe3\xda\x48\xe7\x0c\x71\x4c\xe1\x36\x38\xc9\x87\xf5\xf4\xb1\xaa\x33\x30\x71\xae\x86\x15\x54\x5d\xde\x87\x3d\x6b\x54\x46\xc9\xff\xdf\xf4\x08\xb7\x03\x8f\x04\x53\x00\x9a\x5c\x95\x02\xb1\xc9\x2a\x1b\xf6\xe2\x15\x2c\xda\xdc\xa6\x09\x07\xb7\x02\x10\x5d\x8e\xa6\xc0\xe4\x50\xc6\xf6\x59\x04\xbd\x36\xef\xb3\xf1\x6c\x18\xd7\x43\x7d\x55\x98\x89\x23\x17\xee\x6c\xe3\x2e\x9a\x6e\xf4\x64\x39\x06\x5c\xc2\x53\x10\xb6\xeb\x8a\x32\xba\x34\x7a\x86\x8b\x6f\x04\x76\xc3\xa5\x37\x44\xfa\x35\xc9\x3f\xd7\xf6\x5f\x11\xfd\xe4\xc5\x77\xfc\x04\x37\xff\x54\x0f\xe1\x7a\xce\xd6\x93\xd7\xf9\xdd\x93\x05\x1b\xd6\x93\x7e\xfd\xcd\x5b\x7e\x82\xfa\xc5\x8b\x37\xf4\xf1\xdf\xff\xe7\x9f\x3e\xfe\xec\xc7\x8f\xd6\xab\x3f\x3e\x17\xf9\xec\xf9\xd7\x9f\xe5\x1f\xff\xf2\xc3\xdb\xcf\xbe\xfc\xd8\x5e\xd2\x37\xff\xf2\xfd\xd7\x9f\x7d\xf3\xc5\x27\xbf\xfb\x57\xfd\xcb\x97\xff\xf1\xc9\xf3\xfa\xf2\x67\xa2\xde\x9d\x41\x57\x6f\x3a\x76\xed\x7f\x93\xfd\xf8\x11\xff\xf4\x5f\x7f\xfe\xea\xcd\xd7\xfc\x79\xe8\x3f\xd2\xf9\xf8\xd3\x87\x07\xff\xe8\x8b\xaf\xbe\xf8\xc3\x8f\xdf\xfd\xf8\x87\xaf\x7e\x9f\xcf\x7f\xf8\xe4\xbf\x9f\xfb\x87\x1f\xd2\x0b\x79\xfb\x72\xde\xdf\xf2\x83\xbb\xbb\xbf\x7e\xf0\xd7\x0f\xfe\x37\x00\x00\xff\xff\x9d\xb1\xb2\x96\xa2\x0c\x00\x00") + +func ConfigCliFleetEthProdJsonBytes() ([]byte, error) { + return bindataRead( + _ConfigCliFleetEthProdJson, + "../config/cli/fleet-eth.prod.json", + ) +} + +func ConfigCliFleetEthProdJson() (*asset, error) { + bytes, err := ConfigCliFleetEthProdJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "../config/cli/fleet-eth.prod.json", size: 3234, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x34, 0x5b, 0x62, 0xfa, 0x22, 0x1e, 0xeb, 0xbf, 0x94, 0x1a, 0x40, 0xda, 0x20, 0x18, 0x57, 0x88, 0xbb, 0xa6, 0x67, 0xec, 0xa1, 0x45, 0x93, 0x90, 0x6, 0xac, 0xcc, 0x16, 0x15, 0xb2, 0xe8, 0x89}} + return a, nil +} + +var _ConfigCliFleetEthStagingJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x74\x94\x5d\x6f\x5c\xc7\x0d\x86\xef\xfd\x2b\x16\x7b\x5d\x1c\x91\x33\x1c\x0e\x47\x57\xaa\x1d\xc9\x42\x5a\x1b\xae\x1c\xbb\x81\x8b\x5e\x90\x1c\x52\x52\xa5\x6a\x9d\xdd\x95\x63\xa7\xc8\x7f\x2f\xd6\x16\x10\xc7\x1f\x77\x07\x3c\x00\xdf\x17\x0f\x9e\xe1\xff\x1e\xad\x56\xeb\x8b\xb8\x9b\xf1\xdb\xbb\xcd\xfd\x6e\x7d\xbc\xda\x6f\xef\xe3\x2f\x87\xe9\xf3\xcd\x0f\xd7\x3b\xdf\xbc\x8b\xed\x87\xf5\xf1\x2a\xf5\x76\xf7\x69\xfe\xe4\xf6\x7e\xb7\x8f\xed\x93\xcd\x5d\x5e\x5f\xae\x8f\x57\x87\x15\xab\xd5\xfa\xf4\x4e\xed\x36\xe6\x67\x1b\x56\xab\xf5\xd9\x6d\xc4\x7e\x7d\xbc\x5a\xc7\xfe\x6a\xd9\xed\xf5\xf2\xfa\xee\x72\xfd\xf0\xef\xf1\x66\xb3\x7f\xbe\x99\x71\x08\xfd\xd7\xc7\xd1\x6a\xb5\x8e\xbb\xcd\x8c\xe3\xa3\x23\xae\x60\x50\xa9\xb8\x52\x8c\xd6\x4a\x36\xe8\x48\xc6\x2e\x51\x64\xf2\x68\xcd\x1c\x72\x22\x45\x1f\x0d\x72\x54\xf3\x6a\xc5\xc4\x5d\x1c\xb3\x1a\x4f\x84\x3a\x93\x39\x1b\x2a\xd6\xd9\x7b\xb5\x36\x0d\x12\x2b\x30\x63\x5a\xf3\x6e\x92\x5a\xd0\x49\x64\x80\x33\x79\x1f\x46\xa8\x8d\x95\x06\x9c\x50\x5f\x06\x2e\xa5\x8c\x85\xe8\x98\xa8\x3e\xb4\xfe\xac\x62\xf6\x91\x56\x07\x8e\xec\xc5\xb5\x31\xe8\x04\xaa\x34\xdd\xab\x74\xb5\x0c\xc2\x00\x66\x2e\x80\x61\x53\xa7\x4a\xcc\x00\xe2\x42\x8d\x0e\x95\xc2\xa0\xf9\x54\x6c\x59\xa4\xcf\xe2\x64\x53\xda\x54\xc1\x84\xb0\xd2\x26\x28\x09\x9b\x99\xcb\x4c\x2a\xdd\x46\x47\xf5\x86\xad\x56\x9b\x00\x19\x27\xd8\x69\xc1\x2a\x0b\x42\x5f\x4a\x1d\xdf\x6e\x89\xa0\x5d\x1c\xfb\x28\x43\x3b\xe0\x88\x24\xd5\x52\x68\xcc\x5e\xa1\x64\x67\x0d\x51\xe0\x24\xb0\x32\x5d\xc4\xba\x55\x0c\xcb\x24\xe5\x52\xd3\x8c\xc8\x0e\x9f\x5d\xdd\xb4\x0c\x76\xf4\x98\xb5\xf7\x36\x07\xa6\x05\x0a\x71\x75\x6c\x30\xba\xb2\x56\xce\x69\xc5\x05\x28\xb3\xa6\x37\xab\xed\xa4\xb6\xa5\x54\x59\xc6\xa1\xe3\x27\x92\x1f\x2b\xfe\xfb\xc1\x82\x9f\xb6\x07\x9b\xe6\x33\xbd\xbe\x7d\x19\xdb\x77\xb1\xfd\xa6\x0e\xd6\x49\xda\xc0\xce\x3e\x7a\xc3\x59\x91\x34\x22\xd3\x0b\x87\x8f\x14\x66\x25\x2c\xbd\x95\xe8\x73\x86\x0f\x34\x1c\x80\xa2\x28\xd1\xdd\x55\x26\xd7\xee\x19\xc5\x63\xba\x8d\x5e\x52\xc2\x98\xa6\x20\xa7\xcd\x66\x14\x32\xbc\x87\x78\xcf\xd9\x67\x8a\x62\x2d\x23\x95\xea\x34\x01\x03\xcb\x38\xe8\xd0\xca\x32\x60\xc1\xc6\xdf\x06\xcd\x07\x0f\x4c\xb5\x27\xf6\x52\x26\x22\xaa\xf8\x70\x16\xaf\x43\x2b\x52\x85\x18\xb3\x71\xe7\xd1\x92\x11\x24\x2b\xba\x1b\xfb\x94\x04\x9d\x99\x34\x06\x46\xcf\xe9\x2a\xa9\xbd\x43\xf4\x66\x2e\xda\x0e\x7b\xfa\x2c\xc4\x03\xdc\x5c\x20\x00\x04\x7b\x4b\x02\xc7\xd6\x27\x27\x77\x91\x49\x72\x52\x80\x17\x94\xb1\x14\x82\x05\xbf\x53\x32\x28\x1d\xc1\x31\xb9\xb9\x68\x4c\xa9\xea\x85\xcd\xd1\xd2\x0a\x2a\x35\x77\x54\x69\x0d\xb4\x09\xf4\xee\x32\xcb\x8c\xa2\x10\xe0\x13\x25\x08\x72\x12\x64\x0f\xce\x3e\xa1\x4c\x67\x9f\xc0\x43\x8a\x01\x92\x87\xc8\xe4\x20\x96\x5e\x5a\x1e\x68\x63\x95\x18\x4d\x0e\xfd\x00\xa0\x68\xcf\x4f\x36\x8c\x05\x47\x5d\x08\xbf\xb6\xe1\xe5\x5e\xf7\xd7\xfe\xdd\xab\x00\x50\x47\x63\xe1\x6c\xa3\x11\x73\xd1\xda\x07\x07\x76\xb0\x11\xd2\xcd\x34\x59\x14\x1a\xcc\xd6\x63\x0c\xe9\xd6\x45\x4b\x19\xa5\x41\x99\x1a\x44\xaa\x51\x4c\x04\x6a\x11\x50\xc0\x1e\x3e\x34\x87\x05\x58\xc5\x82\xd3\xc6\x64\xab\x3c\xaa\x5a\x55\xa0\x86\x2a\xcc\xe6\x16\x73\x36\xc9\xa9\xfe\xa0\x41\x29\xbc\x60\xed\xdf\x46\x3c\x90\x1c\xac\x42\x96\x6e\x6a\x15\x1c\x67\xce\x8a\x53\x67\xe7\x56\x94\x38\xa7\x8e\xda\xa1\x51\xd1\x08\x34\xe0\x42\x43\x0c\x2b\xb5\x08\x18\x58\x19\xc9\xc4\x46\xd4\x10\xe2\x52\x42\x48\x7b\x81\xea\x4d\x9a\x68\xe0\x1c\x82\x23\xb9\x6a\x78\x60\x8d\x60\x96\xa0\x64\x66\x01\xae\x43\xc6\x09\x72\x5f\xc6\x01\xf1\x82\x24\x5f\x23\xfe\xe3\xd8\x7f\x85\xf9\xe8\xfa\x2d\x1d\xfd\xe9\xbd\x1e\xed\xfd\xed\x51\x85\x0e\xf5\x28\xf6\x57\xef\xe8\x08\xf9\xd5\xf5\x7d\x39\xff\xeb\x7f\xf9\xe9\xd8\xfd\xf0\xec\x66\xfb\x98\x7e\xd6\x76\x7a\x5e\xdf\xbc\x2f\xf3\xc3\xee\xc9\xfb\xb3\xcb\xc7\x3f\xbd\xbc\xf8\xed\xf2\xea\xda\xeb\x9b\xb1\xbf\x38\xbb\x78\x7e\xfa\x07\xa4\x8f\x09\x5f\xdc\xad\xef\x67\xc8\xab\x37\x3f\xbf\x3a\x3f\x7d\xf1\x66\xfb\xf6\x47\xf3\x7f\xd4\x0f\xaf\xcf\xce\xf9\xd5\xfe\x6f\xdb\x5f\x77\x4f\xf9\x3f\xe7\xa4\xd7\xbd\xbc\xd8\xd9\xdf\xf3\xf5\x99\x7d\x91\xf1\xf9\xf9\xfe\x7e\xc0\xc5\xdd\xbe\x9c\x7e\xd8\xdc\xdc\x5d\x55\xbd\x7f\x7f\x45\xf9\xe3\xaf\x37\x17\x97\xbf\xdc\x9c\xe3\xe5\x2f\xdb\x7f\x3e\x8d\x9d\xbc\xb8\xc1\x9b\xfa\xec\x35\xbd\xbf\x7f\xa0\xf8\x68\xb5\xfa\xfd\xd1\xef\x8f\xfe\x1f\x00\x00\xff\xff\xce\xf8\x53\x10\x38\x07\x00\x00") func ConfigCliFleetEthStagingJsonBytes() ([]byte, error) { return bindataRead( @@ -137,12 +158,12 @@ func ConfigCliFleetEthStagingJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "../config/cli/fleet-eth.staging.json", size: 1862, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xae, 0x85, 0xa1, 0x10, 0x16, 0x87, 0x10, 0x1c, 0xc3, 0xf4, 0xc7, 0xc, 0x2e, 0x51, 0xb7, 0x3, 0x61, 0x16, 0x99, 0x84, 0x3d, 0x5d, 0x82, 0x62, 0xfb, 0xf4, 0x5e, 0x19, 0xda, 0xb9, 0xaa, 0xc4}} + info := bindataFileInfo{name: "../config/cli/fleet-eth.staging.json", size: 1848, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x50, 0x9a, 0xfa, 0x20, 0x5d, 0xed, 0x98, 0x35, 0xfa, 0x16, 0x63, 0x8d, 0x54, 0xa0, 0xaa, 0x6a, 0xef, 0xfb, 0xf, 0x4e, 0x4a, 0x13, 0x9c, 0x8b, 0x88, 0x91, 0x81, 0x21, 0xc4, 0x99, 0xe, 0xe6}} return a, nil } -var _ConfigCliFleetEthTestJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x74\x94\x3d\x8b\x9c\xdd\x0d\x86\xfb\xfd\x15\xc3\xd4\x61\x5e\x1d\x7d\x6b\x2a\xe3\x8f\xa4\x71\xdc\x38\xa9\x42\x8a\xa3\x23\x1d\x67\x61\xf1\xc0\xee\xd8\x10\x82\xff\x7b\x98\xf5\x16\x8e\x63\xb7\xf7\x23\xf4\x5c\xdc\xba\x38\xff\xb9\x3b\x1c\x8e\xef\x2f\x9f\xde\xf7\xd7\x7e\x38\x9e\x0f\xc7\xb7\xef\x5e\xff\xfd\x2f\xc7\x3f\xdd\xe2\x0f\x97\xb7\xf7\x4f\xeb\xf2\xb5\x1f\xff\x7d\x3c\x1f\xf6\x7c\x78\xea\xe7\xfc\xcd\xc3\x97\xa7\x6b\x3f\xbe\xb9\x7c\xde\xf7\x9f\x8e\xe7\xc3\x6d\xc7\xe1\x70\x7c\xf7\x79\xe6\x43\xd7\xf1\x7c\xb8\x3e\x7e\x79\x9e\x3c\x1c\x8e\x7f\x7e\xe8\xbe\xde\xf6\xf6\xf5\x5f\xa7\x6b\x3f\x5d\x8f\x2f\x1f\x5e\x5f\x2e\xd7\x0f\x97\xea\xa7\xe3\xf9\xf0\x8f\xe7\xe8\x70\x38\xf6\xe7\x4b\xf5\xf9\x8f\x3f\x6a\xce\xc6\x36\x74\x84\x76\xed\x60\xdc\x13\xa7\xcf\x69\xa5\x1d\x21\x5c\x0c\x4c\xd3\x84\xd8\xa9\x3c\x8b\xc8\x7b\x68\xb6\xe3\xda\xa1\x48\x81\x25\x0b\x7a\xcc\x16\x5b\x54\x16\xb4\xa8\xa8\xaa\xca\x77\x89\x13\x05\x2a\x36\x23\x71\xad\x50\xdd\x21\xb4\xca\x28\x85\x64\xcb\x9e\xaf\xd8\x4e\x82\xa7\xe1\x7e\x1a\x1c\x67\x02\x06\x7e\x01\xff\x81\x32\x1a\xc2\x5d\x4c\x3a\xcd\x86\x2d\x94\xea\x69\xb8\x6b\x8c\x65\x49\x66\x6a\xb5\x20\xd6\x98\xa6\xae\xdb\x16\xf6\x12\xb3\x22\xf0\x42\xbe\x0d\xac\x4e\x35\xa9\x66\x1a\xc6\xc6\x73\x4c\x37\x68\x36\x77\x34\xc2\x50\xdb\xbc\xa7\xb9\x24\x60\xce\x90\x52\x8d\xa4\x51\xac\x5c\xbd\xe0\x15\x82\x9e\x86\xc7\x09\x99\x4e\x43\xf9\x77\x9c\x6b\xb4\xc0\x70\x77\x5b\xae\x54\xca\xb7\xff\xa5\x46\x6e\x1d\x26\x3a\xc0\xcd\x51\x98\xa0\x99\x61\x18\xd1\x96\x9c\x66\xcb\xa0\x72\x30\x92\xd6\x26\x1f\xbb\x77\x42\x67\x8f\xb9\x18\x31\x38\xa3\x51\x47\x66\x23\x51\x65\xa5\x53\x13\x2e\x71\x5d\xaa\xb3\x51\x97\x57\x1b\xac\xe4\xf5\x8a\xe4\x7b\x95\xea\xa7\x41\xf6\x82\xf9\x4c\xf9\xcf\x17\x1b\xfe\xf6\x78\x53\xaa\xfe\x3a\xef\x1f\x3e\xf6\xe3\xd7\x7e\xfc\xa5\x16\x21\xbc\x40\x15\x68\x6a\x9b\x48\xee\xdd\x11\x81\x3a\x64\xb3\x89\x38\x7b\xd6\x8c\x39\xab\xa6\x71\x05\xc2\x9c\x34\x6a\x94\x37\x6f\x05\xc4\x5a\x22\x5a\x6b\xaa\xa9\x6f\x9f\xb0\x83\x25\xb6\x58\x1a\x86\x40\x54\xd2\xf2\xa4\x4c\x87\xb9\x76\x96\x4f\x1c\x48\xe0\xb6\x75\x65\x59\xd6\x8f\x5a\x84\x9e\x09\xe4\x57\x75\x37\xbb\xca\x6e\x5d\x38\x6f\xb7\x17\xa5\xa9\xcc\x16\x01\xe5\x1d\xab\xd5\x50\x99\x67\x53\x83\xe3\xcd\x01\xf2\x5e\x63\xdf\x2e\x02\xdd\x5b\x09\x61\x81\x4d\x29\x85\x45\xa9\x18\x5b\x8a\x39\x78\x07\x95\xa6\xeb\x34\x96\x09\xb9\x95\x67\x62\x48\xe6\x56\xb1\x80\x61\xb3\x96\x76\xf9\x4f\x5a\x8c\xdf\x71\x1a\x58\x8b\xb1\xd0\x5c\x45\xcd\xee\x8b\x39\xa3\xa0\x87\x85\x09\xd9\x68\xdc\xbe\x6f\x82\xa2\xf4\x6c\xc9\xb9\x66\x64\x2c\x6f\xd0\xe5\xba\xaa\x6d\x59\xf0\xd4\x85\x4d\x8a\x40\xb9\x63\x8b\xae\xd9\x9e\xd0\x02\x9b\x92\x68\xf1\xc2\xd4\xe0\x69\x39\xbb\xe7\x30\x61\x56\x5e\xcd\x4d\xcf\x5a\x04\x9e\x10\xe3\x34\x0c\x5f\x30\xff\x47\x8b\x8f\xd7\x79\xbd\x5f\xbf\x7d\x26\x46\x8d\x20\x25\x69\x18\x12\xc3\x77\xba\x64\xce\x6d\xc6\x37\xcf\x07\x6e\x95\x32\x58\x1a\x66\x02\x3a\xdc\x7a\x03\x33\x42\x19\xf7\x02\x5d\xd1\xbe\xa1\x56\x8a\xf5\x04\xc6\xed\x52\xdb\x8d\x89\x6a\xe6\xb0\x39\x50\xa1\xcb\xab\x7a\x64\xed\x28\x2d\x29\xac\xe6\xb4\xdc\xde\x11\xf4\x53\xd3\x74\x26\x20\x90\xff\x6f\x7a\x4b\xd0\x44\x33\x1a\xb9\x60\x7b\x27\xb8\x37\x16\x05\x22\x2e\x2c\x89\xda\x19\xb9\x21\x29\x04\xca\xa6\xa3\x97\x8c\xf6\x99\xd1\xe0\x7b\xef\xac\x88\xa1\xd3\x71\x57\x04\xad\x31\xc1\x61\x89\x2d\xcc\x32\xe8\xd2\x45\xba\xd9\x63\x86\x46\xb5\x86\xcd\xbd\x83\xc0\xbd\xb2\x7b\xcc\xf8\xde\x34\x9f\x68\x9c\x06\xf8\x0b\xe5\xf7\xa2\xef\x0e\x87\x6f\x77\xdf\xee\xfe\x1b\x00\x00\xff\xff\xfb\xc2\xfb\xfc\x07\x06\x00\x00") +var _ConfigCliFleetEthTestJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x74\x94\x4d\x8b\x9c\x47\x0e\x80\xef\xf3\x2b\x9a\x3e\x2f\xed\x2a\x7d\xd7\x9c\x8c\x3f\x76\x2f\x5e\x5f\xbc\x7b\x0a\x39\xe8\xab\x9c\x81\xc1\x0d\x33\x6d\x43\x08\xfe\xef\xa1\x27\x0e\x18\x67\x7c\xd5\x2b\xf4\x3e\x25\x3d\xd2\x1f\x37\x87\xc3\xf1\xdd\xf9\xe3\xbb\xfe\xd2\xf7\xc7\xdb\xc3\xf1\xcd\xdb\x57\xff\xff\xcf\xf1\x5f\xd7\xf0\xfb\xf3\x9b\xbb\xc7\x3c\x7f\xe9\x87\xdf\x8f\xb7\x87\xed\xf7\x8f\xfd\x14\x7f\x7d\xff\xf9\xf1\xd2\x0f\xaf\xcf\x9f\xf6\xdd\xc7\xe3\xed\xe1\x5a\xe3\x70\x38\xbe\xfd\xe4\x71\xdf\x75\xbc\x3d\x5c\x1e\x3e\x3f\x65\x1e\x0e\xc7\x7f\xdf\x77\x5f\xae\x75\xfb\xf2\xdb\xe9\xd2\x8f\x97\xe3\xb7\x0f\xaf\xce\xe7\xcb\xfb\x73\xf5\xe3\xf1\xf6\xf0\xcb\x53\xe8\x70\x38\xf6\xa7\x73\xf5\xed\x8b\x17\xe5\xde\xd0\x0a\x06\xa3\x4d\x7a\x11\x6c\x07\x37\x77\x2d\xe9\xb5\x98\x8a\x06\xa1\x2b\x23\x19\x96\x45\x21\x5a\x4f\x89\x36\xc8\xbd\x04\x70\x41\x71\x8e\x9e\xde\xac\x89\xa5\x0b\x13\x0b\xab\xaa\x6c\x17\x1b\xe2\x02\x81\x26\x40\xaa\x5c\x22\x7b\x31\x66\x29\x06\x23\x6f\xde\xfe\x92\xf4\xc4\x70\x9a\x66\xa7\x49\xeb\x96\x08\xbf\x61\x7f\xc7\xb8\x7a\x2c\x33\x56\xee\x50\x9d\x9a\xc0\xd5\xae\xb0\x6b\xce\xd4\x40\x55\xd1\xca\xb1\x72\xba\x8a\xc9\xd6\x84\x4e\x56\x2d\x1c\x56\x40\xd7\x84\xec\x10\xe5\x6a\xc2\xa9\xa4\xe4\xd3\x4d\x47\x93\x9a\x81\x22\x2c\xd1\x4d\xdb\xd5\x38\x06\x84\x2f\x2e\x91\x15\x38\x8b\x84\xaa\x73\xbc\x84\x21\xa7\x69\xeb\x04\x84\xa7\x29\xf4\x3c\x65\xce\xe6\x31\xcd\x4c\xd3\x04\x4b\xe8\xfa\xb7\x90\x15\x5b\xa6\xb2\xcc\x61\x6a\xc0\x84\xa3\x89\xc6\x54\xc4\xcd\xe1\xaa\xa9\xa3\x62\x12\xa0\xd4\x46\x9b\xbb\x77\x8c\x8e\x9e\x9e\x04\xb0\x28\x56\x83\xcc\x88\x06\xc4\x8a\x0a\xc3\x46\x48\x36\x49\x11\x6f\x90\xb4\x6a\x1d\x19\x94\x2f\x91\xff\x6a\xa3\xd8\x69\xa2\x3e\x41\x3e\x31\xfe\xfa\xcd\x83\xff\x3d\x5c\x65\xaa\xff\xfa\xdd\xfd\x87\x7e\xf8\xd2\x0f\xcf\x0a\x21\x73\x55\x04\x57\xf9\x84\x36\x8e\x3d\x3a\xb8\x82\xc6\x0e\xac\x16\x60\x19\x6b\x10\x02\x81\xa2\xe6\xe8\xa5\xbc\xb5\x76\x09\xaf\x32\xae\x94\x5a\x6e\xb4\x17\xc9\x74\x05\x4b\xf6\x10\xcb\xa1\xb0\xbb\xd0\xd2\xc5\x19\xd7\xd4\x74\xa0\xb0\x5e\x98\x09\x1a\xd5\x1b\x7d\xb6\x2e\xcf\xef\x85\x58\xf2\x7c\xab\x9b\x4c\x78\xb7\x24\xf8\x75\xea\x2c\xe8\x42\xa4\x6b\x8d\xb2\x5e\xd9\xa2\x20\x44\xde\xd8\xc3\xe0\x3a\x7d\xb4\xce\xb9\xaf\xd3\x18\xdd\x5b\x10\x46\x0e\x75\x2e\x19\x89\x21\xb0\x36\x17\xd1\xa2\xbd\xb0\x24\x4c\x5c\x89\x7d\xc4\x16\xf2\x80\xc5\x11\x5b\x58\xd7\x98\xea\x95\xd2\x65\x3f\x08\x31\x9f\xa7\xd4\xa1\xcd\x4a\x8c\x9e\x85\x4d\x66\x49\x14\xab\x46\x4f\x5d\xca\xa8\xb3\x61\xdb\xbe\x8a\x09\xdc\xde\x1c\x9e\xbe\x62\xa5\xf5\x90\x34\xc9\x6a\x4d\x5d\xe4\x92\xd0\x28\x30\x30\xf6\xda\x2c\xe9\x6d\x31\x9a\xc7\xc6\x40\x4c\x4a\x08\x59\xe4\x1a\xde\xed\x53\x99\x48\x28\x9b\x1a\x9f\x84\x58\x70\x02\x58\xa7\xa9\xf0\x4f\x21\x3e\x5c\xfc\x72\x97\x3f\x3d\x0d\x5e\x68\x7b\xd1\xc0\xe1\x46\x92\xa9\x63\x70\xa8\xcf\x8d\x21\x31\x66\x6c\xea\xcd\xab\x90\xda\x0a\x4b\x36\xd5\x84\xda\x80\x35\x29\xdc\x84\x45\x07\x38\x21\x17\x52\x6e\xaa\x8d\x41\x13\x72\xe4\x5c\x80\xb5\xd9\x2b\xb3\x8d\x64\x22\x4c\x1f\x65\x7b\xc7\x22\xe4\x00\x69\x56\x48\xf8\xfb\x34\x00\x5f\x9f\xf1\x93\xa5\x9b\x35\x17\x0a\x72\x8f\xc9\x6b\xda\x0e\xe3\x08\xdf\xaa\x74\xdd\xc1\x09\x5b\xb8\x74\xa4\x2c\x55\x1e\x32\x4d\x7b\x0f\x22\x18\xa5\xd4\x39\x24\x57\xdb\x1e\x95\xc1\xda\x3e\x08\xb6\x71\x6d\x53\x42\x2c\x8f\xa9\x3e\x41\x46\x97\x55\xf5\x8c\xda\xab\xa4\xb8\xa0\x9a\x42\x63\x5b\xaf\x85\x3f\x98\x80\xdf\x35\xf9\xe6\x70\xf8\x7a\xf3\xf5\xe6\xcf\x00\x00\x00\xff\xff\x0d\xfd\x12\x60\xf7\x05\x00\x00") func ConfigCliFleetEthTestJsonBytes() ([]byte, error) { return bindataRead( @@ -157,8 +178,8 @@ func ConfigCliFleetEthTestJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "../config/cli/fleet-eth.test.json", size: 1543, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x68, 0xef, 0x71, 0xa1, 0x38, 0x37, 0xf0, 0x0, 0xbb, 0x95, 0x26, 0x2a, 0x2a, 0x65, 0x98, 0xfe, 0xe5, 0x3f, 0xbf, 0xb, 0x68, 0xa6, 0xb5, 0xa4, 0x10, 0xc1, 0x4b, 0x67, 0xb4, 0x4e, 0x32, 0xc0}} + info := bindataFileInfo{name: "../config/cli/fleet-eth.test.json", size: 1527, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x88, 0x9c, 0xfe, 0x3f, 0x41, 0x7a, 0x28, 0x2e, 0x65, 0x8f, 0x35, 0x2b, 0xa4, 0x25, 0x93, 0x6c, 0x9, 0x62, 0xd8, 0x9a, 0x51, 0xb0, 0x7c, 0x1e, 0xe, 0x90, 0x24, 0x88, 0xfc, 0x97, 0xa3, 0x64}} return a, nil } @@ -177,7 +198,7 @@ func ConfigCliLesEnabledJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "../config/cli/les-enabled.json", size: 58, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)} + info := bindataFileInfo{name: "../config/cli/les-enabled.json", size: 58, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7e, 0xee, 0x27, 0xa7, 0x74, 0xa0, 0x46, 0xa1, 0x41, 0xed, 0x4d, 0x16, 0x5b, 0xf3, 0xf0, 0x7c, 0xc8, 0x2f, 0x6f, 0x47, 0xa4, 0xbb, 0x5f, 0x43, 0x33, 0xd, 0x9, 0x9d, 0xea, 0x9e, 0x15, 0xee}} return a, nil } @@ -197,7 +218,7 @@ func ConfigCliMailserverEnabledJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "../config/cli/mailserver-enabled.json", size: 176, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)} + info := bindataFileInfo{name: "../config/cli/mailserver-enabled.json", size: 176, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x34, 0xec, 0x81, 0x8b, 0x99, 0xb6, 0xdb, 0xc0, 0x8b, 0x46, 0x97, 0x96, 0xc7, 0x58, 0x30, 0x33, 0xef, 0x54, 0x25, 0x87, 0x7b, 0xb9, 0x94, 0x6b, 0x18, 0xa4, 0x5b, 0x58, 0x67, 0x7c, 0x44, 0xa6}} return a, nil } @@ -217,7 +238,7 @@ func ConfigStatusChainGenesisJson() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "../config/status-chain-genesis.json", size: 612, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)} + info := bindataFileInfo{name: "../config/status-chain-genesis.json", size: 612, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb, 0xf0, 0xc, 0x1, 0x95, 0x65, 0x6, 0x55, 0x48, 0x8f, 0x83, 0xa0, 0xb4, 0x81, 0xda, 0xad, 0x30, 0x6d, 0xb2, 0x78, 0x1b, 0x26, 0x4, 0x13, 0x12, 0x9, 0x6, 0xae, 0x3a, 0x2c, 0x1, 0x71}} return a, nil } @@ -237,7 +258,7 @@ func keysBootnodeKey() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/bootnode.key", size: 65, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)} + info := bindataFileInfo{name: "keys/bootnode.key", size: 65, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x31, 0xcf, 0x27, 0xd4, 0x96, 0x2e, 0x32, 0xcd, 0x58, 0x96, 0x2a, 0xe5, 0x8c, 0xa0, 0xf1, 0x73, 0x1f, 0xd6, 0xd6, 0x8b, 0xb, 0x73, 0xd3, 0x2c, 0x84, 0x1a, 0x56, 0xa4, 0x74, 0xb6, 0x95, 0x20}} return a, nil } @@ -257,7 +278,7 @@ func keysFirebaseauthkey() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/firebaseauthkey", size: 153, mode: os.FileMode(0644), modTime: time.Unix(1536843582, 0)} + info := bindataFileInfo{name: "keys/firebaseauthkey", size: 153, mode: os.FileMode(0644), modTime: time.Unix(1560062905, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xe, 0x69, 0x23, 0x64, 0x7d, 0xf9, 0x14, 0x37, 0x6f, 0x2b, 0x1, 0xf0, 0xb0, 0xa4, 0xb2, 0xd0, 0x18, 0xcd, 0xf9, 0xeb, 0x57, 0xa3, 0xfd, 0x79, 0x25, 0xa7, 0x9c, 0x3, 0xce, 0x26, 0xec, 0xe1}} return a, nil } @@ -277,7 +298,7 @@ func keysTestAccount1StatusChainPk() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/test-account1-status-chain.pk", size: 489, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)} + info := bindataFileInfo{name: "keys/test-account1-status-chain.pk", size: 489, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8f, 0xba, 0x35, 0x1, 0x2b, 0x9d, 0xad, 0xf0, 0x2d, 0x3c, 0x4d, 0x6, 0xb5, 0x22, 0x2, 0x47, 0xd4, 0x1c, 0xf4, 0x31, 0x2f, 0xb, 0x5b, 0x27, 0x5d, 0x43, 0x97, 0x58, 0x2d, 0xf0, 0xe1, 0xbe}} return a, nil } @@ -297,7 +318,7 @@ func keysTestAccount1Pk() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/test-account1.pk", size: 491, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)} + info := bindataFileInfo{name: "keys/test-account1.pk", size: 491, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9, 0x43, 0xc2, 0xf4, 0x8c, 0xc6, 0x64, 0x25, 0x8c, 0x7, 0x8c, 0xa8, 0x89, 0x2b, 0x7b, 0x9b, 0x4f, 0x81, 0xcb, 0xce, 0x3d, 0xef, 0x82, 0x9c, 0x27, 0x27, 0xa9, 0xc5, 0x46, 0x70, 0x30, 0x38}} return a, nil } @@ -317,7 +338,7 @@ func keysTestAccount2StatusChainPk() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/test-account2-status-chain.pk", size: 489, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)} + info := bindataFileInfo{name: "keys/test-account2-status-chain.pk", size: 489, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9, 0xf8, 0x5c, 0xe9, 0x92, 0x96, 0x2d, 0x88, 0x2b, 0x8e, 0x42, 0x3f, 0xa4, 0x93, 0x6c, 0xad, 0xe9, 0xc0, 0x1b, 0x8a, 0x8, 0x8c, 0x5e, 0x7a, 0x84, 0xa2, 0xf, 0x9f, 0x77, 0x58, 0x2c, 0x2c}} return a, nil } @@ -337,7 +358,7 @@ func keysTestAccount2Pk() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/test-account2.pk", size: 491, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)} + info := bindataFileInfo{name: "keys/test-account2.pk", size: 491, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9f, 0x72, 0xd5, 0x95, 0x5c, 0x5a, 0x99, 0x9d, 0x2f, 0x21, 0x83, 0xd7, 0x10, 0x17, 0x4a, 0x3d, 0x65, 0xc9, 0x26, 0x1a, 0x2c, 0x9d, 0x65, 0x63, 0xd2, 0xa0, 0xfc, 0x7c, 0x0, 0x87, 0x38, 0x9f}} return a, nil } @@ -357,7 +378,7 @@ func keysTestAccount3BeforeEip55Pk() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "keys/test-account3-before-eip55.pk", size: 489, mode: os.FileMode(0644), modTime: time.Unix(1573806410, 0)} + info := bindataFileInfo{name: "keys/test-account3-before-eip55.pk", size: 489, mode: os.FileMode(0644), modTime: time.Unix(1578669164, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x81, 0x40, 0x56, 0xc1, 0x5e, 0x10, 0x6e, 0x28, 0x15, 0x3, 0x4e, 0xc4, 0xc4, 0x71, 0x4d, 0x16, 0x99, 0xcc, 0x1b, 0x63, 0xee, 0x10, 0x20, 0xe4, 0x59, 0x52, 0x3f, 0xc0, 0xad, 0x15, 0x13, 0x72}} return a, nil } @@ -457,6 +478,8 @@ var _bindata = map[string]func() (*asset, error){ "../config/cli/fleet-eth.beta.json": ConfigCliFleetEthBetaJson, + "../config/cli/fleet-eth.prod.json": ConfigCliFleetEthProdJson, + "../config/cli/fleet-eth.staging.json": ConfigCliFleetEthStagingJson, "../config/cli/fleet-eth.test.json": ConfigCliFleetEthTestJson, @@ -528,6 +551,7 @@ var _bintree = &bintree{nil, map[string]*bintree{ "README.md": &bintree{ConfigReadmeMd, map[string]*bintree{}}, "cli": &bintree{nil, map[string]*bintree{ "fleet-eth.beta.json": &bintree{ConfigCliFleetEthBetaJson, map[string]*bintree{}}, + "fleet-eth.prod.json": &bintree{ConfigCliFleetEthProdJson, map[string]*bintree{}}, "fleet-eth.staging.json": &bintree{ConfigCliFleetEthStagingJson, map[string]*bintree{}}, "fleet-eth.test.json": &bintree{ConfigCliFleetEthTestJson, map[string]*bintree{}}, "les-enabled.json": &bintree{ConfigCliLesEnabledJson, map[string]*bintree{}}, diff --git a/t/bindata.go b/t/bindata.go index 6b84c0772..bf42c693d 100644 --- a/t/bindata.go +++ b/t/bindata.go @@ -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 } diff --git a/vendor/github.com/status-im/status-go/eth-node/bridge/geth/envelope_error.go b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/envelope_error.go index 5a8edf257..6d24b49fc 100644 --- a/vendor/github.com/status-im/status-go/eth-node/bridge/geth/envelope_error.go +++ b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/envelope_error.go @@ -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 diff --git a/vendor/github.com/status-im/status-go/eth-node/bridge/geth/envelope_event.go b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/envelope_event.go index 9836987a6..c31c509c1 100644 --- a/vendor/github.com/status-im/status-go/eth-node/bridge/geth/envelope_event.go +++ b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/envelope_event.go @@ -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, + } +} diff --git a/vendor/github.com/status-im/status-go/eth-node/bridge/geth/filter.go b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/filter.go deleted file mode 100644 index 914e17df8..000000000 --- a/vendor/github.com/status-im/status-go/eth-node/bridge/geth/filter.go +++ /dev/null @@ -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 -} diff --git a/vendor/github.com/status-im/status-go/eth-node/bridge/geth/mailserver_response.go b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/mailserver_response.go index 01cbb30a2..10b796fb2 100644 --- a/vendor/github.com/status-im/status-go/eth-node/bridge/geth/mailserver_response.go +++ b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/mailserver_response.go @@ -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") } diff --git a/vendor/github.com/status-im/status-go/eth-node/bridge/geth/node.go b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/node.go index 7cfa42b71..7c691c189 100644 --- a/vendor/github.com/status-im/status-go/eth-node/bridge/geth/node.go +++ b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/node.go @@ -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 { diff --git a/vendor/github.com/status-im/status-go/eth-node/bridge/geth/public_waku_api.go b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/public_waku_api.go new file mode 100644 index 000000000..bfd9b76f6 --- /dev/null +++ b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/public_waku_api.go @@ -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) +} diff --git a/vendor/github.com/status-im/status-go/eth-node/bridge/geth/waku.go b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/waku.go new file mode 100644 index 000000000..143562513 --- /dev/null +++ b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/waku.go @@ -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 +} diff --git a/vendor/github.com/status-im/status-go/eth-node/bridge/geth/whisper.go b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/whisper.go index 8e64db81c..2423a3264 100644 --- a/vendor/github.com/status-im/status-go/eth-node/bridge/geth/whisper.go +++ b/vendor/github.com/status-im/status-go/eth-node/bridge/geth/whisper.go @@ -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 +} diff --git a/vendor/github.com/status-im/status-go/eth-node/types/const.go b/vendor/github.com/status-im/status-go/eth-node/types/const.go new file mode 100644 index 000000000..9e3148d0f --- /dev/null +++ b/vendor/github.com/status-im/status-go/eth-node/types/const.go @@ -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 +) diff --git a/vendor/github.com/status-im/status-go/eth-node/types/node.go b/vendor/github.com/status-im/status-go/eth-node/types/node.go index 20f3aead6..4c80c2cb8 100644 --- a/vendor/github.com/status-im/status-go/eth-node/types/node.go +++ b/vendor/github.com/status-im/status-go/eth-node/types/node.go @@ -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 } diff --git a/vendor/github.com/status-im/status-go/eth-node/types/rpc.go b/vendor/github.com/status-im/status-go/eth-node/types/rpc.go index c2c13de70..3ee868804 100644 --- a/vendor/github.com/status-im/status-go/eth-node/types/rpc.go +++ b/vendor/github.com/status-im/status-go/eth-node/types/rpc.go @@ -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) +} diff --git a/vendor/github.com/status-im/status-go/eth-node/types/subscribe.go b/vendor/github.com/status-im/status-go/eth-node/types/subscribe.go new file mode 100644 index 000000000..fbd347acc --- /dev/null +++ b/vendor/github.com/status-im/status-go/eth-node/types/subscribe.go @@ -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 +} diff --git a/vendor/github.com/status-im/status-go/eth-node/types/waku.go b/vendor/github.com/status-im/status-go/eth-node/types/waku.go new file mode 100644 index 000000000..ce81c2cf3 --- /dev/null +++ b/vendor/github.com/status-im/status-go/eth-node/types/waku.go @@ -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 +} diff --git a/vendor/github.com/status-im/status-go/eth-node/types/whisper.go b/vendor/github.com/status-im/status-go/eth-node/types/whisper.go index 55bd0d119..23529c4da 100644 --- a/vendor/github.com/status-im/status-go/eth-node/types/whisper.go +++ b/vendor/github.com/status-im/status-go/eth-node/types/whisper.go @@ -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 { diff --git a/vendor/github.com/status-im/status-go/protocol/encryption/migrations/migrations.go b/vendor/github.com/status-im/status-go/protocol/encryption/migrations/migrations.go index 3e93c617c..ea0a151ab 100644 --- a/vendor/github.com/status-im/status-go/protocol/encryption/migrations/migrations.go +++ b/vendor/github.com/status-im/status-go/protocol/encryption/migrations/migrations.go @@ -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 } diff --git a/vendor/github.com/status-im/status-go/protocol/encryption/protocol_message.pb.go b/vendor/github.com/status-im/status-go/protocol/encryption/protocol_message.pb.go index 81ce4a314..a682bdb61 100644 --- a/vendor/github.com/status-im/status-go/protocol/encryption/protocol_message.pb.go +++ b/vendor/github.com/status-im/status-go/protocol/encryption/protocol_message.pb.go @@ -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. diff --git a/vendor/github.com/status-im/status-go/protocol/go.sum b/vendor/github.com/status-im/status-go/protocol/go.sum index cca0d5f3e..050eb91f7 100644 --- a/vendor/github.com/status-im/status-go/protocol/go.sum +++ b/vendor/github.com/status-im/status-go/protocol/go.sum @@ -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= diff --git a/vendor/github.com/status-im/status-go/protocol/message_processor.go b/vendor/github.com/status-im/status-go/protocol/message_processor.go index f72f10880..1b05403f1 100644 --- a/vendor/github.com/status-im/status-go/protocol/message_processor.go +++ b/vendor/github.com/status-im/status-go/protocol/message_processor.go @@ -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) { diff --git a/vendor/github.com/status-im/status-go/protocol/messenger.go b/vendor/github.com/status-im/status-go/protocol/messenger.go index 95cbec002..111b5f58e 100644 --- a/vendor/github.com/status-im/status-go/protocol/messenger.go +++ b/vendor/github.com/status-im/status-go/protocol/messenger.go @@ -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 diff --git a/vendor/github.com/status-im/status-go/protocol/migrations.go b/vendor/github.com/status-im/status-go/protocol/migrations.go deleted file mode 100644 index c616440fe..000000000 --- a/vendor/github.com/status-im/status-go/protocol/migrations.go +++ /dev/null @@ -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") -} diff --git a/vendor/github.com/status-im/status-go/protocol/migrations/migrations.go b/vendor/github.com/status-im/status-go/protocol/migrations/migrations.go index 597b517f4..ff08e31f9 100644 --- a/vendor/github.com/status-im/status-go/protocol/migrations/migrations.go +++ b/vendor/github.com/status-im/status-go/protocol/migrations/migrations.go @@ -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 } diff --git a/vendor/github.com/status-im/status-go/protocol/protobuf/application_metadata_message.pb.go b/vendor/github.com/status-im/status-go/protocol/protobuf/application_metadata_message.pb.go index bd650fdd6..b166e283f 100644 --- a/vendor/github.com/status-im/status-go/protocol/protobuf/application_metadata_message.pb.go +++ b/vendor/github.com/status-im/status-go/protocol/protobuf/application_metadata_message.pb.go @@ -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. diff --git a/vendor/github.com/status-im/status-go/protocol/protobuf/chat_message.pb.go b/vendor/github.com/status-im/status-go/protocol/protobuf/chat_message.pb.go index 61db6ead5..49247f30c 100644 --- a/vendor/github.com/status-im/status-go/protocol/protobuf/chat_message.pb.go +++ b/vendor/github.com/status-im/status-go/protocol/protobuf/chat_message.pb.go @@ -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. diff --git a/vendor/github.com/status-im/status-go/protocol/protobuf/membership_update_message.pb.go b/vendor/github.com/status-im/status-go/protocol/protobuf/membership_update_message.pb.go index 1e923090d..30dd3d1f2 100644 --- a/vendor/github.com/status-im/status-go/protocol/protobuf/membership_update_message.pb.go +++ b/vendor/github.com/status-im/status-go/protocol/protobuf/membership_update_message.pb.go @@ -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. diff --git a/vendor/github.com/status-im/status-go/protocol/sqlite/migrations.go b/vendor/github.com/status-im/status-go/protocol/sqlite/migrations.go index a6a2cf862..387f7608d 100644 --- a/vendor/github.com/status-im/status-go/protocol/sqlite/migrations.go +++ b/vendor/github.com/status-im/status-go/protocol/sqlite/migrations.go @@ -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(), diff --git a/vendor/github.com/status-im/status-go/protocol/transport/envelopes_monitor.go b/vendor/github.com/status-im/status-go/protocol/transport/envelopes_monitor.go new file mode 100644 index 000000000..523323203 --- /dev/null +++ b/vendor/github.com/status-im/status-go/protocol/transport/envelopes_monitor.go @@ -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) +} diff --git a/vendor/github.com/status-im/status-go/protocol/transport/filter.go b/vendor/github.com/status-im/status-go/protocol/transport/filter.go new file mode 100644 index 000000000..a1f7369a5 --- /dev/null +++ b/vendor/github.com/status-im/status-go/protocol/transport/filter.go @@ -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 +} diff --git a/protocol/transport/whisper/filter.go b/vendor/github.com/status-im/status-go/protocol/transport/filters_manager.go similarity index 57% rename from protocol/transport/whisper/filter.go rename to vendor/github.com/status-im/status-go/protocol/transport/filters_manager.go index e237d78f2..ad914e9d7 100644 --- a/protocol/transport/whisper/filter.go +++ b/vendor/github.com/status-im/status-go/protocol/transport/filters_manager.go @@ -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)] } diff --git a/vendor/github.com/status-im/status-go/protocol/transport/message.go b/vendor/github.com/status-im/status-go/protocol/transport/message.go new file mode 100644 index 000000000..3d7d9d499 --- /dev/null +++ b/vendor/github.com/status-im/status-go/protocol/transport/message.go @@ -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 +} diff --git a/vendor/github.com/status-im/status-go/protocol/transport/topic.go b/vendor/github.com/status-im/status-go/protocol/transport/topic.go new file mode 100644 index 000000000..876e6e39f --- /dev/null +++ b/vendor/github.com/status-im/status-go/protocol/transport/topic.go @@ -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 +} diff --git a/vendor/github.com/status-im/status-go/protocol/transport/transport.go b/vendor/github.com/status-im/status-go/protocol/transport/transport.go new file mode 100644 index 000000000..ea082f4ed --- /dev/null +++ b/vendor/github.com/status-im/status-go/protocol/transport/transport.go @@ -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) +} diff --git a/vendor/github.com/status-im/status-go/protocol/transport/waku/envelopes.go b/vendor/github.com/status-im/status-go/protocol/transport/waku/envelopes.go new file mode 100644 index 000000000..c06b086d6 --- /dev/null +++ b/vendor/github.com/status-im/status-go/protocol/transport/waku/envelopes.go @@ -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) +} diff --git a/vendor/github.com/status-im/status-go/protocol/transport/waku/mailserver.go b/vendor/github.com/status-im/status-go/protocol/transport/waku/mailserver.go new file mode 100644 index 000000000..b4419d10f --- /dev/null +++ b/vendor/github.com/status-im/status-go/protocol/transport/waku/mailserver.go @@ -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 +} diff --git a/vendor/github.com/status-im/status-go/protocol/transport/waku/migrations/migrations.go b/vendor/github.com/status-im/status-go/protocol/transport/waku/migrations/migrations.go new file mode 100644 index 000000000..8809b9b4c --- /dev/null +++ b/vendor/github.com/status-im/status-go/protocol/transport/waku/migrations/migrations.go @@ -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, "/")...)...) +} diff --git a/vendor/github.com/status-im/status-go/protocol/transport/waku/persistence.go b/vendor/github.com/status-im/status-go/protocol/transport/waku/persistence.go new file mode 100644 index 000000000..df5e89e68 --- /dev/null +++ b/vendor/github.com/status-im/status-go/protocol/transport/waku/persistence.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 +} diff --git a/vendor/github.com/status-im/status-go/protocol/transport/waku/waku.go b/vendor/github.com/status-im/status-go/protocol/transport/waku/waku.go new file mode 100644 index 000000000..3a0eaa4ea --- /dev/null +++ b/vendor/github.com/status-im/status-go/protocol/transport/waku/waku.go @@ -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 +} diff --git a/vendor/github.com/status-im/status-go/protocol/transport/waku/waku_service.go b/vendor/github.com/status-im/status-go/protocol/transport/waku/waku_service.go new file mode 100644 index 000000000..57b319382 --- /dev/null +++ b/vendor/github.com/status-im/status-go/protocol/transport/waku/waku_service.go @@ -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() + } + } +} diff --git a/vendor/github.com/status-im/status-go/protocol/transport/whisper/envelopes.go b/vendor/github.com/status-im/status-go/protocol/transport/whisper/envelopes.go index 21da4df38..886e19873 100644 --- a/vendor/github.com/status-im/status-go/protocol/transport/whisper/envelopes.go +++ b/vendor/github.com/status-im/status-go/protocol/transport/whisper/envelopes.go @@ -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 { diff --git a/vendor/github.com/status-im/status-go/protocol/transport/whisper/mailserver.go b/vendor/github.com/status-im/status-go/protocol/transport/whisper/mailserver.go index b25d3d751..d630b69ab 100644 --- a/vendor/github.com/status-im/status-go/protocol/transport/whisper/mailserver.go +++ b/vendor/github.com/status-im/status-go/protocol/transport/whisper/mailserver.go @@ -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...), } diff --git a/vendor/github.com/status-im/status-go/protocol/transport/whisper/migrations/migrations.go b/vendor/github.com/status-im/status-go/protocol/transport/whisper/migrations/migrations.go index 368797f1a..7fdff2a38 100644 --- a/vendor/github.com/status-im/status-go/protocol/transport/whisper/migrations/migrations.go +++ b/vendor/github.com/status-im/status-go/protocol/transport/whisper/migrations/migrations.go @@ -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 } diff --git a/vendor/github.com/status-im/status-go/protocol/transport/whisper/whisper.go b/vendor/github.com/status-im/status-go/protocol/transport/whisper/whisper.go index c9e118348..ef4970900 100644 --- a/vendor/github.com/status-im/status-go/protocol/transport/whisper/whisper.go +++ b/vendor/github.com/status-im/status-go/protocol/transport/whisper/whisper.go @@ -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 -} diff --git a/vendor/github.com/status-im/status-go/protocol/transport/whisper/whisper_service.go b/vendor/github.com/status-im/status-go/protocol/transport/whisper/whisper_service.go index b400561c3..38bc3a0a2 100644 --- a/vendor/github.com/status-im/status-go/protocol/transport/whisper/whisper_service.go +++ b/vendor/github.com/status-im/status-go/protocol/transport/whisper/whisper_service.go @@ -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) diff --git a/vendor/modules.txt b/vendor/modules.txt index d1ab7071b..18421c19b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -393,6 +393,9 @@ github.com/status-im/status-go/protocol/identity/identicon github.com/status-im/status-go/protocol/migrations github.com/status-im/status-go/protocol/protobuf github.com/status-im/status-go/protocol/sqlite +github.com/status-im/status-go/protocol/transport +github.com/status-im/status-go/protocol/transport/waku +github.com/status-im/status-go/protocol/transport/waku/migrations github.com/status-im/status-go/protocol/transport/whisper github.com/status-im/status-go/protocol/transport/whisper/migrations github.com/status-im/status-go/protocol/v1