From b7f3b838f86665ed2c694126c0cd39ae679acac9 Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 1 Mar 2017 13:22:55 +0100 Subject: [PATCH] whisper: made PoW and MaxMsgSize customizable --- cmd/wnode/main.go | 4 ++-- whisper/whisperv5/api.go | 16 +++++++++++++++- whisper/whisperv5/api_test.go | 8 ++++---- whisper/whisperv5/doc.go | 4 ++-- whisper/whisperv5/message.go | 20 -------------------- whisper/whisperv5/peer_test.go | 2 +- whisper/whisperv5/whisper.go | 30 +++++++++++++++++++++++++----- whisper/whisperv5/whisper_test.go | 3 ++- 8 files changed, 51 insertions(+), 36 deletions(-) diff --git a/cmd/wnode/main.go b/cmd/wnode/main.go index 82d7eda3ce..c734d20088 100644 --- a/cmd/wnode/main.go +++ b/cmd/wnode/main.go @@ -84,8 +84,8 @@ var ( argVerbosity = flag.Int("verbosity", int(log.LvlWarn), "log verbosity level") argTTL = flag.Uint("ttl", 30, "time-to-live for messages in seconds") argWorkTime = flag.Uint("work", 5, "work time in seconds") - argPoW = flag.Float64("pow", whisper.MinimumPoW, "PoW for normal messages in float format (e.g. 2.7)") - argServerPoW = flag.Float64("mspow", whisper.MinimumPoW, "PoW requirement for Mail Server request") + argPoW = flag.Float64("pow", whisper.DefaultMinimumPoW, "PoW for normal messages in float format (e.g. 2.7)") + argServerPoW = flag.Float64("mspow", whisper.DefaultMinimumPoW, "PoW requirement for Mail Server request") argIP = flag.String("ip", "", "IP address and port of this node (e.g. 127.0.0.1:30303)") argPub = flag.String("pub", "", "public key for asymmetric encryption") diff --git a/whisper/whisperv5/api.go b/whisper/whisperv5/api.go index 2e69089502..ba99350189 100644 --- a/whisper/whisperv5/api.go +++ b/whisper/whisperv5/api.go @@ -72,6 +72,20 @@ func (api *PublicWhisperAPI) Stats() (string, error) { return api.whisper.Stats(), nil } +func (api *PublicWhisperAPI) SetMaxMessageLength(val int) error { + if api.whisper == nil { + return whisperOffLineErr + } + return api.whisper.SetMaxMessageLength(val) +} + +func (api *PublicWhisperAPI) SetMinimumPoW(val float64) error { + if api.whisper == nil { + return whisperOffLineErr + } + return api.whisper.SetMinimumPoW(val) +} + // MarkPeerTrusted marks specific peer trusted, which will allow it // to send historic (expired) messages. func (api *PublicWhisperAPI) MarkPeerTrusted(peerID hexutil.Bytes) error { @@ -352,7 +366,7 @@ func (api *PublicWhisperAPI) Post(args PostArgs) error { log.Error(fmt.Sprintf(err.Error())) return err } - if envelope.size() > MaxMessageLength { + if envelope.size() > api.whisper.maxMsgLength { info := "Post: message is too big" log.Error(fmt.Sprintf(info)) return errors.New(info) diff --git a/whisper/whisperv5/api_test.go b/whisper/whisperv5/api_test.go index cde84e991a..9c8fb2841b 100644 --- a/whisper/whisperv5/api_test.go +++ b/whisper/whisperv5/api_test.go @@ -323,7 +323,7 @@ func TestIntegrationAsym(t *testing.T) { f.To = key f.From = sig f.Topics = topics[:] - f.PoW = MinimumPoW / 2 + f.PoW = DefaultMinimumPoW / 2 f.AcceptP2P = true id, err := api.NewFilter(f) @@ -337,7 +337,7 @@ func TestIntegrationAsym(t *testing.T) { p.To = f.To p.Padding = []byte("test string") p.Payload = []byte("extended test string") - p.PoW = MinimumPoW + p.PoW = DefaultMinimumPoW p.Topic = TopicType{0xf2, 0x6e, 0x77, 0x79} p.WorkTime = 2 @@ -427,7 +427,7 @@ func TestIntegrationSym(t *testing.T) { p.From = f.From p.Padding = []byte("test string") p.Payload = []byte("extended test string") - p.PoW = MinimumPoW + p.PoW = DefaultMinimumPoW p.Topic = TopicType{0xf2, 0x6e, 0x77, 0x79} p.WorkTime = 2 @@ -517,7 +517,7 @@ func TestIntegrationSymWithFilter(t *testing.T) { p.From = sig p.Padding = []byte("test string") p.Payload = []byte("extended test string") - p.PoW = MinimumPoW + p.PoW = DefaultMinimumPoW p.Topic = TopicType{0xf2, 0x6e, 0x77, 0x79} p.WorkTime = 2 diff --git a/whisper/whisperv5/doc.go b/whisper/whisperv5/doc.go index 9e533010b0..69756eacee 100644 --- a/whisper/whisperv5/doc.go +++ b/whisper/whisperv5/doc.go @@ -55,8 +55,8 @@ const ( saltLength = 12 AESNonceMaxLength = 12 - MaxMessageLength = 1024 * 1024 - MinimumPoW = 10.0 // todo: review after testing. + DefaultMaxMessageLength = 1024 * 1024 + DefaultMinimumPoW = 10.0 // todo: review after testing. padSizeLimitLower = 128 // it can not be less - we don't want to reveal the absence of signature padSizeLimitUpper = 256 // just an arbitrary number, could be changed without losing compatibility diff --git a/whisper/whisperv5/message.go b/whisper/whisperv5/message.go index d6601a512b..24baed62a0 100644 --- a/whisper/whisperv5/message.go +++ b/whisper/whisperv5/message.go @@ -215,17 +215,6 @@ func (msg *SentMessage) encryptSymmetric(key []byte) (salt []byte, nonce []byte, } // Wrap bundles the message into an Envelope to transmit over the network. -// -// pow (Proof Of Work) controls how much time to spend on hashing the message, -// inherently controlling its priority through the network (smaller hash, bigger -// priority). -// -// The user can control the amount of identity, privacy and encryption through -// the options parameter as follows: -// - options.From == nil && options.To == nil: anonymous broadcast -// - options.From != nil && options.To == nil: signed broadcast (known sender) -// - options.From == nil && options.To != nil: encrypted anonymous message -// - options.From != nil && options.To != nil: encrypted signed message func (msg *SentMessage) Wrap(options *MessageParams) (envelope *Envelope, err error) { if options.TTL == 0 { options.TTL = DefaultTTL @@ -236,10 +225,6 @@ func (msg *SentMessage) Wrap(options *MessageParams) (envelope *Envelope, err er return nil, err } } - if len(msg.Raw) > MaxMessageLength { - log.Error(fmt.Sprintf("Message size must not exceed %d bytes", MaxMessageLength)) - return nil, errors.New("Oversized message") - } var salt, nonce []byte if options.Dst != nil { err = msg.encryptAsymmetric(options.Dst) @@ -258,11 +243,6 @@ func (msg *SentMessage) Wrap(options *MessageParams) (envelope *Envelope, err er if err != nil { return nil, err } - if envelope.size() > MaxMessageLength { - log.Error(fmt.Sprintf("Envelope size must not exceed %d bytes", MaxMessageLength)) - return nil, errors.New("Oversized message") - } - return envelope, nil } diff --git a/whisper/whisperv5/peer_test.go b/whisper/whisperv5/peer_test.go index e3073bc6c8..110c3af531 100644 --- a/whisper/whisperv5/peer_test.go +++ b/whisper/whisperv5/peer_test.go @@ -114,7 +114,7 @@ func initialize(t *testing.T) { for i := 0; i < NumNodes; i++ { var node TestNode node.shh = New() - node.shh.test = true + node.shh.SetMinimumPoW(0.00000001) node.shh.Start(nil) topics := make([]TopicType, 0) topics = append(topics, sharedTopic) diff --git a/whisper/whisperv5/whisper.go b/whisper/whisperv5/whisper.go index c4f2b237d5..1b46421ea0 100644 --- a/whisper/whisperv5/whisper.go +++ b/whisper/whisperv5/whisper.go @@ -66,8 +66,9 @@ type Whisper struct { stats Statistics - overflow bool - test bool + minPoW float64 + maxMsgLength int + overflow bool } // New creates a Whisper client ready to communicate through the Ethereum P2P network. @@ -82,6 +83,8 @@ func New() *Whisper { messageQueue: make(chan *Envelope, messageQueueLimit), p2pMsgQueue: make(chan *Envelope, messageQueueLimit), quit: make(chan struct{}), + minPoW: DefaultMinimumPoW, + maxMsgLength: DefaultMaxMessageLength, } whisper.filters = NewFilters(whisper) @@ -122,6 +125,22 @@ func (w *Whisper) Version() uint { return w.protocol.Version } +func (w *Whisper) SetMaxMessageLength(val int) error { + if val <= 0 { + return fmt.Errorf("Invalid message length: %d", val) + } + w.maxMsgLength = val + return nil +} + +func (w *Whisper) SetMinimumPoW(val float64) error { + if val <= 0.0 { + return fmt.Errorf("Invalid PoW: %f", val) + } + w.minPoW = val + return nil +} + func (w *Whisper) getPeer(peerID []byte) (*Peer, error) { w.peerMu.Lock() defer w.peerMu.Unlock() @@ -358,7 +377,7 @@ func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { if err != nil { return err } - if packet.Size > MaxMessageLength { + if packet.Size > uint32(wh.maxMsgLength) { return fmt.Errorf("oversized message received") } @@ -441,7 +460,7 @@ func (wh *Whisper) add(envelope *Envelope) (bool, error) { } } - if envelope.size() > MaxMessageLength { + if envelope.size() > wh.maxMsgLength { return false, fmt.Errorf("huge messages are not allowed [%x]", envelope.Hash()) } @@ -459,7 +478,7 @@ func (wh *Whisper) add(envelope *Envelope) (bool, error) { return false, fmt.Errorf("oversized salt [%x]", envelope.Hash()) } - if envelope.PoW() < MinimumPoW && !wh.test { + if envelope.PoW() < wh.minPoW { log.Debug(fmt.Sprintf("envelope with low PoW dropped: %f [%x]", envelope.PoW(), envelope.Hash())) return false, nil // drop envelope without error } @@ -519,6 +538,7 @@ func (w *Whisper) checkOverflow() { } else if queueSize <= messageQueueLimit/2 { if w.overflow { w.overflow = false + log.Warn(fmt.Sprint("message queue overflow fixed (back to normal)")) } } } diff --git a/whisper/whisperv5/whisper_test.go b/whisper/whisperv5/whisper_test.go index 8d63d443cf..e7141dff4b 100644 --- a/whisper/whisperv5/whisper_test.go +++ b/whisper/whisperv5/whisper_test.go @@ -306,7 +306,8 @@ func TestExpiry(t *testing.T) { InitSingleTest() w := New() - w.test = true + w.SetMinimumPoW(0.0000001) + defer w.SetMinimumPoW(DefaultMinimumPoW) w.Start(nil) defer w.Stop()