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 }