github.com/DxChainNetwork/dxc@v0.8.1-0.20220824085222-1162e304b6e7/cmd/devp2p/internal/ethtest/types.go (about)

     1  // Copyright 2020 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  	"crypto/ecdsa"
    21  	"fmt"
    22  
    23  	"github.com/DxChainNetwork/dxc/eth/protocols/eth"
    24  	"github.com/DxChainNetwork/dxc/p2p"
    25  	"github.com/DxChainNetwork/dxc/p2p/rlpx"
    26  	"github.com/DxChainNetwork/dxc/rlp"
    27  )
    28  
    29  type Message interface {
    30  	Code() int
    31  }
    32  
    33  type Error struct {
    34  	err error
    35  }
    36  
    37  func (e *Error) Unwrap() error  { return e.err }
    38  func (e *Error) Error() string  { return e.err.Error() }
    39  func (e *Error) Code() int      { return -1 }
    40  func (e *Error) String() string { return e.Error() }
    41  
    42  func errorf(format string, args ...interface{}) *Error {
    43  	return &Error{fmt.Errorf(format, args...)}
    44  }
    45  
    46  // Hello is the RLP structure of the protocol handshake.
    47  type Hello struct {
    48  	Version    uint64
    49  	Name       string
    50  	Caps       []p2p.Cap
    51  	ListenPort uint64
    52  	ID         []byte // secp256k1 public key
    53  
    54  	// Ignore additional fields (for forward compatibility).
    55  	Rest []rlp.RawValue `rlp:"tail"`
    56  }
    57  
    58  func (h Hello) Code() int { return 0x00 }
    59  
    60  // Disconnect is the RLP structure for a disconnect message.
    61  type Disconnect struct {
    62  	Reason p2p.DiscReason
    63  }
    64  
    65  func (d Disconnect) Code() int { return 0x01 }
    66  
    67  type Ping struct{}
    68  
    69  func (p Ping) Code() int { return 0x02 }
    70  
    71  type Pong struct{}
    72  
    73  func (p Pong) Code() int { return 0x03 }
    74  
    75  // Status is the network packet for the status message for eth/64 and later.
    76  type Status eth.StatusPacket
    77  
    78  func (s Status) Code() int { return 16 }
    79  
    80  // NewBlockHashes is the network packet for the block announcements.
    81  type NewBlockHashes eth.NewBlockHashesPacket
    82  
    83  func (nbh NewBlockHashes) Code() int { return 17 }
    84  
    85  type Transactions eth.TransactionsPacket
    86  
    87  func (t Transactions) Code() int { return 18 }
    88  
    89  // GetBlockHeaders represents a block header query.
    90  type GetBlockHeaders eth.GetBlockHeadersPacket
    91  
    92  func (g GetBlockHeaders) Code() int { return 19 }
    93  
    94  type BlockHeaders eth.BlockHeadersPacket
    95  
    96  func (bh BlockHeaders) Code() int { return 20 }
    97  
    98  // GetBlockBodies represents a GetBlockBodies request
    99  type GetBlockBodies eth.GetBlockBodiesPacket
   100  
   101  func (gbb GetBlockBodies) Code() int { return 21 }
   102  
   103  // BlockBodies is the network packet for block content distribution.
   104  type BlockBodies eth.BlockBodiesPacket
   105  
   106  func (bb BlockBodies) Code() int { return 22 }
   107  
   108  // NewBlock is the network packet for the block propagation message.
   109  type NewBlock eth.NewBlockPacket
   110  
   111  func (nb NewBlock) Code() int { return 23 }
   112  
   113  // NewPooledTransactionHashes is the network packet for the tx hash propagation message.
   114  type NewPooledTransactionHashes eth.NewPooledTransactionHashesPacket
   115  
   116  func (nb NewPooledTransactionHashes) Code() int { return 24 }
   117  
   118  type GetPooledTransactions eth.GetPooledTransactionsPacket
   119  
   120  func (gpt GetPooledTransactions) Code() int { return 25 }
   121  
   122  type PooledTransactions eth.PooledTransactionsPacket
   123  
   124  func (pt PooledTransactions) Code() int { return 26 }
   125  
   126  // Conn represents an individual connection with a peer
   127  type Conn struct {
   128  	*rlpx.Conn
   129  	ourKey                 *ecdsa.PrivateKey
   130  	negotiatedProtoVersion uint
   131  	ourHighestProtoVersion uint
   132  	caps                   []p2p.Cap
   133  }
   134  
   135  // Read reads an eth packet from the connection.
   136  func (c *Conn) Read() Message {
   137  	code, rawData, _, err := c.Conn.Read()
   138  	if err != nil {
   139  		return errorf("could not read from connection: %v", err)
   140  	}
   141  
   142  	var msg Message
   143  	switch int(code) {
   144  	case (Hello{}).Code():
   145  		msg = new(Hello)
   146  	case (Ping{}).Code():
   147  		msg = new(Ping)
   148  	case (Pong{}).Code():
   149  		msg = new(Pong)
   150  	case (Disconnect{}).Code():
   151  		msg = new(Disconnect)
   152  	case (Status{}).Code():
   153  		msg = new(Status)
   154  	case (GetBlockHeaders{}).Code():
   155  		msg = new(GetBlockHeaders)
   156  	case (BlockHeaders{}).Code():
   157  		msg = new(BlockHeaders)
   158  	case (GetBlockBodies{}).Code():
   159  		msg = new(GetBlockBodies)
   160  	case (BlockBodies{}).Code():
   161  		msg = new(BlockBodies)
   162  	case (NewBlock{}).Code():
   163  		msg = new(NewBlock)
   164  	case (NewBlockHashes{}).Code():
   165  		msg = new(NewBlockHashes)
   166  	case (Transactions{}).Code():
   167  		msg = new(Transactions)
   168  	case (NewPooledTransactionHashes{}).Code():
   169  		msg = new(NewPooledTransactionHashes)
   170  	case (GetPooledTransactions{}.Code()):
   171  		msg = new(GetPooledTransactions)
   172  	case (PooledTransactions{}.Code()):
   173  		msg = new(PooledTransactions)
   174  	default:
   175  		return errorf("invalid message code: %d", code)
   176  	}
   177  	// if message is devp2p, decode here
   178  	if err := rlp.DecodeBytes(rawData, msg); err != nil {
   179  		return errorf("could not rlp decode message: %v", err)
   180  	}
   181  	return msg
   182  }
   183  
   184  // Read66 reads an eth66 packet from the connection.
   185  func (c *Conn) Read66() (uint64, Message) {
   186  	code, rawData, _, err := c.Conn.Read()
   187  	if err != nil {
   188  		return 0, errorf("could not read from connection: %v", err)
   189  	}
   190  
   191  	var msg Message
   192  	switch int(code) {
   193  	case (Hello{}).Code():
   194  		msg = new(Hello)
   195  	case (Ping{}).Code():
   196  		msg = new(Ping)
   197  	case (Pong{}).Code():
   198  		msg = new(Pong)
   199  	case (Disconnect{}).Code():
   200  		msg = new(Disconnect)
   201  	case (Status{}).Code():
   202  		msg = new(Status)
   203  	case (GetBlockHeaders{}).Code():
   204  		ethMsg := new(eth.GetBlockHeadersPacket66)
   205  		if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
   206  			return 0, errorf("could not rlp decode message: %v", err)
   207  		}
   208  		return ethMsg.RequestId, GetBlockHeaders(*ethMsg.GetBlockHeadersPacket)
   209  	case (BlockHeaders{}).Code():
   210  		ethMsg := new(eth.BlockHeadersPacket66)
   211  		if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
   212  			return 0, errorf("could not rlp decode message: %v", err)
   213  		}
   214  		return ethMsg.RequestId, BlockHeaders(ethMsg.BlockHeadersPacket)
   215  	case (GetBlockBodies{}).Code():
   216  		ethMsg := new(eth.GetBlockBodiesPacket66)
   217  		if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
   218  			return 0, errorf("could not rlp decode message: %v", err)
   219  		}
   220  		return ethMsg.RequestId, GetBlockBodies(ethMsg.GetBlockBodiesPacket)
   221  	case (BlockBodies{}).Code():
   222  		ethMsg := new(eth.BlockBodiesPacket66)
   223  		if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
   224  			return 0, errorf("could not rlp decode message: %v", err)
   225  		}
   226  		return ethMsg.RequestId, BlockBodies(ethMsg.BlockBodiesPacket)
   227  	case (NewBlock{}).Code():
   228  		msg = new(NewBlock)
   229  	case (NewBlockHashes{}).Code():
   230  		msg = new(NewBlockHashes)
   231  	case (Transactions{}).Code():
   232  		msg = new(Transactions)
   233  	case (NewPooledTransactionHashes{}).Code():
   234  		msg = new(NewPooledTransactionHashes)
   235  	case (GetPooledTransactions{}.Code()):
   236  		ethMsg := new(eth.GetPooledTransactionsPacket66)
   237  		if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
   238  			return 0, errorf("could not rlp decode message: %v", err)
   239  		}
   240  		return ethMsg.RequestId, GetPooledTransactions(ethMsg.GetPooledTransactionsPacket)
   241  	case (PooledTransactions{}.Code()):
   242  		ethMsg := new(eth.PooledTransactionsPacket66)
   243  		if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
   244  			return 0, errorf("could not rlp decode message: %v", err)
   245  		}
   246  		return ethMsg.RequestId, PooledTransactions(ethMsg.PooledTransactionsPacket)
   247  	default:
   248  		msg = errorf("invalid message code: %d", code)
   249  	}
   250  
   251  	if msg != nil {
   252  		if err := rlp.DecodeBytes(rawData, msg); err != nil {
   253  			return 0, errorf("could not rlp decode message: %v", err)
   254  		}
   255  		return 0, msg
   256  	}
   257  	return 0, errorf("invalid message: %s", string(rawData))
   258  }
   259  
   260  // Write writes a eth packet to the connection.
   261  func (c *Conn) Write(msg Message) error {
   262  	// check if message is eth protocol message
   263  	var (
   264  		payload []byte
   265  		err     error
   266  	)
   267  	payload, err = rlp.EncodeToBytes(msg)
   268  	if err != nil {
   269  		return err
   270  	}
   271  	_, err = c.Conn.Write(uint64(msg.Code()), payload)
   272  	return err
   273  }
   274  
   275  // Write66 writes an eth66 packet to the connection.
   276  func (c *Conn) Write66(req eth.Packet, code int) error {
   277  	payload, err := rlp.EncodeToBytes(req)
   278  	if err != nil {
   279  		return err
   280  	}
   281  	_, err = c.Conn.Write(uint64(code), payload)
   282  	return err
   283  }