/
orphanblockpool.go
96 lines (78 loc) · 2.37 KB
/
orphanblockpool.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package blockchain
import (
"time"
"github.com/fatzero/mass-core/blockchain/orphanpool"
"github.com/fatzero/mass-core/massutil"
"github.com/fatzero/mass-core/wire"
)
const (
// maxOrphanBlocks is the maximum number of orphan blocks that can be
// queued.
maxOrphanBlocks = 100
)
// orphanBlock represents a block that we don't yet have the Parent for. It
// is a normal block plus an expiration time to prevent caching the orphan
// forever.
type orphanBlock struct {
block *massutil.Block
expiration time.Time
}
func (blk *orphanBlock) OrphanPoolID() string {
return blk.block.Hash().String()
}
type OrphanBlockPool struct {
prevOrphans map[wire.Hash][]*orphanBlock
pool *orphanpool.AbstractOrphanPool
oldestOrphan *orphanBlock
}
func newOrphanBlockPool() *OrphanBlockPool {
return &OrphanBlockPool{
prevOrphans: make(map[wire.Hash][]*orphanBlock),
pool: orphanpool.NewAbstractOrphanPool(),
oldestOrphan: nil,
}
}
// removeOrphanBlock removes the passed orphan block from the orphan pool and
// previous orphan index.
func (ors *OrphanBlockPool) removeOrphanBlock(orphan *orphanBlock) {
orphanHash := orphan.block.Hash()
ors.pool.Fetch(orphanHash.String())
}
func (ors *OrphanBlockPool) addOrphanBlock(block *massutil.Block) {
// Remove expired orphan blocks.
for _, entry := range ors.pool.Items() {
oBlock := entry.(*orphanBlock)
if time.Now().After(oBlock.expiration) {
ors.removeOrphanBlock(oBlock)
continue
}
if ors.oldestOrphan == nil || oBlock.expiration.Before(ors.oldestOrphan.expiration) {
ors.oldestOrphan = oBlock
}
}
// Limit orphan blocks to prevent memory exhaustion.
if ors.pool.Count()+1 > maxOrphanBlocks {
ors.removeOrphanBlock(ors.oldestOrphan)
ors.oldestOrphan = nil
}
// Insert the block into the orphan map with an expiration time
// 1 hour from now.
expiration := time.Now().Add(time.Hour)
oBlock := &orphanBlock{
block: block,
expiration: expiration,
}
ors.pool.Put(oBlock, []string{block.MsgBlock().Header.Previous.String()})
return
}
func (ors *OrphanBlockPool) isOrphanInPool(hash *wire.Hash) bool {
return ors.pool.Has(hash.String())
}
func (ors *OrphanBlockPool) getOrphansByPrevious(hash *wire.Hash) []*orphanBlock {
subs := ors.pool.ReadSubs(hash.String())
orphans := make([]*orphanBlock, len(subs))
for i, sub := range subs {
orphans[i] = sub.(*orphanBlock)
}
return orphans
}