diff --git a/whisper/go.mod b/whisper/go.mod index bcc5736f2..a2805d72e 100644 --- a/whisper/go.mod +++ b/whisper/go.mod @@ -8,6 +8,8 @@ require ( github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea github.com/ethereum/go-ethereum v1.9.5 github.com/gorilla/websocket v1.4.1 // indirect + github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect + github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect github.com/stretchr/objx v0.2.0 // indirect github.com/stretchr/testify v1.3.0 github.com/syndtr/goleveldb v0.0.0-20181128100959-b001fa50d6b2 diff --git a/whisper/go.sum b/whisper/go.sum index ab995d6c7..9df409b79 100644 --- a/whisper/go.sum +++ b/whisper/go.sum @@ -4,6 +4,7 @@ github.com/Azure/azure-storage-blob-go v0.0.0-20180712005634-eaae161d9d5e/go.mod github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156 h1:hh7BAWFHv41r0gce0KRYtDJpL4erKfmB1/mpgoSADeI= github.com/allegro/bigcache v0.0.0-20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= @@ -91,7 +92,13 @@ github.com/status-im/go-ethereum v1.9.5-status.6 h1:ytuTO1yBIAuTVRtRQoc2mrdyngtP github.com/status-im/go-ethereum v1.9.5-status.6/go.mod h1:08JvQWE+IOnAFSe4UD4ACLNe2fDd9XmWMCq5Yzy9mk0= github.com/status-im/go-ethereum v1.9.5-status.7 h1:DKH1GiF52LwaZaw6YDBliFEgm/JDsbIT+hn7ph6X94Q= github.com/status-im/go-ethereum v1.9.5-status.7/go.mod h1:YyH5DKB6+z+Vaya7eIm67pnuPZ1oiUMbbsZW41ktN0g= +github.com/status-im/status-go v0.37.3 h1:94/bOA8qrEIgWd23mSLN39SwUJwCu2TPQFV2HzSI2ZE= +github.com/status-im/status-go v0.38.0 h1:3toC1ToY48wbRBVt7CMWSSG5FZAcPPMlnt0+G6iCbcE= github.com/status-im/status-go/extkeys v1.0.0/go.mod h1:GdqJbrcpkNm5ZsSCpp+PdMxnXx+OcRBdm3PI0rs1FpU= +github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= +github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= +github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM= +github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= diff --git a/whisper/shhclient/client.go b/whisper/shhclient/client.go new file mode 100644 index 000000000..cff16cf11 --- /dev/null +++ b/whisper/shhclient/client.go @@ -0,0 +1,193 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package shhclient + +import ( + "context" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/rpc" + "github.com/status-im/status-go/whisper/v6" +) + +// Client defines typed wrappers for the Whisper v6 RPC API. +type Client struct { + c *rpc.Client +} + +// Dial connects a client to the given URL. +func Dial(rawurl string) (*Client, error) { + c, err := rpc.Dial(rawurl) + if err != nil { + return nil, err + } + return NewClient(c), nil +} + +// NewClient creates a client that uses the given RPC client. +func NewClient(c *rpc.Client) *Client { + return &Client{c} +} + +// Version returns the Whisper sub-protocol version. +func (sc *Client) Version(ctx context.Context) (string, error) { + var result string + err := sc.c.CallContext(ctx, &result, "shh_version") + return result, err +} + +// Info returns diagnostic information about the whisper node. +func (sc *Client) Info(ctx context.Context) (whisper.Info, error) { + var info whisper.Info + err := sc.c.CallContext(ctx, &info, "shh_info") + return info, err +} + +// SetMaxMessageSize sets the maximal message size allowed by this node. Incoming +// and outgoing messages with a larger size will be rejected. Whisper message size +// can never exceed the limit imposed by the underlying P2P protocol (10 Mb). +func (sc *Client) SetMaxMessageSize(ctx context.Context, size uint32) error { + var ignored bool + return sc.c.CallContext(ctx, &ignored, "shh_setMaxMessageSize", size) +} + +// SetMinimumPoW (experimental) sets the minimal PoW required by this node. +// This experimental function was introduced for the future dynamic adjustment of +// PoW requirement. If the node is overwhelmed with messages, it should raise the +// PoW requirement and notify the peers. The new value should be set relative to +// the old value (e.g. double). The old value could be obtained via shh_info call. +func (sc *Client) SetMinimumPoW(ctx context.Context, pow float64) error { + var ignored bool + return sc.c.CallContext(ctx, &ignored, "shh_setMinPoW", pow) +} + +// MarkTrustedPeer marks specific peer trusted, which will allow it to send historic (expired) messages. +// Note This function is not adding new nodes, the node needs to exists as a peer. +func (sc *Client) MarkTrustedPeer(ctx context.Context, enode string) error { + var ignored bool + return sc.c.CallContext(ctx, &ignored, "shh_markTrustedPeer", enode) +} + +// NewKeyPair generates a new public and private key pair for message decryption and encryption. +// It returns an identifier that can be used to refer to the key. +func (sc *Client) NewKeyPair(ctx context.Context) (string, error) { + var id string + return id, sc.c.CallContext(ctx, &id, "shh_newKeyPair") +} + +// AddPrivateKey stored the key pair, and returns its ID. +func (sc *Client) AddPrivateKey(ctx context.Context, key []byte) (string, error) { + var id string + return id, sc.c.CallContext(ctx, &id, "shh_addPrivateKey", hexutil.Bytes(key)) +} + +// DeleteKeyPair delete the specifies key. +func (sc *Client) DeleteKeyPair(ctx context.Context, id string) (string, error) { + var ignored bool + return id, sc.c.CallContext(ctx, &ignored, "shh_deleteKeyPair", id) +} + +// HasKeyPair returns an indication if the node has a private key or +// key pair matching the given ID. +func (sc *Client) HasKeyPair(ctx context.Context, id string) (bool, error) { + var has bool + return has, sc.c.CallContext(ctx, &has, "shh_hasKeyPair", id) +} + +// PublicKey return the public key for a key ID. +func (sc *Client) PublicKey(ctx context.Context, id string) ([]byte, error) { + var key hexutil.Bytes + return key, sc.c.CallContext(ctx, &key, "shh_getPublicKey", id) +} + +// PrivateKey return the private key for a key ID. +func (sc *Client) PrivateKey(ctx context.Context, id string) ([]byte, error) { + var key hexutil.Bytes + return key, sc.c.CallContext(ctx, &key, "shh_getPrivateKey", id) +} + +// NewSymmetricKey generates a random symmetric key and returns its identifier. +// Can be used encrypting and decrypting messages where the key is known to both parties. +func (sc *Client) NewSymmetricKey(ctx context.Context) (string, error) { + var id string + return id, sc.c.CallContext(ctx, &id, "shh_newSymKey") +} + +// AddSymmetricKey stores the key, and returns its identifier. +func (sc *Client) AddSymmetricKey(ctx context.Context, key []byte) (string, error) { + var id string + return id, sc.c.CallContext(ctx, &id, "shh_addSymKey", hexutil.Bytes(key)) +} + +// GenerateSymmetricKeyFromPassword generates the key from password, stores it, and returns its identifier. +func (sc *Client) GenerateSymmetricKeyFromPassword(ctx context.Context, passwd string) (string, error) { + var id string + return id, sc.c.CallContext(ctx, &id, "shh_generateSymKeyFromPassword", passwd) +} + +// HasSymmetricKey returns an indication if the key associated with the given id is stored in the node. +func (sc *Client) HasSymmetricKey(ctx context.Context, id string) (bool, error) { + var found bool + return found, sc.c.CallContext(ctx, &found, "shh_hasSymKey", id) +} + +// GetSymmetricKey returns the symmetric key associated with the given identifier. +func (sc *Client) GetSymmetricKey(ctx context.Context, id string) ([]byte, error) { + var key hexutil.Bytes + return key, sc.c.CallContext(ctx, &key, "shh_getSymKey", id) +} + +// DeleteSymmetricKey deletes the symmetric key associated with the given identifier. +func (sc *Client) DeleteSymmetricKey(ctx context.Context, id string) error { + var ignored bool + return sc.c.CallContext(ctx, &ignored, "shh_deleteSymKey", id) +} + +// Post a message onto the network. +func (sc *Client) Post(ctx context.Context, message whisper.NewMessage) (string, error) { + var hash string + return hash, sc.c.CallContext(ctx, &hash, "shh_post", message) +} + +// SubscribeMessages subscribes to messages that match the given criteria. This method +// is only supported on bi-directional connections such as websockets and IPC. +// NewMessageFilter uses polling and is supported over HTTP. +func (sc *Client) SubscribeMessages(ctx context.Context, criteria whisper.Criteria, ch chan<- *whisper.Message) (ethereum.Subscription, error) { + return sc.c.ShhSubscribe(ctx, ch, "messages", criteria) +} + +// NewMessageFilter creates a filter within the node. This filter can be used to poll +// for new messages (see FilterMessages) that satisfy the given criteria. A filter can +// timeout when it was polled for in whisper.filterTimeout. +func (sc *Client) NewMessageFilter(ctx context.Context, criteria whisper.Criteria) (string, error) { + var id string + return id, sc.c.CallContext(ctx, &id, "shh_newMessageFilter", criteria) +} + +// DeleteMessageFilter removes the filter associated with the given id. +func (sc *Client) DeleteMessageFilter(ctx context.Context, id string) error { + var ignored bool + return sc.c.CallContext(ctx, &ignored, "shh_deleteMessageFilter", id) +} + +// FilterMessages retrieves all messages that are received between the last call to +// this function and match the criteria that where given when the filter was created. +func (sc *Client) FilterMessages(ctx context.Context, id string) ([]*whisper.Message, error) { + var messages []*whisper.Message + return messages, sc.c.CallContext(ctx, &messages, "shh_getFilterMessages", id) +}