4
4
from eth_typing import BlockNumber
5
5
6
6
from eth .exceptions import GapTrackingCorrupted
7
- from eth .typing import BlockRange
7
+ from eth .typing import BlockRange , ChainGaps
8
8
9
9
10
10
class GapChange (enum .Enum ):
11
-
12
11
NoChange = enum .auto ()
13
12
NewGap = enum .auto ()
13
+ GapFill = enum .auto ()
14
14
GapSplit = enum .auto ()
15
15
GapShrink = enum .auto ()
16
16
TailWrite = enum .auto ()
17
17
18
18
19
- GapInfo = Tuple [GapChange , Tuple [BlockRange , ...]]
19
+ GAP_WRITES = (GapChange .GapFill , GapChange .GapSplit , GapChange .GapShrink )
20
+ GENESIS_CHAIN_GAPS = ((), BlockNumber (1 ))
21
+
22
+ GapInfo = Tuple [GapChange , ChainGaps ]
20
23
21
24
22
- def calculate_gaps (newly_persisted : BlockNumber , base_gaps : Tuple [ BlockRange , ...] ) -> GapInfo :
25
+ def calculate_gaps (newly_persisted : BlockNumber , base_gaps : ChainGaps ) -> GapInfo :
23
26
24
- # If we have a fresh chain, our highest missing number can only be 1
25
- highest_missing_number = 1 if base_gaps == () else base_gaps [- 1 ][0 ]
27
+ current_gaps , known_missing_tip = base_gaps
26
28
27
- if newly_persisted == highest_missing_number :
29
+ if newly_persisted == known_missing_tip :
28
30
# This is adding a consecutive header at the very tail
29
- new_last_marker = (newly_persisted + 1 , - 1 )
30
- new_gaps = base_gaps [:- 1 ] + (new_last_marker ,)
31
+ new_gaps = (current_gaps , BlockNumber (newly_persisted + 1 ))
31
32
gap_change = GapChange .TailWrite
32
- elif newly_persisted > highest_missing_number :
33
+ elif newly_persisted > known_missing_tip :
33
34
# We are creating a gap in the chain
34
- gap_end = newly_persisted - 1
35
- new_tail = ((highest_missing_number , gap_end ), (newly_persisted + 1 , - 1 ),)
36
- new_gaps = base_gaps [:- 1 ] + new_tail
35
+ gap_end = BlockNumber (newly_persisted - 1 )
36
+ new_gaps = (
37
+ current_gaps + ((known_missing_tip , gap_end ),), BlockNumber (newly_persisted + 1 )
38
+ )
37
39
gap_change = GapChange .NewGap
38
- elif newly_persisted < highest_missing_number :
40
+ elif newly_persisted < known_missing_tip :
39
41
# We are patching a gap which may either shrink an existing gap or divide it
40
42
matching_gaps = [
41
- (index , pair ) for index , pair in enumerate (base_gaps )
43
+ (index , pair ) for index , pair in enumerate (current_gaps )
42
44
if newly_persisted >= pair [0 ] and newly_persisted <= pair [1 ]
43
45
]
44
46
45
47
if len (matching_gaps ) > 1 :
46
48
raise GapTrackingCorrupted (
47
49
"Corrupted chain gap tracking" ,
48
- f"No { newly_persisted } appears to be missing in multiple gaps" ,
50
+ f"No. { newly_persisted } appears to be missing in multiple gaps" ,
49
51
f"1st gap goes from { matching_gaps [0 ][1 ][0 ]} to { matching_gaps [0 ][1 ][1 ]} "
50
52
f"2nd gap goes from { matching_gaps [1 ][1 ][0 ]} to { matching_gaps [1 ][1 ][1 ]} "
51
53
)
@@ -55,26 +57,28 @@ def calculate_gaps(newly_persisted: BlockNumber, base_gaps: Tuple[BlockRange, ..
55
57
elif len (matching_gaps ) == 1 :
56
58
gap_index , gap = matching_gaps [0 ]
57
59
if newly_persisted == gap [0 ] and newly_persisted == gap [1 ]:
58
- updated_center : Tuple [Tuple [ int , int ] , ...] = ()
59
- gap_change = GapChange .GapShrink
60
+ updated_center : Tuple [BlockRange , ...] = ()
61
+ gap_change = GapChange .GapFill
60
62
elif newly_persisted == gap [0 ]:
61
63
# we are shrinking the gap at the start
62
- updated_center = ((gap [0 ] + 1 , gap [1 ],),)
64
+ updated_center = ((BlockNumber ( gap [0 ] + 1 ) , gap [1 ],),)
63
65
gap_change = GapChange .GapShrink
64
66
elif newly_persisted == gap [1 ]:
65
67
# we are shrinking the gap at the tail
66
- updated_center = ((gap [0 ], gap [1 ] - 1 ,),)
68
+ updated_center = ((gap [0 ], BlockNumber ( gap [1 ] - 1 ) ,),)
67
69
gap_change = GapChange .GapShrink
68
- else :
70
+ elif gap [ 0 ] < newly_persisted < gap [ 1 ] :
69
71
# we are dividing the gap
70
- first_new_gap = (gap [0 ], newly_persisted - 1 )
71
- second_new_gap = (newly_persisted + 1 , gap [1 ])
72
+ first_new_gap = (gap [0 ], BlockNumber ( newly_persisted - 1 ) )
73
+ second_new_gap = (BlockNumber ( newly_persisted + 1 ) , gap [1 ])
72
74
updated_center = (first_new_gap , second_new_gap ,)
73
75
gap_change = GapChange .GapSplit
76
+ else :
77
+ raise Exception ("Invariant" )
74
78
75
- before_gap = base_gaps [:gap_index ]
76
- after_gap = base_gaps [gap_index + 1 :]
77
- new_gaps = before_gap + updated_center + after_gap
79
+ before_gap = current_gaps [:gap_index ]
80
+ after_gap = current_gaps [gap_index + 1 :]
81
+ new_gaps = ( before_gap + updated_center + after_gap , known_missing_tip )
78
82
79
83
else :
80
84
raise Exception ("Invariant" )
0 commit comments