Skip to content

Commit 56993b9

Browse files
committed
refactor(p2p): implement P2P dependencies
1 parent 3b27e43 commit 56993b9

31 files changed

+426
-276
lines changed

hathor/builder/builder.py

+17-20
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from hathor.indexes import IndexesManager, MemoryIndexesManager, RocksDBIndexesManager
3535
from hathor.manager import HathorManager
3636
from hathor.mining.cpu_mining_service import CpuMiningService
37+
from hathor.p2p import P2PDependencies
3738
from hathor.p2p.manager import ConnectionsManager
3839
from hathor.p2p.peer import PrivatePeer
3940
from hathor.pubsub import PubSubManager
@@ -64,12 +65,10 @@ class SyncSupportLevel(IntEnum):
6465
@classmethod
6566
def add_factories(
6667
cls,
67-
settings: HathorSettingsType,
6868
p2p_manager: ConnectionsManager,
69+
dependencies: P2PDependencies,
6970
sync_v1_support: 'SyncSupportLevel',
7071
sync_v2_support: 'SyncSupportLevel',
71-
vertex_parser: VertexParser,
72-
vertex_handler: VertexHandler,
7372
) -> None:
7473
"""Adds the sync factory to the manager according to the support level."""
7574
from hathor.p2p.sync_v1.factory import SyncV11Factory
@@ -78,18 +77,12 @@ def add_factories(
7877

7978
# sync-v1 support:
8079
if sync_v1_support > cls.UNAVAILABLE:
81-
p2p_manager.add_sync_factory(SyncVersion.V1_1, SyncV11Factory(p2p_manager, vertex_parser=vertex_parser))
80+
p2p_manager.add_sync_factory(SyncVersion.V1_1, SyncV11Factory(dependencies))
8281
if sync_v1_support is cls.ENABLED:
8382
p2p_manager.enable_sync_version(SyncVersion.V1_1)
8483
# sync-v2 support:
8584
if sync_v2_support > cls.UNAVAILABLE:
86-
sync_v2_factory = SyncV2Factory(
87-
settings,
88-
p2p_manager,
89-
vertex_parser=vertex_parser,
90-
vertex_handler=vertex_handler,
91-
)
92-
p2p_manager.add_sync_factory(SyncVersion.V2, sync_v2_factory)
85+
p2p_manager.add_sync_factory(SyncVersion.V2, SyncV2Factory(dependencies))
9386
if sync_v2_support is cls.ENABLED:
9487
p2p_manager.enable_sync_version(SyncVersion.V2)
9588

@@ -232,7 +225,6 @@ def build(self) -> BuildArtifacts:
232225
vertex_handler = self._get_or_create_vertex_handler()
233226
vertex_parser = self._get_or_create_vertex_parser()
234227
poa_block_producer = self._get_or_create_poa_block_producer()
235-
capabilities = self._get_or_create_capabilities()
236228

237229
if self._enable_address_index:
238230
indexes.enable_address_index(pubsub)
@@ -264,7 +256,6 @@ def build(self) -> BuildArtifacts:
264256
wallet=wallet,
265257
rng=self._rng,
266258
checkpoints=self._checkpoints,
267-
capabilities=capabilities,
268259
environment_info=get_environment_info(self._cmdline, str(peer.id)),
269260
bit_signaling_service=bit_signaling_service,
270261
verification_service=verification_service,
@@ -416,25 +407,31 @@ def _get_or_create_p2p_manager(self) -> ConnectionsManager:
416407
return self._p2p_manager
417408

418409
enable_ssl = True
419-
reactor = self._get_reactor()
420410
my_peer = self._get_peer()
421411

422-
self._p2p_manager = ConnectionsManager(
412+
dependencies = P2PDependencies(
413+
reactor=self._get_reactor(),
423414
settings=self._get_or_create_settings(),
424-
reactor=reactor,
415+
vertex_parser=self._get_or_create_vertex_parser(),
416+
tx_storage=self._get_or_create_tx_storage(),
417+
vertex_handler=self._get_or_create_vertex_handler(),
418+
verification_service=self._get_or_create_verification_service(),
419+
capabilities=self._get_or_create_capabilities(),
420+
whitelist_only=False,
421+
)
422+
423+
self._p2p_manager = ConnectionsManager(
424+
dependencies=dependencies,
425425
my_peer=my_peer,
426426
pubsub=self._get_or_create_pubsub(),
427427
ssl=enable_ssl,
428-
whitelist_only=False,
429428
rng=self._rng,
430429
)
431430
SyncSupportLevel.add_factories(
432-
self._get_or_create_settings(),
433431
self._p2p_manager,
432+
dependencies,
434433
self._sync_v1_support,
435434
self._sync_v2_support,
436-
self._get_or_create_vertex_parser(),
437-
self._get_or_create_vertex_handler(),
438435
)
439436
return self._p2p_manager
440437

hathor/builder/cli_builder.py

+21-14
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from hathor.indexes import IndexesManager, MemoryIndexesManager, RocksDBIndexesManager
3535
from hathor.manager import HathorManager
3636
from hathor.mining.cpu_mining_service import CpuMiningService
37+
from hathor.p2p import P2PDependencies
3738
from hathor.p2p.manager import ConnectionsManager
3839
from hathor.p2p.peer import PrivatePeer
3940
from hathor.p2p.peer_endpoint import PeerEndpoint
@@ -319,16 +320,6 @@ def create_manager(self, reactor: Reactor) -> HathorManager:
319320
cpu_mining_service = CpuMiningService()
320321
capabilities = settings.get_default_capabilities()
321322

322-
p2p_manager = ConnectionsManager(
323-
settings=settings,
324-
reactor=reactor,
325-
my_peer=peer,
326-
pubsub=pubsub,
327-
ssl=True,
328-
whitelist_only=False,
329-
rng=Random(),
330-
)
331-
332323
vertex_handler = VertexHandler(
333324
reactor=reactor,
334325
settings=settings,
@@ -341,13 +332,30 @@ def create_manager(self, reactor: Reactor) -> HathorManager:
341332
log_vertex_bytes=self._args.log_vertex_bytes,
342333
)
343334

335+
p2p_dependencies = P2PDependencies(
336+
reactor=reactor,
337+
settings=settings,
338+
vertex_parser=vertex_parser,
339+
tx_storage=tx_storage,
340+
vertex_handler=vertex_handler,
341+
verification_service=verification_service,
342+
whitelist_only=False,
343+
capabilities=capabilities,
344+
)
345+
346+
p2p_manager = ConnectionsManager(
347+
dependencies=p2p_dependencies,
348+
my_peer=peer,
349+
pubsub=pubsub,
350+
ssl=True,
351+
rng=Random(),
352+
)
353+
344354
SyncSupportLevel.add_factories(
345-
settings,
346355
p2p_manager,
356+
p2p_dependencies,
347357
sync_v1_support,
348358
sync_v2_support,
349-
vertex_parser,
350-
vertex_handler,
351359
)
352360

353361
from hathor.consensus.poa import PoaBlockProducer, PoaSignerFile
@@ -385,7 +393,6 @@ def create_manager(self, reactor: Reactor) -> HathorManager:
385393
vertex_handler=vertex_handler,
386394
vertex_parser=vertex_parser,
387395
poa_block_producer=poa_block_producer,
388-
capabilities=capabilities,
389396
)
390397

391398
if self._args.x_ipython_kernel:

hathor/cli/quick_test.py

+9-5
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,19 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from __future__ import annotations
16+
1517
import os
1618
from argparse import ArgumentParser
17-
from typing import Any
19+
from typing import TYPE_CHECKING
1820

1921
from structlog import get_logger
2022

2123
from hathor.cli.run_node import RunNode
2224

25+
if TYPE_CHECKING:
26+
from hathor.transaction import Vertex
27+
2328
logger = get_logger()
2429

2530

@@ -30,18 +35,17 @@ def __init__(self, vertex_handler, manager, n_blocks):
3035
self._manager = manager
3136
self._n_blocks = n_blocks
3237

33-
def on_new_vertex(self, *args: Any, **kwargs: Any) -> bool:
38+
def on_new_vertex(self, vertex: Vertex, *, fails_silently: bool) -> bool:
3439
from hathor.transaction import Block
3540
from hathor.transaction.base_transaction import GenericVertex
3641

3742
msg: str | None = None
38-
res = self._vertex_handler.on_new_vertex(*args, **kwargs)
43+
res = self._vertex_handler.on_new_vertex(vertex=vertex, fails_silently=fails_silently)
3944

4045
if self._n_blocks is None:
4146
should_quit = res
4247
msg = 'added a tx'
4348
else:
44-
vertex = args[0]
4549
should_quit = False
4650
assert isinstance(vertex, GenericVertex)
4751

@@ -77,7 +81,7 @@ def prepare(self, *, register_resources: bool = True) -> None:
7781
self.log.info('patching vertex_handler.on_new_vertex to quit on success')
7882
p2p_factory = self.manager.connections.get_sync_factory(SyncVersion.V2)
7983
assert isinstance(p2p_factory, SyncV2Factory)
80-
p2p_factory.vertex_handler = VertexHandlerWrapper(
84+
p2p_factory.dependencies.vertex_handler = VertexHandlerWrapper(
8185
self.manager.vertex_handler,
8286
self.manager,
8387
self._args.quit_after_n_blocks,

hathor/manager.py

-7
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ def __init__(
109109
execution_manager: ExecutionManager,
110110
vertex_handler: VertexHandler,
111111
vertex_parser: VertexParser,
112-
capabilities: list[str],
113112
hostname: Optional[str] = None,
114113
wallet: Optional[BaseWallet] = None,
115114
checkpoints: Optional[list[Checkpoint]] = None,
@@ -230,9 +229,6 @@ def __init__(
230229
# List of whitelisted peers
231230
self.peers_whitelist: list[PeerId] = []
232231

233-
# List of capabilities of the peer
234-
self.capabilities = capabilities
235-
236232
# This is included in some logs to provide more context
237233
self.environment_info = environment_info
238234

@@ -975,9 +971,6 @@ def on_new_tx(
975971

976972
return success
977973

978-
def has_sync_version_capability(self) -> bool:
979-
return self._settings.CAPABILITY_SYNC_VERSION in self.capabilities
980-
981974
def add_peer_to_whitelist(self, peer_id: PeerId) -> None:
982975
if not self._settings.ENABLE_PEER_WHITELIST:
983976
return

hathor/p2p/__init__.py

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright 2024 Hathor Labs
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from hathor.p2p.dependencies.p2p_dependencies import P2PDependencies
16+
17+
__all__ = [
18+
'P2PDependencies',
19+
]

hathor/p2p/dependencies/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Copyright 2024 Hathor Labs
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from hathor.conf.settings import HathorSettings
16+
from hathor.p2p.dependencies.protocols import (
17+
P2PTransactionStorageProtocol,
18+
P2PVerificationServiceProtocol,
19+
P2PVertexHandlerProtocol,
20+
)
21+
from hathor.reactor import ReactorProtocol
22+
from hathor.transaction.vertex_parser import VertexParser
23+
24+
25+
class P2PDependencies:
26+
"""A simple class to unify all node dependencies that are required by P2P."""
27+
28+
__slots__ = (
29+
'reactor',
30+
'settings',
31+
'vertex_parser',
32+
'vertex_handler',
33+
'verification_service',
34+
'tx_storage',
35+
'capabilities',
36+
'whitelist_only',
37+
'_has_sync_version_capability',
38+
)
39+
40+
def __init__(
41+
self,
42+
*,
43+
reactor: ReactorProtocol,
44+
settings: HathorSettings,
45+
vertex_parser: VertexParser,
46+
vertex_handler: P2PVertexHandlerProtocol,
47+
verification_service: P2PVerificationServiceProtocol,
48+
tx_storage: P2PTransactionStorageProtocol,
49+
capabilities: list[str],
50+
whitelist_only: bool,
51+
) -> None:
52+
self.reactor = reactor
53+
self.settings = settings
54+
self.vertex_parser = vertex_parser
55+
self.vertex_handler = vertex_handler
56+
self.verification_service = verification_service
57+
self.tx_storage = tx_storage
58+
59+
# List of capabilities of the peer
60+
self.capabilities = capabilities
61+
62+
# Parameter to explicitly enable whitelist-only mode, when False it will still check the whitelist for sync-v1
63+
self.whitelist_only = whitelist_only
64+
65+
self._has_sync_version_capability = settings.CAPABILITY_SYNC_VERSION in capabilities
66+
67+
def has_sync_version_capability(self) -> bool:
68+
return self._has_sync_version_capability

hathor/p2p/dependencies/protocols.py

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Copyright 2024 Hathor Labs
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from typing import Protocol
16+
17+
from hathor.indexes.height_index import HeightInfo
18+
from hathor.transaction import Block, Vertex
19+
from hathor.types import VertexId
20+
21+
22+
class P2PVertexHandlerProtocol(Protocol):
23+
"""Abstract the VertexHandler as a Python protocol to be used in P2P classes."""
24+
25+
def on_new_vertex(self, vertex: Vertex, *, fails_silently: bool = True) -> bool: ...
26+
27+
28+
class P2PVerificationServiceProtocol(Protocol):
29+
"""Abstract the VerificationService as a Python protocol to be used in P2P classes."""
30+
31+
def verify_basic(self, vertex: Vertex) -> None: ...
32+
33+
34+
class P2PTransactionStorageProtocol(Protocol):
35+
"""Abstract the TransactionStorage as a Python protocol to be used in P2P classes."""
36+
37+
def get_vertex(self, vertex_id: VertexId) -> Vertex: ...
38+
def get_block(self, block_id: VertexId) -> Block: ...
39+
def transaction_exists(self, vertex_id: VertexId) -> bool: ...
40+
def can_validate_full(self, vertex: Vertex) -> bool: ...
41+
def compare_bytes_with_local_tx(self, vertex: Vertex) -> bool: ...
42+
def get_best_block(self) -> Block: ...
43+
def get_n_height_tips(self, n_blocks: int) -> list[HeightInfo]: ...
44+
def get_mempool_tips(self) -> set[VertexId]: ...
45+
def get_block_id_by_height(self, height: int) -> VertexId | None: ...
46+
def partial_vertex_exists(self, vertex_id: VertexId) -> bool: ...

0 commit comments

Comments
 (0)