github.com/samgwo/go-ethereum@v1.8.2-0.20180302101319-49bcb5fbd55e/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/ethereum/go-ethereum/common"
    30  	"github.com/ethereum/go-ethereum/core"
    31  	"github.com/ethereum/go-ethereum/crypto"
    32  	"github.com/ethereum/go-ethereum/crypto/secp256k1"
    33  	"github.com/ethereum/go-ethereum/rlp"
    34  )
    35  
    36  // Constants to match up protocol versions and messages
    37  const (
    38  	lpv1 = 1
    39  	lpv2 = 2
    40  )
    41  
    42  // Supported versions of the les protocol (first is primary)
    43  var (
    44  	ClientProtocolVersions    = []uint{lpv2, lpv1}
    45  	ServerProtocolVersions    = []uint{lpv2, lpv1}
    46  	AdvertiseProtocolVersions = []uint{lpv2} // clients are searching for the first advertised protocol in the list
    47  )
    48  
    49  // Number of implemented message corresponding to different protocol versions.
    50  var ProtocolLengths = map[uint]uint64{lpv1: 15, lpv2: 22}
    51  
    52  const (
    53  	NetworkId          = 1
    54  	ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
    55  )
    56  
    57  // les protocol message codes
    58  const (
    59  	// Protocol messages belonging to LPV1
    60  	StatusMsg          = 0x00
    61  	AnnounceMsg        = 0x01
    62  	GetBlockHeadersMsg = 0x02
    63  	BlockHeadersMsg    = 0x03
    64  	GetBlockBodiesMsg  = 0x04
    65  	BlockBodiesMsg     = 0x05
    66  	GetReceiptsMsg     = 0x06
    67  	ReceiptsMsg        = 0x07
    68  	GetProofsV1Msg     = 0x08
    69  	ProofsV1Msg        = 0x09
    70  	GetCodeMsg         = 0x0a
    71  	CodeMsg            = 0x0b
    72  	SendTxMsg          = 0x0c
    73  	GetHeaderProofsMsg = 0x0d
    74  	HeaderProofsMsg    = 0x0e
    75  	// Protocol messages belonging to LPV2
    76  	GetProofsV2Msg         = 0x0f
    77  	ProofsV2Msg            = 0x10
    78  	GetHelperTrieProofsMsg = 0x11
    79  	HelperTrieProofsMsg    = 0x12
    80  	SendTxV2Msg            = 0x13
    81  	GetTxStatusMsg         = 0x14
    82  	TxStatusMsg            = 0x15
    83  )
    84  
    85  type errCode int
    86  
    87  const (
    88  	ErrMsgTooLarge = iota
    89  	ErrDecode
    90  	ErrInvalidMsgCode
    91  	ErrProtocolVersionMismatch
    92  	ErrNetworkIdMismatch
    93  	ErrGenesisBlockMismatch
    94  	ErrNoStatusMsg
    95  	ErrExtraStatusMsg
    96  	ErrSuspendedPeer
    97  	ErrUselessPeer
    98  	ErrRequestRejected
    99  	ErrUnexpectedResponse
   100  	ErrInvalidResponse
   101  	ErrTooManyTimeouts
   102  	ErrMissingKey
   103  )
   104  
   105  func (e errCode) String() string {
   106  	return errorToString[int(e)]
   107  }
   108  
   109  // XXX change once legacy code is out
   110  var errorToString = map[int]string{
   111  	ErrMsgTooLarge:             "Message too long",
   112  	ErrDecode:                  "Invalid message",
   113  	ErrInvalidMsgCode:          "Invalid message code",
   114  	ErrProtocolVersionMismatch: "Protocol version mismatch",
   115  	ErrNetworkIdMismatch:       "NetworkId mismatch",
   116  	ErrGenesisBlockMismatch:    "Genesis block mismatch",
   117  	ErrNoStatusMsg:             "No status message",
   118  	ErrExtraStatusMsg:          "Extra status message",
   119  	ErrSuspendedPeer:           "Suspended peer",
   120  	ErrRequestRejected:         "Request rejected",
   121  	ErrUnexpectedResponse:      "Unexpected response",
   122  	ErrInvalidResponse:         "Invalid response",
   123  	ErrTooManyTimeouts:         "Too many request timeouts",
   124  	ErrMissingKey:              "Key missing from list",
   125  }
   126  
   127  type announceBlock struct {
   128  	Hash   common.Hash // Hash of one particular block being announced
   129  	Number uint64      // Number of one particular block being announced
   130  	Td     *big.Int    // Total difficulty of one particular block being announced
   131  }
   132  
   133  // announceData is the network packet for the block announcements.
   134  type announceData struct {
   135  	Hash       common.Hash // Hash of one particular block being announced
   136  	Number     uint64      // Number of one particular block being announced
   137  	Td         *big.Int    // Total difficulty of one particular block being announced
   138  	ReorgDepth uint64
   139  	Update     keyValueList
   140  }
   141  
   142  // sign adds a signature to the block announcement by the given privKey
   143  func (a *announceData) sign(privKey *ecdsa.PrivateKey) {
   144  	rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td})
   145  	sig, _ := crypto.Sign(crypto.Keccak256(rlp), privKey)
   146  	a.Update = a.Update.add("sign", sig)
   147  }
   148  
   149  // checkSignature verifies if the block announcement has a valid signature by the given pubKey
   150  func (a *announceData) checkSignature(pubKey *ecdsa.PublicKey) error {
   151  	var sig []byte
   152  	if err := a.Update.decode().get("sign", &sig); err != nil {
   153  		return err
   154  	}
   155  	rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td})
   156  	recPubkey, err := secp256k1.RecoverPubkey(crypto.Keccak256(rlp), sig)
   157  	if err != nil {
   158  		return err
   159  	}
   160  	pbytes := elliptic.Marshal(pubKey.Curve, pubKey.X, pubKey.Y)
   161  	if bytes.Equal(pbytes, recPubkey) {
   162  		return nil
   163  	} else {
   164  		return errors.New("Wrong signature")
   165  	}
   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 *core.TxLookupEntry `rlp:"nil"`
   228  	Error  string
   229  }