status-im/status-go

View on GitHub
eth-node/bridge/geth/waku.go

Summary

Maintainability
B
6 hrs
Test Coverage
F
57%
package gethbridge

import (
    "context"
    "crypto/ecdsa"
    "errors"
    "time"

    "github.com/libp2p/go-libp2p/core/peer"

    "github.com/ethereum/go-ethereum/common"
    "github.com/status-im/status-go/connection"
    "github.com/status-im/status-go/eth-node/types"
    "github.com/status-im/status-go/waku"
    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 string) (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 string) (peer.ID, error) {
    return "", errors.New("not available in WakuV1")
}

// DialPeer function only added for compatibility with waku V2
func (w *GethWakuWrapper) DialPeer(address string) error {
    return errors.New("not available in WakuV1")
}

// DialPeerByID function only added for compatibility with waku V2
func (w *GethWakuWrapper) DialPeerByID(peerID string) error {
    return errors.New("not available in WakuV1")
}

// ListenAddresses function only added for compatibility with waku V2
func (w *GethWakuWrapper) ListenAddresses() ([]string, error) {
    return nil, errors.New("not available in WakuV1")
}

// ENR function only added for compatibility with waku V2
func (w *GethWakuWrapper) ENR() (string, error) {
    return "", errors.New("not available in WakuV1")
}

// PeerCount function only added for compatibility with waku V2
func (w *GethWakuWrapper) DropPeer(peerID string) error {
    return errors.New("not available in WakuV1")
}

func (w *GethWakuWrapper) SubscribeToConnStatusChanges() (*types.ConnStatusSubscription, error) {
    return nil, errors.New("not available in WakuV1")
}

// Peers function only added for compatibility with waku V2
func (w *GethWakuWrapper) Peers() map[string]types.WakuV2Peer {
    p := make(map[string]types.WakuV2Peer)
    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 {
    events := make(chan wakucommon.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) 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) {
    return NewWakuFilterWrapper(&wakucommon.Filter{
        KeyAsym:  keyAsym,
        KeySym:   keySym,
        PoW:      pow,
        AllowP2P: true,
        Topics:   topics,
        Messages: wakucommon.NewMemoryMessageStore(),
    }, id), nil
}

func (w *GethWakuWrapper) SendMessagesRequest(peerID []byte, r types.MessagesRequest) error {
    return w.waku.SendMessagesRequest(peerID, wakucommon.MessagesRequest{
        ID:     r.ID,
        From:   r.From,
        To:     r.To,
        Limit:  r.Limit,
        Cursor: r.Cursor,
        Bloom:  r.Bloom,
        Topics: r.ContentTopics,
    })
}

// 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, envelope.Unwrap().(*wakucommon.Envelope), timeout)
}

func (w *GethWakuWrapper) ProcessingP2PMessages() bool {
    return w.waku.ProcessingP2PMessages()
}

func (w *GethWakuWrapper) MarkP2PMessageAsProcessed(hash common.Hash) {
    w.waku.MarkP2PMessageAsProcessed(hash)
}

func (w *GethWakuWrapper) RequestStoreMessages(ctx context.Context, peerID []byte, 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 {
    filter *wakucommon.Filter
    id     string
}

// NewWakuFilterWrapper returns an object that wraps Geth's Filter in a types interface
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
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) {
}