44from eth_typing import BlockNumber
55
66from eth .exceptions import GapTrackingCorrupted
7- from eth .typing import BlockRange
7+ from eth .typing import BlockRange , ChainGaps
88
99
1010class GapChange (enum .Enum ):
11-
1211 NoChange = enum .auto ()
1312 NewGap = enum .auto ()
13+ GapFill = enum .auto ()
1414 GapSplit = enum .auto ()
1515 GapShrink = enum .auto ()
1616 TailWrite = enum .auto ()
1717
1818
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 ]
2023
2124
22- def calculate_gaps (newly_persisted : BlockNumber , base_gaps : Tuple [ BlockRange , ...] ) -> GapInfo :
25+ def calculate_gaps (newly_persisted : BlockNumber , base_gaps : ChainGaps ) -> GapInfo :
2326
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
2628
27- if newly_persisted == highest_missing_number :
29+ if newly_persisted == known_missing_tip :
2830 # 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 ))
3132 gap_change = GapChange .TailWrite
32- elif newly_persisted > highest_missing_number :
33+ elif newly_persisted > known_missing_tip :
3334 # 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+ )
3739 gap_change = GapChange .NewGap
38- elif newly_persisted < highest_missing_number :
40+ elif newly_persisted < known_missing_tip :
3941 # We are patching a gap which may either shrink an existing gap or divide it
4042 matching_gaps = [
41- (index , pair ) for index , pair in enumerate (base_gaps )
43+ (index , pair ) for index , pair in enumerate (current_gaps )
4244 if newly_persisted >= pair [0 ] and newly_persisted <= pair [1 ]
4345 ]
4446
4547 if len (matching_gaps ) > 1 :
4648 raise GapTrackingCorrupted (
4749 "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" ,
4951 f"1st gap goes from { matching_gaps [0 ][1 ][0 ]} to { matching_gaps [0 ][1 ][1 ]} "
5052 f"2nd gap goes from { matching_gaps [1 ][1 ][0 ]} to { matching_gaps [1 ][1 ][1 ]} "
5153 )
@@ -55,26 +57,28 @@ def calculate_gaps(newly_persisted: BlockNumber, base_gaps: Tuple[BlockRange, ..
5557 elif len (matching_gaps ) == 1 :
5658 gap_index , gap = matching_gaps [0 ]
5759 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
6062 elif newly_persisted == gap [0 ]:
6163 # 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 ],),)
6365 gap_change = GapChange .GapShrink
6466 elif newly_persisted == gap [1 ]:
6567 # 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 ) ,),)
6769 gap_change = GapChange .GapShrink
68- else :
70+ elif gap [ 0 ] < newly_persisted < gap [ 1 ] :
6971 # 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 ])
7274 updated_center = (first_new_gap , second_new_gap ,)
7375 gap_change = GapChange .GapSplit
76+ else :
77+ raise Exception ("Invariant" )
7478
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 )
7882
7983 else :
8084 raise Exception ("Invariant" )
0 commit comments