github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/les/odr_requests.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  //</624450095609286656>
    11  
    12  
    13  //package light实现可按需检索的状态和链对象
    14  //对于以太坊Light客户端。
    15  package les
    16  
    17  import (
    18  	"encoding/binary"
    19  	"errors"
    20  	"fmt"
    21  
    22  	"github.com/ethereum/go-ethereum/common"
    23  	"github.com/ethereum/go-ethereum/core/rawdb"
    24  	"github.com/ethereum/go-ethereum/core/types"
    25  	"github.com/ethereum/go-ethereum/crypto"
    26  	"github.com/ethereum/go-ethereum/ethdb"
    27  	"github.com/ethereum/go-ethereum/light"
    28  	"github.com/ethereum/go-ethereum/log"
    29  	"github.com/ethereum/go-ethereum/rlp"
    30  	"github.com/ethereum/go-ethereum/trie"
    31  )
    32  
    33  var (
    34  	errInvalidMessageType  = errors.New("invalid message type")
    35  	errInvalidEntryCount   = errors.New("invalid number of response entries")
    36  	errHeaderUnavailable   = errors.New("header unavailable")
    37  	errTxHashMismatch      = errors.New("transaction hash mismatch")
    38  	errUncleHashMismatch   = errors.New("uncle hash mismatch")
    39  	errReceiptHashMismatch = errors.New("receipt hash mismatch")
    40  	errDataHashMismatch    = errors.New("data hash mismatch")
    41  	errCHTHashMismatch     = errors.New("cht hash mismatch")
    42  	errCHTNumberMismatch   = errors.New("cht number mismatch")
    43  	errUselessNodes        = errors.New("useless nodes in merkle proof nodeset")
    44  )
    45  
    46  type LesOdrRequest interface {
    47  	GetCost(*peer) uint64
    48  	CanSend(*peer) bool
    49  	Request(uint64, *peer) error
    50  	Validate(ethdb.Database, *Msg) error
    51  }
    52  
    53  func LesRequest(req light.OdrRequest) LesOdrRequest {
    54  	switch r := req.(type) {
    55  	case *light.BlockRequest:
    56  		return (*BlockRequest)(r)
    57  	case *light.ReceiptsRequest:
    58  		return (*ReceiptsRequest)(r)
    59  	case *light.TrieRequest:
    60  		return (*TrieRequest)(r)
    61  	case *light.CodeRequest:
    62  		return (*CodeRequest)(r)
    63  	case *light.ChtRequest:
    64  		return (*ChtRequest)(r)
    65  	case *light.BloomRequest:
    66  		return (*BloomRequest)(r)
    67  	default:
    68  		return nil
    69  	}
    70  }
    71  
    72  //BlockRequest是块体的ODR请求类型
    73  type BlockRequest light.BlockRequest
    74  
    75  //getcost根据服务返回给定ODR请求的成本
    76  //同行成本表(lesodrequest的实现)
    77  func (r *BlockRequest) GetCost(peer *peer) uint64 {
    78  	return peer.GetRequestCost(GetBlockBodiesMsg, 1)
    79  }
    80  
    81  //cansend告诉某个对等机是否适合服务于给定的请求
    82  func (r *BlockRequest) CanSend(peer *peer) bool {
    83  	return peer.HasBlock(r.Hash, r.Number, false)
    84  }
    85  
    86  //请求向LES网络发送一个ODR请求(LESODRREQUEST的实现)
    87  func (r *BlockRequest) Request(reqID uint64, peer *peer) error {
    88  	peer.Log().Debug("Requesting block body", "hash", r.Hash)
    89  	return peer.RequestBodies(reqID, r.GetCost(peer), []common.Hash{r.Hash})
    90  }
    91  
    92  //有效处理来自LES网络的ODR请求回复消息
    93  //returns true and stores results in memory if the message was a valid reply
    94  //到请求(lesodrequest的实现)
    95  func (r *BlockRequest) Validate(db ethdb.Database, msg *Msg) error {
    96  	log.Debug("Validating block body", "hash", r.Hash)
    97  
    98  //确保我们有一个正确的信息与一个单一的块体
    99  	if msg.MsgType != MsgBlockBodies {
   100  		return errInvalidMessageType
   101  	}
   102  	bodies := msg.Obj.([]*types.Body)
   103  	if len(bodies) != 1 {
   104  		return errInvalidEntryCount
   105  	}
   106  	body := bodies[0]
   107  
   108  //检索存储的头并根据它验证块内容
   109  	header := rawdb.ReadHeader(db, r.Hash, r.Number)
   110  	if header == nil {
   111  		return errHeaderUnavailable
   112  	}
   113  	if header.TxHash != types.DeriveSha(types.Transactions(body.Transactions)) {
   114  		return errTxHashMismatch
   115  	}
   116  	if header.UncleHash != types.CalcUncleHash(body.Uncles) {
   117  		return errUncleHashMismatch
   118  	}
   119  //Validations passed, encode and store RLP
   120  	data, err := rlp.EncodeToBytes(body)
   121  	if err != nil {
   122  		return err
   123  	}
   124  	r.Rlp = data
   125  	return nil
   126  }
   127  
   128  //ReceiptsRequest是按块哈希列出的块接收的ODR请求类型
   129  type ReceiptsRequest light.ReceiptsRequest
   130  
   131  //getcost根据服务返回给定ODR请求的成本
   132  //同行成本表(lesodrequest的实现)
   133  func (r *ReceiptsRequest) GetCost(peer *peer) uint64 {
   134  	return peer.GetRequestCost(GetReceiptsMsg, 1)
   135  }
   136  
   137  //cansend告诉某个对等机是否适合服务于给定的请求
   138  func (r *ReceiptsRequest) CanSend(peer *peer) bool {
   139  	return peer.HasBlock(r.Hash, r.Number, false)
   140  }
   141  
   142  //请求向LES网络发送一个ODR请求(LESODRREQUEST的实现)
   143  func (r *ReceiptsRequest) Request(reqID uint64, peer *peer) error {
   144  	peer.Log().Debug("Requesting block receipts", "hash", r.Hash)
   145  	return peer.RequestReceipts(reqID, r.GetCost(peer), []common.Hash{r.Hash})
   146  }
   147  
   148  //有效处理来自LES网络的ODR请求回复消息
   149  //如果消息是有效的答复,则返回true并将结果存储在内存中
   150  //到请求(lesodrequest的实现)
   151  func (r *ReceiptsRequest) Validate(db ethdb.Database, msg *Msg) error {
   152  	log.Debug("Validating block receipts", "hash", r.Hash)
   153  
   154  //确保我们有一个正确的消息和一个单块收据
   155  	if msg.MsgType != MsgReceipts {
   156  		return errInvalidMessageType
   157  	}
   158  	receipts := msg.Obj.([]types.Receipts)
   159  	if len(receipts) != 1 {
   160  		return errInvalidEntryCount
   161  	}
   162  	receipt := receipts[0]
   163  
   164  //检索存储的标题并根据其验证收据内容
   165  	header := rawdb.ReadHeader(db, r.Hash, r.Number)
   166  	if header == nil {
   167  		return errHeaderUnavailable
   168  	}
   169  	if header.ReceiptHash != types.DeriveSha(receipt) {
   170  		return errReceiptHashMismatch
   171  	}
   172  //验证通过,存储并返回
   173  	r.Receipts = receipt
   174  	return nil
   175  }
   176  
   177  type ProofReq struct {
   178  	BHash       common.Hash
   179  	AccKey, Key []byte
   180  	FromLevel   uint
   181  }
   182  
   183  //状态/存储trie项的ODR请求类型,请参见leSodrRequest接口
   184  type TrieRequest light.TrieRequest
   185  
   186  //getcost根据服务返回给定ODR请求的成本
   187  //同行成本表(lesodrequest的实现)
   188  func (r *TrieRequest) GetCost(peer *peer) uint64 {
   189  	switch peer.version {
   190  	case lpv1:
   191  		return peer.GetRequestCost(GetProofsV1Msg, 1)
   192  	case lpv2:
   193  		return peer.GetRequestCost(GetProofsV2Msg, 1)
   194  	default:
   195  		panic(nil)
   196  	}
   197  }
   198  
   199  //cansend告诉某个对等机是否适合服务于给定的请求
   200  func (r *TrieRequest) CanSend(peer *peer) bool {
   201  	return peer.HasBlock(r.Id.BlockHash, r.Id.BlockNumber, true)
   202  }
   203  
   204  //请求向LES网络发送一个ODR请求(LESODRREQUEST的实现)
   205  func (r *TrieRequest) Request(reqID uint64, peer *peer) error {
   206  	peer.Log().Debug("Requesting trie proof", "root", r.Id.Root, "key", r.Key)
   207  	req := ProofReq{
   208  		BHash:  r.Id.BlockHash,
   209  		AccKey: r.Id.AccKey,
   210  		Key:    r.Key,
   211  	}
   212  	return peer.RequestProofs(reqID, r.GetCost(peer), []ProofReq{req})
   213  }
   214  
   215  //有效处理来自LES网络的ODR请求回复消息
   216  //如果消息是有效的答复,则返回true并将结果存储在内存中
   217  //到请求(lesodrequest的实现)
   218  func (r *TrieRequest) Validate(db ethdb.Database, msg *Msg) error {
   219  	log.Debug("Validating trie proof", "root", r.Id.Root, "key", r.Key)
   220  
   221  	switch msg.MsgType {
   222  	case MsgProofsV1:
   223  		proofs := msg.Obj.([]light.NodeList)
   224  		if len(proofs) != 1 {
   225  			return errInvalidEntryCount
   226  		}
   227  		nodeSet := proofs[0].NodeSet()
   228  //验证证明,如果签出则保存
   229  		if _, _, err := trie.VerifyProof(r.Id.Root, r.Key, nodeSet); err != nil {
   230  			return fmt.Errorf("merkle proof verification failed: %v", err)
   231  		}
   232  		r.Proof = nodeSet
   233  		return nil
   234  
   235  	case MsgProofsV2:
   236  		proofs := msg.Obj.(light.NodeList)
   237  //验证证明,如果签出则保存
   238  		nodeSet := proofs.NodeSet()
   239  		reads := &readTraceDB{db: nodeSet}
   240  		if _, _, err := trie.VerifyProof(r.Id.Root, r.Key, reads); err != nil {
   241  			return fmt.Errorf("merkle proof verification failed: %v", err)
   242  		}
   243  //检查VerifyProof是否已读取所有节点
   244  		if len(reads.reads) != nodeSet.KeyCount() {
   245  			return errUselessNodes
   246  		}
   247  		r.Proof = nodeSet
   248  		return nil
   249  
   250  	default:
   251  		return errInvalidMessageType
   252  	}
   253  }
   254  
   255  type CodeReq struct {
   256  	BHash  common.Hash
   257  	AccKey []byte
   258  }
   259  
   260  //节点数据的ODR请求类型(用于检索合同代码),请参见LESODRREQUEST接口
   261  type CodeRequest light.CodeRequest
   262  
   263  //getcost根据服务返回给定ODR请求的成本
   264  //同行成本表(lesodrequest的实现)
   265  func (r *CodeRequest) GetCost(peer *peer) uint64 {
   266  	return peer.GetRequestCost(GetCodeMsg, 1)
   267  }
   268  
   269  //cansend告诉某个对等机是否适合服务于给定的请求
   270  func (r *CodeRequest) CanSend(peer *peer) bool {
   271  	return peer.HasBlock(r.Id.BlockHash, r.Id.BlockNumber, true)
   272  }
   273  
   274  //请求向LES网络发送一个ODR请求(LESODRREQUEST的实现)
   275  func (r *CodeRequest) Request(reqID uint64, peer *peer) error {
   276  	peer.Log().Debug("Requesting code data", "hash", r.Hash)
   277  	req := CodeReq{
   278  		BHash:  r.Id.BlockHash,
   279  		AccKey: r.Id.AccKey,
   280  	}
   281  	return peer.RequestCode(reqID, r.GetCost(peer), []CodeReq{req})
   282  }
   283  
   284  //有效处理来自LES网络的ODR请求回复消息
   285  //如果消息是有效的答复,则返回true并将结果存储在内存中
   286  //到请求(lesodrequest的实现)
   287  func (r *CodeRequest) Validate(db ethdb.Database, msg *Msg) error {
   288  	log.Debug("Validating code data", "hash", r.Hash)
   289  
   290  //确保我们有一个带有单个代码元素的正确消息
   291  	if msg.MsgType != MsgCode {
   292  		return errInvalidMessageType
   293  	}
   294  	reply := msg.Obj.([][]byte)
   295  	if len(reply) != 1 {
   296  		return errInvalidEntryCount
   297  	}
   298  	data := reply[0]
   299  
   300  //验证数据并存储是否签出
   301  	if hash := crypto.Keccak256Hash(data); r.Hash != hash {
   302  		return errDataHashMismatch
   303  	}
   304  	r.Data = data
   305  	return nil
   306  }
   307  
   308  const (
   309  //helper trie类型常量
   310  htCanonical = iota //规范哈希trie
   311  htBloomBits        //布卢姆斯特里
   312  
   313  //适用于所有helper trie请求
   314  	auxRoot = 1
   315  //适用于htcanonical
   316  	auxHeader = 2
   317  )
   318  
   319  type HelperTrieReq struct {
   320  	Type              uint
   321  	TrieIdx           uint64
   322  	Key               []byte
   323  	FromLevel, AuxReq uint
   324  }
   325  
   326  type HelperTrieResps struct { //描述所有响应,而不仅仅是单个响应
   327  	Proofs  light.NodeList
   328  	AuxData [][]byte
   329  }
   330  
   331  //遗产LES / 1
   332  type ChtReq struct {
   333  	ChtNum, BlockNum uint64
   334  	FromLevel        uint
   335  }
   336  
   337  //遗产LES / 1
   338  type ChtResp struct {
   339  	Header *types.Header
   340  	Proof  []rlp.RawValue
   341  }
   342  
   343  //ODR request type for requesting headers by Canonical Hash Trie, see LesOdrRequest interface
   344  type ChtRequest light.ChtRequest
   345  
   346  //getcost根据服务返回给定ODR请求的成本
   347  //同行成本表(lesodrequest的实现)
   348  func (r *ChtRequest) GetCost(peer *peer) uint64 {
   349  	switch peer.version {
   350  	case lpv1:
   351  		return peer.GetRequestCost(GetHeaderProofsMsg, 1)
   352  	case lpv2:
   353  		return peer.GetRequestCost(GetHelperTrieProofsMsg, 1)
   354  	default:
   355  		panic(nil)
   356  	}
   357  }
   358  
   359  //cansend告诉某个对等机是否适合服务于给定的请求
   360  func (r *ChtRequest) CanSend(peer *peer) bool {
   361  	peer.lock.RLock()
   362  	defer peer.lock.RUnlock()
   363  
   364  	return peer.headInfo.Number >= r.Config.ChtConfirms && r.ChtNum <= (peer.headInfo.Number-r.Config.ChtConfirms)/r.Config.ChtSize
   365  }
   366  
   367  //请求向LES网络发送一个ODR请求(LESODRREQUEST的实现)
   368  func (r *ChtRequest) Request(reqID uint64, peer *peer) error {
   369  	peer.Log().Debug("Requesting CHT", "cht", r.ChtNum, "block", r.BlockNum)
   370  	var encNum [8]byte
   371  	binary.BigEndian.PutUint64(encNum[:], r.BlockNum)
   372  	req := HelperTrieReq{
   373  		Type:    htCanonical,
   374  		TrieIdx: r.ChtNum,
   375  		Key:     encNum[:],
   376  		AuxReq:  auxHeader,
   377  	}
   378  	switch peer.version {
   379  	case lpv1:
   380  		var reqsV1 ChtReq
   381  		if req.Type != htCanonical || req.AuxReq != auxHeader || len(req.Key) != 8 {
   382  			return fmt.Errorf("Request invalid in LES/1 mode")
   383  		}
   384  		blockNum := binary.BigEndian.Uint64(req.Key)
   385  //将helpertrie请求转换为旧的cht请求
   386  		reqsV1 = ChtReq{ChtNum: (req.TrieIdx + 1) * (r.Config.ChtSize / r.Config.PairChtSize), BlockNum: blockNum, FromLevel: req.FromLevel}
   387  		return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []ChtReq{reqsV1})
   388  	case lpv2:
   389  		return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []HelperTrieReq{req})
   390  	default:
   391  		panic(nil)
   392  	}
   393  }
   394  
   395  //有效处理来自LES网络的ODR请求回复消息
   396  //如果消息是有效的答复,则返回true并将结果存储在内存中
   397  //到请求(lesodrequest的实现)
   398  func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error {
   399  	log.Debug("Validating CHT", "cht", r.ChtNum, "block", r.BlockNum)
   400  
   401  	switch msg.MsgType {
   402  case MsgHeaderProofs: //LES/1向后兼容性
   403  		proofs := msg.Obj.([]ChtResp)
   404  		if len(proofs) != 1 {
   405  			return errInvalidEntryCount
   406  		}
   407  		proof := proofs[0]
   408  
   409  //验证CHT
   410  		var encNumber [8]byte
   411  		binary.BigEndian.PutUint64(encNumber[:], r.BlockNum)
   412  
   413  		value, _, err := trie.VerifyProof(r.ChtRoot, encNumber[:], light.NodeList(proof.Proof).NodeSet())
   414  		if err != nil {
   415  			return err
   416  		}
   417  		var node light.ChtNode
   418  		if err := rlp.DecodeBytes(value, &node); err != nil {
   419  			return err
   420  		}
   421  		if node.Hash != proof.Header.Hash() {
   422  			return errCHTHashMismatch
   423  		}
   424  //验证通过,存储并返回
   425  		r.Header = proof.Header
   426  		r.Proof = light.NodeList(proof.Proof).NodeSet()
   427  		r.Td = node.Td
   428  	case MsgHelperTrieProofs:
   429  		resp := msg.Obj.(HelperTrieResps)
   430  		if len(resp.AuxData) != 1 {
   431  			return errInvalidEntryCount
   432  		}
   433  		nodeSet := resp.Proofs.NodeSet()
   434  		headerEnc := resp.AuxData[0]
   435  		if len(headerEnc) == 0 {
   436  			return errHeaderUnavailable
   437  		}
   438  		header := new(types.Header)
   439  		if err := rlp.DecodeBytes(headerEnc, header); err != nil {
   440  			return errHeaderUnavailable
   441  		}
   442  
   443  //验证CHT
   444  		var encNumber [8]byte
   445  		binary.BigEndian.PutUint64(encNumber[:], r.BlockNum)
   446  
   447  		reads := &readTraceDB{db: nodeSet}
   448  		value, _, err := trie.VerifyProof(r.ChtRoot, encNumber[:], reads)
   449  		if err != nil {
   450  			return fmt.Errorf("merkle proof verification failed: %v", err)
   451  		}
   452  		if len(reads.reads) != nodeSet.KeyCount() {
   453  			return errUselessNodes
   454  		}
   455  
   456  		var node light.ChtNode
   457  		if err := rlp.DecodeBytes(value, &node); err != nil {
   458  			return err
   459  		}
   460  		if node.Hash != header.Hash() {
   461  			return errCHTHashMismatch
   462  		}
   463  		if r.BlockNum != header.Number.Uint64() {
   464  			return errCHTNumberMismatch
   465  		}
   466  //验证通过,存储并返回
   467  		r.Header = header
   468  		r.Proof = nodeSet
   469  		r.Td = node.Td
   470  	default:
   471  		return errInvalidMessageType
   472  	}
   473  	return nil
   474  }
   475  
   476  type BloomReq struct {
   477  	BloomTrieNum, BitIdx, SectionIndex, FromLevel uint64
   478  }
   479  
   480  //用于通过规范哈希检索请求头的ODR请求类型,请参见leSodrRequest接口
   481  type BloomRequest light.BloomRequest
   482  
   483  //getcost根据服务返回给定ODR请求的成本
   484  //同行成本表(lesodrequest的实现)
   485  func (r *BloomRequest) GetCost(peer *peer) uint64 {
   486  	return peer.GetRequestCost(GetHelperTrieProofsMsg, len(r.SectionIndexList))
   487  }
   488  
   489  //cansend告诉某个对等机是否适合服务于给定的请求
   490  func (r *BloomRequest) CanSend(peer *peer) bool {
   491  	peer.lock.RLock()
   492  	defer peer.lock.RUnlock()
   493  
   494  	if peer.version < lpv2 {
   495  		return false
   496  	}
   497  	return peer.headInfo.Number >= r.Config.BloomTrieConfirms && r.BloomTrieNum <= (peer.headInfo.Number-r.Config.BloomTrieConfirms)/r.Config.BloomTrieSize
   498  }
   499  
   500  //请求向LES网络发送一个ODR请求(LESODRREQUEST的实现)
   501  func (r *BloomRequest) Request(reqID uint64, peer *peer) error {
   502  	peer.Log().Debug("Requesting BloomBits", "bloomTrie", r.BloomTrieNum, "bitIdx", r.BitIdx, "sections", r.SectionIndexList)
   503  	reqs := make([]HelperTrieReq, len(r.SectionIndexList))
   504  
   505  	var encNumber [10]byte
   506  	binary.BigEndian.PutUint16(encNumber[:2], uint16(r.BitIdx))
   507  
   508  	for i, sectionIdx := range r.SectionIndexList {
   509  		binary.BigEndian.PutUint64(encNumber[2:], sectionIdx)
   510  		reqs[i] = HelperTrieReq{
   511  			Type:    htBloomBits,
   512  			TrieIdx: r.BloomTrieNum,
   513  			Key:     common.CopyBytes(encNumber[:]),
   514  		}
   515  	}
   516  	return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), reqs)
   517  }
   518  
   519  //有效处理来自LES网络的ODR请求回复消息
   520  //如果消息是有效的答复,则返回true并将结果存储在内存中
   521  //到请求(lesodrequest的实现)
   522  func (r *BloomRequest) Validate(db ethdb.Database, msg *Msg) error {
   523  	log.Debug("Validating BloomBits", "bloomTrie", r.BloomTrieNum, "bitIdx", r.BitIdx, "sections", r.SectionIndexList)
   524  
   525  //确保我们有一个正确的消息和一个证明元素
   526  	if msg.MsgType != MsgHelperTrieProofs {
   527  		return errInvalidMessageType
   528  	}
   529  	resps := msg.Obj.(HelperTrieResps)
   530  	proofs := resps.Proofs
   531  	nodeSet := proofs.NodeSet()
   532  	reads := &readTraceDB{db: nodeSet}
   533  
   534  	r.BloomBits = make([][]byte, len(r.SectionIndexList))
   535  
   536  //核实证据
   537  	var encNumber [10]byte
   538  	binary.BigEndian.PutUint16(encNumber[:2], uint16(r.BitIdx))
   539  
   540  	for i, idx := range r.SectionIndexList {
   541  		binary.BigEndian.PutUint64(encNumber[2:], idx)
   542  		value, _, err := trie.VerifyProof(r.BloomTrieRoot, encNumber[:], reads)
   543  		if err != nil {
   544  			return err
   545  		}
   546  		r.BloomBits[i] = value
   547  	}
   548  
   549  	if len(reads.reads) != nodeSet.KeyCount() {
   550  		return errUselessNodes
   551  	}
   552  	r.Proofs = nodeSet
   553  	return nil
   554  }
   555  
   556  //readTraceDB stores the keys of database reads. We use this to check that received node
   557  //集合只包含使证明通过所需的trie节点。
   558  type readTraceDB struct {
   559  	db    trie.DatabaseReader
   560  	reads map[string]struct{}
   561  }
   562  
   563  //get返回存储节点
   564  func (db *readTraceDB) Get(k []byte) ([]byte, error) {
   565  	if db.reads == nil {
   566  		db.reads = make(map[string]struct{})
   567  	}
   568  	db.reads[string(k)] = struct{}{}
   569  	return db.db.Get(k)
   570  }
   571  
   572  //如果节点集包含给定的键,则返回true
   573  func (db *readTraceDB) Has(key []byte) (bool, error) {
   574  	_, err := db.Get(key)
   575  	return err == nil, nil
   576  }
   577