github.com/FUSIONFoundation/efsn@v3.6.2-0.20200916075423-dbb5dd5d2cc7+incompatible/les/odr_requests.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 light implements on-demand retrieval capable state and chain objects
    18  // for the Ethereum Light Client.
    19  package les
    20  
    21  import (
    22  	"encoding/binary"
    23  	"errors"
    24  	"fmt"
    25  
    26  	"github.com/FusionFoundation/efsn/common"
    27  	"github.com/FusionFoundation/efsn/core/rawdb"
    28  	"github.com/FusionFoundation/efsn/core/types"
    29  	"github.com/FusionFoundation/efsn/crypto"
    30  	"github.com/FusionFoundation/efsn/ethdb"
    31  	"github.com/FusionFoundation/efsn/light"
    32  	"github.com/FusionFoundation/efsn/log"
    33  	"github.com/FusionFoundation/efsn/rlp"
    34  	"github.com/FusionFoundation/efsn/trie"
    35  )
    36  
    37  var (
    38  	errInvalidMessageType  = errors.New("invalid message type")
    39  	errInvalidEntryCount   = errors.New("invalid number of response entries")
    40  	errHeaderUnavailable   = errors.New("header unavailable")
    41  	errTxHashMismatch      = errors.New("transaction hash mismatch")
    42  	errUncleHashMismatch   = errors.New("uncle hash mismatch")
    43  	errReceiptHashMismatch = errors.New("receipt hash mismatch")
    44  	errDataHashMismatch    = errors.New("data hash mismatch")
    45  	errCHTHashMismatch     = errors.New("cht hash mismatch")
    46  	errCHTNumberMismatch   = errors.New("cht number mismatch")
    47  	errUselessNodes        = errors.New("useless nodes in merkle proof nodeset")
    48  )
    49  
    50  type LesOdrRequest interface {
    51  	GetCost(*peer) uint64
    52  	CanSend(*peer) bool
    53  	Request(uint64, *peer) error
    54  	Validate(ethdb.Database, *Msg) error
    55  }
    56  
    57  func LesRequest(req light.OdrRequest) LesOdrRequest {
    58  	switch r := req.(type) {
    59  	case *light.BlockRequest:
    60  		return (*BlockRequest)(r)
    61  	case *light.ReceiptsRequest:
    62  		return (*ReceiptsRequest)(r)
    63  	case *light.TrieRequest:
    64  		return (*TrieRequest)(r)
    65  	case *light.CodeRequest:
    66  		return (*CodeRequest)(r)
    67  	case *light.ChtRequest:
    68  		return (*ChtRequest)(r)
    69  	case *light.BloomRequest:
    70  		return (*BloomRequest)(r)
    71  	default:
    72  		return nil
    73  	}
    74  }
    75  
    76  // BlockRequest is the ODR request type for block bodies
    77  type BlockRequest light.BlockRequest
    78  
    79  // GetCost returns the cost of the given ODR request according to the serving
    80  // peer's cost table (implementation of LesOdrRequest)
    81  func (r *BlockRequest) GetCost(peer *peer) uint64 {
    82  	return peer.GetRequestCost(GetBlockBodiesMsg, 1)
    83  }
    84  
    85  // CanSend tells if a certain peer is suitable for serving the given request
    86  func (r *BlockRequest) CanSend(peer *peer) bool {
    87  	return peer.HasBlock(r.Hash, r.Number)
    88  }
    89  
    90  // Request sends an ODR request to the LES network (implementation of LesOdrRequest)
    91  func (r *BlockRequest) Request(reqID uint64, peer *peer) error {
    92  	peer.Log().Debug("Requesting block body", "hash", r.Hash)
    93  	return peer.RequestBodies(reqID, r.GetCost(peer), []common.Hash{r.Hash})
    94  }
    95  
    96  // Valid processes an ODR request reply message from the LES network
    97  // returns true and stores results in memory if the message was a valid reply
    98  // to the request (implementation of LesOdrRequest)
    99  func (r *BlockRequest) Validate(db ethdb.Database, msg *Msg) error {
   100  	log.Debug("Validating block body", "hash", r.Hash)
   101  
   102  	// Ensure we have a correct message with a single block body
   103  	if msg.MsgType != MsgBlockBodies {
   104  		return errInvalidMessageType
   105  	}
   106  	bodies := msg.Obj.([]*types.Body)
   107  	if len(bodies) != 1 {
   108  		return errInvalidEntryCount
   109  	}
   110  	body := bodies[0]
   111  
   112  	// Retrieve our stored header and validate block content against it
   113  	header := rawdb.ReadHeader(db, r.Hash, r.Number)
   114  	if header == nil {
   115  		return errHeaderUnavailable
   116  	}
   117  	if header.TxHash != types.DeriveSha(types.Transactions(body.Transactions)) {
   118  		return errTxHashMismatch
   119  	}
   120  	// Validations passed, encode and store RLP
   121  	data, err := rlp.EncodeToBytes(body)
   122  	if err != nil {
   123  		return err
   124  	}
   125  	r.Rlp = data
   126  	return nil
   127  }
   128  
   129  // ReceiptsRequest is the ODR request type for block receipts by block hash
   130  type ReceiptsRequest light.ReceiptsRequest
   131  
   132  // GetCost returns the cost of the given ODR request according to the serving
   133  // peer's cost table (implementation of LesOdrRequest)
   134  func (r *ReceiptsRequest) GetCost(peer *peer) uint64 {
   135  	return peer.GetRequestCost(GetReceiptsMsg, 1)
   136  }
   137  
   138  // CanSend tells if a certain peer is suitable for serving the given request
   139  func (r *ReceiptsRequest) CanSend(peer *peer) bool {
   140  	return peer.HasBlock(r.Hash, r.Number)
   141  }
   142  
   143  // Request sends an ODR request to the LES network (implementation of LesOdrRequest)
   144  func (r *ReceiptsRequest) Request(reqID uint64, peer *peer) error {
   145  	peer.Log().Debug("Requesting block receipts", "hash", r.Hash)
   146  	return peer.RequestReceipts(reqID, r.GetCost(peer), []common.Hash{r.Hash})
   147  }
   148  
   149  // Valid processes an ODR request reply message from the LES network
   150  // returns true and stores results in memory if the message was a valid reply
   151  // to the request (implementation of LesOdrRequest)
   152  func (r *ReceiptsRequest) Validate(db ethdb.Database, msg *Msg) error {
   153  	log.Debug("Validating block receipts", "hash", r.Hash)
   154  
   155  	// Ensure we have a correct message with a single block receipt
   156  	if msg.MsgType != MsgReceipts {
   157  		return errInvalidMessageType
   158  	}
   159  	receipts := msg.Obj.([]types.Receipts)
   160  	if len(receipts) != 1 {
   161  		return errInvalidEntryCount
   162  	}
   163  	receipt := receipts[0]
   164  
   165  	// Retrieve our stored header and validate receipt content against it
   166  	header := rawdb.ReadHeader(db, r.Hash, r.Number)
   167  	if header == nil {
   168  		return errHeaderUnavailable
   169  	}
   170  	if header.ReceiptHash != types.DeriveSha(receipt) {
   171  		return errReceiptHashMismatch
   172  	}
   173  	// Validations passed, store and return
   174  	r.Receipts = receipt
   175  	return nil
   176  }
   177  
   178  type ProofReq struct {
   179  	BHash       common.Hash
   180  	AccKey, Key []byte
   181  	FromLevel   uint
   182  }
   183  
   184  // ODR request type for state/storage trie entries, see LesOdrRequest interface
   185  type TrieRequest light.TrieRequest
   186  
   187  // GetCost returns the cost of the given ODR request according to the serving
   188  // peer's cost table (implementation of LesOdrRequest)
   189  func (r *TrieRequest) GetCost(peer *peer) uint64 {
   190  	switch peer.version {
   191  	case lpv1:
   192  		return peer.GetRequestCost(GetProofsV1Msg, 1)
   193  	case lpv2:
   194  		return peer.GetRequestCost(GetProofsV2Msg, 1)
   195  	default:
   196  		panic(nil)
   197  	}
   198  }
   199  
   200  // CanSend tells if a certain peer is suitable for serving the given request
   201  func (r *TrieRequest) CanSend(peer *peer) bool {
   202  	return peer.HasBlock(r.Id.BlockHash, r.Id.BlockNumber)
   203  }
   204  
   205  // Request sends an ODR request to the LES network (implementation of LesOdrRequest)
   206  func (r *TrieRequest) Request(reqID uint64, peer *peer) error {
   207  	peer.Log().Debug("Requesting trie proof", "root", r.Id.Root, "key", r.Key)
   208  	req := ProofReq{
   209  		BHash:  r.Id.BlockHash,
   210  		AccKey: r.Id.AccKey,
   211  		Key:    r.Key,
   212  	}
   213  	return peer.RequestProofs(reqID, r.GetCost(peer), []ProofReq{req})
   214  }
   215  
   216  // Valid processes an ODR request reply message from the LES network
   217  // returns true and stores results in memory if the message was a valid reply
   218  // to the request (implementation of LesOdrRequest)
   219  func (r *TrieRequest) Validate(db ethdb.Database, msg *Msg) error {
   220  	log.Debug("Validating trie proof", "root", r.Id.Root, "key", r.Key)
   221  
   222  	switch msg.MsgType {
   223  	case MsgProofsV1:
   224  		proofs := msg.Obj.([]light.NodeList)
   225  		if len(proofs) != 1 {
   226  			return errInvalidEntryCount
   227  		}
   228  		nodeSet := proofs[0].NodeSet()
   229  		// Verify the proof and store if checks out
   230  		if _, _, err := trie.VerifyProof(r.Id.Root, r.Key, nodeSet); err != nil {
   231  			return fmt.Errorf("merkle proof verification failed: %v", err)
   232  		}
   233  		r.Proof = nodeSet
   234  		return nil
   235  
   236  	case MsgProofsV2:
   237  		proofs := msg.Obj.(light.NodeList)
   238  		// Verify the proof and store if checks out
   239  		nodeSet := proofs.NodeSet()
   240  		reads := &readTraceDB{db: nodeSet}
   241  		if _, _, err := trie.VerifyProof(r.Id.Root, r.Key, reads); err != nil {
   242  			return fmt.Errorf("merkle proof verification failed: %v", err)
   243  		}
   244  		// check if all nodes have been read by VerifyProof
   245  		if len(reads.reads) != nodeSet.KeyCount() {
   246  			return errUselessNodes
   247  		}
   248  		r.Proof = nodeSet
   249  		return nil
   250  
   251  	default:
   252  		return errInvalidMessageType
   253  	}
   254  }
   255  
   256  type CodeReq struct {
   257  	BHash  common.Hash
   258  	AccKey []byte
   259  }
   260  
   261  // ODR request type for node data (used for retrieving contract code), see LesOdrRequest interface
   262  type CodeRequest light.CodeRequest
   263  
   264  // GetCost returns the cost of the given ODR request according to the serving
   265  // peer's cost table (implementation of LesOdrRequest)
   266  func (r *CodeRequest) GetCost(peer *peer) uint64 {
   267  	return peer.GetRequestCost(GetCodeMsg, 1)
   268  }
   269  
   270  // CanSend tells if a certain peer is suitable for serving the given request
   271  func (r *CodeRequest) CanSend(peer *peer) bool {
   272  	return peer.HasBlock(r.Id.BlockHash, r.Id.BlockNumber)
   273  }
   274  
   275  // Request sends an ODR request to the LES network (implementation of LesOdrRequest)
   276  func (r *CodeRequest) Request(reqID uint64, peer *peer) error {
   277  	peer.Log().Debug("Requesting code data", "hash", r.Hash)
   278  	req := CodeReq{
   279  		BHash:  r.Id.BlockHash,
   280  		AccKey: r.Id.AccKey,
   281  	}
   282  	return peer.RequestCode(reqID, r.GetCost(peer), []CodeReq{req})
   283  }
   284  
   285  // Valid processes an ODR request reply message from the LES network
   286  // returns true and stores results in memory if the message was a valid reply
   287  // to the request (implementation of LesOdrRequest)
   288  func (r *CodeRequest) Validate(db ethdb.Database, msg *Msg) error {
   289  	log.Debug("Validating code data", "hash", r.Hash)
   290  
   291  	// Ensure we have a correct message with a single code element
   292  	if msg.MsgType != MsgCode {
   293  		return errInvalidMessageType
   294  	}
   295  	reply := msg.Obj.([][]byte)
   296  	if len(reply) != 1 {
   297  		return errInvalidEntryCount
   298  	}
   299  	data := reply[0]
   300  
   301  	// Verify the data and store if checks out
   302  	if hash := crypto.Keccak256Hash(data); r.Hash != hash {
   303  		return errDataHashMismatch
   304  	}
   305  	r.Data = data
   306  	return nil
   307  }
   308  
   309  const (
   310  	// helper trie type constants
   311  	htCanonical = iota // Canonical hash trie
   312  	htBloomBits        // BloomBits trie
   313  
   314  	// applicable for all helper trie requests
   315  	auxRoot = 1
   316  	// applicable for htCanonical
   317  	auxHeader = 2
   318  )
   319  
   320  type HelperTrieReq struct {
   321  	Type              uint
   322  	TrieIdx           uint64
   323  	Key               []byte
   324  	FromLevel, AuxReq uint
   325  }
   326  
   327  type HelperTrieResps struct { // describes all responses, not just a single one
   328  	Proofs  light.NodeList
   329  	AuxData [][]byte
   330  }
   331  
   332  // legacy LES/1
   333  type ChtReq struct {
   334  	ChtNum, BlockNum uint64
   335  	FromLevel        uint
   336  }
   337  
   338  // legacy LES/1
   339  type ChtResp struct {
   340  	Header *types.Header
   341  	Proof  []rlp.RawValue
   342  }
   343  
   344  // ODR request type for requesting headers by Canonical Hash Trie, see LesOdrRequest interface
   345  type ChtRequest light.ChtRequest
   346  
   347  // GetCost returns the cost of the given ODR request according to the serving
   348  // peer's cost table (implementation of LesOdrRequest)
   349  func (r *ChtRequest) GetCost(peer *peer) uint64 {
   350  	switch peer.version {
   351  	case lpv1:
   352  		return peer.GetRequestCost(GetHeaderProofsMsg, 1)
   353  	case lpv2:
   354  		return peer.GetRequestCost(GetHelperTrieProofsMsg, 1)
   355  	default:
   356  		panic(nil)
   357  	}
   358  }
   359  
   360  // CanSend tells if a certain peer is suitable for serving the given request
   361  func (r *ChtRequest) CanSend(peer *peer) bool {
   362  	peer.lock.RLock()
   363  	defer peer.lock.RUnlock()
   364  
   365  	return peer.headInfo.Number >= r.Config.ChtConfirms && r.ChtNum <= (peer.headInfo.Number-r.Config.ChtConfirms)/r.Config.ChtSize
   366  }
   367  
   368  // Request sends an ODR request to the LES network (implementation of LesOdrRequest)
   369  func (r *ChtRequest) Request(reqID uint64, peer *peer) error {
   370  	peer.Log().Debug("Requesting CHT", "cht", r.ChtNum, "block", r.BlockNum)
   371  	var encNum [8]byte
   372  	binary.BigEndian.PutUint64(encNum[:], r.BlockNum)
   373  	req := HelperTrieReq{
   374  		Type:    htCanonical,
   375  		TrieIdx: r.ChtNum,
   376  		Key:     encNum[:],
   377  		AuxReq:  auxHeader,
   378  	}
   379  	switch peer.version {
   380  	case lpv1:
   381  		var reqsV1 ChtReq
   382  		if req.Type != htCanonical || req.AuxReq != auxHeader || len(req.Key) != 8 {
   383  			return fmt.Errorf("Request invalid in LES/1 mode")
   384  		}
   385  		blockNum := binary.BigEndian.Uint64(req.Key)
   386  		// convert HelperTrie request to old CHT request
   387  		reqsV1 = ChtReq{ChtNum: (req.TrieIdx + 1) * (r.Config.ChtSize / r.Config.PairChtSize), BlockNum: blockNum, FromLevel: req.FromLevel}
   388  		return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []ChtReq{reqsV1})
   389  	case lpv2:
   390  		return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), []HelperTrieReq{req})
   391  	default:
   392  		panic(nil)
   393  	}
   394  }
   395  
   396  // Valid processes an ODR request reply message from the LES network
   397  // returns true and stores results in memory if the message was a valid reply
   398  // to the request (implementation of LesOdrRequest)
   399  func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error {
   400  	log.Debug("Validating CHT", "cht", r.ChtNum, "block", r.BlockNum)
   401  
   402  	switch msg.MsgType {
   403  	case MsgHeaderProofs: // LES/1 backwards compatibility
   404  		proofs := msg.Obj.([]ChtResp)
   405  		if len(proofs) != 1 {
   406  			return errInvalidEntryCount
   407  		}
   408  		proof := proofs[0]
   409  
   410  		// Verify the CHT
   411  		var encNumber [8]byte
   412  		binary.BigEndian.PutUint64(encNumber[:], r.BlockNum)
   413  
   414  		value, _, err := trie.VerifyProof(r.ChtRoot, encNumber[:], light.NodeList(proof.Proof).NodeSet())
   415  		if err != nil {
   416  			return err
   417  		}
   418  		var node light.ChtNode
   419  		if err := rlp.DecodeBytes(value, &node); err != nil {
   420  			return err
   421  		}
   422  		if node.Hash != proof.Header.Hash() {
   423  			return errCHTHashMismatch
   424  		}
   425  		// Verifications passed, store and return
   426  		r.Header = proof.Header
   427  		r.Proof = light.NodeList(proof.Proof).NodeSet()
   428  		r.Td = node.Td
   429  	case MsgHelperTrieProofs:
   430  		resp := msg.Obj.(HelperTrieResps)
   431  		if len(resp.AuxData) != 1 {
   432  			return errInvalidEntryCount
   433  		}
   434  		nodeSet := resp.Proofs.NodeSet()
   435  		headerEnc := resp.AuxData[0]
   436  		if len(headerEnc) == 0 {
   437  			return errHeaderUnavailable
   438  		}
   439  		header := new(types.Header)
   440  		if err := rlp.DecodeBytes(headerEnc, header); err != nil {
   441  			return errHeaderUnavailable
   442  		}
   443  
   444  		// Verify the CHT
   445  		var encNumber [8]byte
   446  		binary.BigEndian.PutUint64(encNumber[:], r.BlockNum)
   447  
   448  		reads := &readTraceDB{db: nodeSet}
   449  		value, _, err := trie.VerifyProof(r.ChtRoot, encNumber[:], reads)
   450  		if err != nil {
   451  			return fmt.Errorf("merkle proof verification failed: %v", err)
   452  		}
   453  		if len(reads.reads) != nodeSet.KeyCount() {
   454  			return errUselessNodes
   455  		}
   456  
   457  		var node light.ChtNode
   458  		if err := rlp.DecodeBytes(value, &node); err != nil {
   459  			return err
   460  		}
   461  		if node.Hash != header.Hash() {
   462  			return errCHTHashMismatch
   463  		}
   464  		if r.BlockNum != header.Number.Uint64() {
   465  			return errCHTNumberMismatch
   466  		}
   467  		// Verifications passed, store and return
   468  		r.Header = header
   469  		r.Proof = nodeSet
   470  		r.Td = node.Td
   471  	default:
   472  		return errInvalidMessageType
   473  	}
   474  	return nil
   475  }
   476  
   477  type BloomReq struct {
   478  	BloomTrieNum, BitIdx, SectionIndex, FromLevel uint64
   479  }
   480  
   481  // ODR request type for requesting headers by Canonical Hash Trie, see LesOdrRequest interface
   482  type BloomRequest light.BloomRequest
   483  
   484  // GetCost returns the cost of the given ODR request according to the serving
   485  // peer's cost table (implementation of LesOdrRequest)
   486  func (r *BloomRequest) GetCost(peer *peer) uint64 {
   487  	return peer.GetRequestCost(GetHelperTrieProofsMsg, len(r.SectionIndexList))
   488  }
   489  
   490  // CanSend tells if a certain peer is suitable for serving the given request
   491  func (r *BloomRequest) CanSend(peer *peer) bool {
   492  	peer.lock.RLock()
   493  	defer peer.lock.RUnlock()
   494  
   495  	if peer.version < lpv2 {
   496  		return false
   497  	}
   498  	return peer.headInfo.Number >= r.Config.BloomTrieConfirms && r.BloomTrieNum <= (peer.headInfo.Number-r.Config.BloomTrieConfirms)/r.Config.BloomTrieSize
   499  }
   500  
   501  // Request sends an ODR request to the LES network (implementation of LesOdrRequest)
   502  func (r *BloomRequest) Request(reqID uint64, peer *peer) error {
   503  	peer.Log().Debug("Requesting BloomBits", "bloomTrie", r.BloomTrieNum, "bitIdx", r.BitIdx, "sections", r.SectionIndexList)
   504  	reqs := make([]HelperTrieReq, len(r.SectionIndexList))
   505  
   506  	var encNumber [10]byte
   507  	binary.BigEndian.PutUint16(encNumber[:2], uint16(r.BitIdx))
   508  
   509  	for i, sectionIdx := range r.SectionIndexList {
   510  		binary.BigEndian.PutUint64(encNumber[2:], sectionIdx)
   511  		reqs[i] = HelperTrieReq{
   512  			Type:    htBloomBits,
   513  			TrieIdx: r.BloomTrieNum,
   514  			Key:     common.CopyBytes(encNumber[:]),
   515  		}
   516  	}
   517  	return peer.RequestHelperTrieProofs(reqID, r.GetCost(peer), reqs)
   518  }
   519  
   520  // Valid processes an ODR request reply message from the LES network
   521  // returns true and stores results in memory if the message was a valid reply
   522  // to the request (implementation of LesOdrRequest)
   523  func (r *BloomRequest) Validate(db ethdb.Database, msg *Msg) error {
   524  	log.Debug("Validating BloomBits", "bloomTrie", r.BloomTrieNum, "bitIdx", r.BitIdx, "sections", r.SectionIndexList)
   525  
   526  	// Ensure we have a correct message with a single proof element
   527  	if msg.MsgType != MsgHelperTrieProofs {
   528  		return errInvalidMessageType
   529  	}
   530  	resps := msg.Obj.(HelperTrieResps)
   531  	proofs := resps.Proofs
   532  	nodeSet := proofs.NodeSet()
   533  	reads := &readTraceDB{db: nodeSet}
   534  
   535  	r.BloomBits = make([][]byte, len(r.SectionIndexList))
   536  
   537  	// Verify the proofs
   538  	var encNumber [10]byte
   539  	binary.BigEndian.PutUint16(encNumber[:2], uint16(r.BitIdx))
   540  
   541  	for i, idx := range r.SectionIndexList {
   542  		binary.BigEndian.PutUint64(encNumber[2:], idx)
   543  		value, _, err := trie.VerifyProof(r.BloomTrieRoot, encNumber[:], reads)
   544  		if err != nil {
   545  			return err
   546  		}
   547  		r.BloomBits[i] = value
   548  	}
   549  
   550  	if len(reads.reads) != nodeSet.KeyCount() {
   551  		return errUselessNodes
   552  	}
   553  	r.Proofs = nodeSet
   554  	return nil
   555  }
   556  
   557  // readTraceDB stores the keys of database reads. We use this to check that received node
   558  // sets contain only the trie nodes necessary to make proofs pass.
   559  type readTraceDB struct {
   560  	db    trie.DatabaseReader
   561  	reads map[string]struct{}
   562  }
   563  
   564  // Get returns a stored node
   565  func (db *readTraceDB) Get(k []byte) ([]byte, error) {
   566  	if db.reads == nil {
   567  		db.reads = make(map[string]struct{})
   568  	}
   569  	db.reads[string(k)] = struct{}{}
   570  	return db.db.Get(k)
   571  }
   572  
   573  // Has returns true if the node set contains the given key
   574  func (db *readTraceDB) Has(key []byte) (bool, error) {
   575  	_, err := db.Get(key)
   576  	return err == nil, nil
   577  }