status-go/eth-node/bridge/geth/waku.go

327 lines
9.3 KiB
Go
Raw Permalink Normal View History

package gethbridge
import (
"context"
"crypto/ecdsa"
"errors"
"time"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-multiaddr"
2021-11-26 12:30:35 +00:00
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/p2p/enode"
gocommon "github.com/status-im/status-go/common"
"github.com/status-im/status-go/connection"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/waku"
Move networking code for waku under `v0` namespace Why make the change? As discussed previously, the way we will move across versions is to maintain completely separate codebases and eventually remove those that are not supported anymore. This has the drawback of some code duplication, but the advantage is that is more explicit what each version requires, and changes in one version will not impact the other, so we won't pile up backward compatible code. This is the same strategy used by `whisper` in go ethereum and is influenced by https://www.youtube.com/watch?v=oyLBGkS5ICk . All the code that is used for the networking protocol is now under `v0/`. Some of the common parts might still be refactored out. The main namespace `waku` deals with `host`->`waku` interactions (through RPC), while `v0` deals with `waku`->`remote-waku` interactions. In order to support `v1`, the namespace `v0` will be copied over, and changed to support `v1`. Once `v0` will be not used anymore, the whole namespace will be removed. This PR does not actually implement `v1`, I'd rather get things looked over to make sure the structure is what we would like before implementing the changes. What has changed? - Moved all code for the common parts under `waku/common/` namespace - Moved code used for bloomfilters in `waku/common/bloomfilter.go` - Removed all version specific code from `waku/common/const` (`ProtocolVersion`, status-codes etc) - Added interfaces for `WakuHost` and `Peer` under `waku/common/protocol.go` Things still to do Some tests in `waku/` are still testing by stubbing components of a particular version (`v0`). I started moving those tests to instead of stubbing using the actual component, which increases the testing surface. Some other tests that can't be easily ported should be likely moved under `v0` instead. Ideally no version specif code should be exported from a version namespace (for example the various codes, as those might change across versions). But this will be a work-in-progress. Some code that will be common in `v0`/`v1` could still be extract to avoid duplication, and duplicated only when implementations diverge across versions.
2020-04-21 12:40:30 +00:00
wakucommon "github.com/status-im/status-go/waku/common"
)
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))
}
func (w *GethWakuWrapper) Version() uint {
return 1
}
// Added for compatibility with waku V2
func (w *GethWakuWrapper) PeerCount() int {
return -1
}
// Added for compatibility with waku V2
func (w *GethWakuWrapper) StartDiscV5() error {
return errors.New("not available in WakuV1")
}
// Added for compatibility with waku V2
func (w *GethWakuWrapper) StopDiscV5() error {
return errors.New("not available in WakuV1")
}
// PeerCount function only added for compatibility with waku V2
func (w *GethWakuWrapper) AddStorePeer(address multiaddr.Multiaddr) (peer.ID, error) {
return "", errors.New("not available in WakuV1")
}
// SubscribeToPubsubTopic function only added for compatibility with waku V2
func (w *GethWakuWrapper) SubscribeToPubsubTopic(topic string, optPublicKey *ecdsa.PublicKey) error {
// not available in WakuV1
return errors.New("not available in WakuV1")
}
func (w *GethWakuWrapper) UnsubscribeFromPubsubTopic(topic string) error {
// not available in WakuV1
return errors.New("not available in WakuV1")
}
func (w *GethWakuWrapper) RetrievePubsubTopicKey(topic string) (*ecdsa.PrivateKey, error) {
// not available in WakuV1
return nil, errors.New("not available in WakuV1")
}
func (w *GethWakuWrapper) StorePubsubTopicKey(topic string, privKey *ecdsa.PrivateKey) error {
// not available in WakuV1
return errors.New("not available in WakuV1")
}
func (w *GethWakuWrapper) RemovePubsubTopicKey(topic string) error {
// not available in WakuV1
return errors.New("not available in WakuV1")
}
// AddRelayPeer function only added for compatibility with waku V2
func (w *GethWakuWrapper) AddRelayPeer(address multiaddr.Multiaddr) (peer.ID, error) {
return "", errors.New("not available in WakuV1")
}
// DialPeer function only added for compatibility with waku V2
func (w *GethWakuWrapper) DialPeer(address multiaddr.Multiaddr) error {
return errors.New("not available in WakuV1")
}
// DialPeerByID function only added for compatibility with waku V2
func (w *GethWakuWrapper) DialPeerByID(peerID peer.ID) error {
return errors.New("not available in WakuV1")
2022-11-24 21:27:46 +00:00
}
// ListenAddresses function only added for compatibility with waku V2
func (w *GethWakuWrapper) ListenAddresses() ([]multiaddr.Multiaddr, error) {
2022-11-24 21:27:46 +00:00
return nil, errors.New("not available in WakuV1")
}
2024-07-01 15:37:54 +00:00
func (w *GethWakuWrapper) RelayPeersByTopic(topic string) (*types.PeerList, error) {
return nil, errors.New("not available in WakuV1")
}
2024-06-18 19:48:49 +00:00
// ENR function only added for compatibility with waku V2
func (w *GethWakuWrapper) ENR() (*enode.Node, error) {
return nil, errors.New("not available in WakuV1")
2024-06-18 19:48:49 +00:00
}
// PeerCount function only added for compatibility with waku V2
func (w *GethWakuWrapper) DropPeer(peerID peer.ID) error {
return errors.New("not available in WakuV1")
}
func (w *GethWakuWrapper) SubscribeToConnStatusChanges() (*types.ConnStatusSubscription, error) {
2022-01-12 16:02:01 +00:00
return nil, errors.New("not available in WakuV1")
}
func (w *GethWakuWrapper) SetCriteriaForMissingMessageVerification(peerID peer.ID, pubsubTopic string, contentTopics []types.TopicType) error {
return errors.New("not available in WakuV1")
}
// Peers function only added for compatibility with waku V2
func (w *GethWakuWrapper) Peers() types.PeerStats {
p := make(types.PeerStats)
return p
}
// MinPow returns the PoW value required by this node.
func (w *GethWakuWrapper) MinPow() float64 {
return w.waku.MinPow()
}
// MaxMessageSize returns the MaxMessageSize set
func (w *GethWakuWrapper) MaxMessageSize() uint32 {
return w.waku.MaxMessageSize()
}
// 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()
}
func (w *GethWakuWrapper) SubscribeEnvelopeEvents(eventsProxy chan<- types.EnvelopeEvent) types.Subscription {
Move networking code for waku under `v0` namespace Why make the change? As discussed previously, the way we will move across versions is to maintain completely separate codebases and eventually remove those that are not supported anymore. This has the drawback of some code duplication, but the advantage is that is more explicit what each version requires, and changes in one version will not impact the other, so we won't pile up backward compatible code. This is the same strategy used by `whisper` in go ethereum and is influenced by https://www.youtube.com/watch?v=oyLBGkS5ICk . All the code that is used for the networking protocol is now under `v0/`. Some of the common parts might still be refactored out. The main namespace `waku` deals with `host`->`waku` interactions (through RPC), while `v0` deals with `waku`->`remote-waku` interactions. In order to support `v1`, the namespace `v0` will be copied over, and changed to support `v1`. Once `v0` will be not used anymore, the whole namespace will be removed. This PR does not actually implement `v1`, I'd rather get things looked over to make sure the structure is what we would like before implementing the changes. What has changed? - Moved all code for the common parts under `waku/common/` namespace - Moved code used for bloomfilters in `waku/common/bloomfilter.go` - Removed all version specific code from `waku/common/const` (`ProtocolVersion`, status-codes etc) - Added interfaces for `WakuHost` and `Peer` under `waku/common/protocol.go` Things still to do Some tests in `waku/` are still testing by stubbing components of a particular version (`v0`). I started moving those tests to instead of stubbing using the actual component, which increases the testing surface. Some other tests that can't be easily ported should be likely moved under `v0` instead. Ideally no version specif code should be exported from a version namespace (for example the various codes, as those might change across versions). But this will be a work-in-progress. Some code that will be common in `v0`/`v1` could still be extract to avoid duplication, and duplicated only when implementations diverge across versions.
2020-04-21 12:40:30 +00:00
events := make(chan wakucommon.EnvelopeEvent, 100) // must be buffered to prevent blocking whisper
go func() {
defer gocommon.LogOnPanic()
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) GetStats() types.StatsSummary {
return w.waku.GetStats()
}
func (w *GethWakuWrapper) GetFilter(id string) types.Filter {
return NewWakuFilterWrapper(w.waku.GetFilter(id), id)
}
func (w *GethWakuWrapper) Unsubscribe(ctx context.Context, id string) error {
return w.waku.Unsubscribe(id)
}
func (w *GethWakuWrapper) UnsubscribeMany(ids []string) error {
return w.waku.UnsubscribeMany(ids)
}
func (w *GethWakuWrapper) createFilterWrapper(id string, keyAsym *ecdsa.PrivateKey, keySym []byte, pow float64, topics [][]byte) (types.Filter, error) {
Move networking code for waku under `v0` namespace Why make the change? As discussed previously, the way we will move across versions is to maintain completely separate codebases and eventually remove those that are not supported anymore. This has the drawback of some code duplication, but the advantage is that is more explicit what each version requires, and changes in one version will not impact the other, so we won't pile up backward compatible code. This is the same strategy used by `whisper` in go ethereum and is influenced by https://www.youtube.com/watch?v=oyLBGkS5ICk . All the code that is used for the networking protocol is now under `v0/`. Some of the common parts might still be refactored out. The main namespace `waku` deals with `host`->`waku` interactions (through RPC), while `v0` deals with `waku`->`remote-waku` interactions. In order to support `v1`, the namespace `v0` will be copied over, and changed to support `v1`. Once `v0` will be not used anymore, the whole namespace will be removed. This PR does not actually implement `v1`, I'd rather get things looked over to make sure the structure is what we would like before implementing the changes. What has changed? - Moved all code for the common parts under `waku/common/` namespace - Moved code used for bloomfilters in `waku/common/bloomfilter.go` - Removed all version specific code from `waku/common/const` (`ProtocolVersion`, status-codes etc) - Added interfaces for `WakuHost` and `Peer` under `waku/common/protocol.go` Things still to do Some tests in `waku/` are still testing by stubbing components of a particular version (`v0`). I started moving those tests to instead of stubbing using the actual component, which increases the testing surface. Some other tests that can't be easily ported should be likely moved under `v0` instead. Ideally no version specif code should be exported from a version namespace (for example the various codes, as those might change across versions). But this will be a work-in-progress. Some code that will be common in `v0`/`v1` could still be extract to avoid duplication, and duplicated only when implementations diverge across versions.
2020-04-21 12:40:30 +00:00
return NewWakuFilterWrapper(&wakucommon.Filter{
KeyAsym: keyAsym,
KeySym: keySym,
PoW: pow,
AllowP2P: true,
Topics: topics,
Move networking code for waku under `v0` namespace Why make the change? As discussed previously, the way we will move across versions is to maintain completely separate codebases and eventually remove those that are not supported anymore. This has the drawback of some code duplication, but the advantage is that is more explicit what each version requires, and changes in one version will not impact the other, so we won't pile up backward compatible code. This is the same strategy used by `whisper` in go ethereum and is influenced by https://www.youtube.com/watch?v=oyLBGkS5ICk . All the code that is used for the networking protocol is now under `v0/`. Some of the common parts might still be refactored out. The main namespace `waku` deals with `host`->`waku` interactions (through RPC), while `v0` deals with `waku`->`remote-waku` interactions. In order to support `v1`, the namespace `v0` will be copied over, and changed to support `v1`. Once `v0` will be not used anymore, the whole namespace will be removed. This PR does not actually implement `v1`, I'd rather get things looked over to make sure the structure is what we would like before implementing the changes. What has changed? - Moved all code for the common parts under `waku/common/` namespace - Moved code used for bloomfilters in `waku/common/bloomfilter.go` - Removed all version specific code from `waku/common/const` (`ProtocolVersion`, status-codes etc) - Added interfaces for `WakuHost` and `Peer` under `waku/common/protocol.go` Things still to do Some tests in `waku/` are still testing by stubbing components of a particular version (`v0`). I started moving those tests to instead of stubbing using the actual component, which increases the testing surface. Some other tests that can't be easily ported should be likely moved under `v0` instead. Ideally no version specif code should be exported from a version namespace (for example the various codes, as those might change across versions). But this will be a work-in-progress. Some code that will be common in `v0`/`v1` could still be extract to avoid duplication, and duplicated only when implementations diverge across versions.
2020-04-21 12:40:30 +00:00
Messages: wakucommon.NewMemoryMessageStore(),
}, id), nil
}
func (w *GethWakuWrapper) ProcessingP2PMessages() bool {
2021-11-26 12:30:35 +00:00
return w.waku.ProcessingP2PMessages()
}
func (w *GethWakuWrapper) MarkP2PMessageAsProcessed(hash common.Hash) {
2021-11-26 12:30:35 +00:00
w.waku.MarkP2PMessageAsProcessed(hash)
}
func (w *GethWakuWrapper) RequestStoreMessages(ctx context.Context, peerID peer.ID, r types.MessagesRequest, processEnvelopes bool) (types.StoreRequestCursor, int, error) {
return nil, 0, errors.New("not implemented")
}
func (w *GethWakuWrapper) ConnectionChanged(_ connection.State) {}
func (w *GethWakuWrapper) ClearEnvelopesCache() {
w.waku.ClearEnvelopesCache()
}
type wakuFilterWrapper struct {
Move networking code for waku under `v0` namespace Why make the change? As discussed previously, the way we will move across versions is to maintain completely separate codebases and eventually remove those that are not supported anymore. This has the drawback of some code duplication, but the advantage is that is more explicit what each version requires, and changes in one version will not impact the other, so we won't pile up backward compatible code. This is the same strategy used by `whisper` in go ethereum and is influenced by https://www.youtube.com/watch?v=oyLBGkS5ICk . All the code that is used for the networking protocol is now under `v0/`. Some of the common parts might still be refactored out. The main namespace `waku` deals with `host`->`waku` interactions (through RPC), while `v0` deals with `waku`->`remote-waku` interactions. In order to support `v1`, the namespace `v0` will be copied over, and changed to support `v1`. Once `v0` will be not used anymore, the whole namespace will be removed. This PR does not actually implement `v1`, I'd rather get things looked over to make sure the structure is what we would like before implementing the changes. What has changed? - Moved all code for the common parts under `waku/common/` namespace - Moved code used for bloomfilters in `waku/common/bloomfilter.go` - Removed all version specific code from `waku/common/const` (`ProtocolVersion`, status-codes etc) - Added interfaces for `WakuHost` and `Peer` under `waku/common/protocol.go` Things still to do Some tests in `waku/` are still testing by stubbing components of a particular version (`v0`). I started moving those tests to instead of stubbing using the actual component, which increases the testing surface. Some other tests that can't be easily ported should be likely moved under `v0` instead. Ideally no version specif code should be exported from a version namespace (for example the various codes, as those might change across versions). But this will be a work-in-progress. Some code that will be common in `v0`/`v1` could still be extract to avoid duplication, and duplicated only when implementations diverge across versions.
2020-04-21 12:40:30 +00:00
filter *wakucommon.Filter
id string
}
// NewWakuFilterWrapper returns an object that wraps Geth's Filter in a types interface
Move networking code for waku under `v0` namespace Why make the change? As discussed previously, the way we will move across versions is to maintain completely separate codebases and eventually remove those that are not supported anymore. This has the drawback of some code duplication, but the advantage is that is more explicit what each version requires, and changes in one version will not impact the other, so we won't pile up backward compatible code. This is the same strategy used by `whisper` in go ethereum and is influenced by https://www.youtube.com/watch?v=oyLBGkS5ICk . All the code that is used for the networking protocol is now under `v0/`. Some of the common parts might still be refactored out. The main namespace `waku` deals with `host`->`waku` interactions (through RPC), while `v0` deals with `waku`->`remote-waku` interactions. In order to support `v1`, the namespace `v0` will be copied over, and changed to support `v1`. Once `v0` will be not used anymore, the whole namespace will be removed. This PR does not actually implement `v1`, I'd rather get things looked over to make sure the structure is what we would like before implementing the changes. What has changed? - Moved all code for the common parts under `waku/common/` namespace - Moved code used for bloomfilters in `waku/common/bloomfilter.go` - Removed all version specific code from `waku/common/const` (`ProtocolVersion`, status-codes etc) - Added interfaces for `WakuHost` and `Peer` under `waku/common/protocol.go` Things still to do Some tests in `waku/` are still testing by stubbing components of a particular version (`v0`). I started moving those tests to instead of stubbing using the actual component, which increases the testing surface. Some other tests that can't be easily ported should be likely moved under `v0` instead. Ideally no version specif code should be exported from a version namespace (for example the various codes, as those might change across versions). But this will be a work-in-progress. Some code that will be common in `v0`/`v1` could still be extract to avoid duplication, and duplicated only when implementations diverge across versions.
2020-04-21 12:40:30 +00:00
func NewWakuFilterWrapper(f *wakucommon.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
Move networking code for waku under `v0` namespace Why make the change? As discussed previously, the way we will move across versions is to maintain completely separate codebases and eventually remove those that are not supported anymore. This has the drawback of some code duplication, but the advantage is that is more explicit what each version requires, and changes in one version will not impact the other, so we won't pile up backward compatible code. This is the same strategy used by `whisper` in go ethereum and is influenced by https://www.youtube.com/watch?v=oyLBGkS5ICk . All the code that is used for the networking protocol is now under `v0/`. Some of the common parts might still be refactored out. The main namespace `waku` deals with `host`->`waku` interactions (through RPC), while `v0` deals with `waku`->`remote-waku` interactions. In order to support `v1`, the namespace `v0` will be copied over, and changed to support `v1`. Once `v0` will be not used anymore, the whole namespace will be removed. This PR does not actually implement `v1`, I'd rather get things looked over to make sure the structure is what we would like before implementing the changes. What has changed? - Moved all code for the common parts under `waku/common/` namespace - Moved code used for bloomfilters in `waku/common/bloomfilter.go` - Removed all version specific code from `waku/common/const` (`ProtocolVersion`, status-codes etc) - Added interfaces for `WakuHost` and `Peer` under `waku/common/protocol.go` Things still to do Some tests in `waku/` are still testing by stubbing components of a particular version (`v0`). I started moving those tests to instead of stubbing using the actual component, which increases the testing surface. Some other tests that can't be easily ported should be likely moved under `v0` instead. Ideally no version specif code should be exported from a version namespace (for example the various codes, as those might change across versions). But this will be a work-in-progress. Some code that will be common in `v0`/`v1` could still be extract to avoid duplication, and duplicated only when implementations diverge across versions.
2020-04-21 12:40:30 +00:00
func GetWakuFilterFrom(f types.Filter) *wakucommon.Filter {
return f.(*wakuFilterWrapper).filter
}
// ID returns the filter ID
func (w *wakuFilterWrapper) ID() string {
return w.id
}
func (w *GethWakuWrapper) ConfirmMessageDelivered(hashes []common.Hash) {
}
func (w *GethWakuWrapper) SetStorePeerID(peerID peer.ID) {
}
func (w *GethWakuWrapper) PeerID() peer.ID {
panic("not implemented")
}
func (w *GethWakuWrapper) PingPeer(context.Context, peer.ID) (time.Duration, error) {
return 0, errors.New("not available in WakuV1")
}