github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/cmd/devp2p/internal/ethtest/suite.go (about)

     1  // Copyright 2020 The go-ethereum Authors
     2  // This file is part of go-ethereum.
     3  //
     4  // go-ethereum is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU 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  // go-ethereum 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 General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU General Public License
    15  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package ethtest
    18  
    19  import (
    20  	"crypto/rand"
    21  	"math/big"
    22  	"reflect"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
    26  	"github.com/ethereum/go-ethereum/core/types"
    27  	"github.com/ethereum/go-ethereum/crypto"
    28  	"github.com/ethereum/go-ethereum/crypto/kzg4844"
    29  	"github.com/ethereum/go-ethereum/eth/protocols/eth"
    30  	"github.com/ethereum/go-ethereum/internal/utesting"
    31  	"github.com/ethereum/go-ethereum/p2p"
    32  	"github.com/ethereum/go-ethereum/p2p/enode"
    33  	"github.com/holiman/uint256"
    34  )
    35  
    36  // Suite represents a structure used to test a node's conformance
    37  // to the eth protocol.
    38  type Suite struct {
    39  	Dest   *enode.Node
    40  	chain  *Chain
    41  	engine *EngineClient
    42  }
    43  
    44  // NewSuite creates and returns a new eth-test suite that can
    45  // be used to test the given node against the given blockchain
    46  // data.
    47  func NewSuite(dest *enode.Node, chainDir, engineURL, jwt string) (*Suite, error) {
    48  	chain, err := NewChain(chainDir)
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  	engine, err := NewEngineClient(chainDir, engineURL, jwt)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  
    57  	return &Suite{
    58  		Dest:   dest,
    59  		chain:  chain,
    60  		engine: engine,
    61  	}, nil
    62  }
    63  
    64  func (s *Suite) EthTests() []utesting.Test {
    65  	return []utesting.Test{
    66  		// status
    67  		{Name: "Status", Fn: s.TestStatus},
    68  		// get block headers
    69  		{Name: "GetBlockHeaders", Fn: s.TestGetBlockHeaders},
    70  		{Name: "SimultaneousRequests", Fn: s.TestSimultaneousRequests},
    71  		{Name: "SameRequestID", Fn: s.TestSameRequestID},
    72  		{Name: "ZeroRequestID", Fn: s.TestZeroRequestID},
    73  		// get block bodies
    74  		{Name: "GetBlockBodies", Fn: s.TestGetBlockBodies},
    75  		// // malicious handshakes + status
    76  		{Name: "MaliciousHandshake", Fn: s.TestMaliciousHandshake},
    77  		{Name: "MaliciousStatus", Fn: s.TestMaliciousStatus},
    78  		// test transactions
    79  		{Name: "LargeTxRequest", Fn: s.TestLargeTxRequest, Slow: true},
    80  		{Name: "Transaction", Fn: s.TestTransaction},
    81  		{Name: "InvalidTxs", Fn: s.TestInvalidTxs},
    82  		{Name: "NewPooledTxs", Fn: s.TestNewPooledTxs},
    83  		{Name: "BlobViolations", Fn: s.TestBlobViolations},
    84  	}
    85  }
    86  
    87  func (s *Suite) SnapTests() []utesting.Test {
    88  	return []utesting.Test{
    89  		{Name: "Status", Fn: s.TestSnapStatus},
    90  		{Name: "AccountRange", Fn: s.TestSnapGetAccountRange},
    91  		{Name: "GetByteCodes", Fn: s.TestSnapGetByteCodes},
    92  		{Name: "GetTrieNodes", Fn: s.TestSnapTrieNodes},
    93  		{Name: "GetStorageRanges", Fn: s.TestSnapGetStorageRanges},
    94  	}
    95  }
    96  
    97  func (s *Suite) TestStatus(t *utesting.T) {
    98  	t.Log(`This test is just a sanity check. It performs an eth protocol handshake.`)
    99  
   100  	conn, err := s.dial()
   101  	if err != nil {
   102  		t.Fatalf("dial failed: %v", err)
   103  	}
   104  	defer conn.Close()
   105  	if err := conn.peer(s.chain, nil); err != nil {
   106  		t.Fatalf("peering failed: %v", err)
   107  	}
   108  }
   109  
   110  // headersMatch returns whether the received headers match the given request
   111  func headersMatch(expected []*types.Header, headers []*types.Header) bool {
   112  	return reflect.DeepEqual(expected, headers)
   113  }
   114  
   115  func (s *Suite) TestGetBlockHeaders(t *utesting.T) {
   116  	t.Log(`This test requests block headers from the node.`)
   117  
   118  	conn, err := s.dial()
   119  	if err != nil {
   120  		t.Fatalf("dial failed: %v", err)
   121  	}
   122  	defer conn.Close()
   123  	if err = conn.peer(s.chain, nil); err != nil {
   124  		t.Fatalf("peering failed: %v", err)
   125  	}
   126  	// Send headers request.
   127  	req := &eth.GetBlockHeadersPacket{
   128  		RequestId: 33,
   129  		GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{
   130  			Origin:  eth.HashOrNumber{Hash: s.chain.blocks[1].Hash()},
   131  			Amount:  2,
   132  			Skip:    1,
   133  			Reverse: false,
   134  		},
   135  	}
   136  	// Read headers response.
   137  	if err := conn.Write(ethProto, eth.GetBlockHeadersMsg, req); err != nil {
   138  		t.Fatalf("could not write to connection: %v", err)
   139  	}
   140  	headers := new(eth.BlockHeadersPacket)
   141  	if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers); err != nil {
   142  		t.Fatalf("error reading msg: %v", err)
   143  	}
   144  	if got, want := headers.RequestId, req.RequestId; got != want {
   145  		t.Fatalf("unexpected request id")
   146  	}
   147  	// Check for correct headers.
   148  	expected, err := s.chain.GetHeaders(req)
   149  	if err != nil {
   150  		t.Fatalf("failed to get headers for given request: %v", err)
   151  	}
   152  	if !headersMatch(expected, headers.BlockHeadersRequest) {
   153  		t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers)
   154  	}
   155  }
   156  
   157  func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
   158  	t.Log(`This test requests blocks headers from the node, performing two requests
   159  concurrently, with different request IDs.`)
   160  
   161  	conn, err := s.dial()
   162  	if err != nil {
   163  		t.Fatalf("dial failed: %v", err)
   164  	}
   165  	defer conn.Close()
   166  	if err := conn.peer(s.chain, nil); err != nil {
   167  		t.Fatalf("peering failed: %v", err)
   168  	}
   169  
   170  	// Create two different requests.
   171  	req1 := &eth.GetBlockHeadersPacket{
   172  		RequestId: uint64(111),
   173  		GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{
   174  			Origin: eth.HashOrNumber{
   175  				Hash: s.chain.blocks[1].Hash(),
   176  			},
   177  			Amount:  2,
   178  			Skip:    1,
   179  			Reverse: false,
   180  		},
   181  	}
   182  	req2 := &eth.GetBlockHeadersPacket{
   183  		RequestId: uint64(222),
   184  		GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{
   185  			Origin: eth.HashOrNumber{
   186  				Hash: s.chain.blocks[1].Hash(),
   187  			},
   188  			Amount:  4,
   189  			Skip:    1,
   190  			Reverse: false,
   191  		},
   192  	}
   193  
   194  	// Send both requests.
   195  	if err := conn.Write(ethProto, eth.GetBlockHeadersMsg, req1); err != nil {
   196  		t.Fatalf("failed to write to connection: %v", err)
   197  	}
   198  	if err := conn.Write(ethProto, eth.GetBlockHeadersMsg, req2); err != nil {
   199  		t.Fatalf("failed to write to connection: %v", err)
   200  	}
   201  
   202  	// Wait for responses.
   203  	headers1 := new(eth.BlockHeadersPacket)
   204  	if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers1); err != nil {
   205  		t.Fatalf("error reading block headers msg: %v", err)
   206  	}
   207  	if got, want := headers1.RequestId, req1.RequestId; got != want {
   208  		t.Fatalf("unexpected request id in response: got %d, want %d", got, want)
   209  	}
   210  	headers2 := new(eth.BlockHeadersPacket)
   211  	if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers2); err != nil {
   212  		t.Fatalf("error reading block headers msg: %v", err)
   213  	}
   214  	if got, want := headers2.RequestId, req2.RequestId; got != want {
   215  		t.Fatalf("unexpected request id in response: got %d, want %d", got, want)
   216  	}
   217  
   218  	// Check received headers for accuracy.
   219  	if expected, err := s.chain.GetHeaders(req1); err != nil {
   220  		t.Fatalf("failed to get expected headers for request 1: %v", err)
   221  	} else if !headersMatch(expected, headers1.BlockHeadersRequest) {
   222  		t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers1)
   223  	}
   224  	if expected, err := s.chain.GetHeaders(req2); err != nil {
   225  		t.Fatalf("failed to get expected headers for request 2: %v", err)
   226  	} else if !headersMatch(expected, headers2.BlockHeadersRequest) {
   227  		t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers2)
   228  	}
   229  }
   230  
   231  func (s *Suite) TestSameRequestID(t *utesting.T) {
   232  	t.Log(`This test requests block headers, performing two concurrent requests with the
   233  same request ID. The node should handle the request by responding to both requests.`)
   234  
   235  	conn, err := s.dial()
   236  	if err != nil {
   237  		t.Fatalf("dial failed: %v", err)
   238  	}
   239  	defer conn.Close()
   240  	if err := conn.peer(s.chain, nil); err != nil {
   241  		t.Fatalf("peering failed: %v", err)
   242  	}
   243  
   244  	// Create two different requests with the same ID.
   245  	reqID := uint64(1234)
   246  	request1 := &eth.GetBlockHeadersPacket{
   247  		RequestId: reqID,
   248  		GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{
   249  			Origin: eth.HashOrNumber{
   250  				Number: 1,
   251  			},
   252  			Amount: 2,
   253  		},
   254  	}
   255  	request2 := &eth.GetBlockHeadersPacket{
   256  		RequestId: reqID,
   257  		GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{
   258  			Origin: eth.HashOrNumber{
   259  				Number: 33,
   260  			},
   261  			Amount: 2,
   262  		},
   263  	}
   264  
   265  	// Send the requests.
   266  	if err = conn.Write(ethProto, eth.GetBlockHeadersMsg, request1); err != nil {
   267  		t.Fatalf("failed to write to connection: %v", err)
   268  	}
   269  	if err = conn.Write(ethProto, eth.GetBlockHeadersMsg, request2); err != nil {
   270  		t.Fatalf("failed to write to connection: %v", err)
   271  	}
   272  
   273  	// Wait for the responses.
   274  	headers1 := new(eth.BlockHeadersPacket)
   275  	if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers1); err != nil {
   276  		t.Fatalf("error reading from connection: %v", err)
   277  	}
   278  	if got, want := headers1.RequestId, request1.RequestId; got != want {
   279  		t.Fatalf("unexpected request id: got %d, want %d", got, want)
   280  	}
   281  	headers2 := new(eth.BlockHeadersPacket)
   282  	if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers2); err != nil {
   283  		t.Fatalf("error reading from connection: %v", err)
   284  	}
   285  	if got, want := headers2.RequestId, request2.RequestId; got != want {
   286  		t.Fatalf("unexpected request id: got %d, want %d", got, want)
   287  	}
   288  
   289  	// Check if headers match.
   290  	if expected, err := s.chain.GetHeaders(request1); err != nil {
   291  		t.Fatalf("failed to get expected block headers: %v", err)
   292  	} else if !headersMatch(expected, headers1.BlockHeadersRequest) {
   293  		t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers1)
   294  	}
   295  	if expected, err := s.chain.GetHeaders(request2); err != nil {
   296  		t.Fatalf("failed to get expected block headers: %v", err)
   297  	} else if !headersMatch(expected, headers2.BlockHeadersRequest) {
   298  		t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers2)
   299  	}
   300  }
   301  
   302  func (s *Suite) TestZeroRequestID(t *utesting.T) {
   303  	t.Log(`This test sends a GetBlockHeaders message with a request-id of zero,
   304  and expects a response.`)
   305  
   306  	conn, err := s.dial()
   307  	if err != nil {
   308  		t.Fatalf("dial failed: %v", err)
   309  	}
   310  	defer conn.Close()
   311  	if err := conn.peer(s.chain, nil); err != nil {
   312  		t.Fatalf("peering failed: %v", err)
   313  	}
   314  	req := &eth.GetBlockHeadersPacket{
   315  		GetBlockHeadersRequest: &eth.GetBlockHeadersRequest{
   316  			Origin: eth.HashOrNumber{Number: 0},
   317  			Amount: 2,
   318  		},
   319  	}
   320  	// Read headers response.
   321  	if err := conn.Write(ethProto, eth.GetBlockHeadersMsg, req); err != nil {
   322  		t.Fatalf("could not write to connection: %v", err)
   323  	}
   324  	headers := new(eth.BlockHeadersPacket)
   325  	if err := conn.ReadMsg(ethProto, eth.BlockHeadersMsg, &headers); err != nil {
   326  		t.Fatalf("error reading msg: %v", err)
   327  	}
   328  	if got, want := headers.RequestId, req.RequestId; got != want {
   329  		t.Fatalf("unexpected request id")
   330  	}
   331  	if expected, err := s.chain.GetHeaders(req); err != nil {
   332  		t.Fatalf("failed to get expected block headers: %v", err)
   333  	} else if !headersMatch(expected, headers.BlockHeadersRequest) {
   334  		t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers)
   335  	}
   336  }
   337  
   338  func (s *Suite) TestGetBlockBodies(t *utesting.T) {
   339  	t.Log(`This test sends GetBlockBodies requests to the node for known blocks in the test chain.`)
   340  
   341  	conn, err := s.dial()
   342  	if err != nil {
   343  		t.Fatalf("dial failed: %v", err)
   344  	}
   345  	defer conn.Close()
   346  	if err := conn.peer(s.chain, nil); err != nil {
   347  		t.Fatalf("peering failed: %v", err)
   348  	}
   349  	// Create block bodies request.
   350  	req := &eth.GetBlockBodiesPacket{
   351  		RequestId: 55,
   352  		GetBlockBodiesRequest: eth.GetBlockBodiesRequest{
   353  			s.chain.blocks[54].Hash(),
   354  			s.chain.blocks[75].Hash(),
   355  		},
   356  	}
   357  	if err := conn.Write(ethProto, eth.GetBlockBodiesMsg, req); err != nil {
   358  		t.Fatalf("could not write to connection: %v", err)
   359  	}
   360  	// Wait for response.
   361  	resp := new(eth.BlockBodiesPacket)
   362  	if err := conn.ReadMsg(ethProto, eth.BlockBodiesMsg, &resp); err != nil {
   363  		t.Fatalf("error reading block bodies msg: %v", err)
   364  	}
   365  	if got, want := resp.RequestId, req.RequestId; got != want {
   366  		t.Fatalf("unexpected request id in respond", got, want)
   367  	}
   368  	bodies := resp.BlockBodiesResponse
   369  	if len(bodies) != len(req.GetBlockBodiesRequest) {
   370  		t.Fatalf("wrong bodies in response: expected %d bodies, got %d", len(req.GetBlockBodiesRequest), len(bodies))
   371  	}
   372  }
   373  
   374  // randBuf makes a random buffer size kilobytes large.
   375  func randBuf(size int) []byte {
   376  	buf := make([]byte, size*1024)
   377  	rand.Read(buf)
   378  	return buf
   379  }
   380  
   381  func (s *Suite) TestMaliciousHandshake(t *utesting.T) {
   382  	t.Log(`This test tries to send malicious data during the devp2p handshake, in various ways.`)
   383  
   384  	// Write hello to client.
   385  	var (
   386  		key, _  = crypto.GenerateKey()
   387  		pub0    = crypto.FromECDSAPub(&key.PublicKey)[1:]
   388  		version = eth.ProtocolVersions[0]
   389  	)
   390  	handshakes := []*protoHandshake{
   391  		{
   392  			Version: 5,
   393  			Caps: []p2p.Cap{
   394  				{Name: string(randBuf(2)), Version: version},
   395  			},
   396  			ID: pub0,
   397  		},
   398  		{
   399  			Version: 5,
   400  			Caps: []p2p.Cap{
   401  				{Name: "eth", Version: version},
   402  			},
   403  			ID: append(pub0, byte(0)),
   404  		},
   405  		{
   406  			Version: 5,
   407  			Caps: []p2p.Cap{
   408  				{Name: "eth", Version: version},
   409  			},
   410  			ID: append(pub0, pub0...),
   411  		},
   412  		{
   413  			Version: 5,
   414  			Caps: []p2p.Cap{
   415  				{Name: "eth", Version: version},
   416  			},
   417  			ID: randBuf(2),
   418  		},
   419  		{
   420  			Version: 5,
   421  			Caps: []p2p.Cap{
   422  				{Name: string(randBuf(2)), Version: version},
   423  			},
   424  			ID: randBuf(2),
   425  		},
   426  	}
   427  	for _, handshake := range handshakes {
   428  		conn, err := s.dialAs(key)
   429  		if err != nil {
   430  			t.Fatalf("dial failed: %v", err)
   431  		}
   432  		defer conn.Close()
   433  
   434  		if err := conn.Write(ethProto, handshakeMsg, handshake); err != nil {
   435  			t.Fatalf("could not write to connection: %v", err)
   436  		}
   437  		// Check that the peer disconnected
   438  		for i := 0; i < 2; i++ {
   439  			code, _, err := conn.Read()
   440  			if err != nil {
   441  				// Client may have disconnected without sending disconnect msg.
   442  				continue
   443  			}
   444  			switch code {
   445  			case discMsg:
   446  			case handshakeMsg:
   447  				// Discard one hello as Hello's are sent concurrently
   448  				continue
   449  			default:
   450  				t.Fatalf("unexpected msg: code %d", code)
   451  			}
   452  		}
   453  	}
   454  }
   455  
   456  func (s *Suite) TestMaliciousStatus(t *utesting.T) {
   457  	t.Log(`This test sends a malicious eth Status message to the node and expects a disconnect.`)
   458  
   459  	conn, err := s.dial()
   460  	if err != nil {
   461  		t.Fatalf("dial failed: %v", err)
   462  	}
   463  	defer conn.Close()
   464  	if err := conn.handshake(); err != nil {
   465  		t.Fatalf("handshake failed: %v", err)
   466  	}
   467  	// Create status with large total difficulty.
   468  	status := &eth.StatusPacket{
   469  		ProtocolVersion: uint32(conn.negotiatedProtoVersion),
   470  		NetworkID:       s.chain.config.ChainID.Uint64(),
   471  		TD:              new(big.Int).SetBytes(randBuf(2048)),
   472  		Head:            s.chain.Head().Hash(),
   473  		Genesis:         s.chain.GetBlock(0).Hash(),
   474  		ForkID:          s.chain.ForkID(),
   475  	}
   476  	if err := conn.statusExchange(s.chain, status); err != nil {
   477  		t.Fatalf("status exchange failed: %v", err)
   478  	}
   479  	// Wait for disconnect.
   480  	code, _, err := conn.Read()
   481  	if err != nil {
   482  		t.Fatalf("error reading from connection: %v", err)
   483  	}
   484  	switch code {
   485  	case discMsg:
   486  		break
   487  	default:
   488  		t.Fatalf("expected disconnect, got: %d", code)
   489  	}
   490  }
   491  
   492  func (s *Suite) TestTransaction(t *utesting.T) {
   493  	t.Log(`This test sends a valid transaction to the node and checks if the
   494  transaction gets propagated.`)
   495  
   496  	// Nudge client out of syncing mode to accept pending txs.
   497  	if err := s.engine.sendForkchoiceUpdated(); err != nil {
   498  		t.Fatalf("failed to send next block: %v", err)
   499  	}
   500  	from, nonce := s.chain.GetSender(0)
   501  	inner := &types.DynamicFeeTx{
   502  		ChainID:   s.chain.config.ChainID,
   503  		Nonce:     nonce,
   504  		GasTipCap: common.Big1,
   505  		GasFeeCap: s.chain.Head().BaseFee(),
   506  		Gas:       30000,
   507  		To:        &common.Address{0xaa},
   508  		Value:     common.Big1,
   509  	}
   510  	tx, err := s.chain.SignTx(from, types.NewTx(inner))
   511  	if err != nil {
   512  		t.Fatalf("failed to sign tx: %v", err)
   513  	}
   514  	if err := s.sendTxs(t, []*types.Transaction{tx}); err != nil {
   515  		t.Fatal(err)
   516  	}
   517  	s.chain.IncNonce(from, 1)
   518  }
   519  
   520  func (s *Suite) TestInvalidTxs(t *utesting.T) {
   521  	t.Log(`This test sends several kinds of invalid transactions and checks that the node
   522  does not propagate them.`)
   523  
   524  	// Nudge client out of syncing mode to accept pending txs.
   525  	if err := s.engine.sendForkchoiceUpdated(); err != nil {
   526  		t.Fatalf("failed to send next block: %v", err)
   527  	}
   528  
   529  	from, nonce := s.chain.GetSender(0)
   530  	inner := &types.DynamicFeeTx{
   531  		ChainID:   s.chain.config.ChainID,
   532  		Nonce:     nonce,
   533  		GasTipCap: common.Big1,
   534  		GasFeeCap: s.chain.Head().BaseFee(),
   535  		Gas:       30000,
   536  		To:        &common.Address{0xaa},
   537  	}
   538  	tx, err := s.chain.SignTx(from, types.NewTx(inner))
   539  	if err != nil {
   540  		t.Fatalf("failed to sign tx: %v", err)
   541  	}
   542  	if err := s.sendTxs(t, []*types.Transaction{tx}); err != nil {
   543  		t.Fatalf("failed to send txs: %v", err)
   544  	}
   545  	s.chain.IncNonce(from, 1)
   546  
   547  	inners := []*types.DynamicFeeTx{
   548  		// Nonce already used
   549  		{
   550  			ChainID:   s.chain.config.ChainID,
   551  			Nonce:     nonce - 1,
   552  			GasTipCap: common.Big1,
   553  			GasFeeCap: s.chain.Head().BaseFee(),
   554  			Gas:       100000,
   555  		},
   556  		// Value exceeds balance
   557  		{
   558  			Nonce:     nonce,
   559  			GasTipCap: common.Big1,
   560  			GasFeeCap: s.chain.Head().BaseFee(),
   561  			Gas:       100000,
   562  			Value:     s.chain.Balance(from),
   563  		},
   564  		// Gas limit too low
   565  		{
   566  			Nonce:     nonce,
   567  			GasTipCap: common.Big1,
   568  			GasFeeCap: s.chain.Head().BaseFee(),
   569  			Gas:       1337,
   570  		},
   571  		// Code size too large
   572  		{
   573  			Nonce:     nonce,
   574  			GasTipCap: common.Big1,
   575  			GasFeeCap: s.chain.Head().BaseFee(),
   576  			Data:      randBuf(50),
   577  			Gas:       1_000_000,
   578  		},
   579  		// Data too large
   580  		{
   581  			Nonce:     nonce,
   582  			GasTipCap: common.Big1,
   583  			GasFeeCap: s.chain.Head().BaseFee(),
   584  			To:        &common.Address{0xaa},
   585  			Data:      randBuf(128),
   586  			Gas:       5_000_000,
   587  		},
   588  	}
   589  
   590  	var txs []*types.Transaction
   591  	for _, inner := range inners {
   592  		tx, err := s.chain.SignTx(from, types.NewTx(inner))
   593  		if err != nil {
   594  			t.Fatalf("failed to sign tx: %v", err)
   595  		}
   596  		txs = append(txs, tx)
   597  	}
   598  	if err := s.sendInvalidTxs(t, txs); err != nil {
   599  		t.Fatalf("failed to send invalid txs: %v", err)
   600  	}
   601  }
   602  
   603  func (s *Suite) TestLargeTxRequest(t *utesting.T) {
   604  	t.Log(`This test first send ~2000 transactions to the node, then requests them
   605  on another peer connection using GetPooledTransactions.`)
   606  
   607  	// Nudge client out of syncing mode to accept pending txs.
   608  	if err := s.engine.sendForkchoiceUpdated(); err != nil {
   609  		t.Fatalf("failed to send next block: %v", err)
   610  	}
   611  
   612  	// Generate many transactions to seed target with.
   613  	var (
   614  		from, nonce = s.chain.GetSender(1)
   615  		count       = 2000
   616  		txs         []*types.Transaction
   617  		hashes      []common.Hash
   618  		set         = make(map[common.Hash]struct{})
   619  	)
   620  	for i := 0; i < count; i++ {
   621  		inner := &types.DynamicFeeTx{
   622  			ChainID:   s.chain.config.ChainID,
   623  			Nonce:     nonce + uint64(i),
   624  			GasTipCap: common.Big1,
   625  			GasFeeCap: s.chain.Head().BaseFee(),
   626  			Gas:       75000,
   627  		}
   628  		tx, err := s.chain.SignTx(from, types.NewTx(inner))
   629  		if err != nil {
   630  			t.Fatalf("failed to sign tx: err")
   631  		}
   632  		txs = append(txs, tx)
   633  		set[tx.Hash()] = struct{}{}
   634  		hashes = append(hashes, tx.Hash())
   635  	}
   636  	s.chain.IncNonce(from, uint64(count))
   637  
   638  	// Send txs.
   639  	if err := s.sendTxs(t, txs); err != nil {
   640  		t.Fatalf("failed to send txs: %v", err)
   641  	}
   642  
   643  	// Set up receive connection to ensure node is peered with the receiving
   644  	// connection before tx request is sent.
   645  	conn, err := s.dial()
   646  	if err != nil {
   647  		t.Fatalf("dial failed: %v", err)
   648  	}
   649  	defer conn.Close()
   650  	if err = conn.peer(s.chain, nil); err != nil {
   651  		t.Fatalf("peering failed: %v", err)
   652  	}
   653  	// Create and send pooled tx request.
   654  	req := &eth.GetPooledTransactionsPacket{
   655  		RequestId:                    1234,
   656  		GetPooledTransactionsRequest: hashes,
   657  	}
   658  	if err = conn.Write(ethProto, eth.GetPooledTransactionsMsg, req); err != nil {
   659  		t.Fatalf("could not write to conn: %v", err)
   660  	}
   661  	// Check that all received transactions match those that were sent to node.
   662  	msg := new(eth.PooledTransactionsPacket)
   663  	if err := conn.ReadMsg(ethProto, eth.PooledTransactionsMsg, &msg); err != nil {
   664  		t.Fatalf("error reading from connection: %v", err)
   665  	}
   666  	if got, want := msg.RequestId, req.RequestId; got != want {
   667  		t.Fatalf("unexpected request id in response: got %d, want %d", got, want)
   668  	}
   669  	for _, got := range msg.PooledTransactionsResponse {
   670  		if _, exists := set[got.Hash()]; !exists {
   671  			t.Fatalf("unexpected tx received: %v", got.Hash())
   672  		}
   673  	}
   674  }
   675  
   676  func (s *Suite) TestNewPooledTxs(t *utesting.T) {
   677  	t.Log(`This test announces transaction hashes to the node and expects it to fetch
   678  the transactions using a GetPooledTransactions request.`)
   679  
   680  	// Nudge client out of syncing mode to accept pending txs.
   681  	if err := s.engine.sendForkchoiceUpdated(); err != nil {
   682  		t.Fatalf("failed to send next block: %v", err)
   683  	}
   684  
   685  	var (
   686  		count       = 50
   687  		from, nonce = s.chain.GetSender(1)
   688  		hashes      = make([]common.Hash, count)
   689  		txTypes     = make([]byte, count)
   690  		sizes       = make([]uint32, count)
   691  	)
   692  	for i := 0; i < count; i++ {
   693  		inner := &types.DynamicFeeTx{
   694  			ChainID:   s.chain.config.ChainID,
   695  			Nonce:     nonce + uint64(i),
   696  			GasTipCap: common.Big1,
   697  			GasFeeCap: s.chain.Head().BaseFee(),
   698  			Gas:       75000,
   699  		}
   700  		tx, err := s.chain.SignTx(from, types.NewTx(inner))
   701  		if err != nil {
   702  			t.Fatalf("failed to sign tx: err")
   703  		}
   704  		hashes[i] = tx.Hash()
   705  		txTypes[i] = tx.Type()
   706  		sizes[i] = uint32(tx.Size())
   707  	}
   708  	s.chain.IncNonce(from, uint64(count))
   709  
   710  	// Connect to peer.
   711  	conn, err := s.dial()
   712  	if err != nil {
   713  		t.Fatalf("dial failed: %v", err)
   714  	}
   715  	defer conn.Close()
   716  	if err = conn.peer(s.chain, nil); err != nil {
   717  		t.Fatalf("peering failed: %v", err)
   718  	}
   719  
   720  	// Send announcement.
   721  	ann := eth.NewPooledTransactionHashesPacket{Types: txTypes, Sizes: sizes, Hashes: hashes}
   722  	err = conn.Write(ethProto, eth.NewPooledTransactionHashesMsg, ann)
   723  	if err != nil {
   724  		t.Fatalf("failed to write to connection: %v", err)
   725  	}
   726  
   727  	// Wait for GetPooledTxs request.
   728  	for {
   729  		msg, err := conn.ReadEth()
   730  		if err != nil {
   731  			t.Fatalf("failed to read eth msg: %v", err)
   732  		}
   733  		switch msg := msg.(type) {
   734  		case *eth.GetPooledTransactionsPacket:
   735  			if len(msg.GetPooledTransactionsRequest) != len(hashes) {
   736  				t.Fatalf("unexpected number of txs requested: wanted %d, got %d", len(hashes), len(msg.GetPooledTransactionsRequest))
   737  			}
   738  			return
   739  		case *eth.NewPooledTransactionHashesPacket:
   740  			continue
   741  		case *eth.TransactionsPacket:
   742  			continue
   743  		default:
   744  			t.Fatalf("unexpected %s", pretty.Sdump(msg))
   745  		}
   746  	}
   747  }
   748  
   749  func makeSidecar(data ...byte) *types.BlobTxSidecar {
   750  	var (
   751  		blobs       = make([]kzg4844.Blob, len(data))
   752  		commitments []kzg4844.Commitment
   753  		proofs      []kzg4844.Proof
   754  	)
   755  	for i := range blobs {
   756  		blobs[i][0] = data[i]
   757  		c, _ := kzg4844.BlobToCommitment(&blobs[i])
   758  		p, _ := kzg4844.ComputeBlobProof(&blobs[i], c)
   759  		commitments = append(commitments, c)
   760  		proofs = append(proofs, p)
   761  	}
   762  	return &types.BlobTxSidecar{
   763  		Blobs:       blobs,
   764  		Commitments: commitments,
   765  		Proofs:      proofs,
   766  	}
   767  }
   768  
   769  func (s *Suite) makeBlobTxs(count, blobs int, discriminator byte) (txs types.Transactions) {
   770  	from, nonce := s.chain.GetSender(5)
   771  	for i := 0; i < count; i++ {
   772  		// Make blob data, max of 2 blobs per tx.
   773  		blobdata := make([]byte, blobs%3)
   774  		for i := range blobdata {
   775  			blobdata[i] = discriminator
   776  			blobs -= 1
   777  		}
   778  		inner := &types.BlobTx{
   779  			ChainID:    uint256.MustFromBig(s.chain.config.ChainID),
   780  			Nonce:      nonce + uint64(i),
   781  			GasTipCap:  uint256.NewInt(1),
   782  			GasFeeCap:  uint256.MustFromBig(s.chain.Head().BaseFee()),
   783  			Gas:        100000,
   784  			BlobFeeCap: uint256.MustFromBig(eip4844.CalcBlobFee(*s.chain.Head().ExcessBlobGas())),
   785  			BlobHashes: makeSidecar(blobdata...).BlobHashes(),
   786  			Sidecar:    makeSidecar(blobdata...),
   787  		}
   788  		tx, err := s.chain.SignTx(from, types.NewTx(inner))
   789  		if err != nil {
   790  			panic("blob tx signing failed")
   791  		}
   792  		txs = append(txs, tx)
   793  	}
   794  	return txs
   795  }
   796  
   797  func (s *Suite) TestBlobViolations(t *utesting.T) {
   798  	t.Log(`This test sends some invalid blob tx announcements and expects the node to disconnect.`)
   799  
   800  	if err := s.engine.sendForkchoiceUpdated(); err != nil {
   801  		t.Fatalf("send fcu failed: %v", err)
   802  	}
   803  	// Create blob txs for each tests with unique tx hashes.
   804  	var (
   805  		t1 = s.makeBlobTxs(2, 3, 0x1)
   806  		t2 = s.makeBlobTxs(2, 3, 0x2)
   807  	)
   808  	for _, test := range []struct {
   809  		ann  eth.NewPooledTransactionHashesPacket
   810  		resp eth.PooledTransactionsResponse
   811  	}{
   812  		// Invalid tx size.
   813  		{
   814  			ann: eth.NewPooledTransactionHashesPacket{
   815  				Types:  []byte{types.BlobTxType, types.BlobTxType},
   816  				Sizes:  []uint32{uint32(t1[0].Size()), uint32(t1[1].Size() + 10)},
   817  				Hashes: []common.Hash{t1[0].Hash(), t1[1].Hash()},
   818  			},
   819  			resp: eth.PooledTransactionsResponse(t1),
   820  		},
   821  		// Wrong tx type.
   822  		{
   823  			ann: eth.NewPooledTransactionHashesPacket{
   824  				Types:  []byte{types.DynamicFeeTxType, types.BlobTxType},
   825  				Sizes:  []uint32{uint32(t2[0].Size()), uint32(t2[1].Size())},
   826  				Hashes: []common.Hash{t2[0].Hash(), t2[1].Hash()},
   827  			},
   828  			resp: eth.PooledTransactionsResponse(t2),
   829  		},
   830  	} {
   831  		conn, err := s.dial()
   832  		if err != nil {
   833  			t.Fatalf("dial fail: %v", err)
   834  		}
   835  		if err := conn.peer(s.chain, nil); err != nil {
   836  			t.Fatalf("peering failed: %v", err)
   837  		}
   838  		if err := conn.Write(ethProto, eth.NewPooledTransactionHashesMsg, test.ann); err != nil {
   839  			t.Fatalf("sending announcement failed: %v", err)
   840  		}
   841  		req := new(eth.GetPooledTransactionsPacket)
   842  		if err := conn.ReadMsg(ethProto, eth.GetPooledTransactionsMsg, req); err != nil {
   843  			t.Fatalf("reading pooled tx request failed: %v", err)
   844  		}
   845  		resp := eth.PooledTransactionsPacket{RequestId: req.RequestId, PooledTransactionsResponse: test.resp}
   846  		if err := conn.Write(ethProto, eth.PooledTransactionsMsg, resp); err != nil {
   847  			t.Fatalf("writing pooled tx response failed: %v", err)
   848  		}
   849  		if code, _, err := conn.Read(); err != nil {
   850  			t.Fatalf("expected disconnect on blob violation, got err: %v", err)
   851  		} else if code != discMsg {
   852  			t.Fatalf("expected disconnect on blob violation, got msg code: %d", code)
   853  		}
   854  		conn.Close()
   855  	}
   856  }