github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/les/odr.go (about) 1 // Copyright 2016 The Spectrum Authors 2 // This file is part of the Spectrum library. 3 // 4 // The Spectrum 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 Spectrum 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 Spectrum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package les 18 19 import ( 20 "context" 21 22 "github.com/SmartMeshFoundation/Spectrum/core" 23 "github.com/SmartMeshFoundation/Spectrum/ethdb" 24 "github.com/SmartMeshFoundation/Spectrum/light" 25 "github.com/SmartMeshFoundation/Spectrum/log" 26 ) 27 28 // LesOdr implements light.OdrBackend 29 type LesOdr struct { 30 db ethdb.Database 31 chtIndexer, bloomTrieIndexer, bloomIndexer *core.ChainIndexer 32 retriever *retrieveManager 33 stop chan struct{} 34 } 35 36 func NewLesOdr(db ethdb.Database, chtIndexer, bloomTrieIndexer, bloomIndexer *core.ChainIndexer, retriever *retrieveManager) *LesOdr { 37 return &LesOdr{ 38 db: db, 39 chtIndexer: chtIndexer, 40 bloomTrieIndexer: bloomTrieIndexer, 41 bloomIndexer: bloomIndexer, 42 retriever: retriever, 43 stop: make(chan struct{}), 44 } 45 } 46 47 // Stop cancels all pending retrievals 48 func (odr *LesOdr) Stop() { 49 close(odr.stop) 50 } 51 52 // Database returns the backing database 53 func (odr *LesOdr) Database() ethdb.Database { 54 return odr.db 55 } 56 57 // ChtIndexer returns the CHT chain indexer 58 func (odr *LesOdr) ChtIndexer() *core.ChainIndexer { 59 return odr.chtIndexer 60 } 61 62 // BloomTrieIndexer returns the bloom trie chain indexer 63 func (odr *LesOdr) BloomTrieIndexer() *core.ChainIndexer { 64 return odr.bloomTrieIndexer 65 } 66 67 // BloomIndexer returns the bloombits chain indexer 68 func (odr *LesOdr) BloomIndexer() *core.ChainIndexer { 69 return odr.bloomIndexer 70 } 71 72 const ( 73 MsgBlockBodies = iota 74 MsgCode 75 MsgReceipts 76 MsgProofsV1 77 MsgProofsV2 78 MsgHeaderProofs 79 MsgHelperTrieProofs 80 ) 81 82 // Msg encodes a LES message that delivers reply data for a request 83 type Msg struct { 84 MsgType int 85 ReqID uint64 86 Obj interface{} 87 } 88 89 // Retrieve tries to fetch an object from the LES network. 90 // If the network retrieval was successful, it stores the object in local db. 91 func (odr *LesOdr) Retrieve(ctx context.Context, req light.OdrRequest) (err error) { 92 lreq := LesRequest(req) 93 94 reqID := genReqID() 95 rq := &distReq{ 96 getCost: func(dp distPeer) uint64 { 97 return lreq.GetCost(dp.(*peer)) 98 }, 99 canSend: func(dp distPeer) bool { 100 p := dp.(*peer) 101 return lreq.CanSend(p) 102 }, 103 request: func(dp distPeer) func() { 104 p := dp.(*peer) 105 cost := lreq.GetCost(p) 106 p.fcServer.QueueRequest(reqID, cost) 107 return func() { lreq.Request(reqID, p) } 108 }, 109 } 110 111 if err = odr.retriever.retrieve(ctx, reqID, rq, func(p distPeer, msg *Msg) error { return lreq.Validate(odr.db, msg) }, odr.stop); err == nil { 112 // retrieved from network, store in db 113 req.StoreResult(odr.db) 114 } else { 115 log.Debug("Failed to retrieve data from network", "err", err) 116 } 117 return 118 }