github.com/luckypickle/go-ethereum-vet@v1.14.2/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  	"bytes"
    22  	"crypto/ecdsa"
    23  	"crypto/elliptic"
    24  	"errors"
    25  	"fmt"
    26  	"io"
    27  	"math/big"
    28  
    29  	"github.com/luckypickle/go-ethereum-vet/common"
    30  	"github.com/luckypickle/go-ethereum-vet/core"
    31  	"github.com/luckypickle/go-ethereum-vet/core/rawdb"
    32  	"github.com/luckypickle/go-ethereum-vet/crypto"
    33  	"github.com/luckypickle/go-ethereum-vet/crypto/secp256k1"
    34  	"github.com/luckypickle/go-ethereum-vet/rlp"
    35  )
    36  
    37  // Constants to match up protocol versions and messages
    38  const (
    39  	lpv1 = 1
    40  	lpv2 = 2
    41  )
    42  
    43  // Supported versions of the les protocol (first is primary)
    44  var (
    45  	ClientProtocolVersions    = []uint{lpv2, lpv1}
    46  	ServerProtocolVersions    = []uint{lpv2, lpv1}
    47  	AdvertiseProtocolVersions = []uint{lpv2} // clients are searching for the first advertised protocol in the list
    48  )
    49  
    50  // Number of implemented message corresponding to different protocol versions.
    51  var ProtocolLengths = map[uint]uint64{lpv1: 15, lpv2: 22}
    52  
    53  const (
    54  	NetworkId          = 1
    55  	ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
    56  )
    57  
    58  // les protocol message codes
    59  const (
    60  	// Protocol messages belonging to LPV1
    61  	StatusMsg          = 0x00
    62  	AnnounceMsg        = 0x01
    63  	GetBlockHeadersMsg = 0x02
    64  	BlockHeadersMsg    = 0x03
    65  	GetBlockBodiesMsg  = 0x04
    66  	BlockBodiesMsg     = 0x05
    67  	GetReceiptsMsg     = 0x06
    68  	ReceiptsMsg        = 0x07
    69  	GetProofsV1Msg     = 0x08
    70  	ProofsV1Msg        = 0x09
    71  	GetCodeMsg         = 0x0a
    72  	CodeMsg            = 0x0b
    73  	SendTxMsg          = 0x0c
    74  	GetHeaderProofsMsg = 0x0d
    75  	HeaderProofsMsg    = 0x0e
    76  	// Protocol messages belonging to LPV2
    77  	GetProofsV2Msg         = 0x0f
    78  	ProofsV2Msg            = 0x10
    79  	GetHelperTrieProofsMsg = 0x11
    80  	HelperTrieProofsMsg    = 0x12
    81  	SendTxV2Msg            = 0x13
    82  	GetTxStatusMsg         = 0x14
    83  	TxStatusMsg            = 0x15
    84  )
    85  
    86  type errCode int
    87  
    88  const (
    89  	ErrMsgTooLarge = iota
    90  	ErrDecode
    91  	ErrInvalidMsgCode
    92  	ErrProtocolVersionMismatch
    93  	ErrNetworkIdMismatch
    94  	ErrGenesisBlockMismatch
    95  	ErrNoStatusMsg
    96  	ErrExtraStatusMsg
    97  	ErrSuspendedPeer
    98  	ErrUselessPeer
    99  	ErrRequestRejected
   100  	ErrUnexpectedResponse
   101  	ErrInvalidResponse
   102  	ErrTooManyTimeouts
   103  	ErrMissingKey
   104  )
   105  
   106  func (e errCode) String() string {
   107  	return errorToString[int(e)]
   108  }
   109  
   110  // XXX change once legacy code is out
   111  var errorToString = map[int]string{
   112  	ErrMsgTooLarge:             "Message too long",
   113  	ErrDecode:                  "Invalid message",
   114  	ErrInvalidMsgCode:          "Invalid message code",
   115  	ErrProtocolVersionMismatch: "Protocol version mismatch",
   116  	ErrNetworkIdMismatch:       "NetworkId mismatch",
   117  	ErrGenesisBlockMismatch:    "Genesis block mismatch",
   118  	ErrNoStatusMsg:             "No status message",
   119  	ErrExtraStatusMsg:          "Extra status message",
   120  	ErrSuspendedPeer:           "Suspended peer",
   121  	ErrRequestRejected:         "Request rejected",
   122  	ErrUnexpectedResponse:      "Unexpected response",
   123  	ErrInvalidResponse:         "Invalid response",
   124  	ErrTooManyTimeouts:         "Too many request timeouts",
   125  	ErrMissingKey:              "Key missing from list",
   126  }
   127  
   128  type announceBlock 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  // announceData is the network packet for the block announcements.
   135  type announceData 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  	ReorgDepth uint64
   140  	Update     keyValueList
   141  }
   142  
   143  // sign adds a signature to the block announcement by the given privKey
   144  func (a *announceData) sign(privKey *ecdsa.PrivateKey) {
   145  	rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td})
   146  	sig, _ := crypto.Sign(crypto.Keccak256(rlp), privKey)
   147  	a.Update = a.Update.add("sign", sig)
   148  }
   149  
   150  // checkSignature verifies if the block announcement has a valid signature by the given pubKey
   151  func (a *announceData) checkSignature(pubKey *ecdsa.PublicKey) error {
   152  	var sig []byte
   153  	if err := a.Update.decode().get("sign", &sig); err != nil {
   154  		return err
   155  	}
   156  	rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td})
   157  	recPubkey, err := secp256k1.RecoverPubkey(crypto.Keccak256(rlp), sig)
   158  	if err != nil {
   159  		return err
   160  	}
   161  	pbytes := elliptic.Marshal(pubKey.Curve, pubKey.X, pubKey.Y)
   162  	if bytes.Equal(pbytes, recPubkey) {
   163  		return nil
   164  	}
   165  	return errors.New("Wrong signature")
   166  }
   167  
   168  type blockInfo struct {
   169  	Hash   common.Hash // Hash of one particular block being announced
   170  	Number uint64      // Number of one particular block being announced
   171  	Td     *big.Int    // Total difficulty of one particular block being announced
   172  }
   173  
   174  // getBlockHeadersData represents a block header query.
   175  type getBlockHeadersData struct {
   176  	Origin  hashOrNumber // Block from which to retrieve headers
   177  	Amount  uint64       // Maximum number of headers to retrieve
   178  	Skip    uint64       // Blocks to skip between consecutive headers
   179  	Reverse bool         // Query direction (false = rising towards latest, true = falling towards genesis)
   180  }
   181  
   182  // hashOrNumber is a combined field for specifying an origin block.
   183  type hashOrNumber struct {
   184  	Hash   common.Hash // Block hash from which to retrieve headers (excludes Number)
   185  	Number uint64      // Block hash from which to retrieve headers (excludes Hash)
   186  }
   187  
   188  // EncodeRLP is a specialized encoder for hashOrNumber to encode only one of the
   189  // two contained union fields.
   190  func (hn *hashOrNumber) EncodeRLP(w io.Writer) error {
   191  	if hn.Hash == (common.Hash{}) {
   192  		return rlp.Encode(w, hn.Number)
   193  	}
   194  	if hn.Number != 0 {
   195  		return fmt.Errorf("both origin hash (%x) and number (%d) provided", hn.Hash, hn.Number)
   196  	}
   197  	return rlp.Encode(w, hn.Hash)
   198  }
   199  
   200  // DecodeRLP is a specialized decoder for hashOrNumber to decode the contents
   201  // into either a block hash or a block number.
   202  func (hn *hashOrNumber) DecodeRLP(s *rlp.Stream) error {
   203  	_, size, _ := s.Kind()
   204  	origin, err := s.Raw()
   205  	if err == nil {
   206  		switch {
   207  		case size == 32:
   208  			err = rlp.DecodeBytes(origin, &hn.Hash)
   209  		case size <= 8:
   210  			err = rlp.DecodeBytes(origin, &hn.Number)
   211  		default:
   212  			err = fmt.Errorf("invalid input size %d for origin", size)
   213  		}
   214  	}
   215  	return err
   216  }
   217  
   218  // CodeData is the network response packet for a node data retrieval.
   219  type CodeData []struct {
   220  	Value []byte
   221  }
   222  
   223  type proofsData [][]rlp.RawValue
   224  
   225  type txStatus struct {
   226  	Status core.TxStatus
   227  	Lookup *rawdb.TxLookupEntry `rlp:"nil"`
   228  	Error  string
   229  }