Skip to content

Commit

Permalink
refactor(p2p): implement P2P dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
glevco committed Nov 7, 2024
1 parent 3b27e43 commit 56993b9
Show file tree
Hide file tree
Showing 31 changed files with 426 additions and 276 deletions.
37 changes: 17 additions & 20 deletions hathor/builder/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from hathor.indexes import IndexesManager, MemoryIndexesManager, RocksDBIndexesManager
from hathor.manager import HathorManager
from hathor.mining.cpu_mining_service import CpuMiningService
from hathor.p2p import P2PDependencies
from hathor.p2p.manager import ConnectionsManager
from hathor.p2p.peer import PrivatePeer
from hathor.pubsub import PubSubManager
Expand Down Expand Up @@ -64,12 +65,10 @@ class SyncSupportLevel(IntEnum):
@classmethod
def add_factories(
cls,
settings: HathorSettingsType,
p2p_manager: ConnectionsManager,
dependencies: P2PDependencies,
sync_v1_support: 'SyncSupportLevel',
sync_v2_support: 'SyncSupportLevel',
vertex_parser: VertexParser,
vertex_handler: VertexHandler,
) -> None:
"""Adds the sync factory to the manager according to the support level."""
from hathor.p2p.sync_v1.factory import SyncV11Factory
Expand All @@ -78,18 +77,12 @@ def add_factories(

# sync-v1 support:
if sync_v1_support > cls.UNAVAILABLE:
p2p_manager.add_sync_factory(SyncVersion.V1_1, SyncV11Factory(p2p_manager, vertex_parser=vertex_parser))
p2p_manager.add_sync_factory(SyncVersion.V1_1, SyncV11Factory(dependencies))
if sync_v1_support is cls.ENABLED:
p2p_manager.enable_sync_version(SyncVersion.V1_1)
# sync-v2 support:
if sync_v2_support > cls.UNAVAILABLE:
sync_v2_factory = SyncV2Factory(
settings,
p2p_manager,
vertex_parser=vertex_parser,
vertex_handler=vertex_handler,
)
p2p_manager.add_sync_factory(SyncVersion.V2, sync_v2_factory)
p2p_manager.add_sync_factory(SyncVersion.V2, SyncV2Factory(dependencies))
if sync_v2_support is cls.ENABLED:
p2p_manager.enable_sync_version(SyncVersion.V2)

Expand Down Expand Up @@ -232,7 +225,6 @@ def build(self) -> BuildArtifacts:
vertex_handler = self._get_or_create_vertex_handler()
vertex_parser = self._get_or_create_vertex_parser()
poa_block_producer = self._get_or_create_poa_block_producer()
capabilities = self._get_or_create_capabilities()

if self._enable_address_index:
indexes.enable_address_index(pubsub)
Expand Down Expand Up @@ -264,7 +256,6 @@ def build(self) -> BuildArtifacts:
wallet=wallet,
rng=self._rng,
checkpoints=self._checkpoints,
capabilities=capabilities,
environment_info=get_environment_info(self._cmdline, str(peer.id)),
bit_signaling_service=bit_signaling_service,
verification_service=verification_service,
Expand Down Expand Up @@ -416,25 +407,31 @@ def _get_or_create_p2p_manager(self) -> ConnectionsManager:
return self._p2p_manager

enable_ssl = True
reactor = self._get_reactor()
my_peer = self._get_peer()

self._p2p_manager = ConnectionsManager(
dependencies = P2PDependencies(
reactor=self._get_reactor(),
settings=self._get_or_create_settings(),
reactor=reactor,
vertex_parser=self._get_or_create_vertex_parser(),
tx_storage=self._get_or_create_tx_storage(),
vertex_handler=self._get_or_create_vertex_handler(),
verification_service=self._get_or_create_verification_service(),
capabilities=self._get_or_create_capabilities(),
whitelist_only=False,
)

self._p2p_manager = ConnectionsManager(
dependencies=dependencies,
my_peer=my_peer,
pubsub=self._get_or_create_pubsub(),
ssl=enable_ssl,
whitelist_only=False,
rng=self._rng,
)
SyncSupportLevel.add_factories(
self._get_or_create_settings(),
self._p2p_manager,
dependencies,
self._sync_v1_support,
self._sync_v2_support,
self._get_or_create_vertex_parser(),
self._get_or_create_vertex_handler(),
)
return self._p2p_manager

Expand Down
35 changes: 21 additions & 14 deletions hathor/builder/cli_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from hathor.indexes import IndexesManager, MemoryIndexesManager, RocksDBIndexesManager
from hathor.manager import HathorManager
from hathor.mining.cpu_mining_service import CpuMiningService
from hathor.p2p import P2PDependencies
from hathor.p2p.manager import ConnectionsManager
from hathor.p2p.peer import PrivatePeer
from hathor.p2p.peer_endpoint import PeerEndpoint
Expand Down Expand Up @@ -319,16 +320,6 @@ def create_manager(self, reactor: Reactor) -> HathorManager:
cpu_mining_service = CpuMiningService()
capabilities = settings.get_default_capabilities()

p2p_manager = ConnectionsManager(
settings=settings,
reactor=reactor,
my_peer=peer,
pubsub=pubsub,
ssl=True,
whitelist_only=False,
rng=Random(),
)

vertex_handler = VertexHandler(
reactor=reactor,
settings=settings,
Expand All @@ -341,13 +332,30 @@ def create_manager(self, reactor: Reactor) -> HathorManager:
log_vertex_bytes=self._args.log_vertex_bytes,
)

p2p_dependencies = P2PDependencies(
reactor=reactor,
settings=settings,
vertex_parser=vertex_parser,
tx_storage=tx_storage,
vertex_handler=vertex_handler,
verification_service=verification_service,
whitelist_only=False,
capabilities=capabilities,
)

p2p_manager = ConnectionsManager(
dependencies=p2p_dependencies,
my_peer=peer,
pubsub=pubsub,
ssl=True,
rng=Random(),
)

SyncSupportLevel.add_factories(
settings,
p2p_manager,
p2p_dependencies,
sync_v1_support,
sync_v2_support,
vertex_parser,
vertex_handler,
)

from hathor.consensus.poa import PoaBlockProducer, PoaSignerFile
Expand Down Expand Up @@ -385,7 +393,6 @@ def create_manager(self, reactor: Reactor) -> HathorManager:
vertex_handler=vertex_handler,
vertex_parser=vertex_parser,
poa_block_producer=poa_block_producer,
capabilities=capabilities,
)

if self._args.x_ipython_kernel:
Expand Down
14 changes: 9 additions & 5 deletions hathor/cli/quick_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import annotations

import os
from argparse import ArgumentParser
from typing import Any
from typing import TYPE_CHECKING

from structlog import get_logger

from hathor.cli.run_node import RunNode

if TYPE_CHECKING:
from hathor.transaction import Vertex

logger = get_logger()


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

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

msg: str | None = None
res = self._vertex_handler.on_new_vertex(*args, **kwargs)
res = self._vertex_handler.on_new_vertex(vertex=vertex, fails_silently=fails_silently)

if self._n_blocks is None:
should_quit = res
msg = 'added a tx'
else:
vertex = args[0]
should_quit = False
assert isinstance(vertex, GenericVertex)

Expand Down Expand Up @@ -77,7 +81,7 @@ def prepare(self, *, register_resources: bool = True) -> None:
self.log.info('patching vertex_handler.on_new_vertex to quit on success')
p2p_factory = self.manager.connections.get_sync_factory(SyncVersion.V2)
assert isinstance(p2p_factory, SyncV2Factory)
p2p_factory.vertex_handler = VertexHandlerWrapper(
p2p_factory.dependencies.vertex_handler = VertexHandlerWrapper(
self.manager.vertex_handler,
self.manager,
self._args.quit_after_n_blocks,
Expand Down
7 changes: 0 additions & 7 deletions hathor/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ def __init__(
execution_manager: ExecutionManager,
vertex_handler: VertexHandler,
vertex_parser: VertexParser,
capabilities: list[str],
hostname: Optional[str] = None,
wallet: Optional[BaseWallet] = None,
checkpoints: Optional[list[Checkpoint]] = None,
Expand Down Expand Up @@ -230,9 +229,6 @@ def __init__(
# List of whitelisted peers
self.peers_whitelist: list[PeerId] = []

# List of capabilities of the peer
self.capabilities = capabilities

# This is included in some logs to provide more context
self.environment_info = environment_info

Expand Down Expand Up @@ -975,9 +971,6 @@ def on_new_tx(

return success

def has_sync_version_capability(self) -> bool:
return self._settings.CAPABILITY_SYNC_VERSION in self.capabilities

def add_peer_to_whitelist(self, peer_id: PeerId) -> None:
if not self._settings.ENABLE_PEER_WHITELIST:
return
Expand Down
19 changes: 19 additions & 0 deletions hathor/p2p/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2024 Hathor Labs
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from hathor.p2p.dependencies.p2p_dependencies import P2PDependencies

__all__ = [
'P2PDependencies',
]
Empty file.
68 changes: 68 additions & 0 deletions hathor/p2p/dependencies/p2p_dependencies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Copyright 2024 Hathor Labs
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from hathor.conf.settings import HathorSettings
from hathor.p2p.dependencies.protocols import (
P2PTransactionStorageProtocol,
P2PVerificationServiceProtocol,
P2PVertexHandlerProtocol,
)
from hathor.reactor import ReactorProtocol
from hathor.transaction.vertex_parser import VertexParser


class P2PDependencies:
"""A simple class to unify all node dependencies that are required by P2P."""

__slots__ = (
'reactor',
'settings',
'vertex_parser',
'vertex_handler',
'verification_service',
'tx_storage',
'capabilities',
'whitelist_only',
'_has_sync_version_capability',
)

def __init__(
self,
*,
reactor: ReactorProtocol,
settings: HathorSettings,
vertex_parser: VertexParser,
vertex_handler: P2PVertexHandlerProtocol,
verification_service: P2PVerificationServiceProtocol,
tx_storage: P2PTransactionStorageProtocol,
capabilities: list[str],
whitelist_only: bool,
) -> None:
self.reactor = reactor
self.settings = settings
self.vertex_parser = vertex_parser
self.vertex_handler = vertex_handler
self.verification_service = verification_service
self.tx_storage = tx_storage

# List of capabilities of the peer
self.capabilities = capabilities

# Parameter to explicitly enable whitelist-only mode, when False it will still check the whitelist for sync-v1
self.whitelist_only = whitelist_only

self._has_sync_version_capability = settings.CAPABILITY_SYNC_VERSION in capabilities

def has_sync_version_capability(self) -> bool:
return self._has_sync_version_capability
46 changes: 46 additions & 0 deletions hathor/p2p/dependencies/protocols.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Copyright 2024 Hathor Labs
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Protocol

from hathor.indexes.height_index import HeightInfo
from hathor.transaction import Block, Vertex
from hathor.types import VertexId


class P2PVertexHandlerProtocol(Protocol):
"""Abstract the VertexHandler as a Python protocol to be used in P2P classes."""

def on_new_vertex(self, vertex: Vertex, *, fails_silently: bool = True) -> bool: ...


class P2PVerificationServiceProtocol(Protocol):
"""Abstract the VerificationService as a Python protocol to be used in P2P classes."""

def verify_basic(self, vertex: Vertex) -> None: ...


class P2PTransactionStorageProtocol(Protocol):
"""Abstract the TransactionStorage as a Python protocol to be used in P2P classes."""

def get_vertex(self, vertex_id: VertexId) -> Vertex: ...
def get_block(self, block_id: VertexId) -> Block: ...
def transaction_exists(self, vertex_id: VertexId) -> bool: ...
def can_validate_full(self, vertex: Vertex) -> bool: ...
def compare_bytes_with_local_tx(self, vertex: Vertex) -> bool: ...
def get_best_block(self) -> Block: ...
def get_n_height_tips(self, n_blocks: int) -> list[HeightInfo]: ...
def get_mempool_tips(self) -> set[VertexId]: ...
def get_block_id_by_height(self, height: int) -> VertexId | None: ...
def partial_vertex_exists(self, vertex_id: VertexId) -> bool: ...
Loading

0 comments on commit 56993b9

Please sign in to comment.