7 log "github.com/sirupsen/logrus"
9 "github.com/vapor/protocol/bc"
10 "github.com/vapor/protocol/bc/types"
14 orphanBlockTTL = 60 * time.Minute
15 orphanExpireWorkInterval = 3 * time.Minute
18 type orphanBlock struct {
23 // OrphanManage is use to handle all the orphan block
24 type OrphanManage struct {
25 orphan map[bc.Hash]*orphanBlock
26 prevOrphans map[bc.Hash][]*bc.Hash
30 // NewOrphanManage return a new orphan block
31 func NewOrphanManage() *OrphanManage {
33 orphan: make(map[bc.Hash]*orphanBlock),
34 prevOrphans: make(map[bc.Hash][]*bc.Hash),
37 go o.orphanExpireWorker()
41 // BlockExist check is the block in OrphanManage
42 func (o *OrphanManage) BlockExist(hash *bc.Hash) bool {
44 _, ok := o.orphan[*hash]
49 // Add will add the block to OrphanManage
50 func (o *OrphanManage) Add(block *types.Block) {
51 blockHash := block.Hash()
55 if _, ok := o.orphan[blockHash]; ok {
59 o.orphan[blockHash] = &orphanBlock{block, time.Now().Add(orphanBlockTTL)}
60 o.prevOrphans[block.PreviousBlockHash] = append(o.prevOrphans[block.PreviousBlockHash], &blockHash)
62 log.WithFields(log.Fields{"hash": blockHash.String(), "height": block.Height}).Info("add block to orphan")
65 // Delete will delete the block from OrphanManage
66 func (o *OrphanManage) Delete(hash *bc.Hash) {
72 // Get return the orphan block by hash
73 func (o *OrphanManage) Get(hash *bc.Hash) (*types.Block, bool) {
75 block, ok := o.orphan[*hash]
77 return block.Block, ok
80 // GetPrevOrphans return the list of child orphans
81 func (o *OrphanManage) GetPrevOrphans(hash *bc.Hash) ([]*bc.Hash, bool) {
83 prevOrphans, ok := o.prevOrphans[*hash]
85 return prevOrphans, ok
88 func (o *OrphanManage) delete(hash *bc.Hash) {
89 block, ok := o.orphan[*hash]
93 delete(o.orphan, *hash)
95 prevOrphans, ok := o.prevOrphans[block.Block.PreviousBlockHash]
96 if !ok || len(prevOrphans) == 1 {
97 delete(o.prevOrphans, block.Block.PreviousBlockHash)
101 for i, preOrphan := range prevOrphans {
102 if preOrphan == hash {
103 o.prevOrphans[block.Block.PreviousBlockHash] = append(prevOrphans[:i], prevOrphans[i+1:]...)
109 func (o *OrphanManage) orphanExpireWorker() {
110 ticker := time.NewTicker(orphanExpireWorkInterval)
111 for now := range ticker.C {
117 func (o *OrphanManage) orphanExpire(now time.Time) {
120 for hash, orphan := range o.orphan {
121 if orphan.expiration.Before(now) {