github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/qct/downloader/fakepeer.go (about)

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