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