github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/les/protocol.go (about)

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