github.com/codingfuture/orig-energi3@v0.8.4/les/protocol.go (about)

     1  // Copyright 2018 The Energi Core Authors
     2  // Copyright 2016 The go-ethereum Authors
     3  // This file is part of the Energi Core library.
     4  //
     5  // The Energi Core library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The Energi Core library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the Energi Core library. If not, see <http://www.gnu.org/licenses/>.
    17  
    18  // Package les implements the Light Ethereum Subprotocol.
    19  package les
    20  
    21  import (
    22  	"crypto/ecdsa"
    23  	"errors"
    24  	"fmt"
    25  	"io"
    26  	"math/big"
    27  
    28  	"github.com/ethereum/go-ethereum/common"
    29  	"github.com/ethereum/go-ethereum/core"
    30  	"github.com/ethereum/go-ethereum/core/rawdb"
    31  	"github.com/ethereum/go-ethereum/crypto"
    32  	"github.com/ethereum/go-ethereum/p2p/enode"
    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          = 39797
    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(id enode.ID) 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 := crypto.SigToPub(crypto.Keccak256(rlp), sig)
   157  	if err != nil {
   158  		return err
   159  	}
   160  	if id == enode.PubkeyToIDV4(recPubkey) {
   161  		return nil
   162  	}
   163  	return errors.New("wrong signature")
   164  }
   165  
   166  type blockInfo struct {
   167  	Hash   common.Hash // Hash of one particular block being announced
   168  	Number uint64      // Number of one particular block being announced
   169  	Td     *big.Int    // Total difficulty of one particular block being announced
   170  }
   171  
   172  // getBlockHeadersData represents a block header query.
   173  type getBlockHeadersData struct {
   174  	Origin  hashOrNumber // Block from which to retrieve headers
   175  	Amount  uint64       // Maximum number of headers to retrieve
   176  	Skip    uint64       // Blocks to skip between consecutive headers
   177  	Reverse bool         // Query direction (false = rising towards latest, true = falling towards genesis)
   178  }
   179  
   180  // hashOrNumber is a combined field for specifying an origin block.
   181  type hashOrNumber struct {
   182  	Hash   common.Hash // Block hash from which to retrieve headers (excludes Number)
   183  	Number uint64      // Block hash from which to retrieve headers (excludes Hash)
   184  }
   185  
   186  // EncodeRLP is a specialized encoder for hashOrNumber to encode only one of the
   187  // two contained union fields.
   188  func (hn *hashOrNumber) EncodeRLP(w io.Writer) error {
   189  	if hn.Hash == (common.Hash{}) {
   190  		return rlp.Encode(w, hn.Number)
   191  	}
   192  	if hn.Number != 0 {
   193  		return fmt.Errorf("both origin hash (%x) and number (%d) provided", hn.Hash, hn.Number)
   194  	}
   195  	return rlp.Encode(w, hn.Hash)
   196  }
   197  
   198  // DecodeRLP is a specialized decoder for hashOrNumber to decode the contents
   199  // into either a block hash or a block number.
   200  func (hn *hashOrNumber) DecodeRLP(s *rlp.Stream) error {
   201  	_, size, _ := s.Kind()
   202  	origin, err := s.Raw()
   203  	if err == nil {
   204  		switch {
   205  		case size == 32:
   206  			err = rlp.DecodeBytes(origin, &hn.Hash)
   207  		case size <= 8:
   208  			err = rlp.DecodeBytes(origin, &hn.Number)
   209  		default:
   210  			err = fmt.Errorf("invalid input size %d for origin", size)
   211  		}
   212  	}
   213  	return err
   214  }
   215  
   216  // CodeData is the network response packet for a node data retrieval.
   217  type CodeData []struct {
   218  	Value []byte
   219  }
   220  
   221  type proofsData [][]rlp.RawValue
   222  
   223  type txStatus struct {
   224  	Status core.TxStatus
   225  	Lookup *rawdb.TxLookupEntry `rlp:"nil"`
   226  	Error  string
   227  }