Skip to content

Commit a73d566

Browse files
committed
refactor(verification): move feature activation dependency
1 parent 204fa2c commit a73d566

File tree

11 files changed

+40
-73
lines changed

11 files changed

+40
-73
lines changed

hathor/builder/builder.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ class BuildArtifacts(NamedTuple):
7474

7575

7676
_VertexVerifiersBuilder: TypeAlias = Callable[
77-
[HathorSettingsType, DifficultyAdjustmentAlgorithm, FeatureService],
77+
[HathorSettingsType, DifficultyAdjustmentAlgorithm],
7878
VertexVerifiers
7979
]
8080

@@ -473,24 +473,20 @@ def _get_or_create_bit_signaling_service(self) -> BitSignalingService:
473473
def _get_or_create_verification_service(self) -> VerificationService:
474474
if self._verification_service is None:
475475
verifiers = self._get_or_create_vertex_verifiers()
476-
self._verification_service = VerificationService(verifiers=verifiers)
476+
feature_service = self._get_or_create_feature_service()
477+
self._verification_service = VerificationService(verifiers=verifiers, feature_service=feature_service)
477478

478479
return self._verification_service
479480

480481
def _get_or_create_vertex_verifiers(self) -> VertexVerifiers:
481482
if self._vertex_verifiers is None:
482483
settings = self._get_or_create_settings()
483-
feature_service = self._get_or_create_feature_service()
484484
daa = self._get_or_create_daa()
485485

486486
if self._vertex_verifiers_builder:
487-
self._vertex_verifiers = self._vertex_verifiers_builder(settings, daa, feature_service)
487+
self._vertex_verifiers = self._vertex_verifiers_builder(settings, daa)
488488
else:
489-
self._vertex_verifiers = VertexVerifiers.create_defaults(
490-
settings=settings,
491-
daa=daa,
492-
feature_service=feature_service,
493-
)
489+
self._vertex_verifiers = VertexVerifiers.create_defaults(settings=settings, daa=daa)
494490

495491
return self._vertex_verifiers
496492

hathor/builder/cli_builder.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -222,12 +222,8 @@ def create_manager(self, reactor: Reactor) -> HathorManager:
222222

223223
daa = DifficultyAdjustmentAlgorithm(settings=settings, test_mode=test_mode)
224224

225-
vertex_verifiers = VertexVerifiers.create_defaults(
226-
settings=settings,
227-
daa=daa,
228-
feature_service=self.feature_service
229-
)
230-
verification_service = VerificationService(verifiers=vertex_verifiers)
225+
vertex_verifiers = VertexVerifiers.create_defaults(settings=settings, daa=daa)
226+
verification_service = VerificationService(verifiers=vertex_verifiers, feature_service=self.feature_service)
231227

232228
cpu_mining_service = CpuMiningService()
233229

hathor/cli/mining.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,12 @@ def execute(args: Namespace) -> None:
135135
block.nonce, block.weight))
136136

137137
try:
138-
from unittest.mock import Mock
139-
140138
from hathor.conf.get_settings import get_global_settings
141139
from hathor.daa import DifficultyAdjustmentAlgorithm
142140
from hathor.verification.verification_service import VerificationService, VertexVerifiers
143141
settings = get_global_settings()
144142
daa = DifficultyAdjustmentAlgorithm(settings=settings)
145-
verifiers = VertexVerifiers.create_defaults(settings=settings, daa=daa, feature_service=Mock())
143+
verifiers = VertexVerifiers.create_defaults(settings=settings, daa=daa)
146144
verification_service = VerificationService(verifiers=verifiers)
147145
verification_service.verify_without_storage(block)
148146
except HathorError:

