github.com/gilgames000/kcc-geth@v1.0.6/cmd/devp2p/internal/ethtest/eth66_suite.go (about)

     1  // Copyright 2021 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 ethtest
    18  
    19  import (
    20  	"time"
    21  
    22  	"github.com/ethereum/go-ethereum/core/types"
    23  	"github.com/ethereum/go-ethereum/crypto"
    24  	"github.com/ethereum/go-ethereum/eth/protocols/eth"
    25  	"github.com/ethereum/go-ethereum/internal/utesting"
    26  	"github.com/ethereum/go-ethereum/p2p"
    27  )
    28  
    29  // TestStatus_66 attempts to connect to the given node and exchange
    30  // a status message with it on the eth66 protocol, and then check to
    31  // make sure the chain head is correct.
    32  func (s *Suite) TestStatus_66(t *utesting.T) {
    33  	conn := s.dial66(t)
    34  	// get protoHandshake
    35  	conn.handshake(t)
    36  	// get status
    37  	switch msg := conn.statusExchange66(t, s.chain).(type) {
    38  	case *Status:
    39  		status := *msg
    40  		if status.ProtocolVersion != uint32(66) {
    41  			t.Fatalf("mismatch in version: wanted 66, got %d", status.ProtocolVersion)
    42  		}
    43  		t.Logf("got status message: %s", pretty.Sdump(msg))
    44  	default:
    45  		t.Fatalf("unexpected: %s", pretty.Sdump(msg))
    46  	}
    47  }
    48  
    49  // TestGetBlockHeaders_66 tests whether the given node can respond to
    50  // an eth66 `GetBlockHeaders` request and that the response is accurate.
    51  func (s *Suite) TestGetBlockHeaders_66(t *utesting.T) {
    52  	conn := s.setupConnection66(t)
    53  	// get block headers
    54  	req := &eth.GetBlockHeadersPacket66{
    55  		RequestId: 3,
    56  		GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
    57  			Origin: eth.HashOrNumber{
    58  				Hash: s.chain.blocks[1].Hash(),
    59  			},
    60  			Amount:  2,
    61  			Skip:    1,
    62  			Reverse: false,
    63  		},
    64  	}
    65  	// write message
    66  	headers := s.getBlockHeaders66(t, conn, req, req.RequestId)
    67  	// check for correct headers
    68  	headersMatch(t, s.chain, headers)
    69  }
    70  
    71  // TestSimultaneousRequests_66 sends two simultaneous `GetBlockHeader` requests
    72  // with different request IDs and checks to make sure the node responds with the correct
    73  // headers per request.
    74  func (s *Suite) TestSimultaneousRequests_66(t *utesting.T) {
    75  	// create two connections
    76  	conn1, conn2 := s.setupConnection66(t), s.setupConnection66(t)
    77  	// create two requests
    78  	req1 := &eth.GetBlockHeadersPacket66{
    79  		RequestId: 111,
    80  		GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
    81  			Origin: eth.HashOrNumber{
    82  				Hash: s.chain.blocks[1].Hash(),
    83  			},
    84  			Amount:  2,
    85  			Skip:    1,
    86  			Reverse: false,
    87  		},
    88  	}
    89  	req2 := &eth.GetBlockHeadersPacket66{
    90  		RequestId: 222,
    91  		GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
    92  			Origin: eth.HashOrNumber{
    93  				Hash: s.chain.blocks[1].Hash(),
    94  			},
    95  			Amount:  4,
    96  			Skip:    1,
    97  			Reverse: false,
    98  		},
    99  	}
   100  	// wait for headers for first request
   101  	headerChan := make(chan BlockHeaders, 1)
   102  	go func(headers chan BlockHeaders) {
   103  		headers <- s.getBlockHeaders66(t, conn1, req1, req1.RequestId)
   104  	}(headerChan)
   105  	// check headers of second request
   106  	headersMatch(t, s.chain, s.getBlockHeaders66(t, conn2, req2, req2.RequestId))
   107  	// check headers of first request
   108  	headersMatch(t, s.chain, <-headerChan)
   109  }
   110  
   111  // TestBroadcast_66 tests whether a block announcement is correctly
   112  // propagated to the given node's peer(s) on the eth66 protocol.
   113  func (s *Suite) TestBroadcast_66(t *utesting.T) {
   114  	sendConn, receiveConn := s.setupConnection66(t), s.setupConnection66(t)
   115  	nextBlock := len(s.chain.blocks)
   116  	blockAnnouncement := &NewBlock{
   117  		Block: s.fullChain.blocks[nextBlock],
   118  		TD:    s.fullChain.TD(nextBlock + 1),
   119  	}
   120  	s.testAnnounce66(t, sendConn, receiveConn, blockAnnouncement)
   121  	// update test suite chain
   122  	s.chain.blocks = append(s.chain.blocks, s.fullChain.blocks[nextBlock])
   123  	// wait for client to update its chain
   124  	if err := receiveConn.waitForBlock66(s.chain.Head()); err != nil {
   125  		t.Fatal(err)
   126  	}
   127  }
   128  
   129  // TestGetBlockBodies_66 tests whether the given node can respond to
   130  // a `GetBlockBodies` request and that the response is accurate over
   131  // the eth66 protocol.
   132  func (s *Suite) TestGetBlockBodies_66(t *utesting.T) {
   133  	conn := s.setupConnection66(t)
   134  	// create block bodies request
   135  	id := uint64(55)
   136  	req := &eth.GetBlockBodiesPacket66{
   137  		RequestId: id,
   138  		GetBlockBodiesPacket: eth.GetBlockBodiesPacket{
   139  			s.chain.blocks[54].Hash(),
   140  			s.chain.blocks[75].Hash(),
   141  		},
   142  	}
   143  	if err := conn.write66(req, GetBlockBodies{}.Code()); err != nil {
   144  		t.Fatalf("could not write to connection: %v", err)
   145  	}
   146  
   147  	reqID, msg := conn.readAndServe66(s.chain, timeout)
   148  	switch msg := msg.(type) {
   149  	case BlockBodies:
   150  		if reqID != req.RequestId {
   151  			t.Fatalf("request ID mismatch: wanted %d, got %d", req.RequestId, reqID)
   152  		}
   153  		t.Logf("received %d block bodies", len(msg))
   154  	default:
   155  		t.Fatalf("unexpected: %s", pretty.Sdump(msg))
   156  	}
   157  }
   158  
   159  // TestLargeAnnounce_66 tests the announcement mechanism with a large block.
   160  func (s *Suite) TestLargeAnnounce_66(t *utesting.T) {
   161  	nextBlock := len(s.chain.blocks)
   162  	blocks := []*NewBlock{
   163  		{
   164  			Block: largeBlock(),
   165  			TD:    s.fullChain.TD(nextBlock + 1),
   166  		},
   167  		{
   168  			Block: s.fullChain.blocks[nextBlock],
   169  			TD:    largeNumber(2),
   170  		},
   171  		{
   172  			Block: largeBlock(),
   173  			TD:    largeNumber(2),
   174  		},
   175  		{
   176  			Block: s.fullChain.blocks[nextBlock],
   177  			TD:    s.fullChain.TD(nextBlock + 1),
   178  		},
   179  	}
   180  
   181  	for i, blockAnnouncement := range blocks[0:3] {
   182  		t.Logf("Testing malicious announcement: %v\n", i)
   183  		sendConn := s.setupConnection66(t)
   184  		if err := sendConn.Write(blockAnnouncement); err != nil {
   185  			t.Fatalf("could not write to connection: %v", err)
   186  		}
   187  		// Invalid announcement, check that peer disconnected
   188  		switch msg := sendConn.ReadAndServe(s.chain, timeout).(type) {
   189  		case *Disconnect:
   190  		case *Error:
   191  			break
   192  		default:
   193  			t.Fatalf("unexpected: %s wanted disconnect", pretty.Sdump(msg))
   194  		}
   195  	}
   196  	// Test the last block as a valid block
   197  	sendConn := s.setupConnection66(t)
   198  	receiveConn := s.setupConnection66(t)
   199  	s.testAnnounce66(t, sendConn, receiveConn, blocks[3])
   200  	// update test suite chain
   201  	s.chain.blocks = append(s.chain.blocks, s.fullChain.blocks[nextBlock])
   202  	// wait for client to update its chain
   203  	if err := receiveConn.waitForBlock66(s.fullChain.blocks[nextBlock]); err != nil {
   204  		t.Fatal(err)
   205  	}
   206  }
   207  
   208  // TestMaliciousHandshake_66 tries to send malicious data during the handshake.
   209  func (s *Suite) TestMaliciousHandshake_66(t *utesting.T) {
   210  	conn := s.dial66(t)
   211  	// write hello to client
   212  	pub0 := crypto.FromECDSAPub(&conn.ourKey.PublicKey)[1:]
   213  	handshakes := []*Hello{
   214  		{
   215  			Version: 5,
   216  			Caps: []p2p.Cap{
   217  				{Name: largeString(2), Version: 66},
   218  			},
   219  			ID: pub0,
   220  		},
   221  		{
   222  			Version: 5,
   223  			Caps: []p2p.Cap{
   224  				{Name: "eth", Version: 64},
   225  				{Name: "eth", Version: 65},
   226  				{Name: "eth", Version: 66},
   227  			},
   228  			ID: append(pub0, byte(0)),
   229  		},
   230  		{
   231  			Version: 5,
   232  			Caps: []p2p.Cap{
   233  				{Name: "eth", Version: 64},
   234  				{Name: "eth", Version: 65},
   235  				{Name: "eth", Version: 66},
   236  			},
   237  			ID: append(pub0, pub0...),
   238  		},
   239  		{
   240  			Version: 5,
   241  			Caps: []p2p.Cap{
   242  				{Name: "eth", Version: 64},
   243  				{Name: "eth", Version: 65},
   244  				{Name: "eth", Version: 66},
   245  			},
   246  			ID: largeBuffer(2),
   247  		},
   248  		{
   249  			Version: 5,
   250  			Caps: []p2p.Cap{
   251  				{Name: largeString(2), Version: 66},
   252  			},
   253  			ID: largeBuffer(2),
   254  		},
   255  	}
   256  	for i, handshake := range handshakes {
   257  		t.Logf("Testing malicious handshake %v\n", i)
   258  		// Init the handshake
   259  		if err := conn.Write(handshake); err != nil {
   260  			t.Fatalf("could not write to connection: %v", err)
   261  		}
   262  		// check that the peer disconnected
   263  		timeout := 20 * time.Second
   264  		// Discard one hello
   265  		for i := 0; i < 2; i++ {
   266  			switch msg := conn.ReadAndServe(s.chain, timeout).(type) {
   267  			case *Disconnect:
   268  			case *Error:
   269  			case *Hello:
   270  				// Hello's are sent concurrently, so ignore them
   271  				continue
   272  			default:
   273  				t.Fatalf("unexpected: %s", pretty.Sdump(msg))
   274  			}
   275  		}
   276  		// Dial for the next round
   277  		conn = s.dial66(t)
   278  	}
   279  }
   280  
   281  // TestMaliciousStatus_66 sends a status package with a large total difficulty.
   282  func (s *Suite) TestMaliciousStatus_66(t *utesting.T) {
   283  	conn := s.dial66(t)
   284  	// get protoHandshake
   285  	conn.handshake(t)
   286  	status := &Status{
   287  		ProtocolVersion: uint32(66),
   288  		NetworkID:       s.chain.chainConfig.ChainID.Uint64(),
   289  		TD:              largeNumber(2),
   290  		Head:            s.chain.blocks[s.chain.Len()-1].Hash(),
   291  		Genesis:         s.chain.blocks[0].Hash(),
   292  		ForkID:          s.chain.ForkID(),
   293  	}
   294  	// get status
   295  	switch msg := conn.statusExchange(t, s.chain, status).(type) {
   296  	case *Status:
   297  		t.Logf("%+v\n", msg)
   298  	default:
   299  		t.Fatalf("expected status, got: %#v ", msg)
   300  	}
   301  	// wait for disconnect
   302  	switch msg := conn.ReadAndServe(s.chain, timeout).(type) {
   303  	case *Disconnect:
   304  	case *Error:
   305  		return
   306  	default:
   307  		t.Fatalf("expected disconnect, got: %s", pretty.Sdump(msg))
   308  	}
   309  }
   310  
   311  func (s *Suite) TestTransaction_66(t *utesting.T) {
   312  	tests := []*types.Transaction{
   313  		getNextTxFromChain(t, s),
   314  		unknownTx(t, s),
   315  	}
   316  	for i, tx := range tests {
   317  		t.Logf("Testing tx propagation: %v\n", i)
   318  		sendSuccessfulTx66(t, s, tx)
   319  	}
   320  }
   321  
   322  func (s *Suite) TestMaliciousTx_66(t *utesting.T) {
   323  	tests := []*types.Transaction{
   324  		getOldTxFromChain(t, s),
   325  		invalidNonceTx(t, s),
   326  		hugeAmount(t, s),
   327  		hugeGasPrice(t, s),
   328  		hugeData(t, s),
   329  	}
   330  	for i, tx := range tests {
   331  		t.Logf("Testing malicious tx propagation: %v\n", i)
   332  		sendFailingTx66(t, s, tx)
   333  	}
   334  }
   335  
   336  // TestZeroRequestID_66 checks that a request ID of zero is still handled
   337  // by the node.
   338  func (s *Suite) TestZeroRequestID_66(t *utesting.T) {
   339  	conn := s.setupConnection66(t)
   340  	req := &eth.GetBlockHeadersPacket66{
   341  		RequestId: 0,
   342  		GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
   343  			Origin: eth.HashOrNumber{
   344  				Number: 0,
   345  			},
   346  			Amount: 2,
   347  		},
   348  	}
   349  	headersMatch(t, s.chain, s.getBlockHeaders66(t, conn, req, req.RequestId))
   350  }
   351  
   352  // TestSameRequestID_66 sends two requests with the same request ID
   353  // concurrently to a single node.
   354  func (s *Suite) TestSameRequestID_66(t *utesting.T) {
   355  	conn := s.setupConnection66(t)
   356  	// create two separate requests with same ID
   357  	reqID := uint64(1234)
   358  	req1 := &eth.GetBlockHeadersPacket66{
   359  		RequestId: reqID,
   360  		GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
   361  			Origin: eth.HashOrNumber{
   362  				Number: 0,
   363  			},
   364  			Amount: 2,
   365  		},
   366  	}
   367  	req2 := &eth.GetBlockHeadersPacket66{
   368  		RequestId: reqID,
   369  		GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
   370  			Origin: eth.HashOrNumber{
   371  				Number: 33,
   372  			},
   373  			Amount: 2,
   374  		},
   375  	}
   376  	// send requests concurrently
   377  	go func() {
   378  		headersMatch(t, s.chain, s.getBlockHeaders66(t, conn, req2, reqID))
   379  	}()
   380  	// check response from first request
   381  	headersMatch(t, s.chain, s.getBlockHeaders66(t, conn, req1, reqID))
   382  }