-
Notifications
You must be signed in to change notification settings - Fork 206
/
wanted_block_data.go
158 lines (146 loc) · 4.99 KB
/
wanted_block_data.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package chaintracker
import (
fmt "fmt"
spectypes "github.com/lavanet/lava/x/spec/types"
)
type BlockRange struct {
fromBlock int64
toBlock int64
startIndexFromEarliest uint64
endIndexFromEarliest uint64 // not inclusive
}
type WantedBlocksData struct {
rangeBlocks *BlockRange
specificBlock *BlockRange
}
func (wbd *WantedBlocksData) New(fromBlock int64, toBlock int64, specificBlock int64, latestBlock int64, earliestBlockSaved int64) (err error) {
if earliestBlockSaved > latestBlock {
return InvalidLatestBlockNumValue
}
ignoreRange := fromBlock == spectypes.NOT_APPLICABLE || toBlock == spectypes.NOT_APPLICABLE
ignoreSpecific := specificBlock == spectypes.NOT_APPLICABLE
if ignoreRange && ignoreSpecific {
return InvalidRequestedBlocks
}
// handle spectypes.LATEST_BLOCK - distance requests
if !ignoreRange {
fromBlock = LatestArgToBlockNum(fromBlock, latestBlock)
toBlock = LatestArgToBlockNum(toBlock, latestBlock)
wbd.rangeBlocks, err = NewBlockRange(fromBlock, toBlock, earliestBlockSaved, latestBlock)
if err != nil {
return err
}
} else {
// for clarity
wbd.rangeBlocks = nil
}
if !ignoreSpecific {
fromBlockArg := LatestArgToBlockNum(specificBlock, latestBlock)
if wbd.rangeBlocks.IsWanted(fromBlockArg) {
// this means the specific block is within the range of [from-to) and there is no reason to create specific block range
wbd.specificBlock = nil
} else {
toBlockArg := fromBlockArg + 1
wbd.specificBlock, err = NewBlockRange(fromBlockArg, toBlockArg, earliestBlockSaved, latestBlock)
if err != nil {
return err
}
}
} else {
// for clarity
wbd.specificBlock = nil
}
return nil
}
func (wbd *WantedBlocksData) IterationIndexes() (returnedIdxs []int) {
if wbd.rangeBlocks != nil {
if wbd.specificBlock != nil {
if wbd.rangeBlocks.startIndexFromEarliest < wbd.specificBlock.startIndexFromEarliest {
returnedIdxs = wbd.rangeBlocks.IterationIndexes()
returnedIdxs = append(returnedIdxs, wbd.specificBlock.IterationIndexes()...)
return
}
returnedIdxs = wbd.specificBlock.IterationIndexes()
returnedIdxs = append(returnedIdxs, wbd.rangeBlocks.IterationIndexes()...)
return
}
returnedIdxs = wbd.rangeBlocks.IterationIndexes()
return
}
if wbd.specificBlock != nil {
return wbd.specificBlock.IterationIndexes()
}
// empty iteration indexes list
return
}
func (wbd *WantedBlocksData) IsWanted(blockNum int64) bool {
// expecting only positive blockNums here
if blockNum < 0 {
return false
}
// if is the specific block return true
if wbd.specificBlock.IsWanted(blockNum) {
return true
}
// if is in range [from,to) return true
if wbd.rangeBlocks.IsWanted(blockNum) {
return true
}
return false
}
func (wbd *WantedBlocksData) String() string {
return fmt.Sprintf("range: %+v specific: %+v", wbd.rangeBlocks, wbd.specificBlock)
}
func NewBlockRange(fromBlock int64, toBlock int64, earliestBlockSaved int64, latestBlock int64) (br *BlockRange, err error) {
if fromBlock < 0 || toBlock < 0 || earliestBlockSaved < 0 {
return nil, RequestedBlocksOutOfRange.Wrapf("invalid input block range: from=%d to=%d earliest=%d", fromBlock, toBlock, earliestBlockSaved)
}
if toBlock <= fromBlock { // if we don't have a range, it should be set with NOT_APPLICABLE
return nil, InvalidRequestedBlocks.Wrapf("invalid input block range: from=%d to=%d earliest=%d", fromBlock, toBlock, earliestBlockSaved)
}
if fromBlock < earliestBlockSaved {
return nil, RequestedBlocksOutOfRange.Wrapf("invalid input block fromBlock: from=%d to=%d earliest=%d", fromBlock, toBlock, earliestBlockSaved)
}
if toBlock > latestBlock+1 { // latest+1 to allow a range to include latest block
return nil, RequestedBlocksOutOfRange.Wrapf("invalid input block toBlock: from=%d to=%d latest=%d", fromBlock, toBlock, latestBlock)
}
blockRange := &BlockRange{}
blockRange.fromBlock = fromBlock
blockRange.toBlock = toBlock
blockRange.startIndexFromEarliest = uint64(blockRange.fromBlock - earliestBlockSaved)
blockRange.endIndexFromEarliest = uint64(blockRange.toBlock - earliestBlockSaved)
return blockRange, nil
}
func (br *BlockRange) IterationIndexes() []int {
indexes := make([]int, br.endIndexFromEarliest-br.startIndexFromEarliest)
for i := 0; i < len(indexes); i++ {
indexes[i] = int(br.startIndexFromEarliest) + i
}
return indexes
}
func (br *BlockRange) IsWanted(blockNum int64) bool {
if br == nil {
return false
}
if br.fromBlock > blockNum {
return false
}
if br.toBlock <= blockNum {
return false
}
return true
}
func LatestArgToBlockNum(request int64, latestBlock int64) int64 {
// only modify latest - X requests
if request > spectypes.LATEST_BLOCK {
return request
}
// we have: spectypes.LATEST_BLOCK - X = request, we need: latest - X
// request - spectypes.LATEST_BLOCK + latest = spectypes.LATEST_BLOCK - X - spectypes.LATEST_BLOCK + latest = latest - X
res := request - spectypes.LATEST_BLOCK + latestBlock
if res < 0 {
// edge case where X is bigger than latest
return latestBlock
}
return res
}