-
Notifications
You must be signed in to change notification settings - Fork 649
/
block_height_index.go
141 lines (112 loc) · 3.73 KB
/
block_height_index.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package state
import (
"github.com/ava-labs/avalanchego/cache"
"github.com/ava-labs/avalanchego/database"
"github.com/ava-labs/avalanchego/database/prefixdb"
"github.com/ava-labs/avalanchego/database/versiondb"
"github.com/ava-labs/avalanchego/ids"
)
const cacheSize = 8192 // max cache entries
var (
_ HeightIndex = (*heightIndex)(nil)
heightPrefix = []byte("height")
metadataPrefix = []byte("metadata")
forkKey = []byte("fork")
checkpointKey = []byte("checkpoint")
)
type HeightIndexGetter interface {
// GetMinimumHeight return the smallest height of an indexed blockID. If
// there are no indexed blockIDs, ErrNotFound will be returned.
GetMinimumHeight() (uint64, error)
GetBlockIDAtHeight(height uint64) (ids.ID, error)
// Fork height is stored when the first post-fork block/option is accepted.
// Before that, fork height won't be found.
GetForkHeight() (uint64, error)
}
type HeightIndexWriter interface {
SetForkHeight(height uint64) error
SetBlockIDAtHeight(height uint64, blkID ids.ID) error
DeleteBlockIDAtHeight(height uint64) error
}
// A checkpoint is the blockID of the next block to be considered
// for height indexing. We store checkpoints to be able to duly resume
// long-running re-indexing ops.
type HeightIndexBatchSupport interface {
versiondb.Commitable
GetCheckpoint() (ids.ID, error)
SetCheckpoint(blkID ids.ID) error
DeleteCheckpoint() error
}
// HeightIndex contains mapping of blockHeights to accepted proposer block IDs
// along with some metadata (fork height and checkpoint).
type HeightIndex interface {
HeightIndexWriter
HeightIndexGetter
HeightIndexBatchSupport
}
type heightIndex struct {
versiondb.Commitable
// Caches block height -> proposerVMBlockID.
heightsCache cache.Cacher[uint64, ids.ID]
heightDB database.Database
metadataDB database.Database
}
func NewHeightIndex(db database.Database, commitable versiondb.Commitable) HeightIndex {
return &heightIndex{
Commitable: commitable,
heightsCache: &cache.LRU[uint64, ids.ID]{Size: cacheSize},
heightDB: prefixdb.New(heightPrefix, db),
metadataDB: prefixdb.New(metadataPrefix, db),
}
}
func (hi *heightIndex) GetMinimumHeight() (uint64, error) {
it := hi.heightDB.NewIterator()
defer it.Release()
if !it.Next() {
return 0, database.ErrNotFound
}
height, err := database.ParseUInt64(it.Key())
if err != nil {
return 0, err
}
return height, it.Error()
}
func (hi *heightIndex) GetBlockIDAtHeight(height uint64) (ids.ID, error) {
if blkID, found := hi.heightsCache.Get(height); found {
return blkID, nil
}
key := database.PackUInt64(height)
blkID, err := database.GetID(hi.heightDB, key)
if err != nil {
return ids.Empty, err
}
hi.heightsCache.Put(height, blkID)
return blkID, err
}
func (hi *heightIndex) SetBlockIDAtHeight(height uint64, blkID ids.ID) error {
hi.heightsCache.Put(height, blkID)
key := database.PackUInt64(height)
return database.PutID(hi.heightDB, key, blkID)
}
func (hi *heightIndex) DeleteBlockIDAtHeight(height uint64) error {
hi.heightsCache.Evict(height)
key := database.PackUInt64(height)
return hi.heightDB.Delete(key)
}
func (hi *heightIndex) GetForkHeight() (uint64, error) {
return database.GetUInt64(hi.metadataDB, forkKey)
}
func (hi *heightIndex) SetForkHeight(height uint64) error {
return database.PutUInt64(hi.metadataDB, forkKey, height)
}
func (hi *heightIndex) GetCheckpoint() (ids.ID, error) {
return database.GetID(hi.metadataDB, checkpointKey)
}
func (hi *heightIndex) SetCheckpoint(blkID ids.ID) error {
return database.PutID(hi.metadataDB, checkpointKey, blkID)
}
func (hi *heightIndex) DeleteCheckpoint() error {
return hi.metadataDB.Delete(checkpointKey)
}