github.com/nitinawathare/ethereumassignment3@v0.0.0-20211021213010-f07344c2b868/go-ethereum/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
    18  
    19  import (
    20  	"crypto/ecdsa"
    21  	"errors"
    22  	"fmt"
    23  	"io"
    24  	"math/big"
    25  
    26  	"github.com/ethereum/go-ethereum/common"
    27  	"github.com/ethereum/go-ethereum/core"
    28  	"github.com/ethereum/go-ethereum/core/rawdb"
    29  	"github.com/ethereum/go-ethereum/crypto"
    30  	"github.com/ethereum/go-ethereum/p2p/enode"
    31  	"github.com/ethereum/go-ethereum/rlp"
    32  )
    33  
    34  // Constants to match up protocol versions and messages
    35  const (
    36  	lpv2 = 2
    37  )
    38  
    39  // Supported versions of the les protocol (first is primary)
    40  var (
    41  	ClientProtocolVersions    = []uint{lpv2}
    42  	ServerProtocolVersions    = []uint{lpv2}
    43  	AdvertiseProtocolVersions = []uint{lpv2} // clients are searching for the first advertised protocol in the list
    44  )
    45  
    46  // Number of implemented message corresponding to different protocol versions.
    47  var ProtocolLengths = map[uint]uint64{lpv2: 22}
    48  
    49  const (
    50  	NetworkId          = 1
    51  	ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
    52  )
    53  
    54  // les protocol message codes
    55  const (
    56  	// Protocol messages inherited from LPV1
    57  	StatusMsg          = 0x00
    58  	AnnounceMsg        = 0x01
    59  	GetBlockHeadersMsg = 0x02
    60  	BlockHeadersMsg    = 0x03
    61  	GetBlockBodiesMsg  = 0x04
    62  	BlockBodiesMsg     = 0x05
    63  	GetReceiptsMsg     = 0x06
    64  	ReceiptsMsg        = 0x07
    65  	GetCodeMsg         = 0x0a
    66  	CodeMsg            = 0x0b
    67  	// Protocol messages introduced in LPV2
    68  	GetProofsV2Msg         = 0x0f
    69  	ProofsV2Msg            = 0x10
    70  	GetHelperTrieProofsMsg = 0x11
    71  	HelperTrieProofsMsg    = 0x12
    72  	SendTxV2Msg            = 0x13
    73  	GetTxStatusMsg         = 0x14
    74  	TxStatusMsg            = 0x15
    75  )
    76  
    77  type requestInfo struct {
    78  	name     string
    79  	maxCount uint64
    80  }
    81  
    82  var requests = map[uint64]requestInfo{
    83  	GetBlockHeadersMsg:     {"GetBlockHeaders", MaxHeaderFetch},
    84  	GetBlockBodiesMsg:      {"GetBlockBodies", MaxBodyFetch},
    85  	GetReceiptsMsg:         {"GetReceipts", MaxReceiptFetch},
    86  	GetCodeMsg:             {"GetCode", MaxCodeFetch},
    87  	GetProofsV2Msg:         {"GetProofsV2", MaxProofsFetch},
    88  	GetHelperTrieProofsMsg: {"GetHelperTrieProofs", MaxHelperTrieProofsFetch},
    89  	SendTxV2Msg:            {"SendTxV2", MaxTxSend},
    90  	GetTxStatusMsg:         {"GetTxStatus", MaxTxStatus},
    91  }
    92  
    93  type errCode int
    94  
    95  const (
    96  	ErrMsgTooLarge = iota
    97  	ErrDecode
    98  	ErrInvalidMsgCode
    99  	ErrProtocolVersionMismatch
   100  	ErrNetworkIdMismatch
   101  	ErrGenesisBlockMismatch
   102  	ErrNoStatusMsg
   103  	ErrExtraStatusMsg
   104  	ErrSuspendedPeer
   105  	ErrUselessPeer
   106  	ErrRequestRejected
   107  	ErrUnexpectedResponse
   108  	ErrInvalidResponse
   109  	ErrTooManyTimeouts
   110  	ErrMissingKey
   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  	ErrRequestRejected:         "Request rejected",
   129  	ErrUnexpectedResponse:      "Unexpected response",
   130  	ErrInvalidResponse:         "Invalid response",
   131  	ErrTooManyTimeouts:         "Too many request timeouts",
   132  	ErrMissingKey:              "Key missing from list",
   133  }
   134  
   135  type announceBlock struct {
   136  	Hash   common.Hash // Hash of one particular block being announced
   137  	Number uint64      // Number of one particular block being announced
   138  	Td     *big.Int    // Total difficulty of one particular block being announced
   139  }
   140  
   141  // announceData is the network packet for the block announcements.
   142  type announceData struct {
   143  	Hash       common.Hash // Hash of one particular block being announced
   144  	Number     uint64      // Number of one particular block being announced
   145  	Td         *big.Int    // Total difficulty of one particular block being announced
   146  	ReorgDepth uint64
   147  	Update     keyValueList
   148  }
   149  
   150  // sign adds a signature to the block announcement by the given privKey
   151  func (a *announceData) sign(privKey *ecdsa.PrivateKey) {
   152  	rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td})
   153  	sig, _ := crypto.Sign(crypto.Keccak256(rlp), privKey)
   154  	a.Update = a.Update.add("sign", sig)
   155  }
   156  
   157  // checkSignature verifies if the block announcement has a valid signature by the given pubKey
   158  func (a *announceData) checkSignature(id enode.ID, update keyValueMap) error {
   159  	var sig []byte
   160  	if err := update.get("sign", &sig); err != nil {
   161  		return err
   162  	}
   163  	rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td})
   164  	recPubkey, err := crypto.SigToPub(crypto.Keccak256(rlp), sig)
   165  	if err != nil {
   166  		return err
   167  	}
   168  	if id == enode.PubkeyToIDV4(recPubkey) {
   169  		return nil
   170  	}
   171  	return errors.New("wrong signature")
   172  }
   173  
   174  type blockInfo struct {
   175  	Hash   common.Hash // Hash of one particular block being announced
   176  	Number uint64      // Number of one particular block being announced
   177  	Td     *big.Int    // Total difficulty of one particular block being announced
   178  }
   179  
   180  // getBlockHeadersData represents a block header query.
   181  type getBlockHeadersData struct {
   182  	Origin  hashOrNumber // Block from which to retrieve headers
   183  	Amount  uint64       // Maximum number of headers to retrieve
   184  	Skip    uint64       // Blocks to skip between consecutive headers
   185  	Reverse bool         // Query direction (false = rising towards latest, true = falling towards genesis)
   186  }
   187  
   188  // hashOrNumber is a combined field for specifying an origin block.
   189  type hashOrNumber struct {
   190  	Hash   common.Hash // Block hash from which to retrieve headers (excludes Number)
   191  	Number uint64      // Block hash from which to retrieve headers (excludes Hash)
   192  }
   193  
   194  // EncodeRLP is a specialized encoder for hashOrNumber to encode only one of the
   195  // two contained union fields.
   196  func (hn *hashOrNumber) EncodeRLP(w io.Writer) error {
   197  	if hn.Hash == (common.Hash{}) {
   198  		return rlp.Encode(w, hn.Number)
   199  	}
   200  	if hn.Number != 0 {
   201  		return fmt.Errorf("both origin hash (%x) and number (%d) provided", hn.Hash, hn.Number)
   202  	}
   203  	return rlp.Encode(w, hn.Hash)
   204  }
   205  
   206  // DecodeRLP is a specialized decoder for hashOrNumber to decode the contents
   207  // into either a block hash or a block number.
   208  func (hn *hashOrNumber) DecodeRLP(s *rlp.Stream) error {
   209  	_, size, _ := s.Kind()
   210  	origin, err := s.Raw()
   211  	if err == nil {
   212  		switch {
   213  		case size == 32:
   214  			err = rlp.DecodeBytes(origin, &hn.Hash)
   215  		case size <= 8:
   216  			err = rlp.DecodeBytes(origin, &hn.Number)
   217  		default:
   218  			err = fmt.Errorf("invalid input size %d for origin", size)
   219  		}
   220  	}
   221  	return err
   222  }
   223  
   224  // CodeData is the network response packet for a node data retrieval.
   225  type CodeData []struct {
   226  	Value []byte
   227  }
   228  
   229  type proofsData [][]rlp.RawValue
   230  
   231  type txStatus struct {
   232  	Status core.TxStatus
   233  	Lookup *rawdb.LegacyTxLookupEntry `rlp:"nil"`
   234  	Error  string
   235  }