7 log "github.com/sirupsen/logrus"
9 "github.com/vapor/protocol/bc"
10 "github.com/vapor/protocol/bc/types"
14 orphanBlockTTL = 3 * time.Minute
15 orphanExpireWorkInterval = 1 * time.Minute
16 numOrphanBlockLimit = 256
19 type orphanBlock struct {
24 // OrphanManage is use to handle all the orphan block
25 type OrphanManage struct {
26 orphan map[bc.Hash]*orphanBlock
27 prevOrphans map[bc.Hash][]*bc.Hash
31 // NewOrphanManage return a new orphan block
32 func NewOrphanManage() *OrphanManage {
34 orphan: make(map[bc.Hash]*orphanBlock),
35 prevOrphans: make(map[bc.Hash][]*bc.Hash),
38 go o.orphanExpireWorker()
42 // BlockExist check is the block in OrphanManage
43 func (o *OrphanManage) BlockExist(hash *bc.Hash) bool {
45 _, ok := o.orphan[*hash]
50 // Add will add the block to OrphanManage
51 func (o *OrphanManage) Add(block *types.Block) {
52 blockHash := block.Hash()
56 if _, ok := o.orphan[blockHash]; ok {
60 if len(o.orphan) >= numOrphanBlockLimit {
62 log.WithFields(log.Fields{"module": logModule, "hash": blockHash.String(), "height": block.Height}).Info("the number of orphan blocks exceeds the limit")
65 o.orphan[blockHash] = &orphanBlock{block, time.Now().Add(orphanBlockTTL)}
66 o.prevOrphans[block.PreviousBlockHash] = append(o.prevOrphans[block.PreviousBlockHash], &blockHash)
68 log.WithFields(log.Fields{"module": logModule, "hash": blockHash.String(), "height": block.Height}).Info("add block to orphan")
71 // Delete will delete the block from OrphanManage
72 func (o *OrphanManage) Delete(hash *bc.Hash) {
78 // Get return the orphan block by hash
79 func (o *OrphanManage) Get(hash *bc.Hash) (*types.Block, bool) {
81 block, ok := o.orphan[*hash]
83 return block.Block, ok
86 // GetPrevOrphans return the list of child orphans
87 func (o *OrphanManage) GetPrevOrphans(hash *bc.Hash) ([]*bc.Hash, bool) {
89 prevOrphans, ok := o.prevOrphans[*hash]
91 return prevOrphans, ok
94 func (o *OrphanManage) delete(hash *bc.Hash) {
95 block, ok := o.orphan[*hash]
99 delete(o.orphan, *hash)
101 prevOrphans, ok := o.prevOrphans[block.Block.PreviousBlockHash]
102 if !ok || len(prevOrphans) == 1 {
103 delete(o.prevOrphans, block.Block.PreviousBlockHash)
107 for i, preOrphan := range prevOrphans {
108 if *preOrphan == *hash {
109 o.prevOrphans[block.Block.PreviousBlockHash] = append(prevOrphans[:i], prevOrphans[i+1:]...)
115 func (o *OrphanManage) deleteLRU() {
116 var deleteBlock *orphanBlock
117 for _, orphan := range o.orphan {
118 if deleteBlock == nil || orphan.expiration.Before(deleteBlock.expiration) {
123 if deleteBlock != nil {
124 blockHash := deleteBlock.Block.Hash()
129 func (o *OrphanManage) orphanExpireWorker() {
130 ticker := time.NewTicker(orphanExpireWorkInterval)
131 for now := range ticker.C {
137 func (o *OrphanManage) orphanExpire(now time.Time) {
140 for hash, orphan := range o.orphan {
141 if orphan.expiration.Before(now) {