github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/les/protocol.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:39</date>
    10  //</624450095793836032>
    11  
    12  
    13  //包les实现轻以太坊子协议。
    14  package les
    15  
    16  import (
    17  	"crypto/ecdsa"
    18  	"errors"
    19  	"fmt"
    20  	"io"
    21  	"math/big"
    22  
    23  	"github.com/ethereum/go-ethereum/common"
    24  	"github.com/ethereum/go-ethereum/core"
    25  	"github.com/ethereum/go-ethereum/core/rawdb"
    26  	"github.com/ethereum/go-ethereum/crypto"
    27  	"github.com/ethereum/go-ethereum/p2p/enode"
    28  	"github.com/ethereum/go-ethereum/rlp"
    29  )
    30  
    31  //用于匹配协议版本和消息的常量
    32  const (
    33  	lpv1 = 1
    34  	lpv2 = 2
    35  )
    36  
    37  //支持的LES协议版本(第一个是主协议)
    38  var (
    39  	ClientProtocolVersions    = []uint{lpv2, lpv1}
    40  	ServerProtocolVersions    = []uint{lpv2, lpv1}
    41  AdvertiseProtocolVersions = []uint{lpv2} //客户端正在搜索列表中的第一个公告协议
    42  )
    43  
    44  //对应于不同协议版本的已实现消息数。
    45  var ProtocolLengths = map[uint]uint64{lpv1: 15, lpv2: 22}
    46  
    47  const (
    48  	NetworkId          = 1
    49  ProtocolMaxMsgSize = 10 * 1024 * 1024 //协议消息大小的最大上限
    50  )
    51  
    52  //LES协议消息代码
    53  const (
    54  //属于lpv1的协议消息
    55  	StatusMsg          = 0x00
    56  	AnnounceMsg        = 0x01
    57  	GetBlockHeadersMsg = 0x02
    58  	BlockHeadersMsg    = 0x03
    59  	GetBlockBodiesMsg  = 0x04
    60  	BlockBodiesMsg     = 0x05
    61  	GetReceiptsMsg     = 0x06
    62  	ReceiptsMsg        = 0x07
    63  	GetProofsV1Msg     = 0x08
    64  	ProofsV1Msg        = 0x09
    65  	GetCodeMsg         = 0x0a
    66  	CodeMsg            = 0x0b
    67  	SendTxMsg          = 0x0c
    68  	GetHeaderProofsMsg = 0x0d
    69  	HeaderProofsMsg    = 0x0e
    70  //属于lpv2的协议消息
    71  	GetProofsV2Msg         = 0x0f
    72  	ProofsV2Msg            = 0x10
    73  	GetHelperTrieProofsMsg = 0x11
    74  	HelperTrieProofsMsg    = 0x12
    75  	SendTxV2Msg            = 0x13
    76  	GetTxStatusMsg         = 0x14
    77  	TxStatusMsg            = 0x15
    78  )
    79  
    80  type errCode int
    81  
    82  const (
    83  	ErrMsgTooLarge = iota
    84  	ErrDecode
    85  	ErrInvalidMsgCode
    86  	ErrProtocolVersionMismatch
    87  	ErrNetworkIdMismatch
    88  	ErrGenesisBlockMismatch
    89  	ErrNoStatusMsg
    90  	ErrExtraStatusMsg
    91  	ErrSuspendedPeer
    92  	ErrUselessPeer
    93  	ErrRequestRejected
    94  	ErrUnexpectedResponse
    95  	ErrInvalidResponse
    96  	ErrTooManyTimeouts
    97  	ErrMissingKey
    98  )
    99  
   100  func (e errCode) String() string {
   101  	return errorToString[int(e)]
   102  }
   103  
   104  //一旦旧代码用完,XXX就会更改
   105  var errorToString = map[int]string{
   106  	ErrMsgTooLarge:             "Message too long",
   107  	ErrDecode:                  "Invalid message",
   108  	ErrInvalidMsgCode:          "Invalid message code",
   109  	ErrProtocolVersionMismatch: "Protocol version mismatch",
   110  	ErrNetworkIdMismatch:       "NetworkId mismatch",
   111  	ErrGenesisBlockMismatch:    "Genesis block mismatch",
   112  	ErrNoStatusMsg:             "No status message",
   113  	ErrExtraStatusMsg:          "Extra status message",
   114  	ErrSuspendedPeer:           "Suspended peer",
   115  	ErrRequestRejected:         "Request rejected",
   116  	ErrUnexpectedResponse:      "Unexpected response",
   117  	ErrInvalidResponse:         "Invalid response",
   118  	ErrTooManyTimeouts:         "Too many request timeouts",
   119  	ErrMissingKey:              "Key missing from list",
   120  }
   121  
   122  type announceBlock struct {
   123  Hash   common.Hash //正在公布的一个特定块的哈希
   124  Number uint64      //公布的一个特定区块的编号
   125  Td     *big.Int    //宣布一个特定区块的总难度
   126  }
   127  
   128  //公告数据是块公告的网络包。
   129  type announceData struct {
   130  Hash       common.Hash //正在公布的一个特定块的哈希
   131  Number     uint64      //公布的一个特定区块的编号
   132  Td         *big.Int    //宣布一个特定区块的总难度
   133  	ReorgDepth uint64
   134  	Update     keyValueList
   135  }
   136  
   137  //签名通过给定的私钥向块公告添加签名
   138  func (a *announceData) sign(privKey *ecdsa.PrivateKey) {
   139  	rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td})
   140  	sig, _ := crypto.Sign(crypto.Keccak256(rlp), privKey)
   141  	a.Update = a.Update.add("sign", sig)
   142  }
   143  
   144  //checksignature验证块通知是否具有给定pubkey的有效签名
   145  func (a *announceData) checkSignature(id enode.ID) error {
   146  	var sig []byte
   147  	if err := a.Update.decode().get("sign", &sig); err != nil {
   148  		return err
   149  	}
   150  	rlp, _ := rlp.EncodeToBytes(announceBlock{a.Hash, a.Number, a.Td})
   151  	recPubkey, err := crypto.SigToPub(crypto.Keccak256(rlp), sig)
   152  	if err != nil {
   153  		return err
   154  	}
   155  	if id == enode.PubkeyToIDV4(recPubkey) {
   156  		return nil
   157  	}
   158  	return errors.New("wrong signature")
   159  }
   160  
   161  type blockInfo struct {
   162  Hash   common.Hash //正在公布的一个特定块的哈希
   163  Number uint64      //公布的一个特定区块的编号
   164  Td     *big.Int    //宣布一个特定区块的总难度
   165  }
   166  
   167  //GetBlockHeadersData表示块头查询。
   168  type getBlockHeadersData struct {
   169  Origin  hashOrNumber //从中检索邮件头的块
   170  Amount  uint64       //要检索的最大头数
   171  Skip    uint64       //要在连续标题之间跳过的块
   172  Reverse bool         //查询方向(假=上升到最新,真=下降到创世纪)
   173  }
   174  
   175  //hashornumber是用于指定源块的组合字段。
   176  type hashOrNumber struct {
   177  Hash   common.Hash //要从中检索头的块哈希(不包括数字)
   178  Number uint64      //要从中检索头的块哈希(不包括哈希)
   179  }
   180  
   181  //encoderlp是一个专门的编码器,用于hashornumber只对
   182  //两个包含联合字段。
   183  func (hn *hashOrNumber) EncodeRLP(w io.Writer) error {
   184  	if hn.Hash == (common.Hash{}) {
   185  		return rlp.Encode(w, hn.Number)
   186  	}
   187  	if hn.Number != 0 {
   188  		return fmt.Errorf("both origin hash (%x) and number (%d) provided", hn.Hash, hn.Number)
   189  	}
   190  	return rlp.Encode(w, hn.Hash)
   191  }
   192  
   193  //decoderlp是一种特殊的译码器,用于hashornumber对内容进行译码。
   194  //分块散列或分块编号。
   195  func (hn *hashOrNumber) DecodeRLP(s *rlp.Stream) error {
   196  	_, size, _ := s.Kind()
   197  	origin, err := s.Raw()
   198  	if err == nil {
   199  		switch {
   200  		case size == 32:
   201  			err = rlp.DecodeBytes(origin, &hn.Hash)
   202  		case size <= 8:
   203  			err = rlp.DecodeBytes(origin, &hn.Number)
   204  		default:
   205  			err = fmt.Errorf("invalid input size %d for origin", size)
   206  		}
   207  	}
   208  	return err
   209  }
   210  
   211  //codedata是用于节点数据检索的网络响应包。
   212  type CodeData []struct {
   213  	Value []byte
   214  }
   215  
   216  type proofsData [][]rlp.RawValue
   217  
   218  type txStatus struct {
   219  	Status core.TxStatus
   220  	Lookup *rawdb.TxLookupEntry `rlp:"nil"`
   221  	Error  string
   222  }
   223