diff options
Diffstat (limited to 'whisper/whisperv6')
-rw-r--r-- | whisper/whisperv6/api.go | 7 | ||||
-rw-r--r-- | whisper/whisperv6/benchmarks_test.go | 14 | ||||
-rw-r--r-- | whisper/whisperv6/config.go | 2 | ||||
-rw-r--r-- | whisper/whisperv6/doc.go | 12 | ||||
-rw-r--r-- | whisper/whisperv6/envelope.go | 2 | ||||
-rw-r--r-- | whisper/whisperv6/envelope_test.go | 2 | ||||
-rw-r--r-- | whisper/whisperv6/filter.go | 21 | ||||
-rw-r--r-- | whisper/whisperv6/filter_test.go | 18 | ||||
-rw-r--r-- | whisper/whisperv6/gen_criteria_json.go | 2 | ||||
-rw-r--r-- | whisper/whisperv6/gen_message_json.go | 2 | ||||
-rw-r--r-- | whisper/whisperv6/gen_newmessage_json.go | 2 | ||||
-rw-r--r-- | whisper/whisperv6/message.go | 10 | ||||
-rw-r--r-- | whisper/whisperv6/message_test.go | 20 | ||||
-rw-r--r-- | whisper/whisperv6/peer.go | 83 | ||||
-rw-r--r-- | whisper/whisperv6/peer_test.go | 30 | ||||
-rw-r--r-- | whisper/whisperv6/topic.go | 4 | ||||
-rw-r--r-- | whisper/whisperv6/whisper.go | 444 | ||||
-rw-r--r-- | whisper/whisperv6/whisper_test.go | 12 |
18 files changed, 361 insertions, 326 deletions
diff --git a/whisper/whisperv6/api.go b/whisper/whisperv6/api.go index 2f6f671e9..6cbce26f0 100644 --- a/whisper/whisperv6/api.go +++ b/whisper/whisperv6/api.go @@ -36,6 +36,7 @@ const ( filterTimeout = 300 // filters are considered timeout out after filterTimeout seconds ) +// List of errors var ( ErrSymAsym = errors.New("specify either a symmetric or an asymmetric key") ErrInvalidSymmetricKey = errors.New("invalid symmetric key") @@ -116,7 +117,7 @@ func (api *PublicWhisperAPI) SetMaxMessageSize(ctx context.Context, size uint32) return true, api.w.SetMaxMessageSize(size) } -// SetMinPow sets the minimum PoW, and notifies the peers. +// SetMinPoW sets the minimum PoW, and notifies the peers. func (api *PublicWhisperAPI) SetMinPoW(ctx context.Context, pow float64) (bool, error) { return true, api.w.SetMinimumPoW(pow) } @@ -174,7 +175,7 @@ func (api *PublicWhisperAPI) GetPublicKey(ctx context.Context, id string) (hexut return crypto.FromECDSAPub(&key.PublicKey), nil } -// GetPublicKey returns the private key associated with the given key. The key is the hex +// GetPrivateKey returns the private key associated with the given key. The key is the hex // encoded representation of a key in the form specified in section 4.3.6 of ANSI X9.62. func (api *PublicWhisperAPI) GetPrivateKey(ctx context.Context, id string) (hexutil.Bytes, error) { key, err := api.w.GetPrivateKey(id) @@ -291,7 +292,7 @@ func (api *PublicWhisperAPI) Post(ctx context.Context, req NewMessage) (bool, er } // encrypt and sent message - whisperMsg, err := NewSentMessage(params) + whisperMsg, err := newSentMessage(params) if err != nil { return false, err } diff --git a/whisper/whisperv6/benchmarks_test.go b/whisper/whisperv6/benchmarks_test.go index 0473179da..52c8f95ea 100644 --- a/whisper/whisperv6/benchmarks_test.go +++ b/whisper/whisperv6/benchmarks_test.go @@ -39,7 +39,7 @@ func BenchmarkEncryptionSym(b *testing.B) { } for i := 0; i < b.N; i++ { - msg, _ := NewSentMessage(params) + msg, _ := newSentMessage(params) _, err := msg.Wrap(params) if err != nil { b.Errorf("failed Wrap with seed %d: %s.", seed, err) @@ -64,7 +64,7 @@ func BenchmarkEncryptionAsym(b *testing.B) { params.Dst = &key.PublicKey for i := 0; i < b.N; i++ { - msg, _ := NewSentMessage(params) + msg, _ := newSentMessage(params) _, err := msg.Wrap(params) if err != nil { b.Fatalf("failed Wrap with seed %d: %s.", seed, err) @@ -79,7 +79,7 @@ func BenchmarkDecryptionSymValid(b *testing.B) { if err != nil { b.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } - msg, _ := NewSentMessage(params) + msg, _ := newSentMessage(params) env, err := msg.Wrap(params) if err != nil { b.Fatalf("failed Wrap with seed %d: %s.", seed, err) @@ -101,7 +101,7 @@ func BenchmarkDecryptionSymInvalid(b *testing.B) { if err != nil { b.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } - msg, _ := NewSentMessage(params) + msg, _ := newSentMessage(params) env, err := msg.Wrap(params) if err != nil { b.Fatalf("failed Wrap with seed %d: %s.", seed, err) @@ -130,7 +130,7 @@ func BenchmarkDecryptionAsymValid(b *testing.B) { f := Filter{KeyAsym: key} params.KeySym = nil params.Dst = &key.PublicKey - msg, _ := NewSentMessage(params) + msg, _ := newSentMessage(params) env, err := msg.Wrap(params) if err != nil { b.Fatalf("failed Wrap with seed %d: %s.", seed, err) @@ -157,7 +157,7 @@ func BenchmarkDecryptionAsymInvalid(b *testing.B) { } params.KeySym = nil params.Dst = &key.PublicKey - msg, _ := NewSentMessage(params) + msg, _ := newSentMessage(params) env, err := msg.Wrap(params) if err != nil { b.Fatalf("failed Wrap with seed %d: %s.", seed, err) @@ -199,7 +199,7 @@ func BenchmarkPoW(b *testing.B) { for i := 0; i < b.N; i++ { increment(params.Payload) - msg, _ := NewSentMessage(params) + msg, _ := newSentMessage(params) _, err := msg.Wrap(params) if err != nil { b.Fatalf("failed Wrap with seed %d: %s.", seed, err) diff --git a/whisper/whisperv6/config.go b/whisper/whisperv6/config.go index d7f817aa2..61419de00 100644 --- a/whisper/whisperv6/config.go +++ b/whisper/whisperv6/config.go @@ -16,11 +16,13 @@ package whisperv6 +// Config represents the configuration state of a whisper node. type Config struct { MaxMessageSize uint32 `toml:",omitempty"` MinimumAcceptedPOW float64 `toml:",omitempty"` } +// DefaultConfig represents (shocker!) the default configuration. var DefaultConfig = Config{ MaxMessageSize: DefaultMaxMessageSize, MinimumAcceptedPOW: DefaultMinimumPoW, diff --git a/whisper/whisperv6/doc.go b/whisper/whisperv6/doc.go index da1b4ee5b..699fd5c76 100644 --- a/whisper/whisperv6/doc.go +++ b/whisper/whisperv6/doc.go @@ -27,6 +27,9 @@ Whisper is a pure identity-based messaging system. Whisper provides a low-level or prejudiced by the low-level hardware attributes and characteristics, particularly the notion of singular endpoints. */ + +// Contains the Whisper protocol constant definitions + package whisperv6 import ( @@ -34,10 +37,11 @@ import ( "time" ) +// Whisper protocol parameters const ( - ProtocolVersion = uint64(6) - ProtocolVersionStr = "6.0" - ProtocolName = "shh" + ProtocolVersion = uint64(6) // Protocol version number + ProtocolVersionStr = "6.0" // The same, as a string + ProtocolName = "shh" // Nickname of the protocol in geth // whisper protocol message codes, according to EIP-627 statusCode = 0 // used by whisper protocol @@ -55,7 +59,7 @@ const ( signatureLength = 65 // in bytes aesKeyLength = 32 // in bytes AESNonceLength = 12 // in bytes - keyIdSize = 32 // in bytes + keyIDSize = 32 // in bytes bloomFilterSize = 64 // in bytes EnvelopeHeaderLength = 20 diff --git a/whisper/whisperv6/envelope.go b/whisper/whisperv6/envelope.go index 9ed712b93..6bc1f2c6b 100644 --- a/whisper/whisperv6/envelope.go +++ b/whisper/whisperv6/envelope.go @@ -115,6 +115,8 @@ func (e *Envelope) Seal(options *MessageParams) error { return nil } +// PoW computes (if necessary) and returns the proof of work target +// of the envelope. func (e *Envelope) PoW() float64 { if e.pow == 0 { e.calculatePoW(0) diff --git a/whisper/whisperv6/envelope_test.go b/whisper/whisperv6/envelope_test.go index 410b250a3..1ee1bec41 100644 --- a/whisper/whisperv6/envelope_test.go +++ b/whisper/whisperv6/envelope_test.go @@ -45,7 +45,7 @@ func TestEnvelopeOpenAcceptsOnlyOneKeyTypeInFilter(t *testing.T) { mrand.Read(params.Payload) - msg, err := NewSentMessage(¶ms) + msg, err := newSentMessage(¶ms) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } diff --git a/whisper/whisperv6/filter.go b/whisper/whisperv6/filter.go index a752c7ac9..eb0c65fa3 100644 --- a/whisper/whisperv6/filter.go +++ b/whisper/whisperv6/filter.go @@ -26,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum/log" ) +// Filter represents a Whisper message filter type Filter struct { Src *ecdsa.PublicKey // Sender of the message KeyAsym *ecdsa.PrivateKey // Private Key of recipient @@ -39,12 +40,14 @@ type Filter struct { mutex sync.RWMutex } +// Filters represents a collection of filters type Filters struct { watchers map[string]*Filter whisper *Whisper mutex sync.RWMutex } +// NewFilters returns a newly created filter collection func NewFilters(w *Whisper) *Filters { return &Filters{ watchers: make(map[string]*Filter), @@ -52,6 +55,7 @@ func NewFilters(w *Whisper) *Filters { } } +// Install will add a new filter to the filter collection func (fs *Filters) Install(watcher *Filter) (string, error) { if watcher.KeySym != nil && watcher.KeyAsym != nil { return "", fmt.Errorf("filters must choose between symmetric and asymmetric keys") @@ -81,6 +85,8 @@ func (fs *Filters) Install(watcher *Filter) (string, error) { return id, err } +// Uninstall will remove a filter whose id has been specified from +// the filter collection func (fs *Filters) Uninstall(id string) bool { fs.mutex.Lock() defer fs.mutex.Unlock() @@ -91,12 +97,15 @@ func (fs *Filters) Uninstall(id string) bool { return false } +// Get returns a filter from the collection with a specific ID func (fs *Filters) Get(id string) *Filter { fs.mutex.RLock() defer fs.mutex.RUnlock() return fs.watchers[id] } +// NotifyWatchers notifies any filter that has declared interest +// for the envelope's topic. func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) { var msg *ReceivedMessage @@ -140,9 +149,9 @@ func (f *Filter) processEnvelope(env *Envelope) *ReceivedMessage { msg := env.Open(f) if msg != nil { return msg - } else { - log.Trace("processing envelope: failed to open", "hash", env.Hash().Hex()) } + + log.Trace("processing envelope: failed to open", "hash", env.Hash().Hex()) } else { log.Trace("processing envelope: does not match", "hash", env.Hash().Hex()) } @@ -157,6 +166,8 @@ func (f *Filter) expectsSymmetricEncryption() bool { return f.KeySym != nil } +// Trigger adds a yet-unknown message to the filter's list of +// received messages. func (f *Filter) Trigger(msg *ReceivedMessage) { f.mutex.Lock() defer f.mutex.Unlock() @@ -166,6 +177,8 @@ func (f *Filter) Trigger(msg *ReceivedMessage) { } } +// Retrieve will return the list of all received messages associated +// to a filter. func (f *Filter) Retrieve() (all []*ReceivedMessage) { f.mutex.Lock() defer f.mutex.Unlock() @@ -195,7 +208,7 @@ func (f *Filter) MatchMessage(msg *ReceivedMessage) bool { return false } -// MatchEvelope checks if it's worth decrypting the message. If +// MatchEnvelope checks if it's worth decrypting the message. If // it returns `true`, client code is expected to attempt decrypting // the message and subsequently call MatchMessage. func (f *Filter) MatchEnvelope(envelope *Envelope) bool { @@ -206,6 +219,7 @@ func (f *Filter) MatchEnvelope(envelope *Envelope) bool { return f.MatchTopic(envelope.Topic) } +// MatchTopic checks that the filter captures a given topic. func (f *Filter) MatchTopic(topic TopicType) bool { if len(f.Topics) == 0 { // any topic matches @@ -237,6 +251,7 @@ func matchSingleTopic(topic TopicType, bt []byte) bool { return true } +// IsPubKeyEqual checks that two public keys are equal func IsPubKeyEqual(a, b *ecdsa.PublicKey) bool { if !ValidatePublicKey(a) { return false diff --git a/whisper/whisperv6/filter_test.go b/whisper/whisperv6/filter_test.go index 9c7fdad95..fc7db7671 100644 --- a/whisper/whisperv6/filter_test.go +++ b/whisper/whisperv6/filter_test.go @@ -109,7 +109,7 @@ func TestInstallFilters(t *testing.T) { t.Fatalf("seed %d: failed to install filter: %s", seed, err) } tst[i].id = j - if len(j) != keyIdSize*2 { + if len(j) != keyIDSize*2 { t.Fatalf("seed %d: wrong filter id size [%d]", seed, len(j)) } } @@ -199,7 +199,7 @@ func TestInstallIdenticalFilters(t *testing.T) { filter1.Src = ¶ms.Src.PublicKey filter2.Src = ¶ms.Src.PublicKey - sentMessage, err := NewSentMessage(params) + sentMessage, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -306,7 +306,7 @@ func TestMatchEnvelope(t *testing.T) { params.Topic[0] = 0xFF // ensure mismatch // mismatch with pseudo-random data - msg, err := NewSentMessage(params) + msg, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -327,7 +327,7 @@ func TestMatchEnvelope(t *testing.T) { i := mrand.Int() % 4 fsym.Topics[i] = params.Topic[:] fasym.Topics[i] = params.Topic[:] - msg, err = NewSentMessage(params) + msg, err = newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -372,7 +372,7 @@ func TestMatchEnvelope(t *testing.T) { } params.KeySym = nil params.Dst = &key.PublicKey - msg, err = NewSentMessage(params) + msg, err = newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -453,7 +453,7 @@ func TestMatchMessageSym(t *testing.T) { params.KeySym = f.KeySym params.Topic = BytesToTopic(f.Topics[index]) - sentMessage, err := NewSentMessage(params) + sentMessage, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -546,7 +546,7 @@ func TestMatchMessageAsym(t *testing.T) { keySymOrig := params.KeySym params.KeySym = nil - sentMessage, err := NewSentMessage(params) + sentMessage, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -630,7 +630,7 @@ func generateCompatibeEnvelope(t *testing.T, f *Filter) *Envelope { params.KeySym = f.KeySym params.Topic = BytesToTopic(f.Topics[2]) - sentMessage, err := NewSentMessage(params) + sentMessage, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -806,7 +806,7 @@ func TestVariableTopics(t *testing.T) { if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } - msg, err := NewSentMessage(params) + msg, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } diff --git a/whisper/whisperv6/gen_criteria_json.go b/whisper/whisperv6/gen_criteria_json.go index a298396cc..1a428d6df 100644 --- a/whisper/whisperv6/gen_criteria_json.go +++ b/whisper/whisperv6/gen_criteria_json.go @@ -10,6 +10,7 @@ import ( var _ = (*criteriaOverride)(nil) +// MarshalJSON marshals type Criteria to a json string func (c Criteria) MarshalJSON() ([]byte, error) { type Criteria struct { SymKeyID string `json:"symKeyID"` @@ -29,6 +30,7 @@ func (c Criteria) MarshalJSON() ([]byte, error) { return json.Marshal(&enc) } +// UnmarshalJSON unmarshals type Criteria to a json string func (c *Criteria) UnmarshalJSON(input []byte) error { type Criteria struct { SymKeyID *string `json:"symKeyID"` diff --git a/whisper/whisperv6/gen_message_json.go b/whisper/whisperv6/gen_message_json.go index e193ba3e2..6218f5df6 100644 --- a/whisper/whisperv6/gen_message_json.go +++ b/whisper/whisperv6/gen_message_json.go @@ -10,6 +10,7 @@ import ( var _ = (*messageOverride)(nil) +// MarshalJSON marshals type Message to a json string func (m Message) MarshalJSON() ([]byte, error) { type Message struct { Sig hexutil.Bytes `json:"sig,omitempty"` @@ -35,6 +36,7 @@ func (m Message) MarshalJSON() ([]byte, error) { return json.Marshal(&enc) } +// UnmarshalJSON unmarshals type Message to a json string func (m *Message) UnmarshalJSON(input []byte) error { type Message struct { Sig *hexutil.Bytes `json:"sig,omitempty"` diff --git a/whisper/whisperv6/gen_newmessage_json.go b/whisper/whisperv6/gen_newmessage_json.go index 6250579f4..75a1279ae 100644 --- a/whisper/whisperv6/gen_newmessage_json.go +++ b/whisper/whisperv6/gen_newmessage_json.go @@ -10,6 +10,7 @@ import ( var _ = (*newMessageOverride)(nil) +// MarshalJSON marshals type NewMessage to a json string func (n NewMessage) MarshalJSON() ([]byte, error) { type NewMessage struct { SymKeyID string `json:"symKeyID"` @@ -37,6 +38,7 @@ func (n NewMessage) MarshalJSON() ([]byte, error) { return json.Marshal(&enc) } +// UnmarshalJSON unmarshals type NewMessage to a json string func (n *NewMessage) UnmarshalJSON(input []byte) error { type NewMessage struct { SymKeyID *string `json:"symKeyID"` diff --git a/whisper/whisperv6/message.go b/whisper/whisperv6/message.go index f8df50336..b5c8279b1 100644 --- a/whisper/whisperv6/message.go +++ b/whisper/whisperv6/message.go @@ -33,7 +33,8 @@ import ( "github.com/ethereum/go-ethereum/log" ) -// Options specifies the exact way a message should be wrapped into an Envelope. +// MessageParams specifies the exact way a message should be wrapped +// into an Envelope. type MessageParams struct { TTL uint32 Src *ecdsa.PrivateKey @@ -86,8 +87,8 @@ func (msg *ReceivedMessage) isAsymmetricEncryption() bool { return msg.Dst != nil } -// NewMessage creates and initializes a non-signed, non-encrypted Whisper message. -func NewSentMessage(params *MessageParams) (*sentMessage, error) { +// NewSentMessage creates and initializes a non-signed, non-encrypted Whisper message. +func newSentMessage(params *MessageParams) (*sentMessage, error) { msg := sentMessage{} msg.Raw = make([]byte, 1, len(params.Payload)+len(params.Padding)+signatureLength+padSizeLimit) msg.Raw[0] = 0 // set all the flags to zero @@ -341,7 +342,8 @@ func (msg *ReceivedMessage) extractPadding(end int) (int, bool) { return paddingSize, true } -// Recover retrieves the public key of the message signer. +// SigToPubKey returns the public key associated to the message's +// signature. func (msg *ReceivedMessage) SigToPubKey() *ecdsa.PublicKey { defer func() { recover() }() // in case of invalid signature diff --git a/whisper/whisperv6/message_test.go b/whisper/whisperv6/message_test.go index c90bcc01e..5f8b41edc 100644 --- a/whisper/whisperv6/message_test.go +++ b/whisper/whisperv6/message_test.go @@ -70,7 +70,7 @@ func singleMessageTest(t *testing.T, symmetric bool) { text := make([]byte, 0, 512) text = append(text, params.Payload...) - msg, err := NewSentMessage(params) + msg, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -128,7 +128,7 @@ func TestMessageWrap(t *testing.T) { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } - msg, err := NewSentMessage(params) + msg, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -146,7 +146,7 @@ func TestMessageWrap(t *testing.T) { } // set PoW target too high, expect error - msg2, err := NewSentMessage(params) + msg2, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -169,7 +169,7 @@ func TestMessageSeal(t *testing.T) { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } - msg, err := NewSentMessage(params) + msg, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -231,7 +231,7 @@ func singleEnvelopeOpenTest(t *testing.T, symmetric bool) { text := make([]byte, 0, 512) text = append(text, params.Payload...) - msg, err := NewSentMessage(params) + msg, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -286,7 +286,7 @@ func TestEncryptWithZeroKey(t *testing.T) { if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } - msg, err := NewSentMessage(params) + msg, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -300,7 +300,7 @@ func TestEncryptWithZeroKey(t *testing.T) { if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } - msg, err = NewSentMessage(params) + msg, err = newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -314,7 +314,7 @@ func TestEncryptWithZeroKey(t *testing.T) { if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } - msg, err = NewSentMessage(params) + msg, err = newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -332,7 +332,7 @@ func TestRlpEncode(t *testing.T) { if err != nil { t.Fatalf("failed generateMessageParams with seed %d: %s.", seed, err) } - msg, err := NewSentMessage(params) + msg, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -376,7 +376,7 @@ func singlePaddingTest(t *testing.T, padSize int) { if n != padSize { t.Fatalf("padding is not copied (seed %d): %s", seed, err) } - msg, err := NewSentMessage(params) + msg, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } diff --git a/whisper/whisperv6/peer.go b/whisper/whisperv6/peer.go index 08071c0f7..4f9a7c378 100644 --- a/whisper/whisperv6/peer.go +++ b/whisper/whisperv6/peer.go @@ -28,7 +28,7 @@ import ( set "gopkg.in/fatih/set.v0" ) -// peer represents a whisper protocol peer connection. +// Peer represents a whisper protocol peer connection. type Peer struct { host *Whisper peer *p2p.Peer @@ -58,48 +58,48 @@ func newPeer(host *Whisper, remote *p2p.Peer, rw p2p.MsgReadWriter) *Peer { // start initiates the peer updater, periodically broadcasting the whisper packets // into the network. -func (p *Peer) start() { - go p.update() - log.Trace("start", "peer", p.ID()) +func (peer *Peer) start() { + go peer.update() + log.Trace("start", "peer", peer.ID()) } // stop terminates the peer updater, stopping message forwarding to it. -func (p *Peer) stop() { - close(p.quit) - log.Trace("stop", "peer", p.ID()) +func (peer *Peer) stop() { + close(peer.quit) + log.Trace("stop", "peer", peer.ID()) } // handshake sends the protocol initiation status message to the remote peer and // verifies the remote status too. -func (p *Peer) handshake() error { +func (peer *Peer) handshake() error { // Send the handshake status message asynchronously errc := make(chan error, 1) go func() { - pow := p.host.MinPow() + pow := peer.host.MinPow() powConverted := math.Float64bits(pow) - bloom := p.host.BloomFilter() - errc <- p2p.SendItems(p.ws, statusCode, ProtocolVersion, powConverted, bloom) + bloom := peer.host.BloomFilter() + errc <- p2p.SendItems(peer.ws, statusCode, ProtocolVersion, powConverted, bloom) }() // Fetch the remote status packet and verify protocol match - packet, err := p.ws.ReadMsg() + packet, err := peer.ws.ReadMsg() if err != nil { return err } if packet.Code != statusCode { - return fmt.Errorf("peer [%x] sent packet %x before status packet", p.ID(), packet.Code) + return fmt.Errorf("peer [%x] sent packet %x before status packet", peer.ID(), packet.Code) } s := rlp.NewStream(packet.Payload, uint64(packet.Size)) _, err = s.List() if err != nil { - return fmt.Errorf("peer [%x] sent bad status message: %v", p.ID(), err) + return fmt.Errorf("peer [%x] sent bad status message: %v", peer.ID(), err) } peerVersion, err := s.Uint() if err != nil { - return fmt.Errorf("peer [%x] sent bad status message (unable to decode version): %v", p.ID(), err) + return fmt.Errorf("peer [%x] sent bad status message (unable to decode version): %v", peer.ID(), err) } if peerVersion != ProtocolVersion { - return fmt.Errorf("peer [%x]: protocol version mismatch %d != %d", p.ID(), peerVersion, ProtocolVersion) + return fmt.Errorf("peer [%x]: protocol version mismatch %d != %d", peer.ID(), peerVersion, ProtocolVersion) } // only version is mandatory, subsequent parameters are optional @@ -107,34 +107,34 @@ func (p *Peer) handshake() error { if err == nil { pow := math.Float64frombits(powRaw) if math.IsInf(pow, 0) || math.IsNaN(pow) || pow < 0.0 { - return fmt.Errorf("peer [%x] sent bad status message: invalid pow", p.ID()) + return fmt.Errorf("peer [%x] sent bad status message: invalid pow", peer.ID()) } - p.powRequirement = pow + peer.powRequirement = pow var bloom []byte err = s.Decode(&bloom) if err == nil { sz := len(bloom) if sz != bloomFilterSize && sz != 0 { - return fmt.Errorf("peer [%x] sent bad status message: wrong bloom filter size %d", p.ID(), sz) + return fmt.Errorf("peer [%x] sent bad status message: wrong bloom filter size %d", peer.ID(), sz) } if isFullNode(bloom) { - p.bloomFilter = nil + peer.bloomFilter = nil } else { - p.bloomFilter = bloom + peer.bloomFilter = bloom } } } if err := <-errc; err != nil { - return fmt.Errorf("peer [%x] failed to send status packet: %v", p.ID(), err) + return fmt.Errorf("peer [%x] failed to send status packet: %v", peer.ID(), err) } return nil } // update executes periodic operations on the peer, including message transmission // and expiration. -func (p *Peer) update() { +func (peer *Peer) update() { // Start the tickers for the updates expire := time.NewTicker(expirationCycle) transmit := time.NewTicker(transmissionCycle) @@ -143,15 +143,15 @@ func (p *Peer) update() { for { select { case <-expire.C: - p.expire() + peer.expire() case <-transmit.C: - if err := p.broadcast(); err != nil { - log.Trace("broadcast failed", "reason", err, "peer", p.ID()) + if err := peer.broadcast(); err != nil { + log.Trace("broadcast failed", "reason", err, "peer", peer.ID()) return } - case <-p.quit: + case <-peer.quit: return } } @@ -185,24 +185,24 @@ func (peer *Peer) expire() { // broadcast iterates over the collection of envelopes and transmits yet unknown // ones over the network. -func (p *Peer) broadcast() error { - envelopes := p.host.Envelopes() +func (peer *Peer) broadcast() error { + envelopes := peer.host.Envelopes() bundle := make([]*Envelope, 0, len(envelopes)) for _, envelope := range envelopes { - if !p.marked(envelope) && envelope.PoW() >= p.powRequirement && p.bloomMatch(envelope) { + if !peer.marked(envelope) && envelope.PoW() >= peer.powRequirement && peer.bloomMatch(envelope) { bundle = append(bundle, envelope) } } if len(bundle) > 0 { // transmit the batch of envelopes - if err := p2p.Send(p.ws, messagesCode, bundle); err != nil { + if err := p2p.Send(peer.ws, messagesCode, bundle); err != nil { return err } // mark envelopes only if they were successfully sent for _, e := range bundle { - p.mark(e) + peer.mark(e) } log.Trace("broadcast", "num. messages", len(bundle)) @@ -210,25 +210,26 @@ func (p *Peer) broadcast() error { return nil } -func (p *Peer) ID() []byte { - id := p.peer.ID() +// ID returns a peer's id +func (peer *Peer) ID() []byte { + id := peer.peer.ID() return id[:] } -func (p *Peer) notifyAboutPowRequirementChange(pow float64) error { +func (peer *Peer) notifyAboutPowRequirementChange(pow float64) error { i := math.Float64bits(pow) - return p2p.Send(p.ws, powRequirementCode, i) + return p2p.Send(peer.ws, powRequirementCode, i) } -func (p *Peer) notifyAboutBloomFilterChange(bloom []byte) error { - return p2p.Send(p.ws, bloomFilterExCode, bloom) +func (peer *Peer) notifyAboutBloomFilterChange(bloom []byte) error { + return p2p.Send(peer.ws, bloomFilterExCode, bloom) } -func (p *Peer) bloomMatch(env *Envelope) bool { - if p.bloomFilter == nil { +func (peer *Peer) bloomMatch(env *Envelope) bool { + if peer.bloomFilter == nil { // no filter - full node, accepts all envelops return true } - return bloomFilterMatch(p.bloomFilter, env.Bloom()) + return bloomFilterMatch(peer.bloomFilter, env.Bloom()) } diff --git a/whisper/whisperv6/peer_test.go b/whisper/whisperv6/peer_test.go index 8a65cb714..b0709c927 100644 --- a/whisper/whisperv6/peer_test.go +++ b/whisper/whisperv6/peer_test.go @@ -33,7 +33,7 @@ import ( "github.com/ethereum/go-ethereum/p2p/nat" ) -var keys []string = []string{ +var keys = []string{ "d49dcf37238dc8a7aac57dc61b9fee68f0a97f062968978b9fafa7d1033d03a9", "73fd6143c48e80ed3c56ea159fe7494a0b6b393a392227b422f4c3e8f1b54f98", "119dd32adb1daa7a4c7bf77f847fb28730785aa92947edf42fdd997b54de40dc", @@ -80,17 +80,17 @@ type TestNode struct { shh *Whisper id *ecdsa.PrivateKey server *p2p.Server - filerId string + filerID string } var result TestData var nodes [NumNodes]*TestNode -var sharedKey []byte = []byte("some arbitrary data here") -var sharedTopic TopicType = TopicType{0xF, 0x1, 0x2, 0} -var expectedMessage []byte = []byte("per rectum ad astra") +var sharedKey = []byte("some arbitrary data here") +var sharedTopic = TopicType{0xF, 0x1, 0x2, 0} +var expectedMessage = []byte("per rectum ad astra") var masterBloomFilter []byte var masterPow = 0.00000001 -var round int = 1 +var round = 1 func TestSimulation(t *testing.T) { // create a chain of whisper nodes, @@ -186,7 +186,7 @@ func initialize(t *testing.T) { topics = append(topics, sharedTopic) f := Filter{KeySym: sharedKey} f.Topics = [][]byte{topics[0][:]} - node.filerId, err = node.shh.Subscribe(&f) + node.filerID, err = node.shh.Subscribe(&f) if err != nil { t.Fatalf("failed to install the filter: %s.", err) } @@ -199,9 +199,9 @@ func initialize(t *testing.T) { name := common.MakeName("whisper-go", "2.0") var peers []*discover.Node if i > 0 { - peerNodeId := nodes[i-1].id + peerNodeID := nodes[i-1].id peerPort := uint16(port - 1) - peerNode := discover.PubkeyID(&peerNodeId.PublicKey) + peerNode := discover.PubkeyID(&peerNodeID.PublicKey) peer := discover.NewNode(peerNode, ip, peerPort, peerPort) peers = append(peers, peer) } @@ -238,7 +238,7 @@ func stopServers() { for i := 0; i < NumNodes; i++ { n := nodes[i] if n != nil { - n.shh.Unsubscribe(n.filerId) + n.shh.Unsubscribe(n.filerID) n.shh.Stop() n.server.Stop() } @@ -260,9 +260,9 @@ func checkPropagation(t *testing.T, includingNodeZero bool) { for j := 0; j < iterations; j++ { for i := first; i < NumNodes; i++ { - f := nodes[i].shh.GetFilter(nodes[i].filerId) + f := nodes[i].shh.GetFilter(nodes[i].filerID) if f == nil { - t.Fatalf("failed to get filterId %s from node %d, round %d.", nodes[i].filerId, i, round) + t.Fatalf("failed to get filterId %s from node %d, round %d.", nodes[i].filerID, i, round) } mail := f.Retrieve() @@ -281,7 +281,7 @@ func checkPropagation(t *testing.T, includingNodeZero bool) { t.Fatalf("Test was not complete: timeout %d seconds.", iterations*cycle/1000) if !includingNodeZero { - f := nodes[0].shh.GetFilter(nodes[0].filerId) + f := nodes[0].shh.GetFilter(nodes[0].filerID) if f != nil { t.Fatalf("node zero received a message with low PoW.") } @@ -348,7 +348,7 @@ func sendMsg(t *testing.T, expected bool, id int) { opt.Payload = opt.Payload[1:] } - msg, err := NewSentMessage(&opt) + msg, err := newSentMessage(&opt) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -372,7 +372,7 @@ func TestPeerBasic(t *testing.T) { } params.PoW = 0.001 - msg, err := NewSentMessage(params) + msg, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } diff --git a/whisper/whisperv6/topic.go b/whisper/whisperv6/topic.go index bf5da01e3..4dd8f283c 100644 --- a/whisper/whisperv6/topic.go +++ b/whisper/whisperv6/topic.go @@ -23,11 +23,13 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" ) -// Topic represents a cryptographically secure, probabilistic partial +// TopicType represents a cryptographically secure, probabilistic partial // classifications of a message, determined as the first (left) 4 bytes of the // SHA3 hash of some arbitrary data given by the original author of the message. type TopicType [TopicLength]byte +// BytesToTopic converts from the byte array representation of a topic +// into the TopicType type. func BytesToTopic(b []byte) (t TopicType) { sz := TopicLength if x := len(b); x < TopicLength { diff --git a/whisper/whisperv6/whisper.go b/whisper/whisperv6/whisper.go index bc89aadcc..1b440a7f9 100644 --- a/whisper/whisperv6/whisper.go +++ b/whisper/whisperv6/whisper.go @@ -39,6 +39,8 @@ import ( set "gopkg.in/fatih/set.v0" ) +// Statistics holds several message-related counter for analytics +// purposes. type Statistics struct { messagesCleared int memoryCleared int @@ -130,8 +132,8 @@ func New(cfg *Config) *Whisper { } // MinPow returns the PoW value required by this node. -func (w *Whisper) MinPow() float64 { - val, exist := w.settings.Load(minPowIdx) +func (whisper *Whisper) MinPow() float64 { + val, exist := whisper.settings.Load(minPowIdx) if !exist || val == nil { return DefaultMinimumPoW } @@ -146,8 +148,8 @@ func (w *Whisper) MinPow() float64 { // MinPowTolerance returns the value of minimum PoW which is tolerated for a limited // time after PoW was changed. If sufficient time have elapsed or no change of PoW // have ever occurred, the return value will be the same as return value of MinPow(). -func (w *Whisper) MinPowTolerance() float64 { - val, exist := w.settings.Load(minPowToleranceIdx) +func (whisper *Whisper) MinPowTolerance() float64 { + val, exist := whisper.settings.Load(minPowToleranceIdx) if !exist || val == nil { return DefaultMinimumPoW } @@ -158,8 +160,8 @@ func (w *Whisper) MinPowTolerance() float64 { // 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 *Whisper) BloomFilter() []byte { - val, exist := w.settings.Load(bloomFilterIdx) +func (whisper *Whisper) BloomFilter() []byte { + val, exist := whisper.settings.Load(bloomFilterIdx) if !exist || val == nil { return nil } @@ -170,8 +172,8 @@ func (w *Whisper) BloomFilter() []byte { // time after new bloom was advertised to the peers. If sufficient time have elapsed // or no change of bloom filter have ever occurred, the return value will be the same // as return value of BloomFilter(). -func (w *Whisper) BloomFilterTolerance() []byte { - val, exist := w.settings.Load(bloomFilterToleranceIdx) +func (whisper *Whisper) BloomFilterTolerance() []byte { + val, exist := whisper.settings.Load(bloomFilterToleranceIdx) if !exist || val == nil { return nil } @@ -179,24 +181,24 @@ func (w *Whisper) BloomFilterTolerance() []byte { } // MaxMessageSize returns the maximum accepted message size. -func (w *Whisper) MaxMessageSize() uint32 { - val, _ := w.settings.Load(maxMsgSizeIdx) +func (whisper *Whisper) MaxMessageSize() uint32 { + val, _ := whisper.settings.Load(maxMsgSizeIdx) return val.(uint32) } // Overflow returns an indication if the message queue is full. -func (w *Whisper) Overflow() bool { - val, _ := w.settings.Load(overflowIdx) +func (whisper *Whisper) Overflow() bool { + val, _ := whisper.settings.Load(overflowIdx) return val.(bool) } // APIs returns the RPC descriptors the Whisper implementation offers -func (w *Whisper) APIs() []rpc.API { +func (whisper *Whisper) APIs() []rpc.API { return []rpc.API{ { Namespace: ProtocolName, Version: ProtocolVersionStr, - Service: NewPublicWhisperAPI(w), + Service: NewPublicWhisperAPI(whisper), Public: true, }, } @@ -204,31 +206,31 @@ func (w *Whisper) APIs() []rpc.API { // RegisterServer registers MailServer interface. // MailServer will process all the incoming messages with p2pRequestCode. -func (w *Whisper) RegisterServer(server MailServer) { - w.mailServer = server +func (whisper *Whisper) RegisterServer(server MailServer) { + whisper.mailServer = server } // Protocols returns the whisper sub-protocols ran by this particular client. -func (w *Whisper) Protocols() []p2p.Protocol { - return []p2p.Protocol{w.protocol} +func (whisper *Whisper) Protocols() []p2p.Protocol { + return []p2p.Protocol{whisper.protocol} } // Version returns the whisper sub-protocols version number. -func (w *Whisper) Version() uint { - return w.protocol.Version +func (whisper *Whisper) Version() uint { + return whisper.protocol.Version } // SetMaxMessageSize sets the maximal message size allowed by this node -func (w *Whisper) SetMaxMessageSize(size uint32) error { +func (whisper *Whisper) SetMaxMessageSize(size uint32) error { if size > MaxMessageSize { return fmt.Errorf("message size too large [%d>%d]", size, MaxMessageSize) } - w.settings.Store(maxMsgSizeIdx, size) + whisper.settings.Store(maxMsgSizeIdx, size) return nil } // SetBloomFilter sets the new bloom filter -func (w *Whisper) SetBloomFilter(bloom []byte) error { +func (whisper *Whisper) SetBloomFilter(bloom []byte) error { if len(bloom) != bloomFilterSize { return fmt.Errorf("invalid bloom filter size: %d", len(bloom)) } @@ -236,45 +238,45 @@ func (w *Whisper) SetBloomFilter(bloom []byte) error { b := make([]byte, bloomFilterSize) copy(b, bloom) - w.settings.Store(bloomFilterIdx, b) - w.notifyPeersAboutBloomFilterChange(b) + whisper.settings.Store(bloomFilterIdx, b) + whisper.notifyPeersAboutBloomFilterChange(b) go func() { // allow some time before all the peers have processed the notification - time.Sleep(time.Duration(w.syncAllowance) * time.Second) - w.settings.Store(bloomFilterToleranceIdx, b) + time.Sleep(time.Duration(whisper.syncAllowance) * time.Second) + whisper.settings.Store(bloomFilterToleranceIdx, b) }() return nil } // SetMinimumPoW sets the minimal PoW required by this node -func (w *Whisper) SetMinimumPoW(val float64) error { +func (whisper *Whisper) SetMinimumPoW(val float64) error { if val < 0.0 { return fmt.Errorf("invalid PoW: %f", val) } - w.settings.Store(minPowIdx, val) - w.notifyPeersAboutPowRequirementChange(val) + whisper.settings.Store(minPowIdx, val) + whisper.notifyPeersAboutPowRequirementChange(val) go func() { // allow some time before all the peers have processed the notification - time.Sleep(time.Duration(w.syncAllowance) * time.Second) - w.settings.Store(minPowToleranceIdx, val) + time.Sleep(time.Duration(whisper.syncAllowance) * time.Second) + whisper.settings.Store(minPowToleranceIdx, val) }() return nil } -// SetMinimumPoW sets the minimal PoW in test environment -func (w *Whisper) SetMinimumPowTest(val float64) { - w.settings.Store(minPowIdx, val) - w.notifyPeersAboutPowRequirementChange(val) - w.settings.Store(minPowToleranceIdx, val) +// SetMinimumPowTest sets the minimal PoW in test environment +func (whisper *Whisper) SetMinimumPowTest(val float64) { + whisper.settings.Store(minPowIdx, val) + whisper.notifyPeersAboutPowRequirementChange(val) + whisper.settings.Store(minPowToleranceIdx, val) } -func (w *Whisper) notifyPeersAboutPowRequirementChange(pow float64) { - arr := w.getPeers() +func (whisper *Whisper) notifyPeersAboutPowRequirementChange(pow float64) { + arr := whisper.getPeers() for _, p := range arr { err := p.notifyAboutPowRequirementChange(pow) if err != nil { @@ -287,8 +289,8 @@ func (w *Whisper) notifyPeersAboutPowRequirementChange(pow float64) { } } -func (w *Whisper) notifyPeersAboutBloomFilterChange(bloom []byte) { - arr := w.getPeers() +func (whisper *Whisper) notifyPeersAboutBloomFilterChange(bloom []byte) { + arr := whisper.getPeers() for _, p := range arr { err := p.notifyAboutBloomFilterChange(bloom) if err != nil { @@ -301,23 +303,23 @@ func (w *Whisper) notifyPeersAboutBloomFilterChange(bloom []byte) { } } -func (w *Whisper) getPeers() []*Peer { - arr := make([]*Peer, len(w.peers)) +func (whisper *Whisper) getPeers() []*Peer { + arr := make([]*Peer, len(whisper.peers)) i := 0 - w.peerMu.Lock() - for p := range w.peers { + whisper.peerMu.Lock() + for p := range whisper.peers { arr[i] = p i++ } - w.peerMu.Unlock() + whisper.peerMu.Unlock() return arr } // getPeer retrieves peer by ID -func (w *Whisper) getPeer(peerID []byte) (*Peer, error) { - w.peerMu.Lock() - defer w.peerMu.Unlock() - for p := range w.peers { +func (whisper *Whisper) getPeer(peerID []byte) (*Peer, error) { + whisper.peerMu.Lock() + defer whisper.peerMu.Unlock() + for p := range whisper.peers { id := p.peer.ID() if bytes.Equal(peerID, id[:]) { return p, nil @@ -328,8 +330,8 @@ func (w *Whisper) getPeer(peerID []byte) (*Peer, error) { // AllowP2PMessagesFromPeer marks specific peer trusted, // which will allow it to send historic (expired) messages. -func (w *Whisper) AllowP2PMessagesFromPeer(peerID []byte) error { - p, err := w.getPeer(peerID) +func (whisper *Whisper) AllowP2PMessagesFromPeer(peerID []byte) error { + p, err := whisper.getPeer(peerID) if err != nil { return err } @@ -342,8 +344,8 @@ func (w *Whisper) AllowP2PMessagesFromPeer(peerID []byte) error { // 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 *Whisper) RequestHistoricMessages(peerID []byte, envelope *Envelope) error { - p, err := w.getPeer(peerID) +func (whisper *Whisper) RequestHistoricMessages(peerID []byte, envelope *Envelope) error { + p, err := whisper.getPeer(peerID) if err != nil { return err } @@ -352,22 +354,22 @@ func (w *Whisper) RequestHistoricMessages(peerID []byte, envelope *Envelope) err } // SendP2PMessage sends a peer-to-peer message to a specific peer. -func (w *Whisper) SendP2PMessage(peerID []byte, envelope *Envelope) error { - p, err := w.getPeer(peerID) +func (whisper *Whisper) SendP2PMessage(peerID []byte, envelope *Envelope) error { + p, err := whisper.getPeer(peerID) if err != nil { return err } - return w.SendP2PDirect(p, envelope) + return whisper.SendP2PDirect(p, envelope) } // SendP2PDirect sends a peer-to-peer message to a specific peer. -func (w *Whisper) SendP2PDirect(peer *Peer, envelope *Envelope) error { +func (whisper *Whisper) SendP2PDirect(peer *Peer, envelope *Envelope) error { return p2p.Send(peer.ws, p2pMessageCode, envelope) } // NewKeyPair generates a new cryptographic identity for the client, and injects // it into the known identities for message decryption. Returns ID of the new key pair. -func (w *Whisper) NewKeyPair() (string, error) { +func (whisper *Whisper) NewKeyPair() (string, error) { key, err := crypto.GenerateKey() if err != nil || !validatePrivateKey(key) { key, err = crypto.GenerateKey() // retry once @@ -384,55 +386,55 @@ func (w *Whisper) NewKeyPair() (string, error) { return "", fmt.Errorf("failed to generate ID: %s", err) } - w.keyMu.Lock() - defer w.keyMu.Unlock() + whisper.keyMu.Lock() + defer whisper.keyMu.Unlock() - if w.privateKeys[id] != nil { + if whisper.privateKeys[id] != nil { return "", fmt.Errorf("failed to generate unique ID") } - w.privateKeys[id] = key + whisper.privateKeys[id] = key return id, nil } // DeleteKeyPair deletes the specified key if it exists. -func (w *Whisper) DeleteKeyPair(key string) bool { - w.keyMu.Lock() - defer w.keyMu.Unlock() +func (whisper *Whisper) DeleteKeyPair(key string) bool { + whisper.keyMu.Lock() + defer whisper.keyMu.Unlock() - if w.privateKeys[key] != nil { - delete(w.privateKeys, key) + if whisper.privateKeys[key] != nil { + delete(whisper.privateKeys, key) return true } return false } // AddKeyPair imports a asymmetric private key and returns it identifier. -func (w *Whisper) AddKeyPair(key *ecdsa.PrivateKey) (string, error) { +func (whisper *Whisper) AddKeyPair(key *ecdsa.PrivateKey) (string, error) { id, err := GenerateRandomID() if err != nil { return "", fmt.Errorf("failed to generate ID: %s", err) } - w.keyMu.Lock() - w.privateKeys[id] = key - w.keyMu.Unlock() + whisper.keyMu.Lock() + whisper.privateKeys[id] = key + whisper.keyMu.Unlock() return id, nil } // HasKeyPair checks if the the whisper node is configured with the private key // of the specified public pair. -func (w *Whisper) HasKeyPair(id string) bool { - w.keyMu.RLock() - defer w.keyMu.RUnlock() - return w.privateKeys[id] != nil +func (whisper *Whisper) HasKeyPair(id string) bool { + whisper.keyMu.RLock() + defer whisper.keyMu.RUnlock() + return whisper.privateKeys[id] != nil } // GetPrivateKey retrieves the private key of the specified identity. -func (w *Whisper) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) { - w.keyMu.RLock() - defer w.keyMu.RUnlock() - key := w.privateKeys[id] +func (whisper *Whisper) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) { + whisper.keyMu.RLock() + defer whisper.keyMu.RUnlock() + key := whisper.privateKeys[id] if key == nil { return nil, fmt.Errorf("invalid id") } @@ -441,7 +443,7 @@ func (w *Whisper) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) { // GenerateSymKey generates a random symmetric key and stores it under id, // which is then returned. Will be used in the future for session key exchange. -func (w *Whisper) GenerateSymKey() (string, error) { +func (whisper *Whisper) GenerateSymKey() (string, error) { key := make([]byte, aesKeyLength) _, err := crand.Read(key) if err != nil { @@ -455,18 +457,18 @@ func (w *Whisper) GenerateSymKey() (string, error) { return "", fmt.Errorf("failed to generate ID: %s", err) } - w.keyMu.Lock() - defer w.keyMu.Unlock() + whisper.keyMu.Lock() + defer whisper.keyMu.Unlock() - if w.symKeys[id] != nil { + if whisper.symKeys[id] != nil { return "", fmt.Errorf("failed to generate unique ID") } - w.symKeys[id] = key + whisper.symKeys[id] = key return id, nil } // AddSymKeyDirect stores the key, and returns its id. -func (w *Whisper) AddSymKeyDirect(key []byte) (string, error) { +func (whisper *Whisper) AddSymKeyDirect(key []byte) (string, error) { if len(key) != aesKeyLength { return "", fmt.Errorf("wrong key size: %d", len(key)) } @@ -476,23 +478,23 @@ func (w *Whisper) AddSymKeyDirect(key []byte) (string, error) { return "", fmt.Errorf("failed to generate ID: %s", err) } - w.keyMu.Lock() - defer w.keyMu.Unlock() + whisper.keyMu.Lock() + defer whisper.keyMu.Unlock() - if w.symKeys[id] != nil { + if whisper.symKeys[id] != nil { return "", fmt.Errorf("failed to generate unique ID") } - w.symKeys[id] = key + whisper.symKeys[id] = key return id, nil } // AddSymKeyFromPassword generates the key from password, stores it, and returns its id. -func (w *Whisper) AddSymKeyFromPassword(password string) (string, error) { +func (whisper *Whisper) AddSymKeyFromPassword(password string) (string, error) { id, err := GenerateRandomID() if err != nil { return "", fmt.Errorf("failed to generate ID: %s", err) } - if w.HasSymKey(id) { + if whisper.HasSymKey(id) { return "", fmt.Errorf("failed to generate unique ID") } @@ -503,59 +505,59 @@ func (w *Whisper) AddSymKeyFromPassword(password string) (string, error) { return "", err } - w.keyMu.Lock() - defer w.keyMu.Unlock() + whisper.keyMu.Lock() + defer whisper.keyMu.Unlock() // double check is necessary, because deriveKeyMaterial() is very slow - if w.symKeys[id] != nil { + if whisper.symKeys[id] != nil { return "", fmt.Errorf("critical error: failed to generate unique ID") } - w.symKeys[id] = derived + whisper.symKeys[id] = derived return id, nil } // HasSymKey returns true if there is a key associated with the given id. // Otherwise returns false. -func (w *Whisper) HasSymKey(id string) bool { - w.keyMu.RLock() - defer w.keyMu.RUnlock() - return w.symKeys[id] != nil +func (whisper *Whisper) HasSymKey(id string) bool { + whisper.keyMu.RLock() + defer whisper.keyMu.RUnlock() + return whisper.symKeys[id] != nil } // DeleteSymKey deletes the key associated with the name string if it exists. -func (w *Whisper) DeleteSymKey(id string) bool { - w.keyMu.Lock() - defer w.keyMu.Unlock() - if w.symKeys[id] != nil { - delete(w.symKeys, id) +func (whisper *Whisper) DeleteSymKey(id string) bool { + whisper.keyMu.Lock() + defer whisper.keyMu.Unlock() + if whisper.symKeys[id] != nil { + delete(whisper.symKeys, id) return true } return false } // GetSymKey returns the symmetric key associated with the given id. -func (w *Whisper) GetSymKey(id string) ([]byte, error) { - w.keyMu.RLock() - defer w.keyMu.RUnlock() - if w.symKeys[id] != nil { - return w.symKeys[id], nil +func (whisper *Whisper) GetSymKey(id string) ([]byte, error) { + whisper.keyMu.RLock() + defer whisper.keyMu.RUnlock() + if whisper.symKeys[id] != nil { + return whisper.symKeys[id], nil } return nil, fmt.Errorf("non-existent key ID") } // Subscribe installs a new message handler used for filtering, decrypting // and subsequent storing of incoming messages. -func (w *Whisper) Subscribe(f *Filter) (string, error) { - s, err := w.filters.Install(f) +func (whisper *Whisper) Subscribe(f *Filter) (string, error) { + s, err := whisper.filters.Install(f) if err == nil { - w.updateBloomFilter(f) + whisper.updateBloomFilter(f) } return s, err } // updateBloomFilter recalculates the new value of bloom filter, // and informs the peers if necessary. -func (w *Whisper) updateBloomFilter(f *Filter) { +func (whisper *Whisper) updateBloomFilter(f *Filter) { aggregate := make([]byte, bloomFilterSize) for _, t := range f.Topics { top := BytesToTopic(t) @@ -563,21 +565,21 @@ func (w *Whisper) updateBloomFilter(f *Filter) { aggregate = addBloom(aggregate, b) } - if !bloomFilterMatch(w.BloomFilter(), aggregate) { + if !bloomFilterMatch(whisper.BloomFilter(), aggregate) { // existing bloom filter must be updated - aggregate = addBloom(w.BloomFilter(), aggregate) - w.SetBloomFilter(aggregate) + aggregate = addBloom(whisper.BloomFilter(), aggregate) + whisper.SetBloomFilter(aggregate) } } // GetFilter returns the filter by id. -func (w *Whisper) GetFilter(id string) *Filter { - return w.filters.Get(id) +func (whisper *Whisper) GetFilter(id string) *Filter { + return whisper.filters.Get(id) } // Unsubscribe removes an installed message handler. -func (w *Whisper) Unsubscribe(id string) error { - ok := w.filters.Uninstall(id) +func (whisper *Whisper) Unsubscribe(id string) error { + ok := whisper.filters.Uninstall(id) if !ok { return fmt.Errorf("Unsubscribe: Invalid ID") } @@ -586,8 +588,8 @@ func (w *Whisper) Unsubscribe(id string) error { // Send injects a message into the whisper send queue, to be distributed in the // network in the coming cycles. -func (w *Whisper) Send(envelope *Envelope) error { - ok, err := w.add(envelope) +func (whisper *Whisper) Send(envelope *Envelope) error { + ok, err := whisper.add(envelope) if err != nil { return err } @@ -599,13 +601,13 @@ func (w *Whisper) Send(envelope *Envelope) error { // Start implements node.Service, starting the background data propagation thread // of the Whisper protocol. -func (w *Whisper) Start(*p2p.Server) error { +func (whisper *Whisper) Start(*p2p.Server) error { log.Info("started whisper v." + ProtocolVersionStr) - go w.update() + go whisper.update() numCPU := runtime.NumCPU() for i := 0; i < numCPU; i++ { - go w.processQueue() + go whisper.processQueue() } return nil @@ -613,26 +615,26 @@ func (w *Whisper) Start(*p2p.Server) error { // Stop implements node.Service, stopping the background data propagation thread // of the Whisper protocol. -func (w *Whisper) Stop() error { - close(w.quit) +func (whisper *Whisper) Stop() error { + close(whisper.quit) log.Info("whisper stopped") return nil } // HandlePeer is called by the underlying P2P layer when the whisper sub-protocol // connection is negotiated. -func (wh *Whisper) HandlePeer(peer *p2p.Peer, rw p2p.MsgReadWriter) error { +func (whisper *Whisper) HandlePeer(peer *p2p.Peer, rw p2p.MsgReadWriter) error { // Create the new peer and start tracking it - whisperPeer := newPeer(wh, peer, rw) + whisperPeer := newPeer(whisper, peer, rw) - wh.peerMu.Lock() - wh.peers[whisperPeer] = struct{}{} - wh.peerMu.Unlock() + whisper.peerMu.Lock() + whisper.peers[whisperPeer] = struct{}{} + whisper.peerMu.Unlock() defer func() { - wh.peerMu.Lock() - delete(wh.peers, whisperPeer) - wh.peerMu.Unlock() + whisper.peerMu.Lock() + delete(whisper.peers, whisperPeer) + whisper.peerMu.Unlock() }() // Run the peer handshake and state updates @@ -642,11 +644,11 @@ func (wh *Whisper) HandlePeer(peer *p2p.Peer, rw p2p.MsgReadWriter) error { whisperPeer.start() defer whisperPeer.stop() - return wh.runMessageLoop(whisperPeer, rw) + return whisper.runMessageLoop(whisperPeer, rw) } // runMessageLoop reads and processes inbound messages directly to merge into client-global state. -func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { +func (whisper *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { for { // fetch the next packet packet, err := rw.ReadMsg() @@ -654,7 +656,7 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { log.Warn("message loop", "peer", p.peer.ID(), "err", err) return err } - if packet.Size > wh.MaxMessageSize() { + if packet.Size > whisper.MaxMessageSize() { log.Warn("oversized message received", "peer", p.peer.ID()) return errors.New("oversized message received") } @@ -673,7 +675,7 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { trouble := false for _, env := range envelopes { - cached, err := wh.add(env) + cached, err := whisper.add(env) if err != nil { trouble = true log.Error("bad envelope received, peer will be disconnected", "peer", p.peer.ID(), "err", err) @@ -726,17 +728,17 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { log.Warn("failed to decode direct message, peer will be disconnected", "peer", p.peer.ID(), "err", err) return errors.New("invalid direct message") } - wh.postEvent(&envelope, true) + whisper.postEvent(&envelope, true) } case p2pRequestCode: // Must be processed if mail server is implemented. Otherwise ignore. - if wh.mailServer != nil { + if whisper.mailServer != nil { var request Envelope if err := packet.Decode(&request); err != nil { log.Warn("failed to decode p2p request message, peer will be disconnected", "peer", p.peer.ID(), "err", err) return errors.New("invalid p2p request") } - wh.mailServer.DeliverMail(p, &request) + whisper.mailServer.DeliverMail(p, &request) } default: // New message types might be implemented in the future versions of Whisper. @@ -750,128 +752,126 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { // add inserts a new envelope into the message pool to be distributed within the // whisper network. It also inserts the envelope into the expiration pool at the // appropriate time-stamp. In case of error, connection should be dropped. -func (wh *Whisper) add(envelope *Envelope) (bool, error) { +func (whisper *Whisper) add(envelope *Envelope) (bool, error) { now := uint32(time.Now().Unix()) sent := envelope.Expiry - envelope.TTL if sent > now { if sent-DefaultSyncAllowance > now { return false, fmt.Errorf("envelope created in the future [%x]", envelope.Hash()) - } else { - // recalculate PoW, adjusted for the time difference, plus one second for latency - envelope.calculatePoW(sent - now + 1) } + // recalculate PoW, adjusted for the time difference, plus one second for latency + envelope.calculatePoW(sent - now + 1) } if envelope.Expiry < now { if envelope.Expiry+DefaultSyncAllowance*2 < now { return false, fmt.Errorf("very old message") - } else { - log.Debug("expired envelope dropped", "hash", envelope.Hash().Hex()) - return false, nil // drop envelope without error } + log.Debug("expired envelope dropped", "hash", envelope.Hash().Hex()) + return false, nil // drop envelope without error } - if uint32(envelope.size()) > wh.MaxMessageSize() { + if uint32(envelope.size()) > whisper.MaxMessageSize() { return false, fmt.Errorf("huge messages are not allowed [%x]", envelope.Hash()) } - if envelope.PoW() < wh.MinPow() { + if envelope.PoW() < whisper.MinPow() { // maybe the value was recently changed, and the peers did not adjust yet. // in this case the previous value is retrieved by MinPowTolerance() // for a short period of peer synchronization. - if envelope.PoW() < wh.MinPowTolerance() { + if envelope.PoW() < whisper.MinPowTolerance() { return false, fmt.Errorf("envelope with low PoW received: PoW=%f, hash=[%v]", envelope.PoW(), envelope.Hash().Hex()) } } - if !bloomFilterMatch(wh.BloomFilter(), envelope.Bloom()) { + if !bloomFilterMatch(whisper.BloomFilter(), envelope.Bloom()) { // maybe the value was recently changed, and the peers did not adjust yet. // in this case the previous value is retrieved by BloomFilterTolerance() // for a short period of peer synchronization. - if !bloomFilterMatch(wh.BloomFilterTolerance(), envelope.Bloom()) { + if !bloomFilterMatch(whisper.BloomFilterTolerance(), envelope.Bloom()) { return false, fmt.Errorf("envelope does not match bloom filter, hash=[%v], bloom: \n%x \n%x \n%x", - envelope.Hash().Hex(), wh.BloomFilter(), envelope.Bloom(), envelope.Topic) + envelope.Hash().Hex(), whisper.BloomFilter(), envelope.Bloom(), envelope.Topic) } } hash := envelope.Hash() - wh.poolMu.Lock() - _, alreadyCached := wh.envelopes[hash] + whisper.poolMu.Lock() + _, alreadyCached := whisper.envelopes[hash] if !alreadyCached { - wh.envelopes[hash] = envelope - if wh.expirations[envelope.Expiry] == nil { - wh.expirations[envelope.Expiry] = set.NewNonTS() + whisper.envelopes[hash] = envelope + if whisper.expirations[envelope.Expiry] == nil { + whisper.expirations[envelope.Expiry] = set.NewNonTS() } - if !wh.expirations[envelope.Expiry].Has(hash) { - wh.expirations[envelope.Expiry].Add(hash) + if !whisper.expirations[envelope.Expiry].Has(hash) { + whisper.expirations[envelope.Expiry].Add(hash) } } - wh.poolMu.Unlock() + whisper.poolMu.Unlock() if alreadyCached { log.Trace("whisper envelope already cached", "hash", envelope.Hash().Hex()) } else { log.Trace("cached whisper envelope", "hash", envelope.Hash().Hex()) - wh.statsMu.Lock() - wh.stats.memoryUsed += envelope.size() - wh.statsMu.Unlock() - wh.postEvent(envelope, false) // notify the local node about the new message - if wh.mailServer != nil { - wh.mailServer.Archive(envelope) + whisper.statsMu.Lock() + whisper.stats.memoryUsed += envelope.size() + whisper.statsMu.Unlock() + whisper.postEvent(envelope, false) // notify the local node about the new message + if whisper.mailServer != nil { + whisper.mailServer.Archive(envelope) } } return true, nil } // postEvent queues the message for further processing. -func (w *Whisper) postEvent(envelope *Envelope, isP2P bool) { +func (whisper *Whisper) postEvent(envelope *Envelope, isP2P bool) { if isP2P { - w.p2pMsgQueue <- envelope + whisper.p2pMsgQueue <- envelope } else { - w.checkOverflow() - w.messageQueue <- envelope + whisper.checkOverflow() + whisper.messageQueue <- envelope } } // checkOverflow checks if message queue overflow occurs and reports it if necessary. -func (w *Whisper) checkOverflow() { - queueSize := len(w.messageQueue) +func (whisper *Whisper) checkOverflow() { + queueSize := len(whisper.messageQueue) if queueSize == messageQueueLimit { - if !w.Overflow() { - w.settings.Store(overflowIdx, true) + if !whisper.Overflow() { + whisper.settings.Store(overflowIdx, true) log.Warn("message queue overflow") } } else if queueSize <= messageQueueLimit/2 { - if w.Overflow() { - w.settings.Store(overflowIdx, false) + if whisper.Overflow() { + whisper.settings.Store(overflowIdx, false) log.Warn("message queue overflow fixed (back to normal)") } } } // processQueue delivers the messages to the watchers during the lifetime of the whisper node. -func (w *Whisper) processQueue() { +func (whisper *Whisper) processQueue() { var e *Envelope for { select { - case <-w.quit: + case <-whisper.quit: return - case e = <-w.messageQueue: - w.filters.NotifyWatchers(e, false) + case e = <-whisper.messageQueue: + whisper.filters.NotifyWatchers(e, false) - case e = <-w.p2pMsgQueue: - w.filters.NotifyWatchers(e, true) + case e = <-whisper.p2pMsgQueue: + whisper.filters.NotifyWatchers(e, true) } } } // update loops until the lifetime of the whisper node, updating its internal // state by expiring stale messages from the pool. -func (w *Whisper) update() { +func (whisper *Whisper) update() { // Start a ticker to check for expirations expire := time.NewTicker(expirationCycle) @@ -879,9 +879,9 @@ func (w *Whisper) update() { for { select { case <-expire.C: - w.expire() + whisper.expire() - case <-w.quit: + case <-whisper.quit: return } } @@ -889,46 +889,46 @@ func (w *Whisper) update() { // expire iterates over all the expiration timestamps, removing all stale // messages from the pools. -func (w *Whisper) expire() { - w.poolMu.Lock() - defer w.poolMu.Unlock() +func (whisper *Whisper) expire() { + whisper.poolMu.Lock() + defer whisper.poolMu.Unlock() - w.statsMu.Lock() - defer w.statsMu.Unlock() - w.stats.reset() + whisper.statsMu.Lock() + defer whisper.statsMu.Unlock() + whisper.stats.reset() now := uint32(time.Now().Unix()) - for expiry, hashSet := range w.expirations { + for expiry, hashSet := range whisper.expirations { if expiry < now { // Dump all expired messages and remove timestamp hashSet.Each(func(v interface{}) bool { - sz := w.envelopes[v.(common.Hash)].size() - delete(w.envelopes, v.(common.Hash)) - w.stats.messagesCleared++ - w.stats.memoryCleared += sz - w.stats.memoryUsed -= sz + sz := whisper.envelopes[v.(common.Hash)].size() + delete(whisper.envelopes, v.(common.Hash)) + whisper.stats.messagesCleared++ + whisper.stats.memoryCleared += sz + whisper.stats.memoryUsed -= sz return true }) - w.expirations[expiry].Clear() - delete(w.expirations, expiry) + whisper.expirations[expiry].Clear() + delete(whisper.expirations, expiry) } } } // Stats returns the whisper node statistics. -func (w *Whisper) Stats() Statistics { - w.statsMu.Lock() - defer w.statsMu.Unlock() +func (whisper *Whisper) Stats() Statistics { + whisper.statsMu.Lock() + defer whisper.statsMu.Unlock() - return w.stats + return whisper.stats } // Envelopes retrieves all the messages currently pooled by the node. -func (w *Whisper) Envelopes() []*Envelope { - w.poolMu.RLock() - defer w.poolMu.RUnlock() +func (whisper *Whisper) Envelopes() []*Envelope { + whisper.poolMu.RLock() + defer whisper.poolMu.RUnlock() - all := make([]*Envelope, 0, len(w.envelopes)) - for _, envelope := range w.envelopes { + all := make([]*Envelope, 0, len(whisper.envelopes)) + for _, envelope := range whisper.envelopes { all = append(all, envelope) } return all @@ -936,13 +936,13 @@ func (w *Whisper) Envelopes() []*Envelope { // Messages iterates through all currently floating envelopes // and retrieves all the messages, that this filter could decrypt. -func (w *Whisper) Messages(id string) []*ReceivedMessage { +func (whisper *Whisper) Messages(id string) []*ReceivedMessage { result := make([]*ReceivedMessage, 0) - w.poolMu.RLock() - defer w.poolMu.RUnlock() + whisper.poolMu.RLock() + defer whisper.poolMu.RUnlock() - if filter := w.filters.Get(id); filter != nil { - for _, env := range w.envelopes { + if filter := whisper.filters.Get(id); filter != nil { + for _, env := range whisper.envelopes { msg := filter.processEnvelope(env) if msg != nil { result = append(result, msg) @@ -953,11 +953,11 @@ func (w *Whisper) Messages(id string) []*ReceivedMessage { } // isEnvelopeCached checks if envelope with specific hash has already been received and cached. -func (w *Whisper) isEnvelopeCached(hash common.Hash) bool { - w.poolMu.Lock() - defer w.poolMu.Unlock() +func (whisper *Whisper) isEnvelopeCached(hash common.Hash) bool { + whisper.poolMu.Lock() + defer whisper.poolMu.Unlock() - _, exist := w.envelopes[hash] + _, exist := whisper.envelopes[hash] return exist } @@ -1019,7 +1019,7 @@ func BytesToUintBigEndian(b []byte) (res uint64) { // GenerateRandomID generates a random string, which is then returned to be used as a key id func GenerateRandomID() (id string, err error) { - buf := make([]byte, keyIdSize) + buf := make([]byte, keyIDSize) _, err = crand.Read(buf) if err != nil { return "", err diff --git a/whisper/whisperv6/whisper_test.go b/whisper/whisperv6/whisper_test.go index fa14acb1b..23a289bfe 100644 --- a/whisper/whisperv6/whisper_test.go +++ b/whisper/whisperv6/whisper_test.go @@ -483,7 +483,7 @@ func TestExpiry(t *testing.T) { } params.TTL = 1 - msg, err := NewSentMessage(params) + msg, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -549,7 +549,7 @@ func TestCustomization(t *testing.T) { params.Topic = BytesToTopic(f.Topics[2]) params.PoW = smallPoW params.TTL = 3600 * 24 // one day - msg, err := NewSentMessage(params) + msg, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -570,7 +570,7 @@ func TestCustomization(t *testing.T) { } params.TTL++ - msg, err = NewSentMessage(params) + msg, err = newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -659,7 +659,7 @@ func TestSymmetricSendCycle(t *testing.T) { params.PoW = filter1.PoW params.WorkTime = 10 params.TTL = 50 - msg, err := NewSentMessage(params) + msg, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -737,7 +737,7 @@ func TestSymmetricSendWithoutAKey(t *testing.T) { params.PoW = filter.PoW params.WorkTime = 10 params.TTL = 50 - msg, err := NewSentMessage(params) + msg, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } @@ -803,7 +803,7 @@ func TestSymmetricSendKeyMismatch(t *testing.T) { params.PoW = filter.PoW params.WorkTime = 10 params.TTL = 50 - msg, err := NewSentMessage(params) + msg, err := newSentMessage(params) if err != nil { t.Fatalf("failed to create new message with seed %d: %s.", seed, err) } |