From fac0300f168d5485e356770b65b0d0035a9cd6f9 Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 15 Dec 2017 10:27:00 +0200 Subject: [PATCH 01/10] whisper: powRequirementCode introduced --- whisper/whisperv6/doc.go | 11 +++++++---- whisper/whisperv6/peer.go | 5 +++++ whisper/whisperv6/whisper.go | 20 ++++++++++++++++++-- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/whisper/whisperv6/doc.go b/whisper/whisperv6/doc.go index 64925ba48b86..2a4911d65aa3 100644 --- a/whisper/whisperv6/doc.go +++ b/whisper/whisperv6/doc.go @@ -40,10 +40,13 @@ const ( ProtocolVersionStr = "6.0" ProtocolName = "shh" - statusCode = 0 // used by whisper protocol - messagesCode = 1 // normal whisper message - p2pCode = 2 // peer-to-peer message (to be consumed by the peer, but not forwarded any further) - p2pRequestCode = 3 // peer-to-peer message, used by Dapp protocol + // whisper protocol message codes, according to EIP-627 + statusCode = 0 // used by whisper protocol + messagesCode = 1 // normal whisper message + powRequirementCode = 2 // PoW requirement + bloomFilterExCode = 3 // bloom filter exchange + p2pRequestCode = 126 // peer-to-peer message, used by Dapp protocol + p2pMessageCode = 127 // peer-to-peer message (to be consumed by the peer, but not forwarded any further) NumberOfMessageCodes = 128 paddingMask = byte(3) diff --git a/whisper/whisperv6/peer.go b/whisper/whisperv6/peer.go index ac7b3b12b659..c104720b3707 100644 --- a/whisper/whisperv6/peer.go +++ b/whisper/whisperv6/peer.go @@ -172,3 +172,8 @@ func (p *Peer) ID() []byte { id := p.peer.ID() return id[:] } + +func (p *Peer) notifyAboutPowRequirementChange(pow float64) error { + val := float32(pow) + return p2p.Send(p.ws, powRequirementCode, val) +} diff --git a/whisper/whisperv6/whisper.go b/whisper/whisperv6/whisper.go index d09baab3fddb..0aeba180f198 100644 --- a/whisper/whisperv6/whisper.go +++ b/whisper/whisperv6/whisper.go @@ -181,9 +181,25 @@ func (w *Whisper) SetMinimumPoW(val float64) error { return fmt.Errorf("invalid PoW: %f", val) } w.settings.Store(minPowIdx, val) + w.notifyPeersAboutPowRequirementChange(val) return nil } +func (w *Whisper) notifyPeersAboutPowRequirementChange(pow float64) { + w.peerMu.Lock() + defer w.peerMu.Unlock() + for p := range w.peers { + err := p.notifyAboutPowRequirementChange(pow) + if err != nil { + // allow one retry + err = p.notifyAboutPowRequirementChange(pow) + } + if err != nil { + fmt.Errorf("Error sending PoW notification to peer [%x]: %s", p.ID(), err) + } + } +} + // getPeer retrieves peer by ID func (w *Whisper) getPeer(peerID []byte) (*Peer, error) { w.peerMu.Lock() @@ -233,7 +249,7 @@ func (w *Whisper) SendP2PMessage(peerID []byte, envelope *Envelope) error { // SendP2PDirect sends a peer-to-peer message to a specific peer. func (w *Whisper) SendP2PDirect(peer *Peer, envelope *Envelope) error { - return p2p.Send(peer.ws, p2pCode, envelope) + return p2p.Send(peer.ws, p2pMessageCode, envelope) } // NewKeyPair generates a new cryptographic identity for the client, and injects @@ -528,7 +544,7 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { if cached { p.mark(&envelope) } - case p2pCode: + case p2pMessageCode: // peer-to-peer message, sent directly to peer bypassing PoW checks, etc. // this message is not supposed to be forwarded to other peers, and // therefore might not satisfy the PoW, expiry and other requirements. From 4bd592a70c64a65dd7a4152ba50a04d389cfdece Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 15 Dec 2017 14:33:24 +0200 Subject: [PATCH 02/10] whisper: powRequirementCode processing added --- whisper/whisperv6/peer.go | 28 +++++++++++++---------- whisper/whisperv6/whisper.go | 44 ++++++++++++++++++++++++++++-------- 2 files changed, 51 insertions(+), 21 deletions(-) diff --git a/whisper/whisperv6/peer.go b/whisper/whisperv6/peer.go index c104720b3707..29d13bc6efc7 100644 --- a/whisper/whisperv6/peer.go +++ b/whisper/whisperv6/peer.go @@ -18,6 +18,7 @@ package whisperv6 import ( "fmt" + "math" "time" "github.com/ethereum/go-ethereum/common" @@ -29,10 +30,12 @@ import ( // peer represents a whisper protocol peer connection. type Peer struct { - host *Whisper - peer *p2p.Peer - ws p2p.MsgReadWriter - trusted bool + host *Whisper + peer *p2p.Peer + ws p2p.MsgReadWriter + + trusted bool + powRequirement float64 known *set.Set // Messages already known by the peer to avoid wasting bandwidth @@ -42,12 +45,13 @@ type Peer struct { // newPeer creates a new whisper peer object, but does not run the handshake itself. func newPeer(host *Whisper, remote *p2p.Peer, rw p2p.MsgReadWriter) *Peer { return &Peer{ - host: host, - peer: remote, - ws: rw, - trusted: false, - known: set.New(), - quit: make(chan struct{}), + host: host, + peer: remote, + ws: rw, + trusted: false, + powRequirement: 0.0, + known: set.New(), + quit: make(chan struct{}), } } @@ -174,6 +178,6 @@ func (p *Peer) ID() []byte { } func (p *Peer) notifyAboutPowRequirementChange(pow float64) error { - val := float32(pow) - return p2p.Send(p.ws, powRequirementCode, val) + i := math.Float64bits(pow) + return p2p.Send(p.ws, powRequirementCode, i) } diff --git a/whisper/whisperv6/whisper.go b/whisper/whisperv6/whisper.go index 0aeba180f198..f52ee6e9ee6b 100644 --- a/whisper/whisperv6/whisper.go +++ b/whisper/whisperv6/whisper.go @@ -22,6 +22,7 @@ import ( crand "crypto/rand" "crypto/sha256" "fmt" + "math" "runtime" "sync" "time" @@ -30,6 +31,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p" + "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" "github.com/syndtr/goleveldb/leveldb/errors" "golang.org/x/crypto/pbkdf2" @@ -74,6 +76,8 @@ type Whisper struct { settings syncmap.Map // holds configuration settings that can be dynamically changed + reactionAllowance int // maximum time in seconds allowed to process the whisper-related messages + statsMu sync.Mutex // guard stats stats Statistics // Statistics of whisper node @@ -87,14 +91,15 @@ func New(cfg *Config) *Whisper { } whisper := &Whisper{ - privateKeys: make(map[string]*ecdsa.PrivateKey), - symKeys: make(map[string][]byte), - envelopes: make(map[common.Hash]*Envelope), - expirations: make(map[uint32]*set.SetNonTS), - peers: make(map[*Peer]struct{}), - messageQueue: make(chan *Envelope, messageQueueLimit), - p2pMsgQueue: make(chan *Envelope, messageQueueLimit), - quit: make(chan struct{}), + privateKeys: make(map[string]*ecdsa.PrivateKey), + symKeys: make(map[string][]byte), + envelopes: make(map[common.Hash]*Envelope), + expirations: make(map[uint32]*set.SetNonTS), + peers: make(map[*Peer]struct{}), + messageQueue: make(chan *Envelope, messageQueueLimit), + p2pMsgQueue: make(chan *Envelope, messageQueueLimit), + quit: make(chan struct{}), + reactionAllowance: SynchAllowance, } whisper.filters = NewFilters(whisper) @@ -180,8 +185,14 @@ func (w *Whisper) SetMinimumPoW(val float64) error { if val <= 0.0 { return fmt.Errorf("invalid PoW: %f", val) } - w.settings.Store(minPowIdx, val) w.notifyPeersAboutPowRequirementChange(val) + + go func() { + // allow some time before all the peers have processed the notification + time.Sleep(time.Duration(w.reactionAllowance) * time.Second) + w.settings.Store(minPowIdx, val) + }() + return nil } @@ -544,6 +555,21 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { if cached { p.mark(&envelope) } + case powRequirementCode: + s := rlp.NewStream(packet.Payload, uint64(packet.Size)) + i, err := s.Uint() + if err != nil { + log.Warn("failed to decode powRequirementCode message, peer will be disconnected", "peer", p.peer.ID(), "err", err) + return errors.New("invalid powRequirementCode message") + } + f := math.Float64frombits(i) + if math.IsInf(f, 0) || math.IsNaN(f) { + log.Warn("invalid value in powRequirementCode message, peer will be disconnected", "peer", p.peer.ID(), "err", err) + return errors.New("invalid value in powRequirementCode message") + } + p.powRequirement = float64(f) + case bloomFilterExCode: + // to be implemented case p2pMessageCode: // peer-to-peer message, sent directly to peer bypassing PoW checks, etc. // this message is not supposed to be forwarded to other peers, and From 8b96630df634afc23ddb91a2e8eea8980adba10a Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 15 Dec 2017 15:24:19 +0200 Subject: [PATCH 03/10] whisper: fixed the tests --- whisper/whisperv6/api.go | 2 +- whisper/whisperv6/peer_test.go | 2 +- whisper/whisperv6/whisper.go | 15 ++++++++++----- whisper/whisperv6/whisper_test.go | 14 +++++++------- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/whisper/whisperv6/api.go b/whisper/whisperv6/api.go index 3dddb69539f0..f6158b641c6e 100644 --- a/whisper/whisperv6/api.go +++ b/whisper/whisperv6/api.go @@ -118,7 +118,7 @@ func (api *PublicWhisperAPI) SetMaxMessageSize(ctx context.Context, size uint32) // SetMinPow sets the minimum PoW for a message before it is accepted. func (api *PublicWhisperAPI) SetMinPoW(ctx context.Context, pow float64) (bool, error) { - return true, api.w.SetMinimumPoW(pow) + return true, api.w.SetMinimumPoW(pow, false) } // MarkTrustedPeer marks a peer trusted. , which will allow it to send historic (expired) messages. diff --git a/whisper/whisperv6/peer_test.go b/whisper/whisperv6/peer_test.go index 39a4ab198069..d1c217da9564 100644 --- a/whisper/whisperv6/peer_test.go +++ b/whisper/whisperv6/peer_test.go @@ -114,7 +114,7 @@ func initialize(t *testing.T) { for i := 0; i < NumNodes; i++ { var node TestNode node.shh = New(&DefaultConfig) - node.shh.SetMinimumPoW(0.00000001) + node.shh.SetMinimumPoW(0.00000001, true) node.shh.Start(nil) topics := make([]TopicType, 0) topics = append(topics, sharedTopic) diff --git a/whisper/whisperv6/whisper.go b/whisper/whisperv6/whisper.go index f52ee6e9ee6b..ad1897e8022e 100644 --- a/whisper/whisperv6/whisper.go +++ b/whisper/whisperv6/whisper.go @@ -181,17 +181,22 @@ func (w *Whisper) SetMaxMessageSize(size uint32) error { } // SetMinimumPoW sets the minimal PoW required by this node -func (w *Whisper) SetMinimumPoW(val float64) error { +func (w *Whisper) SetMinimumPoW(val float64, testMode bool) error { if val <= 0.0 { return fmt.Errorf("invalid PoW: %f", val) } + w.notifyPeersAboutPowRequirementChange(val) - go func() { - // allow some time before all the peers have processed the notification - time.Sleep(time.Duration(w.reactionAllowance) * time.Second) + if testMode { w.settings.Store(minPowIdx, val) - }() + } else { + go func() { + // // allow some time before all the peers have processed the notification + time.Sleep(time.Duration(w.reactionAllowance) * time.Second) + w.settings.Store(minPowIdx, val) + }() + } return nil } diff --git a/whisper/whisperv6/whisper_test.go b/whisper/whisperv6/whisper_test.go index c8f3a9ed7464..009f50d3cb44 100644 --- a/whisper/whisperv6/whisper_test.go +++ b/whisper/whisperv6/whisper_test.go @@ -472,8 +472,8 @@ func TestExpiry(t *testing.T) { InitSingleTest() w := New(&DefaultConfig) - w.SetMinimumPoW(0.0000001) - defer w.SetMinimumPoW(DefaultMinimumPoW) + w.SetMinimumPoW(0.0000001, true) + defer w.SetMinimumPoW(DefaultMinimumPoW, true) w.Start(nil) defer w.Stop() @@ -529,7 +529,7 @@ func TestCustomization(t *testing.T) { InitSingleTest() w := New(&DefaultConfig) - defer w.SetMinimumPoW(DefaultMinimumPoW) + defer w.SetMinimumPoW(DefaultMinimumPoW, true) defer w.SetMaxMessageSize(DefaultMaxMessageSize) w.Start(nil) defer w.Stop() @@ -563,7 +563,7 @@ func TestCustomization(t *testing.T) { t.Fatalf("successfully sent envelope with PoW %.06f, false positive (seed %d).", env.PoW(), seed) } - w.SetMinimumPoW(smallPoW / 2) + w.SetMinimumPoW(smallPoW/2, true) err = w.Send(env) if err != nil { t.Fatalf("failed to send envelope with seed %d: %s.", seed, err) @@ -625,7 +625,7 @@ func TestSymmetricSendCycle(t *testing.T) { InitSingleTest() w := New(&DefaultConfig) - defer w.SetMinimumPoW(DefaultMinimumPoW) + defer w.SetMinimumPoW(DefaultMinimumPoW, true) defer w.SetMaxMessageSize(DefaultMaxMessageSize) w.Start(nil) defer w.Stop() @@ -714,7 +714,7 @@ func TestSymmetricSendWithoutAKey(t *testing.T) { InitSingleTest() w := New(&DefaultConfig) - defer w.SetMinimumPoW(DefaultMinimumPoW) + defer w.SetMinimumPoW(DefaultMinimumPoW, true) defer w.SetMaxMessageSize(DefaultMaxMessageSize) w.Start(nil) defer w.Stop() @@ -782,7 +782,7 @@ func TestSymmetricSendKeyMismatch(t *testing.T) { InitSingleTest() w := New(&DefaultConfig) - defer w.SetMinimumPoW(DefaultMinimumPoW) + defer w.SetMinimumPoW(DefaultMinimumPoW, true) defer w.SetMaxMessageSize(DefaultMaxMessageSize) w.Start(nil) defer w.Stop() From 1501a11750d7ec27e4df69abd453af2f84499655 Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 15 Dec 2017 17:59:14 +0200 Subject: [PATCH 04/10] whisper: test added - pow exchange protocol --- whisper/whisperv6/peer_test.go | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/whisper/whisperv6/peer_test.go b/whisper/whisperv6/peer_test.go index d1c217da9564..5fe35cec96e2 100644 --- a/whisper/whisperv6/peer_test.go +++ b/whisper/whisperv6/peer_test.go @@ -93,7 +93,8 @@ var expectedMessage []byte = []byte("per rectum ad astra") // 2. installs the filters with shared (predefined) parameters, // 3. each node sends a number of random (undecryptable) messages, // 4. first node sends one expected (decryptable) message, -// 5. checks if each node have received and decrypted exactly one message. +// 5. checks if each node have received and decrypted exactly one message, +// 6. sends protocol-level messages (powRequirementCode) and checks the new PoW requirement values. func TestSimulation(t *testing.T) { initialize(t) @@ -103,6 +104,7 @@ func TestSimulation(t *testing.T) { sendMsg(t, true, 0) checkPropagation(t) + powReqExchange(t) stopServers() } @@ -304,3 +306,33 @@ func TestPeerBasic(t *testing.T) { t.Fatalf("failed mark with seed %d.", seed) } } + +func powReqExchange(t *testing.T) { + for i, node := range nodes { + for peer, _ := range node.shh.peers { + if peer.powRequirement > 1000.0 { + t.Fatalf("node %d: one of the peers' pow requirement is too big (%f).", i, peer.powRequirement) + } + } + } + + const pow float64 = 7777777.0 + nodes[0].shh.SetMinimumPoW(pow, true) + time.Sleep(5 * time.Millisecond) + + cnt := 0 + for i, node := range nodes { + for peer, _ := range node.shh.peers { + if peer.peer.ID() == discover.PubkeyID(&nodes[0].id.PublicKey) { + cnt++ + if peer.powRequirement != pow { + t.Fatalf("node %d: failed to set the new pow requirement.", i) + } + } + } + } + + if cnt == 0 { + t.Fatalf("no matching peers found.") + } +} From 8e6fe2c9cfd141271029ee80d68feae41840a986 Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 15 Dec 2017 18:35:50 +0200 Subject: [PATCH 05/10] whisper: TestSimulation optimized --- whisper/whisperv6/peer_test.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/whisper/whisperv6/peer_test.go b/whisper/whisperv6/peer_test.go index 5fe35cec96e2..2c5aa468ab85 100644 --- a/whisper/whisperv6/peer_test.go +++ b/whisper/whisperv6/peer_test.go @@ -156,13 +156,18 @@ func initialize(t *testing.T) { }, } - err = node.server.Start() - if err != nil { - t.Fatalf("failed to start server %d.", i) - } - nodes[i] = &node } + + for i := 1; i < NumNodes; i++ { + go nodes[i].server.Start() + } + + // we need to wait until the first node actually starts + err = nodes[0].server.Start() + if err != nil { + t.Fatalf("failed to start the fisrt server.") + } } func stopServers() { From 0fec3e7f2ec142154d4b55ecc0dc087038666a3e Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 15 Dec 2017 18:47:22 +0200 Subject: [PATCH 06/10] whisper: test fix - wait for message delivery --- whisper/whisperv6/peer_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/whisper/whisperv6/peer_test.go b/whisper/whisperv6/peer_test.go index 2c5aa468ab85..7dd93238c8c5 100644 --- a/whisper/whisperv6/peer_test.go +++ b/whisper/whisperv6/peer_test.go @@ -323,7 +323,9 @@ func powReqExchange(t *testing.T) { const pow float64 = 7777777.0 nodes[0].shh.SetMinimumPoW(pow, true) - time.Sleep(5 * time.Millisecond) + + // wait until all the messages are delivered + time.Sleep(64 * time.Millisecond) cnt := 0 for i, node := range nodes { From c6f32a8c6088d575698b3b111ae052d98286a5e9 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 18 Dec 2017 17:37:08 +0200 Subject: [PATCH 07/10] whisper: respect the PoW requirement --- whisper/whisperv6/peer.go | 2 +- whisper/whisperv6/peer_test.go | 48 ++++++++++++++++++++++++---------- whisper/whisperv6/whisper.go | 5 +++- 3 files changed, 39 insertions(+), 16 deletions(-) diff --git a/whisper/whisperv6/peer.go b/whisper/whisperv6/peer.go index 29d13bc6efc7..f4611b8a71a6 100644 --- a/whisper/whisperv6/peer.go +++ b/whisper/whisperv6/peer.go @@ -156,7 +156,7 @@ func (p *Peer) broadcast() error { var cnt int envelopes := p.host.Envelopes() for _, envelope := range envelopes { - if !p.marked(envelope) { + if !p.marked(envelope) && envelope.PoW() >= p.powRequirement { err := p2p.Send(p.ws, messagesCode, envelope) if err != nil { return err diff --git a/whisper/whisperv6/peer_test.go b/whisper/whisperv6/peer_test.go index 7dd93238c8c5..40b4cc5eadcb 100644 --- a/whisper/whisperv6/peer_test.go +++ b/whisper/whisperv6/peer_test.go @@ -88,23 +88,31 @@ var sharedKey []byte = []byte("some arbitrary data here") var sharedTopic TopicType = TopicType{0xF, 0x1, 0x2, 0} var expectedMessage []byte = []byte("per rectum ad astra") -// This test does the following: -// 1. creates a chain of whisper nodes, -// 2. installs the filters with shared (predefined) parameters, -// 3. each node sends a number of random (undecryptable) messages, -// 4. first node sends one expected (decryptable) message, -// 5. checks if each node have received and decrypted exactly one message, -// 6. sends protocol-level messages (powRequirementCode) and checks the new PoW requirement values. func TestSimulation(t *testing.T) { + // create a chain of whisper nodes, + // installs the filters with shared (predefined) parameters initialize(t) + // each node sends a number of random (undecryptable) messages for i := 0; i < NumNodes; i++ { sendMsg(t, false, i) } + // node #0 sends one expected (decryptable) message sendMsg(t, true, 0) - checkPropagation(t) + + // check if each node have received and decrypted exactly one message + checkPropagation(t, true) + + // send protocol-level messages (powRequirementCode) and check the new PoW requirement values powReqExchange(t) + + // node #1 sends one expected (decryptable) message + sendMsg(t, true, 1) + + // check if each node (except node #0) have received and decrypted exactly one message + checkPropagation(t, false) + stopServers() } @@ -181,18 +189,21 @@ func stopServers() { } } -func checkPropagation(t *testing.T) { +func checkPropagation(t *testing.T, includingNodeZero bool) { if t.Failed() { return } - const cycle = 100 - const iterations = 100 + const cycle = 50 + const iterations = 200 - for j := 0; j < iterations; j++ { - time.Sleep(cycle * time.Millisecond) + first := 0 + if !includingNodeZero { + first = 1 + } - for i := 0; i < NumNodes; i++ { + for j := 0; j < iterations; j++ { + for i := first; i < NumNodes; i++ { f := nodes[i].shh.GetFilter(nodes[i].filerId) if f == nil { t.Fatalf("failed to get filterId %s from node %d.", nodes[i].filerId, i) @@ -207,9 +218,18 @@ func checkPropagation(t *testing.T) { return } } + + time.Sleep(cycle * time.Millisecond) } t.Fatalf("Test was not complete: timeout %d seconds.", iterations*cycle/1000) + + if !includingNodeZero { + f := nodes[0].shh.GetFilter(nodes[0].filerId) + if f != nil { + t.Fatalf("node zero received a message with low PoW.") + } + } } func validateMail(t *testing.T, index int, mail []*ReceivedMessage) bool { diff --git a/whisper/whisperv6/whisper.go b/whisper/whisperv6/whisper.go index ad1897e8022e..1cdea2aba398 100644 --- a/whisper/whisperv6/whisper.go +++ b/whisper/whisperv6/whisper.go @@ -638,7 +638,10 @@ func (wh *Whisper) add(envelope *Envelope) (bool, error) { if envelope.PoW() < wh.MinPow() { log.Debug("envelope with low PoW dropped", "PoW", envelope.PoW(), "hash", envelope.Hash().Hex()) - return false, nil // drop envelope without error + return false, nil // drop envelope without error for now + + // after the Status message will include the PoW requirement, it should return an error here: + //return false, fmt.Errorf("envelope with low PoW dropped: PoW=%f, hash=[%v]", envelope.PoW(), envelope.Hash().Hex()) } hash := envelope.Hash() From 04353a80f31628d72299308e851c46389cc80aa0 Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 20 Dec 2017 15:01:50 +0200 Subject: [PATCH 08/10] whisper: minor fixes --- whisper/whisperv6/peer_test.go | 4 ++-- whisper/whisperv6/whisper.go | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/whisper/whisperv6/peer_test.go b/whisper/whisperv6/peer_test.go index 40b4cc5eadcb..2c36fd7cb57b 100644 --- a/whisper/whisperv6/peer_test.go +++ b/whisper/whisperv6/peer_test.go @@ -334,7 +334,7 @@ func TestPeerBasic(t *testing.T) { func powReqExchange(t *testing.T) { for i, node := range nodes { - for peer, _ := range node.shh.peers { + for peer := range node.shh.peers { if peer.powRequirement > 1000.0 { t.Fatalf("node %d: one of the peers' pow requirement is too big (%f).", i, peer.powRequirement) } @@ -349,7 +349,7 @@ func powReqExchange(t *testing.T) { cnt := 0 for i, node := range nodes { - for peer, _ := range node.shh.peers { + for peer := range node.shh.peers { if peer.peer.ID() == discover.PubkeyID(&nodes[0].id.PublicKey) { cnt++ if peer.powRequirement != pow { diff --git a/whisper/whisperv6/whisper.go b/whisper/whisperv6/whisper.go index 1cdea2aba398..57b190368d8c 100644 --- a/whisper/whisperv6/whisper.go +++ b/whisper/whisperv6/whisper.go @@ -192,7 +192,7 @@ func (w *Whisper) SetMinimumPoW(val float64, testMode bool) error { w.settings.Store(minPowIdx, val) } else { go func() { - // // allow some time before all the peers have processed the notification + // allow some time before all the peers have processed the notification time.Sleep(time.Duration(w.reactionAllowance) * time.Second) w.settings.Store(minPowIdx, val) }() @@ -211,7 +211,7 @@ func (w *Whisper) notifyPeersAboutPowRequirementChange(pow float64) { err = p.notifyAboutPowRequirementChange(pow) } if err != nil { - fmt.Errorf("Error sending PoW notification to peer [%x]: %s", p.ID(), err) + log.Warn("oversized message received", "peer", p.ID(), "error", err) } } } @@ -568,7 +568,7 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { return errors.New("invalid powRequirementCode message") } f := math.Float64frombits(i) - if math.IsInf(f, 0) || math.IsNaN(f) { + if math.IsInf(f, 0) || math.IsNaN(f) || f < 0.0 { log.Warn("invalid value in powRequirementCode message, peer will be disconnected", "peer", p.peer.ID(), "err", err) return errors.New("invalid value in powRequirementCode message") } @@ -640,7 +640,7 @@ func (wh *Whisper) add(envelope *Envelope) (bool, error) { log.Debug("envelope with low PoW dropped", "PoW", envelope.PoW(), "hash", envelope.Hash().Hex()) return false, nil // drop envelope without error for now - // after the Status message will include the PoW requirement, it should return an error here: + // once the status message includes the PoW requirement, an error should be returned here: //return false, fmt.Errorf("envelope with low PoW dropped: PoW=%f, hash=[%v]", envelope.PoW(), envelope.Hash().Hex()) } From f78a54c6d9ead9ef6fe4019ffa76bc862d61a7f5 Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 20 Dec 2017 17:24:23 +0200 Subject: [PATCH 09/10] whisper: test function introduced --- whisper/whisperv6/api.go | 2 +- whisper/whisperv6/peer_test.go | 4 ++-- whisper/whisperv6/whisper.go | 32 ++++++++++++++++++++----------- whisper/whisperv6/whisper_test.go | 14 +++++++------- 4 files changed, 31 insertions(+), 21 deletions(-) diff --git a/whisper/whisperv6/api.go b/whisper/whisperv6/api.go index f6158b641c6e..3dddb69539f0 100644 --- a/whisper/whisperv6/api.go +++ b/whisper/whisperv6/api.go @@ -118,7 +118,7 @@ func (api *PublicWhisperAPI) SetMaxMessageSize(ctx context.Context, size uint32) // SetMinPow sets the minimum PoW for a message before it is accepted. func (api *PublicWhisperAPI) SetMinPoW(ctx context.Context, pow float64) (bool, error) { - return true, api.w.SetMinimumPoW(pow, false) + return true, api.w.SetMinimumPoW(pow) } // MarkTrustedPeer marks a peer trusted. , which will allow it to send historic (expired) messages. diff --git a/whisper/whisperv6/peer_test.go b/whisper/whisperv6/peer_test.go index 2c36fd7cb57b..599a479be490 100644 --- a/whisper/whisperv6/peer_test.go +++ b/whisper/whisperv6/peer_test.go @@ -124,7 +124,7 @@ func initialize(t *testing.T) { for i := 0; i < NumNodes; i++ { var node TestNode node.shh = New(&DefaultConfig) - node.shh.SetMinimumPoW(0.00000001, true) + node.shh.SetMinimumPowTest(0.00000001) node.shh.Start(nil) topics := make([]TopicType, 0) topics = append(topics, sharedTopic) @@ -342,7 +342,7 @@ func powReqExchange(t *testing.T) { } const pow float64 = 7777777.0 - nodes[0].shh.SetMinimumPoW(pow, true) + nodes[0].shh.SetMinimumPoW(pow) // wait until all the messages are delivered time.Sleep(64 * time.Millisecond) diff --git a/whisper/whisperv6/whisper.go b/whisper/whisperv6/whisper.go index 57b190368d8c..497819ef9f83 100644 --- a/whisper/whisperv6/whisper.go +++ b/whisper/whisperv6/whisper.go @@ -181,30 +181,40 @@ func (w *Whisper) SetMaxMessageSize(size uint32) error { } // SetMinimumPoW sets the minimal PoW required by this node -func (w *Whisper) SetMinimumPoW(val float64, testMode bool) error { - if val <= 0.0 { +func (w *Whisper) SetMinimumPoW(val float64) error { + if val < 0.0 { return fmt.Errorf("invalid PoW: %f", val) } w.notifyPeersAboutPowRequirementChange(val) - if testMode { + go func() { + // allow some time before all the peers have processed the notification + time.Sleep(time.Duration(w.reactionAllowance) * time.Second) w.settings.Store(minPowIdx, val) - } else { - go func() { - // allow some time before all the peers have processed the notification - time.Sleep(time.Duration(w.reactionAllowance) * time.Second) - w.settings.Store(minPowIdx, val) - }() - } + }() return nil } +// SetMinimumPoW sets the minimal PoW in test environment +func (w *Whisper) SetMinimumPowTest(val float64) { + w.notifyPeersAboutPowRequirementChange(val) + w.settings.Store(minPowIdx, val) +} + func (w *Whisper) notifyPeersAboutPowRequirementChange(pow float64) { + arr := make([]*Peer, len(w.peers)) + i := 0 + w.peerMu.Lock() - defer w.peerMu.Unlock() for p := range w.peers { + arr[i] = p + i++ + } + w.peerMu.Unlock() + + for _, p := range arr { err := p.notifyAboutPowRequirementChange(pow) if err != nil { // allow one retry diff --git a/whisper/whisperv6/whisper_test.go b/whisper/whisperv6/whisper_test.go index 009f50d3cb44..b391a1161b45 100644 --- a/whisper/whisperv6/whisper_test.go +++ b/whisper/whisperv6/whisper_test.go @@ -472,8 +472,8 @@ func TestExpiry(t *testing.T) { InitSingleTest() w := New(&DefaultConfig) - w.SetMinimumPoW(0.0000001, true) - defer w.SetMinimumPoW(DefaultMinimumPoW, true) + w.SetMinimumPowTest(0.0000001) + defer w.SetMinimumPowTest(DefaultMinimumPoW) w.Start(nil) defer w.Stop() @@ -529,7 +529,7 @@ func TestCustomization(t *testing.T) { InitSingleTest() w := New(&DefaultConfig) - defer w.SetMinimumPoW(DefaultMinimumPoW, true) + defer w.SetMinimumPowTest(DefaultMinimumPoW) defer w.SetMaxMessageSize(DefaultMaxMessageSize) w.Start(nil) defer w.Stop() @@ -563,7 +563,7 @@ func TestCustomization(t *testing.T) { t.Fatalf("successfully sent envelope with PoW %.06f, false positive (seed %d).", env.PoW(), seed) } - w.SetMinimumPoW(smallPoW/2, true) + w.SetMinimumPowTest(smallPoW / 2) err = w.Send(env) if err != nil { t.Fatalf("failed to send envelope with seed %d: %s.", seed, err) @@ -625,7 +625,7 @@ func TestSymmetricSendCycle(t *testing.T) { InitSingleTest() w := New(&DefaultConfig) - defer w.SetMinimumPoW(DefaultMinimumPoW, true) + defer w.SetMinimumPowTest(DefaultMinimumPoW) defer w.SetMaxMessageSize(DefaultMaxMessageSize) w.Start(nil) defer w.Stop() @@ -714,7 +714,7 @@ func TestSymmetricSendWithoutAKey(t *testing.T) { InitSingleTest() w := New(&DefaultConfig) - defer w.SetMinimumPoW(DefaultMinimumPoW, true) + defer w.SetMinimumPowTest(DefaultMinimumPoW) defer w.SetMaxMessageSize(DefaultMaxMessageSize) w.Start(nil) defer w.Stop() @@ -782,7 +782,7 @@ func TestSymmetricSendKeyMismatch(t *testing.T) { InitSingleTest() w := New(&DefaultConfig) - defer w.SetMinimumPoW(DefaultMinimumPoW, true) + defer w.SetMinimumPowTest(DefaultMinimumPoW) defer w.SetMaxMessageSize(DefaultMaxMessageSize) w.Start(nil) defer w.Stop() From 45bfeb834c68a3030f387eb4c40a09c4097f169f Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 20 Dec 2017 19:50:40 +0200 Subject: [PATCH 10/10] whisper: fixed travis error --- whisper/whisperv6/whisper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/whisper/whisperv6/whisper.go b/whisper/whisperv6/whisper.go index 497819ef9f83..0e0e32a4a97a 100644 --- a/whisper/whisperv6/whisper.go +++ b/whisper/whisperv6/whisper.go @@ -582,7 +582,7 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { log.Warn("invalid value in powRequirementCode message, peer will be disconnected", "peer", p.peer.ID(), "err", err) return errors.New("invalid value in powRequirementCode message") } - p.powRequirement = float64(f) + p.powRequirement = f case bloomFilterExCode: // to be implemented case p2pMessageCode: