github.com/ylsGit/go-ethereum@v1.6.5/les/protocol.go (about)

     1  // Copyright 2016 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 les implements the Light Ethereum Subprotocol.
    18  package les
    19  
    20  import (
    21  	"fmt"
    22  	"io"
    23  	"math/big"
    24  
    25  	"github.com/ethereum/go-ethereum/common"
    26  	"github.com/ethereum/go-ethereum/core/types"
    27  	"github.com/ethereum/go-ethereum/rlp"
    28  )
    29  
    30  // Constants to match up protocol versions and messages
    31  const (
    32  	lpv1 = 1
    33  )
    34  
    35  // Supported versions of the les protocol (first is primary).
    36  var ProtocolVersions = []uint{lpv1}
    37  
    38  // Number of implemented message corresponding to different protocol versions.
    39  var ProtocolLengths = []uint64{15}
    40  
    41  const (
    42  	NetworkId          = 1
    43  	ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
    44  )
    45  
    46  // les protocol message codes
    47  const (
    48  	// Protocol messages belonging to LPV1
    49  	StatusMsg          = 0x00
    50  	AnnounceMsg        = 0x01
    51  	GetBlockHeadersMsg = 0x02
    52  	BlockHeadersMsg    = 0x03
    53  	GetBlockBodiesMsg  = 0x04
    54  	BlockBodiesMsg     = 0x05
    55  	GetReceiptsMsg     = 0x06
    56  	ReceiptsMsg        = 0x07
    57  	GetProofsMsg       = 0x08
    58  	ProofsMsg          = 0x09
    59  	GetCodeMsg         = 0x0a
    60  	CodeMsg            = 0x0b
    61  	SendTxMsg          = 0x0c
    62  	GetHeaderProofsMsg = 0x0d
    63  	HeaderProofsMsg    = 0x0e
    64  )
    65  
    66  type errCode int
    67  
    68  const (
    69  	ErrMsgTooLarge = iota
    70  	ErrDecode
    71  	ErrInvalidMsgCode
    72  	ErrProtocolVersionMismatch
    73  	ErrNetworkIdMismatch
    74  	ErrGenesisBlockMismatch
    75  	ErrNoStatusMsg
    76  	ErrExtraStatusMsg
    77  	ErrSuspendedPeer
    78  	ErrUselessPeer
    79  	ErrRequestRejected
    80  	ErrUnexpectedResponse
    81  	ErrInvalidResponse
    82  	ErrTooManyTimeouts
    83  	ErrHandshakeMissingKey
    84  )
    85  
    86  func (e errCode) String() string {
    87  	return errorToString[int(e)]
    88  }
    89  
    90  // XXX change once legacy code is out
    91  var errorToString = map[int]string{
    92  	ErrMsgTooLarge:             "Message too long",
    93  	ErrDecode:                  "Invalid message",
    94  	ErrInvalidMsgCode:          "Invalid message code",
    95  	ErrProtocolVersionMismatch: "Protocol version mismatch",
    96  	ErrNetworkIdMismatch:       "NetworkId mismatch",
    97  	ErrGenesisBlockMismatch:    "Genesis block mismatch",
    98  	ErrNoStatusMsg:             "No status message",
    99  	ErrExtraStatusMsg:          "Extra status message",
   100  	ErrSuspendedPeer:           "Suspended peer",
   101  	ErrRequestRejected:         "Request rejected",
   102  	ErrUnexpectedResponse:      "Unexpected response",
   103  	ErrInvalidResponse:         "Invalid response",
   104  	ErrTooManyTimeouts:         "Too many request timeouts",
   105  	ErrHandshakeMissingKey:     "Key missing from handshake message",
   106  }
   107  
   108  type chainManager interface {
   109  	GetBlockHashesFromHash(hash common.Hash, amount uint64) (hashes []common.Hash)
   110  	GetBlock(hash common.Hash) (block *types.Block)
   111  	Status() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash)
   112  }
   113  
   114  // announceData is the network packet for the block announcements.
   115  type announceData struct {
   116  	Hash       common.Hash // Hash of one particular block being announced
   117  	Number     uint64      // Number of one particular block being announced
   118  	Td         *big.Int    // Total difficulty of one particular block being announced
   119  	ReorgDepth uint64
   120  	Update     keyValueList
   121  
   122  	haveHeaders uint64 // we have the headers of the remote peer's chain up to this number
   123  	headKnown   bool
   124  	requested   bool
   125  	next        *announceData
   126  }
   127  
   128  type blockInfo struct {
   129  	Hash   common.Hash // Hash of one particular block being announced
   130  	Number uint64      // Number of one particular block being announced
   131  	Td     *big.Int    // Total difficulty of one particular block being announced
   132  }
   133  
   134  // getBlockHashesData is the network packet for the hash based hash retrieval.
   135  type getBlockHashesData struct {
   136  	Hash   common.Hash
   137  	Amount uint64
   138  }
   139  
   140  // getBlockHeadersData represents a block header query.
   141  type getBlockHeadersData struct {
   142  	Origin  hashOrNumber // Block from which to retrieve headers
   143  	Amount  uint64       // Maximum number of headers to retrieve
   144  	Skip    uint64       // Blocks to skip between consecutive headers
   145  	Reverse bool         // Query direction (false = rising towards latest, true = falling towards genesis)
   146  }
   147  
   148  // hashOrNumber is a combined field for specifying an origin block.
   149  type hashOrNumber struct {
   150  	Hash   common.Hash // Block hash from which to retrieve headers (excludes Number)
   151  	Number uint64      // Block hash from which to retrieve headers (excludes Hash)
   152  }
   153  
   154  // EncodeRLP is a specialized encoder for hashOrNumber to encode only one of the
   155  // two contained union fields.
   156  func (hn *hashOrNumber) EncodeRLP(w io.Writer) error {
   157  	if hn.Hash == (common.Hash{}) {
   158  		return rlp.Encode(w, hn.Number)
   159  	}
   160  	if hn.Number != 0 {
   161  		return fmt.Errorf("both origin hash (%x) and number (%d) provided", hn.Hash, hn.Number)
   162  	}
   163  	return rlp.Encode(w, hn.Hash)
   164  }
   165  
   166  // DecodeRLP is a specialized decoder for hashOrNumber to decode the contents
   167  // into either a block hash or a block number.
   168  func (hn *hashOrNumber) DecodeRLP(s *rlp.Stream) error {
   169  	_, size, _ := s.Kind()
   170  	origin, err := s.Raw()
   171  	if err == nil {
   172  		switch {
   173  		case size == 32:
   174  			err = rlp.DecodeBytes(origin, &hn.Hash)
   175  		case size <= 8:
   176  			err = rlp.DecodeBytes(origin, &hn.Number)
   177  		default:
   178  			err = fmt.Errorf("invalid input size %d for origin", size)
   179  		}
   180  	}
   181  	return err
   182  }
   183  
   184  // newBlockData is the network packet for the block propagation message.
   185  type newBlockData struct {
   186  	Block *types.Block
   187  	TD    *big.Int
   188  }
   189  
   190  // blockBodiesData is the network packet for block content distribution.
   191  type blockBodiesData []*types.Body
   192  
   193  // CodeData is the network response packet for a node data retrieval.
   194  type CodeData []struct {
   195  	Value []byte
   196  }
   197  
   198  type proofsData [][]rlp.RawValue