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