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