github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/les/odr.go (about) 1 package les 2 3 import ( 4 "context" 5 6 "github.com/quickchainproject/quickchain/core" 7 "github.com/quickchainproject/quickchain/qctdb" 8 "github.com/quickchainproject/quickchain/light" 9 "github.com/quickchainproject/quickchain/log" 10 ) 11 12 // LesOdr implements light.OdrBackend 13 type LesOdr struct { 14 db qctdb.Database 15 chtIndexer, bloomTrieIndexer, bloomIndexer *core.ChainIndexer 16 retriever *retrieveManager 17 stop chan struct{} 18 } 19 20 func NewLesOdr(db qctdb.Database, chtIndexer, bloomTrieIndexer, bloomIndexer *core.ChainIndexer, retriever *retrieveManager) *LesOdr { 21 return &LesOdr{ 22 db: db, 23 chtIndexer: chtIndexer, 24 bloomTrieIndexer: bloomTrieIndexer, 25 bloomIndexer: bloomIndexer, 26 retriever: retriever, 27 stop: make(chan struct{}), 28 } 29 } 30 31 // Stop cancels all pending retrievals 32 func (odr *LesOdr) Stop() { 33 close(odr.stop) 34 } 35 36 // Database returns the backing database 37 func (odr *LesOdr) Database() qctdb.Database { 38 return odr.db 39 } 40 41 // ChtIndexer returns the CHT chain indexer 42 func (odr *LesOdr) ChtIndexer() *core.ChainIndexer { 43 return odr.chtIndexer 44 } 45 46 // BloomTrieIndexer returns the bloom trie chain indexer 47 func (odr *LesOdr) BloomTrieIndexer() *core.ChainIndexer { 48 return odr.bloomTrieIndexer 49 } 50 51 // BloomIndexer returns the bloombits chain indexer 52 func (odr *LesOdr) BloomIndexer() *core.ChainIndexer { 53 return odr.bloomIndexer 54 } 55 56 const ( 57 MsgBlockBodies = iota 58 MsgCode 59 MsgReceipts 60 MsgProofsV1 61 MsgProofsV2 62 MsgHeaderProofs 63 MsgHelperTrieProofs 64 ) 65 66 // Msg encodes a LES message that delivers reply data for a request 67 type Msg struct { 68 MsgType int 69 ReqID uint64 70 Obj interface{} 71 } 72 73 // Retrieve tries to fetch an object from the LES network. 74 // If the network retrieval was successful, it stores the object in local db. 75 func (odr *LesOdr) Retrieve(ctx context.Context, req light.OdrRequest) (err error) { 76 lreq := LesRequest(req) 77 78 reqID := genReqID() 79 rq := &distReq{ 80 getCost: func(dp distPeer) uint64 { 81 return lreq.GetCost(dp.(*peer)) 82 }, 83 canSend: func(dp distPeer) bool { 84 p := dp.(*peer) 85 return lreq.CanSend(p) 86 }, 87 request: func(dp distPeer) func() { 88 p := dp.(*peer) 89 cost := lreq.GetCost(p) 90 p.fcServer.QueueRequest(reqID, cost) 91 return func() { lreq.Request(reqID, p) } 92 }, 93 } 94 95 if err = odr.retriever.retrieve(ctx, reqID, rq, func(p distPeer, msg *Msg) error { return lreq.Validate(odr.db, msg) }, odr.stop); err == nil { 96 // retrieved from network, store in db 97 req.StoreResult(odr.db) 98 } else { 99 log.Debug("Failed to retrieve data from network", "err", err) 100 } 101 return 102 }