github.com/core-coin/go-core/v2@v2.1.9/xcb/downloader/fakepeer.go (about) 1 // Copyright 2017 by the Authors 2 // This file is part of the go-core library. 3 // 4 // The go-core 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-core 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-core library. If not, see <http://www.gnu.org/licenses/>. 16 17 package downloader 18 19 import ( 20 "math/big" 21 22 "github.com/core-coin/go-core/v2/xcbdb" 23 24 "github.com/core-coin/go-core/v2/common" 25 "github.com/core-coin/go-core/v2/core" 26 "github.com/core-coin/go-core/v2/core/rawdb" 27 "github.com/core-coin/go-core/v2/core/types" 28 ) 29 30 // FakePeer is a mock downloader peer that operates on a local database instance 31 // instead of being an actual live node. It's useful for testing and to implement 32 // sync commands from an existing local database. 33 type FakePeer struct { 34 id string 35 db xcbdb.Database 36 hc *core.HeaderChain 37 dl *Downloader 38 } 39 40 // NewFakePeer creates a new mock downloader peer with the given data sources. 41 func NewFakePeer(id string, db xcbdb.Database, hc *core.HeaderChain, dl *Downloader) *FakePeer { 42 return &FakePeer{id: id, db: db, hc: hc, dl: dl} 43 } 44 45 // Head implements downloader.Peer, returning the current head hash and number 46 // of the best known header. 47 func (p *FakePeer) Head() (common.Hash, *big.Int) { 48 header := p.hc.CurrentHeader() 49 return header.Hash(), header.Number 50 } 51 52 // RequestHeadersByHash implements downloader.Peer, returning a batch of headers 53 // defined by the origin hash and the associated query parameters. 54 func (p *FakePeer) RequestHeadersByHash(hash common.Hash, amount int, skip int, reverse bool) error { 55 var ( 56 headers []*types.Header 57 unknown bool 58 ) 59 for !unknown && len(headers) < amount { 60 origin := p.hc.GetHeaderByHash(hash) 61 if origin == nil { 62 break 63 } 64 number := origin.Number.Uint64() 65 headers = append(headers, origin) 66 if reverse { 67 for i := 0; i <= skip; i++ { 68 if header := p.hc.GetHeader(hash, number); header != nil { 69 hash = header.ParentHash 70 number-- 71 } else { 72 unknown = true 73 break 74 } 75 } 76 } else { 77 var ( 78 current = origin.Number.Uint64() 79 next = current + uint64(skip) + 1 80 ) 81 if header := p.hc.GetHeaderByNumber(next); header != nil { 82 if p.hc.GetBlockHashesFromHash(header.Hash(), uint64(skip+1))[skip] == hash { 83 hash = header.Hash() 84 } else { 85 unknown = true 86 } 87 } else { 88 unknown = true 89 } 90 } 91 } 92 p.dl.DeliverHeaders(p.id, headers) 93 return nil 94 } 95 96 // RequestHeadersByNumber implements downloader.Peer, returning a batch of headers 97 // defined by the origin number and the associated query parameters. 98 func (p *FakePeer) RequestHeadersByNumber(number uint64, amount int, skip int, reverse bool) error { 99 var ( 100 headers []*types.Header 101 unknown bool 102 ) 103 for !unknown && len(headers) < amount { 104 origin := p.hc.GetHeaderByNumber(number) 105 if origin == nil { 106 break 107 } 108 if reverse { 109 if number >= uint64(skip+1) { 110 number -= uint64(skip + 1) 111 } else { 112 unknown = true 113 } 114 } else { 115 number += uint64(skip + 1) 116 } 117 headers = append(headers, origin) 118 } 119 p.dl.DeliverHeaders(p.id, headers) 120 return nil 121 } 122 123 // RequestBodies implements downloader.Peer, returning a batch of block bodies 124 // corresponding to the specified block hashes. 125 func (p *FakePeer) RequestBodies(hashes []common.Hash) error { 126 var ( 127 txs [][]*types.Transaction 128 uncles [][]*types.Header 129 ) 130 for _, hash := range hashes { 131 block := rawdb.ReadBlock(p.db, hash, *p.hc.GetBlockNumber(hash)) 132 133 txs = append(txs, block.Transactions()) 134 uncles = append(uncles, block.Uncles()) 135 } 136 p.dl.DeliverBodies(p.id, txs, uncles) 137 return nil 138 } 139 140 // RequestReceipts implements downloader.Peer, returning a batch of transaction 141 // receipts corresponding to the specified block hashes. 142 func (p *FakePeer) RequestReceipts(hashes []common.Hash) error { 143 var receipts [][]*types.Receipt 144 for _, hash := range hashes { 145 receipts = append(receipts, rawdb.ReadRawReceipts(p.db, hash, *p.hc.GetBlockNumber(hash))) 146 } 147 p.dl.DeliverReceipts(p.id, receipts) 148 return nil 149 } 150 151 // RequestNodeData implements downloader.Peer, returning a batch of state trie 152 // nodes corresponding to the specified trie hashes. 153 func (p *FakePeer) RequestNodeData(hashes []common.Hash) error { 154 var data [][]byte 155 for _, hash := range hashes { 156 if entry, err := p.db.Get(hash.Bytes()); err == nil { 157 data = append(data, entry) 158 } 159 } 160 p.dl.DeliverNodeData(p.id, data) 161 return nil 162 }