hathor/simulator/simulator.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
from hathor.conf.get_settings import get_global_settings
2525
from hathor.conf.settings import HathorSettings
2626
from hathor.daa import DifficultyAdjustmentAlgorithm
27-
from hathor.feature_activation.feature_service import FeatureService
2827
from hathor.manager import HathorManager
2928
from hathor.p2p.peer_id import PeerId
3029
from hathor.simulator.clock import HeapClock, MemoryReactorHeapClock
@@ -243,17 +242,12 @@ def run(self,
243242
return True
244243

245244

246-
def _build_vertex_verifiers(
247-
settings: HathorSettings,
248-
daa: DifficultyAdjustmentAlgorithm,
249-
feature_service: FeatureService
250-
) -> VertexVerifiers:
245+
def _build_vertex_verifiers(settings: HathorSettings, daa: DifficultyAdjustmentAlgorithm) -> VertexVerifiers:
251246
"""
252247
A custom VertexVerifiers builder to be used by the simulator.
253248
"""
254249
return VertexVerifiers.create(
255250
settings=settings,
256251
vertex_verifier=SimulatorVertexVerifier(settings=settings, daa=daa),
257252
daa=daa,
258-
feature_service=feature_service,
259253
)

hathor/verification/block_verifier.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from typing_extensions import assert_never
16+
1517
from hathor.conf.settings import HathorSettings
1618
from hathor.daa import DifficultyAdjustmentAlgorithm
17-
from hathor.feature_activation.feature_service import BlockIsMissingSignal, BlockIsSignaling, FeatureService
19+
from hathor.feature_activation.feature_service import BlockIsMissingSignal, BlockIsSignaling, BlockSignalingState
1820
from hathor.transaction import Block
1921
from hathor.transaction.exceptions import (
2022
BlockMustSignalError,
@@ -30,18 +32,16 @@
3032

3133

3234
class BlockVerifier:
33-
__slots__ = ('_settings', '_daa', '_feature_service')
35+
__slots__ = ('_settings', '_daa')
3436

3537
def __init__(
3638
self,
3739
*,
3840
settings: HathorSettings,
3941
daa: DifficultyAdjustmentAlgorithm,
40-
feature_service: FeatureService,
4142
) -> None:
4243
self._settings = settings
4344
self._daa = daa
44-
self._feature_service = feature_service
4545

4646
def verify_height(self, block: Block) -> None:
4747
"""Validate that the block height is enough to confirm all transactions being confirmed."""
@@ -86,10 +86,8 @@ def verify_data(self, block: Block) -> None:
8686
if len(block.data) > self._settings.BLOCK_DATA_MAX_SIZE:
8787
raise TransactionDataError('block data has {} bytes'.format(len(block.data)))
8888

89-
def verify_mandatory_signaling(self, block: Block) -> None:
89+
def verify_mandatory_signaling(self, signaling_state: BlockSignalingState) -> None:
9090
"""Verify whether this block is missing mandatory signaling for any feature."""
91-
signaling_state = self._feature_service.is_signaling_mandatory_features(block)
92-
9391
match signaling_state:
9492
case BlockIsSignaling():
9593
return
@@ -98,5 +96,4 @@ def verify_mandatory_signaling(self, block: Block) -> None:
9896
f"Block must signal support for feature '{feature.value}' during MUST_SIGNAL phase."
9997
)
10098
case _:
101-
# TODO: This will be changed to assert_never() so mypy can check it.
102-
raise NotImplementedError
99+
assert_never(signaling_state)

hathor/verification/verification_service.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
from typing_extensions import assert_never
1616

17+
from hathor.feature_activation.feature_service import BlockSignalingState, FeatureService
1718
from hathor.profiler import get_cpu_profiler
1819
from hathor.transaction import BaseTransaction, Block, MergeMinedBlock, Transaction, TxVersion
1920
from hathor.transaction.token_creation_tx import TokenCreationTransaction
@@ -26,10 +27,11 @@
2627

2728

2829
class VerificationService:
29-
__slots__ = ('verifiers', )
30+
__slots__ = ('verifiers', '_feature_service')
3031

31-
def __init__(self, *, verifiers: VertexVerifiers) -> None:
32+
def __init__(self, *, verifiers: VertexVerifiers, feature_service: FeatureService | None = None) -> None:
3233
self.verifiers = verifiers
34+
self._feature_service = feature_service
3335

3436
def validate_basic(self, vertex: BaseTransaction, *, skip_block_weight_verification: bool = False) -> bool:
3537
""" Run basic validations (all that are possible without dependencies) and update the validation state.
@@ -124,14 +126,17 @@ def verify(self, vertex: BaseTransaction, *, reject_locked_reward: bool = True)
124126
"""Run all verifications. Raises on error.
125127
126128
Used by `self.validate_full`. Should not modify the validation state."""
129+
assert self._feature_service is not None
127130
# We assert with type() instead of isinstance() because each subclass has a specific branch.
128131
match vertex.version:
129132
case TxVersion.REGULAR_BLOCK:
130133
assert type(vertex) is Block
131-
self._verify_block(vertex)
134+
signaling_state = self._feature_service.is_signaling_mandatory_features(vertex)
135+
self._verify_block(vertex, signaling_state)
132136
case TxVersion.MERGE_MINED_BLOCK:
133137
assert type(vertex) is MergeMinedBlock
134-
self._verify_merge_mined_block(vertex)
138+
signaling_state = self._feature_service.is_signaling_mandatory_features(vertex)
139+
self._verify_merge_mined_block(vertex, signaling_state)
135140
case TxVersion.REGULAR_TRANSACTION:
136141
assert type(vertex) is Transaction
137142
self._verify_tx(vertex, reject_locked_reward=reject_locked_reward)
@@ -142,7 +147,7 @@ def verify(self, vertex: BaseTransaction, *, reject_locked_reward: bool = True)
142147
assert_never(vertex.version)
143148

144149
@cpu.profiler(key=lambda _, block: 'block-verify!{}'.format(block.hash.hex()))
145-
def _verify_block(self, block: Block) -> None:
150+
def _verify_block(self, block: Block, signaling_state: BlockSignalingState) -> None:
146151
"""
147152
(1) confirms at least two pending transactions and references last block
148153
(2) solves the pow with the correct weight (done in HathorManager)
@@ -163,10 +168,10 @@ def _verify_block(self, block: Block) -> None:
163168

164169
self.verifiers.block.verify_height(block)
165170

166-
self.verifiers.block.verify_mandatory_signaling(block)
171+
self.verifiers.block.verify_mandatory_signaling(signaling_state)
167172

168-
def _verify_merge_mined_block(self, block: MergeMinedBlock) -> None:
169-
self._verify_block(block)
173+
def _verify_merge_mined_block(self, block: MergeMinedBlock, signaling_state: BlockSignalingState) -> None:
174+
self._verify_block(block, signaling_state)
170175

171176
@cpu.profiler(key=lambda _, tx: 'tx-verify!{}'.format(tx.hash.hex()))
172177
def _verify_tx(

hathor/verification/vertex_verifiers.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
from hathor.conf.settings import HathorSettings
1818
from hathor.daa import DifficultyAdjustmentAlgorithm
19-
from hathor.feature_activation.feature_service import FeatureService
2019
from hathor.verification.block_verifier import BlockVerifier
2120
from hathor.verification.merge_mined_block_verifier import MergeMinedBlockVerifier
2221
from hathor.verification.token_creation_transaction_verifier import TokenCreationTransactionVerifier
@@ -33,13 +32,7 @@ class VertexVerifiers(NamedTuple):
3332
token_creation_tx: TokenCreationTransactionVerifier
3433

3534
@classmethod
36-
def create_defaults(
37-
cls,
38-
*,
39-
settings: HathorSettings,
40-
daa: DifficultyAdjustmentAlgorithm,
41-
feature_service: FeatureService,
42-
) -> 'VertexVerifiers':
35+
def create_defaults(cls, *, settings: HathorSettings, daa: DifficultyAdjustmentAlgorithm) -> 'VertexVerifiers':
4336
"""
4437
Create a VertexVerifiers instance using the default verifier for each vertex type,
4538
from all required dependencies.
@@ -50,7 +43,6 @@ def create_defaults(
5043
settings=settings,
5144
vertex_verifier=vertex_verifier,
5245
daa=daa,
53-
feature_service=feature_service
5446
)
5547

5648
@classmethod
@@ -60,12 +52,11 @@ def create(
6052
settings: HathorSettings,
6153
vertex_verifier: VertexVerifier,
6254
daa: DifficultyAdjustmentAlgorithm,
63-
feature_service: FeatureService,
6455
) -> 'VertexVerifiers':
6556
"""
6657
Create a VertexVerifiers instance using a custom vertex_verifier.
6758
"""
68-
block_verifier = BlockVerifier(settings=settings, daa=daa, feature_service=feature_service)
59+
block_verifier = BlockVerifier(settings=settings, daa=daa)
6960
merge_mined_block_verifier = MergeMinedBlockVerifier()
7061
tx_verifier = TransactionVerifier(settings=settings, daa=daa)
7162
token_creation_tx_verifier = TokenCreationTransactionVerifier(settings=settings)

tests/tx/test_block.py

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from hathor.conf.get_settings import get_global_settings
2020
from hathor.conf.settings import HathorSettings
2121
from hathor.feature_activation.feature import Feature
22-
from hathor.feature_activation.feature_service import BlockIsMissingSignal, BlockIsSignaling, FeatureService
22+
from hathor.feature_activation.feature_service import BlockIsMissingSignal, BlockIsSignaling
2323
from hathor.transaction import Block, TransactionMetadata
2424
from hathor.transaction.exceptions import BlockMustSignalError
2525
from hathor.transaction.storage import TransactionMemoryStorage, TransactionStorage
@@ -140,24 +140,16 @@ def test_get_feature_activation_bit_value() -> None:
140140

141141
def test_verify_must_signal() -> None:
142142
settings = Mock(spec_set=HathorSettings)
143-
feature_service = Mock(spec_set=FeatureService)
144-
feature_service.is_signaling_mandatory_features = Mock(
145-
return_value=BlockIsMissingSignal(feature=Feature.NOP_FEATURE_1)
146-
)
147-
verifier = BlockVerifier(settings=settings, feature_service=feature_service, daa=Mock())
148-
block = Block()
143+
verifier = BlockVerifier(settings=settings, daa=Mock())
149144

150145
with pytest.raises(BlockMustSignalError) as e:
151-
verifier.verify_mandatory_signaling(block)
146+
verifier.verify_mandatory_signaling(BlockIsMissingSignal(feature=Feature.NOP_FEATURE_1))
152147

153148
assert str(e.value) == "Block must signal support for feature 'NOP_FEATURE_1' during MUST_SIGNAL phase."
154149

155150

156151
def test_verify_must_not_signal() -> None:
157152
settings = Mock(spec_set=HathorSettings)
158-
feature_service = Mock(spec_set=FeatureService)
159-
feature_service.is_signaling_mandatory_features = Mock(return_value=BlockIsSignaling())
160-
verifier = BlockVerifier(settings=settings, feature_service=feature_service, daa=Mock())
161-
block = Block()
153+
verifier = BlockVerifier(settings=settings, daa=Mock())
162154

163-
verifier.verify_mandatory_signaling(block)
155+
verifier.verify_mandatory_signaling(BlockIsSignaling())

tests/tx/test_genesis.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class GenesisTest(unittest.TestCase):
3232
def setUp(self):
3333
super().setUp()
3434
self._daa = DifficultyAdjustmentAlgorithm(settings=self._settings)
35-
verifiers = VertexVerifiers.create_defaults(settings=self._settings, daa=self._daa, feature_service=Mock())
35+
verifiers = VertexVerifiers.create_defaults(settings=self._settings, daa=self._daa)
3636
self._verification_service = VerificationService(verifiers=verifiers)
3737
self.storage = TransactionMemoryStorage()
3838

tests/tx/test_tx.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ def test_block_inputs(self):
214214
self.manager.cpu_mining_service.resolve(block)
215215

216216
with self.assertRaises(BlockWithInputs):
217-
self.manager.verification_service.verify(block)
217+
self._verifiers.block.verify_no_inputs(block)
218218

219219
def test_merge_mined_no_magic(self):
220220
from hathor.merged_mining import MAGIC_NUMBER
@@ -416,7 +416,7 @@ def test_block_unknown_parent(self):
416416

417417
self.manager.cpu_mining_service.resolve(block)
418418
with self.assertRaises(ParentDoesNotExist):
419-
self.manager.verification_service.verify(block)
419+
self._verifiers.vertex.verify_parents(block)
420420

421421
def test_block_number_parents(self):
422422
address = get_address_from_public_key(self.genesis_public_key)
@@ -434,7 +434,7 @@ def test_block_number_parents(self):
434434

435435
self.manager.cpu_mining_service.resolve(block)
436436
with self.assertRaises(IncorrectParents):
437-
self.manager.verification_service.verify(block)
437+
self._verifiers.vertex.verify_parents(block)
438438

439439
def test_tx_inputs_out_of_range(self):
440440
# we'll try to spend output 3 from genesis transaction, which does not exist

tests/tx/test_tx_deserialization.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from unittest.mock import Mock
2-
31
from hathor.daa import DifficultyAdjustmentAlgorithm
42
from hathor.transaction import Block, MergeMinedBlock, Transaction, TxVersion
53
from hathor.transaction.token_creation_tx import TokenCreationTransaction
@@ -13,7 +11,7 @@ class _DeserializationTest(unittest.TestCase):
1311
def setUp(self) -> None:
1412
super().setUp()
1513
daa = DifficultyAdjustmentAlgorithm(settings=self._settings)
16-
verifiers = VertexVerifiers.create_defaults(settings=self._settings, daa=daa, feature_service=Mock())
14+
verifiers = VertexVerifiers.create_defaults(settings=self._settings, daa=daa)
1715
self._verification_service = VerificationService(verifiers=verifiers)
1816

1917
def test_deserialize(self):

0 commit comments

Comments
 (0)