github.com/Openstars/go-ethereum@v1.9.7/les/peer_test.go (about)

     1  // Copyright 2019 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package les
    18  
    19  import (
    20  	"math/big"
    21  	"net"
    22  	"testing"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/common/mclock"
    26  	"github.com/ethereum/go-ethereum/core/rawdb"
    27  	"github.com/ethereum/go-ethereum/crypto"
    28  	"github.com/ethereum/go-ethereum/eth"
    29  	"github.com/ethereum/go-ethereum/les/flowcontrol"
    30  	"github.com/ethereum/go-ethereum/p2p"
    31  	"github.com/ethereum/go-ethereum/p2p/enode"
    32  	"github.com/ethereum/go-ethereum/rlp"
    33  )
    34  
    35  const protocolVersion = lpv2
    36  
    37  var (
    38  	hash    = common.HexToHash("deadbeef")
    39  	genesis = common.HexToHash("cafebabe")
    40  	headNum = uint64(1234)
    41  	td      = big.NewInt(123)
    42  )
    43  
    44  func newNodeID(t *testing.T) *enode.Node {
    45  	key, err := crypto.GenerateKey()
    46  	if err != nil {
    47  		t.Fatal("generate key err:", err)
    48  	}
    49  	return enode.NewV4(&key.PublicKey, net.IP{}, 35000, 35000)
    50  }
    51  
    52  // ulc connects to trusted peer and send announceType=announceTypeSigned
    53  func TestPeerHandshakeSetAnnounceTypeToAnnounceTypeSignedForTrustedPeer(t *testing.T) {
    54  	id := newNodeID(t).ID()
    55  
    56  	// peer to connect(on ulc side)
    57  	p := peer{
    58  		Peer:    p2p.NewPeer(id, "test peer", []p2p.Cap{}),
    59  		version: protocolVersion,
    60  		trusted: true,
    61  		rw: &rwStub{
    62  			WriteHook: func(recvList keyValueList) {
    63  				recv, _ := recvList.decode()
    64  				var reqType uint64
    65  				err := recv.get("announceType", &reqType)
    66  				if err != nil {
    67  					t.Fatal(err)
    68  				}
    69  				if reqType != announceTypeSigned {
    70  					t.Fatal("Expected announceTypeSigned")
    71  				}
    72  			},
    73  			ReadHook: func(l keyValueList) keyValueList {
    74  				l = l.add("serveHeaders", nil)
    75  				l = l.add("serveChainSince", uint64(0))
    76  				l = l.add("serveStateSince", uint64(0))
    77  				l = l.add("txRelay", nil)
    78  				l = l.add("flowControl/BL", uint64(0))
    79  				l = l.add("flowControl/MRR", uint64(0))
    80  				l = l.add("flowControl/MRC", testCostList(0))
    81  				return l
    82  			},
    83  		},
    84  		network: NetworkId,
    85  	}
    86  	err := p.Handshake(td, hash, headNum, genesis, nil)
    87  	if err != nil {
    88  		t.Fatalf("Handshake error: %s", err)
    89  	}
    90  	if p.announceType != announceTypeSigned {
    91  		t.Fatal("Incorrect announceType")
    92  	}
    93  }
    94  
    95  func TestPeerHandshakeAnnounceTypeSignedForTrustedPeersPeerNotInTrusted(t *testing.T) {
    96  	id := newNodeID(t).ID()
    97  	p := peer{
    98  		Peer:    p2p.NewPeer(id, "test peer", []p2p.Cap{}),
    99  		version: protocolVersion,
   100  		rw: &rwStub{
   101  			WriteHook: func(recvList keyValueList) {
   102  				// checking that ulc sends to peer allowedRequests=noRequests and announceType != announceTypeSigned
   103  				recv, _ := recvList.decode()
   104  				var reqType uint64
   105  				err := recv.get("announceType", &reqType)
   106  				if err != nil {
   107  					t.Fatal(err)
   108  				}
   109  				if reqType == announceTypeSigned {
   110  					t.Fatal("Expected not announceTypeSigned")
   111  				}
   112  			},
   113  			ReadHook: func(l keyValueList) keyValueList {
   114  				l = l.add("serveHeaders", nil)
   115  				l = l.add("serveChainSince", uint64(0))
   116  				l = l.add("serveStateSince", uint64(0))
   117  				l = l.add("txRelay", nil)
   118  				l = l.add("flowControl/BL", uint64(0))
   119  				l = l.add("flowControl/MRR", uint64(0))
   120  				l = l.add("flowControl/MRC", testCostList(0))
   121  				return l
   122  			},
   123  		},
   124  		network: NetworkId,
   125  	}
   126  	err := p.Handshake(td, hash, headNum, genesis, nil)
   127  	if err != nil {
   128  		t.Fatal(err)
   129  	}
   130  	if p.announceType == announceTypeSigned {
   131  		t.Fatal("Incorrect announceType")
   132  	}
   133  }
   134  
   135  func TestPeerHandshakeDefaultAllRequests(t *testing.T) {
   136  	id := newNodeID(t).ID()
   137  
   138  	s := generateLesServer()
   139  
   140  	p := peer{
   141  		Peer:    p2p.NewPeer(id, "test peer", []p2p.Cap{}),
   142  		version: protocolVersion,
   143  		rw: &rwStub{
   144  			ReadHook: func(l keyValueList) keyValueList {
   145  				l = l.add("announceType", uint64(announceTypeSigned))
   146  				l = l.add("allowedRequests", uint64(0))
   147  				return l
   148  			},
   149  		},
   150  		network: NetworkId,
   151  	}
   152  
   153  	err := p.Handshake(td, hash, headNum, genesis, s)
   154  	if err != nil {
   155  		t.Fatal(err)
   156  	}
   157  
   158  	if p.onlyAnnounce {
   159  		t.Fatal("Incorrect announceType")
   160  	}
   161  }
   162  
   163  func TestPeerHandshakeServerSendOnlyAnnounceRequestsHeaders(t *testing.T) {
   164  	id := newNodeID(t).ID()
   165  
   166  	s := generateLesServer()
   167  	s.config.UltraLightOnlyAnnounce = true
   168  
   169  	p := peer{
   170  		Peer:    p2p.NewPeer(id, "test peer", []p2p.Cap{}),
   171  		version: protocolVersion,
   172  		rw: &rwStub{
   173  			ReadHook: func(l keyValueList) keyValueList {
   174  				l = l.add("announceType", uint64(announceTypeSigned))
   175  				return l
   176  			},
   177  			WriteHook: func(l keyValueList) {
   178  				for _, v := range l {
   179  					if v.Key == "serveHeaders" ||
   180  						v.Key == "serveChainSince" ||
   181  						v.Key == "serveStateSince" ||
   182  						v.Key == "txRelay" {
   183  						t.Fatalf("%v exists", v.Key)
   184  					}
   185  				}
   186  			},
   187  		},
   188  		network: NetworkId,
   189  	}
   190  
   191  	err := p.Handshake(td, hash, headNum, genesis, s)
   192  	if err != nil {
   193  		t.Fatal(err)
   194  	}
   195  }
   196  func TestPeerHandshakeClientReceiveOnlyAnnounceRequestsHeaders(t *testing.T) {
   197  	id := newNodeID(t).ID()
   198  
   199  	p := peer{
   200  		Peer:    p2p.NewPeer(id, "test peer", []p2p.Cap{}),
   201  		version: protocolVersion,
   202  		rw: &rwStub{
   203  			ReadHook: func(l keyValueList) keyValueList {
   204  				l = l.add("flowControl/BL", uint64(0))
   205  				l = l.add("flowControl/MRR", uint64(0))
   206  				l = l.add("flowControl/MRC", RequestCostList{})
   207  
   208  				l = l.add("announceType", uint64(announceTypeSigned))
   209  
   210  				return l
   211  			},
   212  		},
   213  		network: NetworkId,
   214  		trusted: true,
   215  	}
   216  
   217  	err := p.Handshake(td, hash, headNum, genesis, nil)
   218  	if err != nil {
   219  		t.Fatal(err)
   220  	}
   221  
   222  	if !p.onlyAnnounce {
   223  		t.Fatal("onlyAnnounce must be true")
   224  	}
   225  }
   226  
   227  func TestPeerHandshakeClientReturnErrorOnUselessPeer(t *testing.T) {
   228  	id := newNodeID(t).ID()
   229  
   230  	p := peer{
   231  		Peer:    p2p.NewPeer(id, "test peer", []p2p.Cap{}),
   232  		version: protocolVersion,
   233  		rw: &rwStub{
   234  			ReadHook: func(l keyValueList) keyValueList {
   235  				l = l.add("flowControl/BL", uint64(0))
   236  				l = l.add("flowControl/MRR", uint64(0))
   237  				l = l.add("flowControl/MRC", RequestCostList{})
   238  				l = l.add("announceType", uint64(announceTypeSigned))
   239  				return l
   240  			},
   241  		},
   242  		network: NetworkId,
   243  	}
   244  
   245  	err := p.Handshake(td, hash, headNum, genesis, nil)
   246  	if err == nil {
   247  		t.FailNow()
   248  	}
   249  }
   250  
   251  func generateLesServer() *LesServer {
   252  	s := &LesServer{
   253  		lesCommons: lesCommons{
   254  			config: &eth.Config{UltraLightOnlyAnnounce: true},
   255  		},
   256  		defParams: flowcontrol.ServerParams{
   257  			BufLimit:    uint64(300000000),
   258  			MinRecharge: uint64(50000),
   259  		},
   260  		fcManager: flowcontrol.NewClientManager(nil, &mclock.System{}),
   261  	}
   262  	s.costTracker, _ = newCostTracker(rawdb.NewMemoryDatabase(), s.config)
   263  	return s
   264  }
   265  
   266  type rwStub struct {
   267  	ReadHook  func(l keyValueList) keyValueList
   268  	WriteHook func(l keyValueList)
   269  }
   270  
   271  func (s *rwStub) ReadMsg() (p2p.Msg, error) {
   272  	payload := keyValueList{}
   273  	payload = payload.add("protocolVersion", uint64(protocolVersion))
   274  	payload = payload.add("networkId", uint64(NetworkId))
   275  	payload = payload.add("headTd", td)
   276  	payload = payload.add("headHash", hash)
   277  	payload = payload.add("headNum", headNum)
   278  	payload = payload.add("genesisHash", genesis)
   279  
   280  	if s.ReadHook != nil {
   281  		payload = s.ReadHook(payload)
   282  	}
   283  	size, p, err := rlp.EncodeToReader(payload)
   284  	if err != nil {
   285  		return p2p.Msg{}, err
   286  	}
   287  	return p2p.Msg{
   288  		Size:    uint32(size),
   289  		Payload: p,
   290  	}, nil
   291  }
   292  
   293  func (s *rwStub) WriteMsg(m p2p.Msg) error {
   294  	recvList := keyValueList{}
   295  	if err := m.Decode(&recvList); err != nil {
   296  		return err
   297  	}
   298  	if s.WriteHook != nil {
   299  		s.WriteHook(recvList)
   300  	}
   301  	return nil
   302  }