aboutsummaryrefslogtreecommitdiffstats
path: root/whisper
diff options
context:
space:
mode:
authorb00ris <b00ris@mail.ru>2018-09-05 16:57:45 +0800
committerGuillaume Ballet <gballet@gmail.com>2018-09-05 16:57:45 +0800
commit8711e2b6366109912057e8fb20add325a1051a4e (patch)
tree70ad2598573f8774ec77acf57598e24d7200634b /whisper
parentcf33d8b83ce78d1e79cd8c43a21070b2050d5c7e (diff)
downloaddexon-8711e2b6366109912057e8fb20add325a1051a4e.tar
dexon-8711e2b6366109912057e8fb20add325a1051a4e.tar.gz
dexon-8711e2b6366109912057e8fb20add325a1051a4e.tar.bz2
dexon-8711e2b6366109912057e8fb20add325a1051a4e.tar.lz
dexon-8711e2b6366109912057e8fb20add325a1051a4e.tar.xz
dexon-8711e2b6366109912057e8fb20add325a1051a4e.tar.zst
dexon-8711e2b6366109912057e8fb20add325a1051a4e.zip
whisper: add light mode check to handshake (#16725)
Diffstat (limited to 'whisper')
-rw-r--r--whisper/whisperv6/api.go8
-rw-r--r--whisper/whisperv6/config.go10
-rw-r--r--whisper/whisperv6/peer.go10
-rw-r--r--whisper/whisperv6/peer_test.go61
-rw-r--r--whisper/whisperv6/whisper.go44
5 files changed, 115 insertions, 18 deletions
diff --git a/whisper/whisperv6/api.go b/whisper/whisperv6/api.go
index d729e79c3..e1dab7b22 100644
--- a/whisper/whisperv6/api.go
+++ b/whisper/whisperv6/api.go
@@ -195,14 +195,14 @@ func (api *PublicWhisperAPI) DeleteSymKey(ctx context.Context, id string) bool {
// MakeLightClient turns the node into light client, which does not forward
// any incoming messages, and sends only messages originated in this node.
func (api *PublicWhisperAPI) MakeLightClient(ctx context.Context) bool {
- api.w.lightClient = true
- return api.w.lightClient
+ api.w.SetLightClientMode(true)
+ return api.w.LightClientMode()
}
// CancelLightClient cancels light client mode.
func (api *PublicWhisperAPI) CancelLightClient(ctx context.Context) bool {
- api.w.lightClient = false
- return !api.w.lightClient
+ api.w.SetLightClientMode(false)
+ return !api.w.LightClientMode()
}
//go:generate gencodec -type NewMessage -field-override newMessageOverride -out gen_newmessage_json.go
diff --git a/whisper/whisperv6/config.go b/whisper/whisperv6/config.go
index 61419de00..38eb9551c 100644
--- a/whisper/whisperv6/config.go
+++ b/whisper/whisperv6/config.go
@@ -18,12 +18,14 @@ package whisperv6
// Config represents the configuration state of a whisper node.
type Config struct {
- MaxMessageSize uint32 `toml:",omitempty"`
- MinimumAcceptedPOW float64 `toml:",omitempty"`
+ MaxMessageSize uint32 `toml:",omitempty"`
+ MinimumAcceptedPOW float64 `toml:",omitempty"`
+ RestrictConnectionBetweenLightClients bool `toml:",omitempty"`
}
// DefaultConfig represents (shocker!) the default configuration.
var DefaultConfig = Config{
- MaxMessageSize: DefaultMaxMessageSize,
- MinimumAcceptedPOW: DefaultMinimumPoW,
+ MaxMessageSize: DefaultMaxMessageSize,
+ MinimumAcceptedPOW: DefaultMinimumPoW,
+ RestrictConnectionBetweenLightClients: true,
}
diff --git a/whisper/whisperv6/peer.go b/whisper/whisperv6/peer.go
index 79cc21270..621d51208 100644
--- a/whisper/whisperv6/peer.go
+++ b/whisper/whisperv6/peer.go
@@ -79,11 +79,14 @@ func (peer *Peer) stop() {
func (peer *Peer) handshake() error {
// Send the handshake status message asynchronously
errc := make(chan error, 1)
+ isLightNode := peer.host.LightClientMode()
+ isRestrictedLightNodeConnection := peer.host.LightClientModeConnectionRestricted()
go func() {
pow := peer.host.MinPow()
powConverted := math.Float64bits(pow)
bloom := peer.host.BloomFilter()
- errc <- p2p.SendItems(peer.ws, statusCode, ProtocolVersion, powConverted, bloom)
+
+ errc <- p2p.SendItems(peer.ws, statusCode, ProtocolVersion, powConverted, bloom, isLightNode)
}()
// Fetch the remote status packet and verify protocol match
@@ -127,6 +130,11 @@ func (peer *Peer) handshake() error {
}
}
+ isRemotePeerLightNode, err := s.Bool()
+ if isRemotePeerLightNode && isLightNode && isRestrictedLightNodeConnection {
+ return fmt.Errorf("peer [%x] is useless: two light client communication restricted", peer.ID())
+ }
+
if err := <-errc; err != nil {
return fmt.Errorf("peer [%x] failed to send status packet: %v", peer.ID(), err)
}
diff --git a/whisper/whisperv6/peer_test.go b/whisper/whisperv6/peer_test.go
index 0c9b38090..fe31922cb 100644
--- a/whisper/whisperv6/peer_test.go
+++ b/whisper/whisperv6/peer_test.go
@@ -34,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/p2p/nat"
+ "github.com/ethereum/go-ethereum/rlp"
)
var keys = []string{
@@ -507,3 +508,63 @@ func waitForServersToStart(t *testing.T) {
}
t.Fatalf("Failed to start all the servers, running: %d", started)
}
+
+//two generic whisper node handshake
+func TestPeerHandshakeWithTwoFullNode(t *testing.T) {
+ w1 := Whisper{}
+ p1 := newPeer(&w1, p2p.NewPeer(discover.NodeID{}, "test", []p2p.Cap{}), &rwStub{[]interface{}{ProtocolVersion, uint64(123), make([]byte, BloomFilterSize), false}})
+ err := p1.handshake()
+ if err != nil {
+ t.Fatal()
+ }
+}
+
+//two generic whisper node handshake. one don't send light flag
+func TestHandshakeWithOldVersionWithoutLightModeFlag(t *testing.T) {
+ w1 := Whisper{}
+ p1 := newPeer(&w1, p2p.NewPeer(discover.NodeID{}, "test", []p2p.Cap{}), &rwStub{[]interface{}{ProtocolVersion, uint64(123), make([]byte, BloomFilterSize)}})
+ err := p1.handshake()
+ if err != nil {
+ t.Fatal()
+ }
+}
+
+//two light nodes handshake. restriction disabled
+func TestTwoLightPeerHandshakeRestrictionOff(t *testing.T) {
+ w1 := Whisper{}
+ w1.settings.Store(restrictConnectionBetweenLightClientsIdx, false)
+ w1.SetLightClientMode(true)
+ p1 := newPeer(&w1, p2p.NewPeer(discover.NodeID{}, "test", []p2p.Cap{}), &rwStub{[]interface{}{ProtocolVersion, uint64(123), make([]byte, BloomFilterSize), true}})
+ err := p1.handshake()
+ if err != nil {
+ t.FailNow()
+ }
+}
+
+//two light nodes handshake. restriction enabled
+func TestTwoLightPeerHandshakeError(t *testing.T) {
+ w1 := Whisper{}
+ w1.settings.Store(restrictConnectionBetweenLightClientsIdx, true)
+ w1.SetLightClientMode(true)
+ p1 := newPeer(&w1, p2p.NewPeer(discover.NodeID{}, "test", []p2p.Cap{}), &rwStub{[]interface{}{ProtocolVersion, uint64(123), make([]byte, BloomFilterSize), true}})
+ err := p1.handshake()
+ if err == nil {
+ t.FailNow()
+ }
+}
+
+type rwStub struct {
+ payload []interface{}
+}
+
+func (stub *rwStub) ReadMsg() (p2p.Msg, error) {
+ size, r, err := rlp.EncodeToReader(stub.payload)
+ if err != nil {
+ return p2p.Msg{}, err
+ }
+ return p2p.Msg{Code: statusCode, Size: uint32(size), Payload: r}, nil
+}
+
+func (stub *rwStub) WriteMsg(m p2p.Msg) error {
+ return nil
+}
diff --git a/whisper/whisperv6/whisper.go b/whisper/whisperv6/whisper.go
index be633e7ff..eb713f84e 100644
--- a/whisper/whisperv6/whisper.go
+++ b/whisper/whisperv6/whisper.go
@@ -49,12 +49,14 @@ type Statistics struct {
}
const (
- maxMsgSizeIdx = iota // Maximal message length allowed by the whisper node
- overflowIdx // Indicator of message queue overflow
- minPowIdx // Minimal PoW required by the whisper node
- minPowToleranceIdx // Minimal PoW tolerated by the whisper node for a limited time
- bloomFilterIdx // Bloom filter for topics of interest for this node
- bloomFilterToleranceIdx // Bloom filter tolerated by the whisper node for a limited time
+ maxMsgSizeIdx = iota // Maximal message length allowed by the whisper node
+ overflowIdx // Indicator of message queue overflow
+ minPowIdx // Minimal PoW required by the whisper node
+ minPowToleranceIdx // Minimal PoW tolerated by the whisper node for a limited time
+ bloomFilterIdx // Bloom filter for topics of interest for this node
+ bloomFilterToleranceIdx // Bloom filter tolerated by the whisper node for a limited time
+ lightClientModeIdx // Light client mode. (does not forward any messages)
+ restrictConnectionBetweenLightClientsIdx // Restrict connection between two light clients
)
// Whisper represents a dark communication interface through the Ethereum
@@ -82,8 +84,6 @@ type Whisper struct {
syncAllowance int // maximum time in seconds allowed to process the whisper-related messages
- lightClient bool // indicates is this node is pure light client (does not forward any messages)
-
statsMu sync.Mutex // guard stats
stats Statistics // Statistics of whisper node
@@ -113,6 +113,7 @@ func New(cfg *Config) *Whisper {
whisper.settings.Store(minPowIdx, cfg.MinimumAcceptedPOW)
whisper.settings.Store(maxMsgSizeIdx, cfg.MaxMessageSize)
whisper.settings.Store(overflowIdx, false)
+ whisper.settings.Store(restrictConnectionBetweenLightClientsIdx, cfg.RestrictConnectionBetweenLightClients)
// p2p whisper sub protocol handler
whisper.protocol = p2p.Protocol{
@@ -276,6 +277,31 @@ func (whisper *Whisper) SetMinimumPowTest(val float64) {
whisper.settings.Store(minPowToleranceIdx, val)
}
+//SetLightClientMode makes node light client (does not forward any messages)
+func (whisper *Whisper) SetLightClientMode(v bool) {
+ whisper.settings.Store(lightClientModeIdx, v)
+}
+
+//LightClientMode indicates is this node is light client (does not forward any messages)
+func (whisper *Whisper) LightClientMode() bool {
+ val, exist := whisper.settings.Load(lightClientModeIdx)
+ if !exist || val == nil {
+ return false
+ }
+ v, ok := val.(bool)
+ return v && ok
+}
+
+//LightClientModeConnectionRestricted indicates that connection to light client in light client mode not allowed
+func (whisper *Whisper) LightClientModeConnectionRestricted() bool {
+ val, exist := whisper.settings.Load(restrictConnectionBetweenLightClientsIdx)
+ if !exist || val == nil {
+ return false
+ }
+ v, ok := val.(bool)
+ return v && ok
+}
+
func (whisper *Whisper) notifyPeersAboutPowRequirementChange(pow float64) {
arr := whisper.getPeers()
for _, p := range arr {
@@ -672,7 +698,7 @@ func (whisper *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error {
trouble := false
for _, env := range envelopes {
- cached, err := whisper.add(env, whisper.lightClient)
+ cached, err := whisper.add(env, whisper.LightClientMode())
if err != nil {
trouble = true
log.Error("bad envelope received, peer will be disconnected", "peer", p.peer.ID(), "err", err)