Skip to content

Commit

Permalink
refactor(p2p): implement P2PDependencies class
Browse files Browse the repository at this point in the history
  • Loading branch information
glevco committed Oct 15, 2024
1 parent dc2977f commit 3aa3acd
Show file tree
Hide file tree
Showing 29 changed files with 571 additions and 267 deletions.
34 changes: 16 additions & 18 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, SingleProcessP2PDependencies
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 @@ -415,25 +408,30 @@ 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 = SingleProcessP2PDependencies(
reactor=self._get_reactor(),
settings=self._get_or_create_settings(),
reactor=reactor,
my_peer=my_peer,
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(),
pubsub=self._get_or_create_pubsub(),
)

self._p2p_manager = ConnectionsManager(
dependencies=dependencies,
my_peer=my_peer,
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
33 changes: 20 additions & 13 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 SingleProcessP2PDependencies
from hathor.p2p.entrypoint import Entrypoint
from hathor.p2p.manager import ConnectionsManager
from hathor.p2p.peer import PrivatePeer
Expand Down Expand Up @@ -318,16 +319,6 @@ def create_manager(self, reactor: Reactor) -> HathorManager:

cpu_mining_service = CpuMiningService()

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 @@ -340,13 +331,29 @@ def create_manager(self, reactor: Reactor) -> HathorManager:
log_vertex_bytes=self._args.log_vertex_bytes,
)

p2p_dependencies = SingleProcessP2PDependencies(
reactor=reactor,
settings=settings,
vertex_parser=vertex_parser,
tx_storage=tx_storage,
vertex_handler=vertex_handler,
verification_service=verification_service,
pubsub=pubsub,
)

p2p_manager = ConnectionsManager(
dependencies=p2p_dependencies,
my_peer=peer,
ssl=True,
whitelist_only=False,
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
16 changes: 11 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 All @@ -68,6 +72,7 @@ def create_parser(cls) -> ArgumentParser:
return parser

def prepare(self, *, register_resources: bool = True) -> None:
from hathor.p2p import SingleProcessP2PDependencies
from hathor.p2p.sync_v2.factory import SyncV2Factory
from hathor.p2p.sync_version import SyncVersion

Expand All @@ -77,7 +82,8 @@ 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(
assert isinstance(p2p_factory.dependencies, SingleProcessP2PDependencies)
p2p_factory.dependencies._vertex_handler = VertexHandlerWrapper(
self.manager.vertex_handler,
self.manager,
self._args.quit_after_n_blocks,
Expand Down
21 changes: 21 additions & 0 deletions hathor/p2p/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# 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
from hathor.p2p.dependencies.single_process_p2p_dependencies import SingleProcessP2PDependencies

__all__ = [
'P2PDependencies',
'SingleProcessP2PDependencies'
]
Empty file.
131 changes: 131 additions & 0 deletions hathor/p2p/dependencies/p2p_dependencies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# 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 abc import ABC, abstractmethod
from typing import Any

from intervaltree import Interval

from hathor.conf.settings import HathorSettings
from hathor.indexes.height_index import HeightInfo
from hathor.indexes.timestamp_index import RangeIdx
from hathor.pubsub import HathorEvents
from hathor.reactor import ReactorProtocol
from hathor.transaction import Block, Vertex
from hathor.transaction.vertex_parser import VertexParser
from hathor.types import VertexId


class P2PDependencies(ABC):
"""
This abstract class serves as an interface for all communications between P2P-related classes
and the rest of the full node.
"""

__slots__ = ('reactor', 'settings', 'vertex_parser')

def __init__(
self,
*,
reactor: ReactorProtocol,
settings: HathorSettings,
vertex_parser: VertexParser,
) -> None:
self.reactor = reactor
self.settings = settings
self.vertex_parser = vertex_parser

@abstractmethod
def on_new_vertex(self, vertex: Vertex, *, fails_silently: bool = True) -> bool:
raise NotImplementedError

@abstractmethod
def verify_basic(self, vertex: Vertex) -> None:
raise NotImplementedError

@abstractmethod
def publish(self, key: HathorEvents, **kwargs: Any) -> None:
raise NotImplementedError

@abstractmethod
def get_genesis(self, vertex_id: VertexId) -> Vertex | None:
raise NotImplementedError

@abstractmethod
def get_vertex(self, vertex_id: VertexId) -> Vertex:
raise NotImplementedError

@abstractmethod
def get_block(self, block_id: VertexId) -> Block:
raise NotImplementedError

@abstractmethod
def get_latest_timestamp(self) -> int:
raise NotImplementedError

@abstractmethod
def get_first_timestamp(self) -> int:
raise NotImplementedError

@abstractmethod
def vertex_exists(self, vertex_id: VertexId) -> bool:
raise NotImplementedError

@abstractmethod
def can_validate_full(self, vertex: Vertex) -> bool:
raise NotImplementedError

@abstractmethod
def get_merkle_tree(self, timestamp: int) -> tuple[bytes, list[bytes]]:
raise NotImplementedError

@abstractmethod
def get_hashes_and_next_idx(self, from_idx: RangeIdx, count: int) -> tuple[list[bytes], RangeIdx | None]:
raise NotImplementedError

@abstractmethod
def compare_bytes_with_local_vertex(self, vertex: Vertex) -> bool:
raise NotImplementedError

@abstractmethod
def get_best_block(self) -> Block:
raise NotImplementedError

@abstractmethod
def get_n_height_tips(self, n_blocks: int) -> list[HeightInfo]:
raise NotImplementedError

@abstractmethod
def get_tx_tips(self, timestamp: float | None = None) -> set[Interval]:
raise NotImplementedError

@abstractmethod
def get_mempool_tips(self) -> set[VertexId]:
raise NotImplementedError

@abstractmethod
def height_index_get(self, height: int) -> VertexId | None:
raise NotImplementedError

@abstractmethod
def get_parent_block(self, block: Block) -> Block:
raise NotImplementedError

@abstractmethod
def get_best_block_tips(self) -> list[VertexId]:
raise NotImplementedError

@abstractmethod
def partial_vertex_exists(self, vertex_id: VertexId) -> bool:
raise NotImplementedError
Loading

0 comments on commit 3aa3acd

Please sign in to comment.