diff --git a/Makefile b/Makefile index 75f117cf1..a4f954389 100644 --- a/Makefile +++ b/Makefile @@ -261,7 +261,8 @@ test-unit: UNIT_TEST_PACKAGES = $(shell go list ./... | \ grep -v /lib | \ grep -v /transactions/fake ) test-unit: ##@tests Run unit and integration tests - go test -v -failfast $(UNIT_TEST_PACKAGES) $(gotest_extraflags) && cd ./protocol && $(MAKE) test + go test -v -failfast $(UNIT_TEST_PACKAGES) $(gotest_extraflags) + cd ./waku && go test -v -failfast ./... $(gotest_extraflags) test-unit-race: gotest_extraflags=-race test-unit-race: test-unit ##@tests Run unit and integration tests with -race flag diff --git a/protocol/Makefile b/protocol/Makefile deleted file mode 100644 index 0938c512b..000000000 --- a/protocol/Makefile +++ /dev/null @@ -1,52 +0,0 @@ -GO111MODULE = on - -ENABLE_METRICS ?= true -BUILD_FLAGS ?= $(shell echo "-ldflags '\ - -X github.com/status-im/status-go/protocol/vendor/github.com/ethereum/go-ethereum/metrics.EnabledStr=$(ENABLE_METRICS)'") - -test: - go test ./... -.PHONY: test - -test-race: - go test -race ./... -.PHONY: test-race - -lint: - golangci-lint run -v -.PHONY: lint - -install-linter: - # install linter - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(shell go env GOPATH)/bin v1.21.0 -.PHONY: install-linter - -install-dev: - # a tool to vendor non-go files - go get github.com/goware/modvendor@latest - - go get github.com/golang/mock/gomock@latest - go install github.com/golang/mock/mockgen - - go get github.com/kevinburke/go-bindata/go-bindata@v3.13.0 - go get github.com/golang/protobuf/protoc-gen-go@v1.3.1 -.PHONY: install-dev - -generate: - go generate ./... -.PHONY: generate - -new-migration: - @if [ -z "$$DIR" ]; then \ - echo 'missing DIR var'; \ - exit 1; \ - fi - - @if [ -z "$$NAME" ]; then \ - echo 'missing NAME var'; \ - exit 1; \ - fi - - mkdir -p $(DIR) - touch $(DIR)/`date +"%s"`_$(NAME).down.sql ./$(DIR)/`date +"%s"`_$(NAME).up.sql -.PHONY: create-migration diff --git a/waku/go.mod b/waku/go.mod index dee45c4c4..b11bde74d 100644 --- a/waku/go.mod +++ b/waku/go.mod @@ -2,7 +2,7 @@ module github.com/status-im/status-go/waku go 1.13 -replace github.com/ethereum/go-ethereum v1.9.5 => github.com/status-im/go-ethereum v1.9.5-status.6 +replace github.com/ethereum/go-ethereum v1.9.5 => github.com/status-im/go-ethereum v1.9.5-status.7 require ( github.com/aristanetworks/goarista v0.0.0-20191106175434-873d404c7f40 // indirect diff --git a/waku/go.sum b/waku/go.sum index e1e50ef6b..d8b156dc4 100644 --- a/waku/go.sum +++ b/waku/go.sum @@ -27,6 +27,7 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/btcsuite/btcd v0.20.0-beta h1:DnZGUjFbRkpytojHWwy6nfUSA7vFrzWXDLpFNzt74ZA= github.com/btcsuite/btcd v0.20.0-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= @@ -191,6 +192,9 @@ github.com/status-im/go-ethereum v1.9.5-status.5 h1:d2RJC6ltNZJM2mrAW6kDWYdzewF8 github.com/status-im/go-ethereum v1.9.5-status.5/go.mod h1:g2+E89NWtyA+55p6XEl5Sdt7Mtez3V0T3+Y7mJNb+tI= github.com/status-im/go-ethereum v1.9.5-status.6 h1:ytuTO1yBIAuTVRtRQoc2mrdyngtP+XOQ9IHIibbz7/I= github.com/status-im/go-ethereum v1.9.5-status.6/go.mod h1:08JvQWE+IOnAFSe4UD4ACLNe2fDd9XmWMCq5Yzy9mk0= +github.com/status-im/go-ethereum v1.9.5-status.7 h1:DKH1GiF52LwaZaw6YDBliFEgm/JDsbIT+hn7ph6X94Q= +github.com/status-im/go-ethereum v1.9.5-status.7/go.mod h1:YyH5DKB6+z+Vaya7eIm67pnuPZ1oiUMbbsZW41ktN0g= +github.com/status-im/status-go/extkeys v1.0.0/go.mod h1:GdqJbrcpkNm5ZsSCpp+PdMxnXx+OcRBdm3PI0rs1FpU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -226,6 +230,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c h1:/nJuwDLoL/zrqY6gf57vxC+Pi+pZ8bfhpPkicO5H7W4= golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= diff --git a/waku/handshake.go b/waku/handshake.go new file mode 100644 index 000000000..99effbe37 --- /dev/null +++ b/waku/handshake.go @@ -0,0 +1,125 @@ +package waku + +import ( + "errors" + "fmt" + "io" + "math" + "reflect" + "strings" + + "github.com/ethereum/go-ethereum/rlp" +) + +// statusOptions defines additional information shared between peers +// during the handshake. +// There might be more options provided then fields in statusOptions +// and they should be ignored during deserialization to stay forward compatible. +// In the case of RLP, options should be serialized to an array of tuples +// where the first item is a field name and the second is a RLP-serialized value. +type statusOptions struct { + PoWRequirement uint64 `rlp:"key=0"` // RLP does not support float64 natively + BloomFilter []byte `rlp:"key=1"` + LightNodeEnabled bool `rlp:"key=2"` + ConfirmationsEnabled bool `rlp:"key=3"` + RateLimits RateLimits `rlp:"key=4"` + TopicInterest []TopicType `rlp:"key=5"` +} + +var idxFieldKey = make(map[int]string) +var keyFieldIdx = func() map[string]int { + result := make(map[string]int) + opts := statusOptions{} + v := reflect.ValueOf(opts) + for i := 0; i < v.NumField(); i++ { + // skip unexported fields + if !v.Field(i).CanInterface() { + continue + } + rlpTag := v.Type().Field(i).Tag.Get("rlp") + // skip fields without rlp field tag + if rlpTag == "" { + continue + } + key := strings.Split(rlpTag, "=")[1] + result[key] = i + idxFieldKey[i] = key + } + return result +}() + +func (o statusOptions) PoWRequirementF() float64 { + return math.Float64frombits(o.PoWRequirement) +} + +func (o *statusOptions) SetPoWRequirementFromF(val float64) { + o.PoWRequirement = math.Float64bits(val) +} + +func (o statusOptions) EncodeRLP(w io.Writer) error { + v := reflect.ValueOf(o) + optionsList := make([]interface{}, 0, v.NumField()) + for i := 0; i < v.NumField(); i++ { + value := v.Field(i).Interface() + key, ok := idxFieldKey[i] + if !ok { + continue + } + optionsList = append(optionsList, []interface{}{key, value}) + } + return rlp.Encode(w, optionsList) +} + +func (o *statusOptions) DecodeRLP(s *rlp.Stream) error { + _, err := s.List() + if err != nil { + return fmt.Errorf("expected an outer list: %w", err) + } + + v := reflect.ValueOf(o) + +loop: + for { + _, err := s.List() + switch err { + case nil: + // continue to decode a key + case rlp.EOL: + break loop + default: + return fmt.Errorf("expected an inner list: %w", err) + } + var key string + if err := s.Decode(&key); err != nil { + return fmt.Errorf("invalid key: %w", err) + } + // Skip processing if a key does not exist. + // It might happen when there is a new peer + // which supports a new option with + // a higher index. + idx, ok := keyFieldIdx[key] + if !ok { + // Read the rest of the list items and dump them. + _, err := s.Raw() + if err != nil { + return fmt.Errorf("failed to read the value of key %s: %w", key, err) + } + continue + } + if err := s.Decode(v.Elem().Field(idx).Addr().Interface()); err != nil { + return fmt.Errorf("failed to decode an option %s: %w", key, err) + } + if err := s.ListEnd(); err != nil { + return err + } + } + + return s.ListEnd() +} + +func (o statusOptions) Validate() error { + if len(o.TopicInterest) > 1000 { + return errors.New("topic interest is limited by 1000 items") + } + return nil +} diff --git a/waku/handshake_test.go b/waku/handshake_test.go new file mode 100644 index 000000000..002f7064c --- /dev/null +++ b/waku/handshake_test.go @@ -0,0 +1,59 @@ +package waku + +import ( + "math" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/rlp" +) + +func TestEncodeDecodeRLP(t *testing.T) { + opts := statusOptions{ + PoWRequirement: math.Float64bits(6.02), + BloomFilter: TopicToBloom(TopicType{0xaa, 0xbb, 0xcc, 0xdd}), + LightNodeEnabled: true, + ConfirmationsEnabled: true, + RateLimits: RateLimits{ + IPLimits: 10, + PeerIDLimits: 5, + TopicLimits: 1, + }, + TopicInterest: []TopicType{{0x01}, {0x02}, {0x03}, {0x04}}, + } + data, err := rlp.EncodeToBytes(opts) + require.NoError(t, err) + + var optsDecoded statusOptions + err = rlp.DecodeBytes(data, &optsDecoded) + require.NoError(t, err) + require.EqualValues(t, opts, optsDecoded) +} + +func TestBackwardCompatibility(t *testing.T) { + alist := []interface{}{ + []interface{}{"0", math.Float64bits(2.05)}, + } + data, err := rlp.EncodeToBytes(alist) + require.NoError(t, err) + + var optsDecoded statusOptions + err = rlp.DecodeBytes(data, &optsDecoded) + require.NoError(t, err) + require.EqualValues(t, statusOptions{PoWRequirement: math.Float64bits(2.05)}, optsDecoded) +} + +func TestForwardCompatibility(t *testing.T) { + alist := []interface{}{ + []interface{}{"0", math.Float64bits(2.05)}, + []interface{}{"99", uint(10)}, // some future option + } + data, err := rlp.EncodeToBytes(alist) + require.NoError(t, err) + + var optsDecoded statusOptions + err = rlp.DecodeBytes(data, &optsDecoded) + require.NoError(t, err) + require.EqualValues(t, statusOptions{PoWRequirement: math.Float64bits(2.05)}, optsDecoded) +} diff --git a/waku/peer.go b/waku/peer.go index 92506173e..01d8edc78 100644 --- a/waku/peer.go +++ b/waku/peer.go @@ -96,13 +96,15 @@ func (p *Peer) handshake() error { isLightNode := p.host.LightClientMode() isRestrictedLightNodeConnection := p.host.LightClientModeConnectionRestricted() go func() { - pow := p.host.MinPow() - powConverted := math.Float64bits(pow) - bloom := p.host.BloomFilter() - confirmationsEnabled := p.host.ConfirmationsEnabled() - rateLimits := p.host.RateLimits() - - errc <- p2p.SendItems(p.ws, statusCode, ProtocolVersion, powConverted, bloom, isLightNode, confirmationsEnabled, rateLimits) + opts := statusOptions{ + BloomFilter: p.host.BloomFilter(), + LightNodeEnabled: isLightNode, + ConfirmationsEnabled: p.host.ConfirmationsEnabled(), + RateLimits: p.host.RateLimits(), + TopicInterest: nil, + } + opts.SetPoWRequirementFromF(p.host.MinPow()) + errc <- p2p.SendItems(p.ws, statusCode, ProtocolVersion, opts) }() // Fetch the remote status packet and verify protocol match @@ -113,56 +115,51 @@ func (p *Peer) handshake() error { if packet.Code != statusCode { return fmt.Errorf("p [%x] sent packet %x before status packet", p.ID(), packet.Code) } + + var ( + peerProtocolVersion uint64 + peerOptions statusOptions + ) s := rlp.NewStream(packet.Payload, uint64(packet.Size)) - _, err = s.List() - if err != nil { - return fmt.Errorf("p [%x] sent bad status message: %v", p.ID(), err) + if _, err := s.List(); err != nil { + return fmt.Errorf("p [%x]: failed to decode status packet: %w", p.ID(), err) } - peerVersion, err := s.Uint() - if err != nil { - return fmt.Errorf("p [%x] sent bad status message (unable to decode version): %v", p.ID(), err) + // Validate protocol version. + if err := s.Decode(&peerProtocolVersion); err != nil { + return fmt.Errorf("p [%x]: failed to decode peer protocol version: %w", p.ID(), err) } - if peerVersion != ProtocolVersion { - return fmt.Errorf("p [%x]: protocol version mismatch %d != %d", p.ID(), peerVersion, ProtocolVersion) + if peerProtocolVersion != ProtocolVersion { + return fmt.Errorf("p [%x]: protocol version mismatch %d != %d", p.ID(), peerProtocolVersion, ProtocolVersion) } - - // only version is mandatory, subsequent parameters are optional - powRaw, err := s.Uint() - if err == nil { - pow := math.Float64frombits(powRaw) - if math.IsInf(pow, 0) || math.IsNaN(pow) || pow < 0.0 { - return fmt.Errorf("p [%x] sent bad status message: invalid pow", p.ID()) - } - p.powRequirement = pow - - var bloom []byte - err = s.Decode(&bloom) - if err == nil { - sz := len(bloom) - if sz != BloomFilterSize && sz != 0 { - return fmt.Errorf("p [%x] sent bad status message: wrong bloom filter size %d", p.ID(), sz) - } - p.setBloomFilter(bloom) - } + // Decode and validate other status packet options. + if err := s.Decode(&peerOptions); err != nil { + return fmt.Errorf("p [%x]: failed to decode status options: %w", p.ID(), err) } - - isRemotePeerLightNode, _ := s.Bool() - if isRemotePeerLightNode && isLightNode && isRestrictedLightNodeConnection { + if err := s.ListEnd(); err != nil { + return fmt.Errorf("p [%x]: failed to decode status packet: %w", p.ID(), err) + } + if err := peerOptions.Validate(); err != nil { + return fmt.Errorf("p [%x]: sent invalid options: %w", p.ID(), err) + } + // Validate and save peer's PoW. + pow := peerOptions.PoWRequirementF() + if math.IsInf(pow, 0) || math.IsNaN(pow) || pow < 0.0 { + return fmt.Errorf("p [%x]: sent bad status message: invalid pow", p.ID()) + } + p.powRequirement = pow + // Validate and save peer's bloom filters. + bloom := peerOptions.BloomFilter + bloomSize := len(bloom) + if bloomSize != 0 && bloomSize != BloomFilterSize { + return fmt.Errorf("p [%x] sent bad status message: wrong bloom filter size %d", p.ID(), bloomSize) + } + p.setBloomFilter(bloom) + // Validate and save other peer's options. + if peerOptions.LightNodeEnabled && isLightNode && isRestrictedLightNodeConnection { return fmt.Errorf("p [%x] is useless: two light client communication restricted", p.ID()) } - confirmationsEnabled, err := s.Bool() - if err != nil || !confirmationsEnabled { - p.logger.Info("confirmations are disabled for peer", zap.Binary("peer", p.ID())) - } else { - p.confirmationsEnabled = confirmationsEnabled - } - - var rateLimits RateLimits - if err := s.Decode(&rateLimits); err != nil { - p.logger.Info("rate limiting is disabled for peer", zap.Binary("peer", p.ID())) - } else { - p.setRateLimits(rateLimits) - } + p.confirmationsEnabled = peerOptions.ConfirmationsEnabled + p.setRateLimits(peerOptions.RateLimits) if err := <-errc; err != nil { return fmt.Errorf("p [%x] failed to send status packet: %v", p.ID(), err) diff --git a/waku/peer_test.go b/waku/peer_test.go index bb3937aad..8875d0021 100644 --- a/waku/peer_test.go +++ b/waku/peer_test.go @@ -514,7 +514,10 @@ func TestPeerHandshakeWithTwoFullNode(t *testing.T) { p1 := newPeer( &w1, p2p.NewPeer(enode.ID{}, "test", []p2p.Cap{}), - &rwStub{[]interface{}{ProtocolVersion, uint64(123), make([]byte, BloomFilterSize), false}}, + &rwStub{[]interface{}{ + ProtocolVersion, + statusOptions{PoWRequirement: 123}, + }}, nil, ) err := p1.handshake() @@ -529,7 +532,10 @@ func TestHandshakeWithOldVersionWithoutLightModeFlag(t *testing.T) { p1 := newPeer( &w1, p2p.NewPeer(enode.ID{}, "test", []p2p.Cap{}), - &rwStub{[]interface{}{ProtocolVersion, uint64(123), make([]byte, BloomFilterSize)}}, + &rwStub{[]interface{}{ + ProtocolVersion, + statusOptions{PoWRequirement: 123}, + }}, nil, ) err := p1.handshake() @@ -546,7 +552,10 @@ func TestTwoLightPeerHandshakeRestrictionOff(t *testing.T) { p1 := newPeer( &w1, p2p.NewPeer(enode.ID{}, "test", []p2p.Cap{}), - &rwStub{[]interface{}{ProtocolVersion, uint64(123), make([]byte, BloomFilterSize), true}}, + &rwStub{[]interface{}{ + ProtocolVersion, + statusOptions{PoWRequirement: 123, LightNodeEnabled: true}, + }}, nil, ) err := p1.handshake() diff --git a/waku/waku_test.go b/waku/waku_test.go index eab3960b6..5b75822f3 100644 --- a/waku/waku_test.go +++ b/waku/waku_test.go @@ -28,6 +28,8 @@ import ( "testing" "time" + "go.uber.org/zap" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "golang.org/x/crypto/pbkdf2" @@ -913,6 +915,7 @@ func TestSendP2PDirect(t *testing.T) { rwStub := &rwP2PMessagesStub{} peerW := newPeer(w, p2p.NewPeer(enode.ID{}, "test", []p2p.Cap{}), rwStub, nil) + w.peers[peerW] = struct{}{} params, err := generateMessageParams() if err != nil { @@ -929,7 +932,7 @@ func TestSendP2PDirect(t *testing.T) { t.Fatalf("failed Wrap with seed %d: %s.", seed, err) } - err = w.SendP2PDirect(peerW, env, env, env) + err = w.SendP2PDirect(peerW.ID(), env, env, env) if err != nil { t.Fatalf("failed to send envelope with seed %d: %s.", seed, err) } @@ -1053,7 +1056,14 @@ func testConfirmationsHandshake(t *testing.T, expectConfirmations bool) { p2p.ExpectMsg( rw1, statusCode, - []interface{}{ProtocolVersion, math.Float64bits(w.MinPow()), w.BloomFilter(), false, expectConfirmations, RateLimits{}}, + []interface{}{ + ProtocolVersion, + statusOptions{ + PoWRequirement: math.Float64bits(w.MinPow()), + LightNodeEnabled: false, + ConfirmationsEnabled: expectConfirmations, + }, + }, ), ) } @@ -1067,12 +1077,14 @@ func TestHandshakeWithConfirmationsDisabled(t *testing.T) { } func TestConfirmationReceived(t *testing.T) { + logger, err := zap.NewDevelopment() + require.NoError(t, err) conf := &Config{ MinimumAcceptedPoW: 0, MaxMessageSize: 10 << 20, EnableConfirmations: true, } - w := New(conf, nil) + w := New(conf, logger) p := p2p.NewPeer(enode.ID{1}, "1", []p2p.Cap{{"waku", 0}}) rw1, rw2 := p2p.MsgPipe() errorc := make(chan error, 1) @@ -1080,15 +1092,27 @@ func TestConfirmationReceived(t *testing.T) { err := w.HandlePeer(p, rw2) errorc <- err }() - time.AfterFunc(5*time.Second, func() { - rw1.Close() - }) + go func() { + select { + case err := <-errorc: + t.Log(err) + case <-time.After(time.Second * 5): + rw1.Close() + } + }() require.NoError( t, p2p.ExpectMsg( rw1, statusCode, - []interface{}{ProtocolVersion, math.Float64bits(w.MinPow()), w.BloomFilter(), false, true, RateLimits{}}, + []interface{}{ + ProtocolVersion, + statusOptions{ + PoWRequirement: math.Float64bits(w.MinPow()), + BloomFilter: w.BloomFilter(), + ConfirmationsEnabled: true, + }, + }, ), ) require.NoError( @@ -1097,10 +1121,12 @@ func TestConfirmationReceived(t *testing.T) { rw1, statusCode, ProtocolVersion, - math.Float64bits(w.MinPow()), - w.BloomFilter(), - true, - true, + statusOptions{ + PoWRequirement: math.Float64bits(w.MinPow()), + BloomFilter: w.BloomFilter(), + ConfirmationsEnabled: true, + LightNodeEnabled: true, + }, ), ) @@ -1142,7 +1168,14 @@ func TestMessagesResponseWithError(t *testing.T) { p2p.ExpectMsg( rw1, statusCode, - []interface{}{ProtocolVersion, math.Float64bits(w.MinPow()), w.BloomFilter(), false, true, RateLimits{}}, + []interface{}{ + ProtocolVersion, + statusOptions{ + PoWRequirement: math.Float64bits(w.MinPow()), + BloomFilter: w.BloomFilter(), + ConfirmationsEnabled: true, + }, + }, ), ) require.NoError( @@ -1151,10 +1184,12 @@ func TestMessagesResponseWithError(t *testing.T) { rw1, statusCode, ProtocolVersion, - math.Float64bits(w.MinPow()), w.BloomFilter(), - true, - true, - RateLimits{}, + statusOptions{ + PoWRequirement: math.Float64bits(w.MinPow()), + BloomFilter: w.BloomFilter(), + ConfirmationsEnabled: true, + LightNodeEnabled: true, + }, ), ) @@ -1204,9 +1239,29 @@ func testConfirmationEvents(t *testing.T, envelope Envelope, envelopeErrors []En time.AfterFunc(5*time.Second, func() { rw1.Close() }) - require.NoError(t, p2p.ExpectMsg(rw1, statusCode, []interface{}{ProtocolVersion, math.Float64bits(w.MinPow()), w.BloomFilter(), false, true, RateLimits{}})) - require.NoError(t, p2p.SendItems(rw1, statusCode, ProtocolVersion, math.Float64bits(w.MinPow()), w.BloomFilter(), true, true)) - + require.NoError(t, p2p.ExpectMsg( + rw1, + statusCode, + []interface{}{ + ProtocolVersion, + statusOptions{ + PoWRequirement: math.Float64bits(w.MinPow()), + BloomFilter: w.BloomFilter(), + ConfirmationsEnabled: true, + }, + }, + )) + require.NoError(t, p2p.SendItems( + rw1, + statusCode, + ProtocolVersion, + statusOptions{ + PoWRequirement: math.Float64bits(w.MinPow()), + BloomFilter: w.BloomFilter(), + ConfirmationsEnabled: true, + LightNodeEnabled: true, + }, + )) require.NoError(t, w.Send(&envelope)) require.NoError(t, p2p.ExpectMsg(rw1, messagesCode, []*Envelope{&envelope})) @@ -1286,7 +1341,13 @@ func TestEventsWithoutConfirmation(t *testing.T) { p2p.ExpectMsg( rw1, statusCode, - []interface{}{ProtocolVersion, math.Float64bits(w.MinPow()), w.BloomFilter(), false, false, RateLimits{}}, + []interface{}{ + ProtocolVersion, + statusOptions{ + PoWRequirement: math.Float64bits(w.MinPow()), + BloomFilter: w.BloomFilter(), + }, + }, ), ) require.NoError( @@ -1295,11 +1356,11 @@ func TestEventsWithoutConfirmation(t *testing.T) { rw1, statusCode, ProtocolVersion, - math.Float64bits(w.MinPow()), - w.BloomFilter(), - true, - false, - RateLimits{}, + statusOptions{ + PoWRequirement: math.Float64bits(w.MinPow()), + BloomFilter: w.BloomFilter(), + LightNodeEnabled: true, + }, ), ) @@ -1464,10 +1525,17 @@ func TestRateLimiterIntegration(t *testing.T) { p2p.ExpectMsg( rw1, statusCode, - []interface{}{ProtocolVersion, math.Float64bits(w.MinPow()), w.BloomFilter(), false, false, RateLimits{ - IPLimits: 10, - PeerIDLimits: 5, - }}, + []interface{}{ + ProtocolVersion, + statusOptions{ + PoWRequirement: math.Float64bits(w.MinPow()), + BloomFilter: w.BloomFilter(), + RateLimits: RateLimits{ + IPLimits: 10, + PeerIDLimits: 5, + }, + }, + }, ), ) select { diff --git a/whisper/whisper_test.go b/whisper/whisper_test.go index 343addfef..3416c8757 100644 --- a/whisper/whisper_test.go +++ b/whisper/whisper_test.go @@ -911,6 +911,7 @@ func TestSendP2PDirect(t *testing.T) { rwStub := &rwP2PMessagesStub{} peerW := newPeer(w, p2p.NewPeer(enode.ID{}, "test", []p2p.Cap{}), rwStub) + w.peers[peerW] = struct{}{} params, err := generateMessageParams() if err != nil { @@ -928,7 +929,7 @@ func TestSendP2PDirect(t *testing.T) { } // verify sending a single envelope - err = w.SendP2PDirect(peerW, env) + err = w.SendP2PDirect(peerW.ID(), env) if err != nil { t.Fatalf("failed to send envelope with seed %d: %s.", seed, err) }