github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/eth/protocol.go (about)

     1  // Copyright 2014 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 eth
    18  
    19  import (
    20  	"fmt"
    21  	"io"
    22  	"math/big"
    23  
    24  	"github.com/ethereumproject/go-ethereum/common"
    25  	"github.com/ethereumproject/go-ethereum/core/types"
    26  	"github.com/ethereumproject/go-ethereum/rlp"
    27  )
    28  
    29  // Constants to match up protocol versions and messages
    30  const (
    31  	eth62 = 62
    32  	eth63 = 63
    33  )
    34  
    35  // Official short name of the protocol used during capability negotiation.
    36  var ProtocolName = "eth"
    37  
    38  // Supported versions of the eth protocol (first is primary).
    39  var ProtocolVersions = []uint{eth63, eth62}
    40  
    41  // Number of implemented message corresponding to different protocol versions.
    42  var ProtocolLengths = []uint64{17, 8}
    43  
    44  const (
    45  	NetworkId          = 1
    46  	ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
    47  )
    48  
    49  // eth protocol message codes
    50  const (
    51  	// Protocol messages belonging to eth/62
    52  	StatusMsg          = 0x00
    53  	NewBlockHashesMsg  = 0x01
    54  	TxMsg              = 0x02
    55  	GetBlockHeadersMsg = 0x03
    56  	BlockHeadersMsg    = 0x04
    57  	GetBlockBodiesMsg  = 0x05
    58  	BlockBodiesMsg     = 0x06
    59  	NewBlockMsg        = 0x07
    60  
    61  	// Protocol messages belonging to eth/63
    62  	GetNodeDataMsg = 0x0d
    63  	NodeDataMsg    = 0x0e
    64  	GetReceiptsMsg = 0x0f
    65  	ReceiptsMsg    = 0x10
    66  )
    67  
    68  func ProtocolMessageStringer(m uint) string {
    69  	switch m {
    70  	case StatusMsg:
    71  		return "Status"
    72  	case NewBlockHashesMsg:
    73  		return "NewBlockHashes"
    74  	case TxMsg:
    75  		return "Txs"
    76  	case GetBlockHeadersMsg:
    77  		return "GetBlockHeaders"
    78  	case BlockHeadersMsg:
    79  		return "BlockHeaders"
    80  	case GetBlockBodiesMsg:
    81  		return "GetBlockBodies"
    82  	case BlockBodiesMsg:
    83  		return "BlockBodies"
    84  	case NewBlockMsg:
    85  		return "NewBlock"
    86  	case GetNodeDataMsg:
    87  		return "GetNodeData"
    88  	case NodeDataMsg:
    89  		return "NodeData"
    90  	case GetReceiptsMsg:
    91  		return "GetReceipts"
    92  	case ReceiptsMsg:
    93  		return "Receipts"
    94  	default:
    95  		return "Unknown"
    96  	}
    97  }
    98  
    99  type errCode int
   100  
   101  const (
   102  	ErrMsgTooLarge = iota
   103  	ErrDecode
   104  	ErrInvalidMsgCode
   105  	ErrProtocolVersionMismatch
   106  	ErrNetworkIdMismatch
   107  	ErrGenesisBlockMismatch
   108  	ErrNoStatusMsg
   109  	ErrExtraStatusMsg
   110  	ErrSuspendedPeer
   111  )
   112  
   113  func (e errCode) String() string {
   114  	return errorToString[int(e)]
   115  }
   116  
   117  // XXX change once legacy code is out
   118  var errorToString = map[int]string{
   119  	ErrMsgTooLarge:             "Message too long",
   120  	ErrDecode:                  "Invalid message",
   121  	ErrInvalidMsgCode:          "Invalid message code",
   122  	ErrProtocolVersionMismatch: "Protocol version mismatch",
   123  	ErrNetworkIdMismatch:       "NetworkId mismatch",
   124  	ErrGenesisBlockMismatch:    "Genesis block mismatch",
   125  	ErrNoStatusMsg:             "No status message",
   126  	ErrExtraStatusMsg:          "Extra status message",
   127  	ErrSuspendedPeer:           "Suspended peer",
   128  }
   129  
   130  type txPool interface {
   131  	// AddTransactions should add the given transactions to the pool.
   132  	AddTransactions([]*types.Transaction)
   133  
   134  	// GetTransactions should return pending transactions.
   135  	// The slice should be modifiable by the caller.
   136  	GetTransactions() types.Transactions
   137  }
   138  
   139  // statusData is the network packet for the status message.
   140  type statusData struct {
   141  	ProtocolVersion uint32
   142  	NetworkId       uint32
   143  	TD              *big.Int
   144  	CurrentBlock    common.Hash
   145  	GenesisBlock    common.Hash
   146  }
   147  
   148  // newBlockData is the network packet for the block propagation message.
   149  type newBlockData struct {
   150  	Block *types.Block
   151  	TD    *big.Int
   152  }
   153  
   154  // blockBody represents the data content of a single block.
   155  type blockBody struct {
   156  	Transactions []*types.Transaction // Transactions contained within a block
   157  	Uncles       []*types.Header      // Uncles contained within a block
   158  }
   159  
   160  // blockBodiesData is the network packet for block content distribution.
   161  type blockBodiesData []*blockBody
   162  
   163  // announce is received with NewBlockHashesMsg
   164  type announce struct {
   165  	Hash   common.Hash // Hash of one particular block being announced
   166  	Number uint64      // Number of one particular block being announced
   167  }
   168  
   169  // newBlockHashesData is the network packet for the block announcements.
   170  type newBlockHashesData []announce
   171  
   172  // getBlockHeadersData represents a block header query.
   173  type getBlockHeadersData struct {
   174  	Origin  hashOrNumber // Block from which to retrieve headers
   175  	Amount  uint64       // Maximum number of headers to retrieve
   176  	Skip    uint64       // Blocks to skip between consecutive headers
   177  	Reverse bool         // Query direction (false = rising towards latest, true = falling towards genesis)
   178  }
   179  
   180  // hashOrNumber is a combined field for specifying an origin block.
   181  type hashOrNumber struct {
   182  	Hash   common.Hash // Block hash from which to retrieve headers (excludes Number)
   183  	Number uint64      // Block hash from which to retrieve headers (excludes Hash)
   184  }
   185  
   186  // EncodeRLP is a specialized encoder for hashOrNumber to encode only one of the
   187  // two contained union fields.
   188  func (hn *hashOrNumber) EncodeRLP(w io.Writer) error {
   189  	if hn.Hash == (common.Hash{}) {
   190  		return rlp.Encode(w, hn.Number)
   191  	}
   192  	if hn.Number != 0 {
   193  		return fmt.Errorf("both origin hash (%x) and number (%d) provided", hn.Hash, hn.Number)
   194  	}
   195  	return rlp.Encode(w, hn.Hash)
   196  }
   197  
   198  // DecodeRLP is a specialized decoder for hashOrNumber to decode the contents
   199  // into either a block hash or a block number.
   200  func (hn *hashOrNumber) DecodeRLP(s *rlp.Stream) error {
   201  	_, size, _ := s.Kind()
   202  	origin, err := s.Raw()
   203  	if err == nil {
   204  		switch {
   205  		case size == 32:
   206  			err = rlp.DecodeBytes(origin, &hn.Hash)
   207  		case size <= 8:
   208  			err = rlp.DecodeBytes(origin, &hn.Number)
   209  		default:
   210  			err = fmt.Errorf("invalid input size %d for origin", size)
   211  		}
   212  	}
   213  	return err
   214  }