github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/netsync/block_fetcher.go (about)

     1  package netsync
     2  
     3  import (
     4  	log "github.com/sirupsen/logrus"
     5  	"gopkg.in/karalabe/cookiejar.v2/collections/prque"
     6  
     7  	"github.com/bytom/bytom/p2p/security"
     8  	"github.com/bytom/bytom/protocol/bc"
     9  )
    10  
    11  const (
    12  	maxBlockDistance = 64
    13  	maxMsgSetSize    = 128
    14  	newBlockChSize   = 64
    15  )
    16  
    17  // blockFetcher is responsible for accumulating block announcements from various peers
    18  // and scheduling them for retrieval.
    19  type blockFetcher struct {
    20  	chain Chain
    21  	peers *peerSet
    22  
    23  	newBlockCh chan *blockMsg
    24  	queue      *prque.Prque
    25  	msgSet     map[bc.Hash]*blockMsg
    26  }
    27  
    28  //NewBlockFetcher creates a block fetcher to retrieve blocks of the new mined.
    29  func newBlockFetcher(chain Chain, peers *peerSet) *blockFetcher {
    30  	f := &blockFetcher{
    31  		chain:      chain,
    32  		peers:      peers,
    33  		newBlockCh: make(chan *blockMsg, newBlockChSize),
    34  		queue:      prque.New(),
    35  		msgSet:     make(map[bc.Hash]*blockMsg),
    36  	}
    37  	go f.blockProcessor()
    38  	return f
    39  }
    40  
    41  func (f *blockFetcher) blockProcessor() {
    42  	for {
    43  		for !f.queue.Empty() {
    44  			msg := f.queue.PopItem().(*blockMsg)
    45  			if msg.block.Height > f.chain.BestBlockHeight()+1 {
    46  				f.queue.Push(msg, -float32(msg.block.Height))
    47  				break
    48  			}
    49  
    50  			f.insert(msg)
    51  			delete(f.msgSet, msg.block.Hash())
    52  		}
    53  		f.add(<-f.newBlockCh)
    54  	}
    55  }
    56  
    57  func (f *blockFetcher) add(msg *blockMsg) {
    58  	bestHeight := f.chain.BestBlockHeight()
    59  	if len(f.msgSet) > maxMsgSetSize || bestHeight > msg.block.Height || msg.block.Height-bestHeight > maxBlockDistance {
    60  		return
    61  	}
    62  
    63  	blockHash := msg.block.Hash()
    64  	if _, ok := f.msgSet[blockHash]; !ok {
    65  		f.msgSet[blockHash] = msg
    66  		f.queue.Push(msg, -float32(msg.block.Height))
    67  		log.WithFields(log.Fields{
    68  			"module":       logModule,
    69  			"block height": msg.block.Height,
    70  			"block hash":   blockHash.String(),
    71  		}).Debug("blockFetcher receive mine block")
    72  	}
    73  }
    74  
    75  func (f *blockFetcher) insert(msg *blockMsg) {
    76  	isOrphan, err := f.chain.ProcessBlock(msg.block)
    77  	if err != nil {
    78  		peer := f.peers.getPeer(msg.peerID)
    79  		if peer == nil {
    80  			return
    81  		}
    82  
    83  		f.peers.ProcessIllegal(msg.peerID, security.LevelMsgIllegal, err.Error())
    84  		return
    85  	}
    86  
    87  	if isOrphan {
    88  		return
    89  	}
    90  
    91  	if err := f.peers.broadcastMinedBlock(msg.block); err != nil {
    92  		log.WithFields(log.Fields{"module": logModule, "err": err}).Error("blockFetcher fail on broadcast new block")
    93  		return
    94  	}
    95  }
    96  
    97  func (f *blockFetcher) processNewBlock(msg *blockMsg) {
    98  	f.newBlockCh <- msg
    99  }