numOrphanBlockLimit = 256
)
-type orphanBlock struct {
+type OrphanBlock struct {
*types.Block
expiration time.Time
}
+func NewOrphanBlock(block *types.Block, expiration time.Time) *OrphanBlock {
+ return &OrphanBlock{
+ Block: block,
+ expiration: expiration,
+ }
+}
+
+func (o *OrphanBlock) Equals(o1 *OrphanBlock) bool {
+ return testutil.DeepEqual(o.Block, o1.Block)
+}
+
// OrphanManage is use to handle all the orphan block
type OrphanManage struct {
- orphan map[bc.Hash]*orphanBlock
+ orphan map[bc.Hash]*OrphanBlock
prevOrphans map[bc.Hash][]*bc.Hash
mtx sync.RWMutex
}
// NewOrphanManage return a new orphan block
func NewOrphanManage() *OrphanManage {
o := &OrphanManage{
- orphan: make(map[bc.Hash]*orphanBlock),
+ orphan: make(map[bc.Hash]*OrphanBlock),
prevOrphans: make(map[bc.Hash][]*bc.Hash),
}
return o
}
+// NewOrphanManageWithData return a new orphan manage with specify data
+func NewOrphanManageWithData(orphan map[bc.Hash]*OrphanBlock, prevOrphans map[bc.Hash][]*bc.Hash) *OrphanManage {
+ return &OrphanManage{
+ orphan: orphan,
+ prevOrphans: prevOrphans,
+ }
+}
+
// Add will add the block to OrphanManage
func (o *OrphanManage) Add(block *types.Block) {
blockHash := block.Hash()
}
if len(o.orphan) >= numOrphanBlockLimit {
+ o.deleteLRU()
log.WithFields(log.Fields{"module": logModule, "hash": blockHash.String(), "height": block.Height}).Info("the number of orphan blocks exceeds the limit")
- return
}
- o.orphan[blockHash] = &orphanBlock{block, time.Now().Add(orphanBlockTTL)}
+ o.orphan[blockHash] = &OrphanBlock{block, time.Now().Add(orphanBlockTTL)}
o.prevOrphans[block.PreviousBlockHash] = append(o.prevOrphans[block.PreviousBlockHash], &blockHash)
log.WithFields(log.Fields{"module": logModule, "hash": blockHash.String(), "height": block.Height}).Info("add block to orphan")
if o1 == nil {
return false
}
- return testutil.DeepEqual(o.orphan, o1.orphan) && testutil.DeepEqual(o.prevOrphans, o1.prevOrphans)
+ for hash, block := range o.orphan {
+ if block1, ok := o1.orphan[hash]; !ok || !block.Equals(block1) {
+ return false
+ }
+ }
+ return testutil.DeepEqual(o.prevOrphans, o1.prevOrphans)
}
// Get return the orphan block by hash
}
for i, preOrphan := range prevOrphans {
- if preOrphan == hash {
+ if *preOrphan == *hash {
o.prevOrphans[block.Block.PreviousBlockHash] = append(prevOrphans[:i], prevOrphans[i+1:]...)
return
}
}
}
+func (o *OrphanManage) deleteLRU() {
+ var deleteBlock *OrphanBlock
+ for _, orphan := range o.orphan {
+ if deleteBlock == nil || orphan.expiration.Before(deleteBlock.expiration) {
+ deleteBlock = orphan
+ }
+ }
+
+ if deleteBlock != nil {
+ blockHash := deleteBlock.Block.Hash()
+ o.delete(&blockHash)
+ }
+}
+
func (o *OrphanManage) orphanExpireWorker() {
ticker := time.NewTicker(orphanExpireWorkInterval)
for now := range ticker.C {