13
13
# limitations under the License.
14
14
15
15
from dataclasses import dataclass
16
- from typing import TYPE_CHECKING , Optional , TypeAlias
16
+ from typing import TYPE_CHECKING , TypeAlias
17
17
18
+ from hathor .conf .settings import HathorSettings
18
19
from hathor .feature_activation .feature import Feature
19
- from hathor .feature_activation .model .feature_description import FeatureDescription
20
+ from hathor .feature_activation .model .feature_info import FeatureInfo
20
21
from hathor .feature_activation .model .feature_state import FeatureState
21
- from hathor .feature_activation .settings import Settings as FeatureSettings
22
22
23
23
if TYPE_CHECKING :
24
- from hathor .feature_activation .bit_signaling_service import BitSignalingService
25
24
from hathor .transaction import Block
26
25
from hathor .transaction .storage import TransactionStorage
27
26
@@ -42,12 +41,11 @@ class BlockIsMissingSignal:
42
41
43
42
44
43
class FeatureService :
45
- __slots__ = ('_feature_settings' , '_tx_storage' , 'bit_signaling_service' )
44
+ __slots__ = ('_feature_settings' , '_tx_storage' )
46
45
47
- def __init__ (self , * , feature_settings : FeatureSettings , tx_storage : 'TransactionStorage' ) -> None :
48
- self ._feature_settings = feature_settings
46
+ def __init__ (self , * , settings : HathorSettings , tx_storage : 'TransactionStorage' ) -> None :
47
+ self ._feature_settings = settings . FEATURE_ACTIVATION
49
48
self ._tx_storage = tx_storage
50
- self .bit_signaling_service : Optional ['BitSignalingService' ] = None
51
49
52
50
def is_feature_active (self , * , block : 'Block' , feature : Feature ) -> bool :
53
51
"""Returns whether a Feature is active at a certain block."""
@@ -64,11 +62,11 @@ def is_signaling_mandatory_features(self, block: 'Block') -> BlockSignalingState
64
62
height = block .static_metadata .height
65
63
offset_to_boundary = height % self ._feature_settings .evaluation_interval
66
64
remaining_blocks = self ._feature_settings .evaluation_interval - offset_to_boundary - 1
67
- descriptions = self .get_bits_description (block = block )
65
+ feature_infos = self .get_feature_infos (block = block )
68
66
69
67
must_signal_features = (
70
- feature for feature , description in descriptions .items ()
71
- if description .state is FeatureState .MUST_SIGNAL
68
+ feature for feature , feature_info in feature_infos .items ()
69
+ if feature_info .state is FeatureState .MUST_SIGNAL
72
70
)
73
71
74
72
for feature in must_signal_features :
@@ -115,10 +113,6 @@ def get_state(self, *, block: 'Block', feature: Feature) -> FeatureState:
115
113
previous_state = previous_boundary_state
116
114
)
117
115
118
- if new_state == FeatureState .MUST_SIGNAL :
119
- assert self .bit_signaling_service is not None
120
- self .bit_signaling_service .on_must_signal (feature )
121
-
122
116
# We cache the just calculated state of the current block _without saving it_, as it may still be unverified,
123
117
# so we cannot persist its metadata. That's why we cache and save the previous boundary block above.
124
118
block .set_feature_state (feature = feature , state = new_state )
@@ -192,12 +186,12 @@ def _calculate_new_state(
192
186
if previous_state is FeatureState .FAILED :
193
187
return FeatureState .FAILED
194
188
195
- raise ValueError (f'Unknown previous state: { previous_state } ' )
189
+ raise NotImplementedError (f'Unknown previous state: { previous_state } ' )
196
190
197
- def get_bits_description (self , * , block : 'Block' ) -> dict [Feature , FeatureDescription ]:
191
+ def get_feature_infos (self , * , block : 'Block' ) -> dict [Feature , FeatureInfo ]:
198
192
"""Returns the criteria definition and feature state for all features at a certain block."""
199
193
return {
200
- feature : FeatureDescription (
194
+ feature : FeatureInfo (
201
195
criteria = criteria ,
202
196
state = self .get_state (block = block , feature = feature )
203
197
)
@@ -223,9 +217,11 @@ def _get_ancestor_at_height(self, *, block: 'Block', ancestor_height: int) -> 'B
223
217
if parent_block .static_metadata .height == ancestor_height :
224
218
return parent_block
225
219
226
- if not parent_metadata .voided_by and (ancestor := self ._tx_storage .get_block_by_height (ancestor_height )):
227
- from hathor .transaction import Block
228
- assert isinstance (ancestor , Block )
220
+ if not parent_metadata .voided_by :
221
+ ancestor = self ._tx_storage .get_block_by_height (ancestor_height )
222
+ assert ancestor is not None , (
223
+ 'it is guaranteed that the ancestor of a fully connected and non-voided block is in the height index'
224
+ )
229
225
return ancestor
230
226
231
227
return self ._get_ancestor_iteratively (block = parent_block , ancestor_height = ancestor_height )
0 commit comments