github.com/edxfund/validator@v1.8.16-0.20181020093046-c1def72855da/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/EDXFund/Validator/common"
    30  	"github.com/EDXFund/Validator/core"
    31  	"github.com/EDXFund/Validator/core/rawdb"
    32  	"github.com/EDXFund/Validator/crypto"
    33  	"github.com/EDXFund/Validator/crypto/secp256k1"
    34  	"github.com/EDXFund/Validator/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  	ErrNotImplemented
   105  )
   106  
   107  func (e errCode) String() string {
   108  	return errorToString[int(e)]
   109  }
   110  
   111  // XXX change once legacy code is out
   112  var errorToString = map[int]string{
   113  	ErrMsgTooLarge:             "Message too long",
   114  	ErrDecode:                  "Invalid message",
   115  	ErrInvalidMsgCode:          "Invalid message code",
   116  	ErrProtocolVersionMismatch: "Protocol version mismatch",
   117  	ErrNetworkIdMismatch:       "NetworkId mismatch",
   118  	ErrGenesisBlockMismatch:    "Genesis block mismatch",
   119  	ErrNoStatusMsg:             "No status message",
   120  	ErrExtraStatusMsg:          "Extra status message",
   121  	ErrSuspendedPeer:           "Suspended peer",
   122  	ErrRequestRejected:         "Request rejected",
   123  	ErrUnexpectedResponse:      "Unexpected response",
   124  	ErrInvalidResponse:         "Invalid response",
   125  	ErrTooManyTimeouts:         "Too many request timeouts",
   126  	ErrMissingKey:              "Key missing from list",
   127  }
   128  
   129  type announceBlock struct {
   130  	Hash   common.Hash // Hash of one particular block being announced
   131  	Number uint64      // Number of one particular block being announced
   132  	Td     *big.Int    // Total difficulty of one particular block being announced
   133  }
   134  
   135  // announceData is the network packet for the block announcements.
   136  type announceData struct {
   137  	Hash       common.Hash // Hash of one particular block being announced
   138  	Number     uint64      // Number of one particular block being announced
   139  	Td         *big.Int    // Total difficulty of one particular block being announced
   140  	ReorgDepth uint64
   141  	Update     keyValueList
   142  }
   143  
   144  // sign adds a signature to the block announcement by the given privKey
   145  func (a *announceData) sign(privKey *ecdsa.PrivateKey) {
   146  	rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td})
   147  	sig, _ := crypto.Sign(crypto.Keccak256(rlp), privKey)
   148  	a.Update = a.Update.add("sign", sig)
   149  }
   150  
   151  // checkSignature verifies if the block announcement has a valid signature by the given pubKey
   152  func (a *announceData) checkSignature(pubKey *ecdsa.PublicKey) error {
   153  	var sig []byte
   154  	if err := a.Update.decode().get("sign", &sig); err != nil {
   155  		return err
   156  	}
   157  	rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td})
   158  	recPubkey, err := secp256k1.RecoverPubkey(crypto.Keccak256(rlp), sig)
   159  	if err != nil {
   160  		return err
   161  	}
   162  	pbytes := elliptic.Marshal(pubKey.Curve, pubKey.X, pubKey.Y)
   163  	if bytes.Equal(pbytes, recPubkey) {
   164  		return nil
   165  	}
   166  	return errors.New("Wrong signature")
   167  }
   168  
   169  type blockInfo struct {
   170  	Hash   common.Hash // Hash of one particular block being announced
   171  	Number uint64      // Number of one particular block being announced
   172  	Td     *big.Int    // Total difficulty of one particular block being announced
   173  }
   174  
   175  // getBlockHeadersData represents a block header query.
   176  type getBlockHeadersData struct {
   177  	Origin  hashOrNumber // Block from which to retrieve headers
   178  	Amount  uint64       // Maximum number of headers to retrieve
   179  	Skip    uint64       // Blocks to skip between consecutive headers
   180  	Reverse bool         // Query direction (false = rising towards latest, true = falling towards genesis)
   181  }
   182  
   183  // hashOrNumber is a combined field for specifying an origin block.
   184  type hashOrNumber struct {
   185  	Hash   common.Hash // Block hash from which to retrieve headers (excludes Number)
   186  	Number uint64      // Block hash from which to retrieve headers (excludes Hash)
   187  }
   188  
   189  // EncodeRLP is a specialized encoder for hashOrNumber to encode only one of the
   190  // two contained union fields.
   191  func (hn *hashOrNumber) EncodeRLP(w io.Writer) error {
   192  	if hn.Hash == (common.Hash{}) {
   193  		return rlp.Encode(w, hn.Number)
   194  	}
   195  	if hn.Number != 0 {
   196  		return fmt.Errorf("both origin hash (%x) and number (%d) provided", hn.Hash, hn.Number)
   197  	}
   198  	return rlp.Encode(w, hn.Hash)
   199  }
   200  
   201  // DecodeRLP is a specialized decoder for hashOrNumber to decode the contents
   202  // into either a block hash or a block number.
   203  func (hn *hashOrNumber) DecodeRLP(s *rlp.Stream) error {
   204  	_, size, _ := s.Kind()
   205  	origin, err := s.Raw()
   206  	if err == nil {
   207  		switch {
   208  		case size == 32:
   209  			err = rlp.DecodeBytes(origin, &hn.Hash)
   210  		case size <= 8:
   211  			err = rlp.DecodeBytes(origin, &hn.Number)
   212  		default:
   213  			err = fmt.Errorf("invalid input size %d for origin", size)
   214  		}
   215  	}
   216  	return err
   217  }
   218  
   219  // CodeData is the network response packet for a node data retrieval.
   220  type CodeData []struct {
   221  	Value []byte
   222  }
   223  
   224  type proofsData [][]rlp.RawValue
   225  
   226  type txStatus struct {
   227  	Status core.TxStatus
   228  	Lookup *rawdb.TxLookupEntry `rlp:"nil"`
   229  	Error  string
   230  }