From 14e65b5d0e8c0eb1158f424c908554974309d9c8 Mon Sep 17 00:00:00 2001 From: rjl493456442 Date: Sun, 15 Jul 2018 15:20:50 +0800 Subject: [PATCH] les, light: redef cht request --- les/odr_requests.go | 41 +++++++++++++++++++++++------------------ light/odr.go | 18 +++++++++--------- light/odr_util.go | 4 ++-- 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/les/odr_requests.go b/les/odr_requests.go index b9ed1fa5ec..a4fe9c8fc4 100644 --- a/les/odr_requests.go +++ b/les/odr_requests.go @@ -353,9 +353,9 @@ type ChtRequest light.ChtRequest func (r *ChtRequest) GetCost(peer *peer) uint64 { switch peer.version { case lpv1: - return peer.GetRequestCost(GetHeaderProofsMsg, len(r.BlockNum)) + return peer.GetRequestCost(GetHeaderProofsMsg, len(r.Numbers)) case lpv2: - return peer.GetRequestCost(GetHelperTrieProofsMsg, len(r.BlockNum)) + return peer.GetRequestCost(GetHelperTrieProofsMsg, len(r.Numbers)) default: panic(nil) } @@ -371,17 +371,17 @@ func (r *ChtRequest) CanSend(peer *peer, config *light.IndexerConfig) bool { // Request sends an ODR request to the LES network (implementation of LesOdrRequest) func (r *ChtRequest) Request(reqID uint64, peer *peer, config *light.IndexerConfig) error { - peer.Log().Debug("Requesting CHT", "cht", r.ChtNum, "block", r.BlockNum) + peer.Log().Debug("Requesting CHT", "cht", r.ChtNum, "block", r.Numbers) var ( encNum [8]byte - reqs []HelperTrieReq + reqs = make([]HelperTrieReq, 0, len(r.Numbers)) ) - for _, num := range r.BlockNum { + for _, num := range r.Numbers { binary.BigEndian.PutUint64(encNum[:], num) reqs = append(reqs, HelperTrieReq{ Type: htCanonical, TrieIdx: r.ChtNum, - Key: encNum[:], + Key: common.CopyBytes(encNum[:]), AuxReq: auxHeader, }) } @@ -408,22 +408,21 @@ func (r *ChtRequest) Request(reqID uint64, peer *peer, config *light.IndexerConf // returns true and stores results in memory if the message was a valid reply // to the request (implementation of LesOdrRequest) func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error { - log.Debug("Validating CHT", "cht", r.ChtNum, "block", r.BlockNum) + log.Debug("Validating CHT", "cht", r.ChtNum, "block", r.Numbers) switch msg.MsgType { case MsgHeaderProofs: // LES/1 backwards compatibility resps := msg.Obj.([]ChtResp) - if len(resps) != len(r.BlockNum) { + if len(resps) != len(r.Numbers) { return errInvalidEntryCount } var ( headers []*types.Header tds []*big.Int encNumber [8]byte - node light.ChtNode nodeset = light.NewNodeSet() ) - for i, num := range r.BlockNum { + for i, num := range r.Numbers { resp := resps[i] // Verify the CHT binary.BigEndian.PutUint64(encNumber[:], num) @@ -431,6 +430,7 @@ func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error { if err != nil { return err } + var node light.ChtNode if err := rlp.DecodeBytes(value, &node); err != nil { return err } @@ -445,24 +445,24 @@ func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error { tds = append(tds, node.Td) light.NodeList(resp.Proof).Store(nodeset) } - r.Header = headers - r.Td = tds + r.Headers = headers + r.Tds = tds r.Proof = nodeset case MsgHelperTrieProofs: // Check if the number of items in the response is the same as we requested. resp := msg.Obj.(HelperTrieResps) - if len(resp.AuxData) != len(r.BlockNum) { + if len(resp.AuxData) != len(r.Numbers) { return errInvalidEntryCount } var ( headers []*types.Header tds []*big.Int encNumber [8]byte - node light.ChtNode nodeSet = resp.Proofs.NodeSet() + reads = &readTraceDB{db: nodeSet} ) - for i, num := range r.BlockNum { + for i, num := range r.Numbers { enc := resp.AuxData[i] if len(enc) == 0 { return errHeaderUnavailable @@ -473,10 +473,11 @@ func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error { } // Verify the CHT binary.BigEndian.PutUint64(encNumber[:], num) - value, _, err := trie.VerifyProof(r.ChtRoot, encNumber[:], nodeSet) + value, _, err := trie.VerifyProof(r.ChtRoot, encNumber[:], reads) if err != nil { return fmt.Errorf("merkle proof verification failed: %v", err) } + var node light.ChtNode if err := rlp.DecodeBytes(value, &node); err != nil { return err } @@ -490,8 +491,12 @@ func (r *ChtRequest) Validate(db ethdb.Database, msg *Msg) error { headers = append(headers, header) tds = append(tds, node.Td) } - r.Header = headers - r.Td = tds + if len(reads.reads) != nodeSet.KeyCount() { + return errUselessNodes + } + + r.Headers = headers + r.Tds = tds r.Proof = nodeSet default: diff --git a/light/odr.go b/light/odr.go index 9e6b6d3fe4..7e6a9eb300 100644 --- a/light/odr.go +++ b/light/odr.go @@ -133,24 +133,24 @@ func (req *ReceiptsRequest) StoreResult(db ethdb.Database, config *IndexerConfig // ChtRequest is the ODR request type for state/storage trie entries type ChtRequest struct { OdrRequest - ChtNum uint64 - ChtRoot common.Hash - BlockNum []uint64 - Header []*types.Header - Td []*big.Int - Proof *NodeSet + ChtNum uint64 + ChtRoot common.Hash + Numbers []uint64 + Headers []*types.Header + Tds []*big.Int + Proof *NodeSet } // StoreResult stores the retrieved data in local database func (req *ChtRequest) StoreResult(db ethdb.Database, config *IndexerConfig) { // The block number, header, td, proof length consistency has been verified // in the validation phase. - for index := range req.BlockNum { - header := req.Header[index] + for index := range req.Numbers { + header := req.Headers[index] hash, num := header.Hash(), header.Number.Uint64() rawdb.WriteHeader(db, header) - rawdb.WriteTd(db, hash, num, req.Td[index]) + rawdb.WriteTd(db, hash, num, req.Tds[index]) rawdb.WriteCanonicalHash(db, hash, num) } } diff --git a/light/odr_util.go b/light/odr_util.go index c54acc5dcf..659bc4c8d1 100644 --- a/light/odr_util.go +++ b/light/odr_util.go @@ -62,12 +62,12 @@ func GetHeaderByNumber(ctx context.Context, odr OdrBackend, number uint64) (*typ if number >= chtCount*odr.IndexerConfig().ChtSize { return nil, ErrNoTrustedCht } - r := &ChtRequest{ChtRoot: GetChtRoot(db, chtCount-1, sectionHead), ChtNum: chtCount - 1, BlockNum: []uint64{number}} + r := &ChtRequest{ChtRoot: GetChtRoot(db, chtCount-1, sectionHead), ChtNum: chtCount - 1, Numbers: []uint64{number}} if err := odr.Retrieve(ctx, r); err != nil { return nil, err } // Response item number has been checked in validation stage, no extra checking needed. - return r.Header[0], nil + return r.Headers[0], nil } func GetCanonicalHash(ctx context.Context, odr OdrBackend, number uint64) (common.Hash, error) {