7 log "github.com/sirupsen/logrus"
9 "github.com/bytom/protocol/bc"
10 "github.com/bytom/protocol/bc/types"
11 "github.com/bytom/testutil"
15 orphanBlockTTL = 60 * time.Minute
16 orphanExpireWorkInterval = 3 * time.Minute
17 numOrphanBlockLimit = 256
20 type orphanBlock struct {
25 // OrphanManage is use to handle all the orphan block
26 type OrphanManage struct {
27 orphan map[bc.Hash]*orphanBlock
28 prevOrphans map[bc.Hash][]*bc.Hash
32 // NewOrphanManage return a new orphan block
33 func NewOrphanManage() *OrphanManage {
35 orphan: make(map[bc.Hash]*orphanBlock),
36 prevOrphans: make(map[bc.Hash][]*bc.Hash),
39 go o.orphanExpireWorker()
43 // Add will add the block to OrphanManage
44 func (o *OrphanManage) Add(block *types.Block) {
45 blockHash := block.Hash()
49 if _, ok := o.orphan[blockHash]; ok {
53 if len(o.orphan) >= numOrphanBlockLimit {
54 log.WithFields(log.Fields{"module": logModule, "hash": blockHash.String(), "height": block.Height}).Info("the number of orphan blocks exceeds the limit")
58 o.orphan[blockHash] = &orphanBlock{block, time.Now().Add(orphanBlockTTL)}
59 o.prevOrphans[block.PreviousBlockHash] = append(o.prevOrphans[block.PreviousBlockHash], &blockHash)
61 log.WithFields(log.Fields{"module": logModule, "hash": blockHash.String(), "height": block.Height}).Info("add block to orphan")
64 // BlockExist check is the block in OrphanManage
65 func (o *OrphanManage) BlockExist(hash *bc.Hash) bool {
67 _, ok := o.orphan[*hash]
72 // Delete will delete the block from OrphanManage
73 func (o *OrphanManage) Delete(hash *bc.Hash) {
79 func (o *OrphanManage) Equals(o1 *OrphanManage) bool {
83 return testutil.DeepEqual(o.orphan, o1.orphan) && testutil.DeepEqual(o.prevOrphans, o1.prevOrphans)
86 // Get return the orphan block by hash
87 func (o *OrphanManage) Get(hash *bc.Hash) (*types.Block, bool) {
89 block, ok := o.orphan[*hash]
91 return block.Block, ok
94 // GetPrevOrphans return the list of child orphans
95 func (o *OrphanManage) GetPrevOrphans(hash *bc.Hash) ([]*bc.Hash, bool) {
97 prevOrphans, ok := o.prevOrphans[*hash]
99 return prevOrphans, ok
102 func (o *OrphanManage) delete(hash *bc.Hash) {
103 block, ok := o.orphan[*hash]
107 delete(o.orphan, *hash)
109 prevOrphans, ok := o.prevOrphans[block.Block.PreviousBlockHash]
110 if !ok || len(prevOrphans) == 1 {
111 delete(o.prevOrphans, block.Block.PreviousBlockHash)
115 for i, preOrphan := range prevOrphans {
116 if preOrphan == hash {
117 o.prevOrphans[block.Block.PreviousBlockHash] = append(prevOrphans[:i], prevOrphans[i+1:]...)
123 func (o *OrphanManage) orphanExpireWorker() {
124 ticker := time.NewTicker(orphanExpireWorkInterval)
125 for now := range ticker.C {
131 func (o *OrphanManage) orphanExpire(now time.Time) {
134 for hash, orphan := range o.orphan {
135 if orphan.expiration.Before(now) {