Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion hathor/builder/cli_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
from hathor.pubsub import PubSubManager
from hathor.stratum import StratumFactory
from hathor.util import Random, Reactor, not_none
from hathor.verification.verification_service import VerificationService, VertexVerifiers
from hathor.verification.verification_service import VerificationService
from hathor.verification.vertex_verifiers import VertexVerifiers
from hathor.wallet import BaseWallet, HDWallet, Wallet

logger = get_logger()
Expand Down
7 changes: 4 additions & 3 deletions hathor/cli/mining.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,12 @@ def execute(args: Namespace) -> None:

try:
from hathor.daa import DifficultyAdjustmentAlgorithm
from hathor.verification.block_verifier import BlockVerifier
from hathor.verification.verification_service import VerificationService, VertexVerifiers
settings = get_settings()
daa = DifficultyAdjustmentAlgorithm(settings=settings)
verifier = BlockVerifier(settings=settings, daa=daa)
verifier.verify_without_storage(block)
verifiers = VertexVerifiers.create_defaults(settings=settings, daa=daa)
verification_service = VerificationService(verifiers=verifiers)
verification_service.verify_without_storage(block)
except HathorError:
print('[{}] ERROR: Block has not been pushed because it is not valid.'.format(datetime.datetime.now()))
else:
Expand Down
1 change: 1 addition & 0 deletions hathor/cli/openapi_files/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def get_registered_resources() -> list[type[Resource]]:
"""
import hathor.event.resources.event # noqa: 401
import hathor.feature_activation.resources.feature # noqa: 401
import hathor.healthcheck.resources.healthcheck # noqa: 401
import hathor.p2p.resources # noqa: 401
import hathor.profiler.resources # noqa: 401
import hathor.stratum.resources # noqa: 401
Expand Down
116 changes: 0 additions & 116 deletions hathor/healthcheck/models.py

This file was deleted.

32 changes: 15 additions & 17 deletions hathor/healthcheck/resources/healthcheck.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import hathor
import asyncio

from healthcheck import Healthcheck, HealthcheckCallbackResponse, HealthcheckInternalComponent, HealthcheckStatus

from hathor.api_util import Resource, get_arg_default, get_args
from hathor.cli.openapi_files.register import register_resource
from hathor.healthcheck.models import ComponentHealthCheck, ComponentType, HealthCheckStatus, ServiceHealthCheck
from hathor.manager import HathorManager
from hathor.util import json_dumpb


def build_sync_health_status(manager: HathorManager) -> ComponentHealthCheck:
"""Builds the sync health status object."""
async def sync_healthcheck(manager: HathorManager) -> HealthcheckCallbackResponse:
healthy, reason = manager.is_sync_healthy()

return ComponentHealthCheck(
component_name='sync',
component_type=ComponentType.INTERNAL,
status=HealthCheckStatus.PASS if healthy else HealthCheckStatus.FAIL,
return HealthcheckCallbackResponse(
status=HealthcheckStatus.PASS if healthy else HealthcheckStatus.FAIL,
output=reason or 'Healthy',
)

Expand All @@ -38,22 +37,21 @@ def render_GET(self, request):
raw_args = get_args(request)
strict_status_code = get_arg_default(raw_args, 'strict_status_code', '0') == '1'

components_health_checks = [
build_sync_health_status(self.manager)
]

health_check = ServiceHealthCheck(
description=f'Hathor-core {hathor.__version__}',
checks={c.component_name: [c] for c in components_health_checks},
sync_component = HealthcheckInternalComponent(
name='sync',
)
sync_component.add_healthcheck(lambda: sync_healthcheck(self.manager))

healthcheck = Healthcheck(name='hathor-core', components=[sync_component])
status = asyncio.get_event_loop().run_until_complete(healthcheck.run())

if strict_status_code:
request.setResponseCode(200)
else:
status_code = health_check.get_http_status_code()
status_code = status.get_http_status_code()
request.setResponseCode(status_code)

return json_dumpb(health_check.to_json())
return json_dumpb(status.to_json())


HealthcheckResource.openapi = {
Expand Down
3 changes: 2 additions & 1 deletion hathor/p2p/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,8 @@ def do_discovery(self) -> None:
Do a discovery and connect on all discovery strategies.
"""
for peer_discovery in self.peer_discoveries:
peer_discovery.discover_and_connect(self.connect_to)
coro = peer_discovery.discover_and_connect(self.connect_to)
Deferred.fromCoroutine(coro)

def disable_rate_limiter(self) -> None:
"""Disable global rate limiter."""
Expand Down
20 changes: 10 additions & 10 deletions hathor/p2p/peer_discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@

import socket
from abc import ABC, abstractmethod
from typing import Any, Callable, Generator
from typing import Callable

from structlog import get_logger
from twisted.internet import defer
from twisted.internet.defer import inlineCallbacks
from twisted.names.client import lookupAddress, lookupText
from twisted.names.dns import Record_A, Record_TXT, RRHeader
from typing_extensions import override

logger = get_logger()

Expand All @@ -30,7 +30,7 @@ class PeerDiscovery(ABC):
"""

@abstractmethod
def discover_and_connect(self, connect_to: Callable[[str], None]) -> Any:
async def discover_and_connect(self, connect_to: Callable[[str], None]) -> None:
""" This method must discover the peers and call `connect_to` for each of them.

:param connect_to: Function which will be called for each discovered peer.
Expand All @@ -51,7 +51,8 @@ def __init__(self, descriptions: list[str]):
self.log = logger.new()
self.descriptions = descriptions

def discover_and_connect(self, connect_to: Callable[[str], None]) -> Any:
@override
async def discover_and_connect(self, connect_to: Callable[[str], None]) -> None:
for description in self.descriptions:
connect_to(description)

Expand All @@ -70,18 +71,17 @@ def __init__(self, hosts: list[str], default_port: int = 40403, test_mode: int =
self.default_port = default_port
self.test_mode = test_mode

@inlineCallbacks
def discover_and_connect(self, connect_to: Callable[[str], None]) -> Generator[Any, Any, None]:
@override
async def discover_and_connect(self, connect_to: Callable[[str], None]) -> None:
""" Run DNS lookup for host and connect to it
This is executed when starting the DNS Peer Discovery and first connecting to the network
"""
for host in self.hosts:
url_list = yield self.dns_seed_lookup(host)
url_list = await self.dns_seed_lookup(host)
for url in url_list:
connect_to(url)

@inlineCallbacks
def dns_seed_lookup(self, host: str) -> Generator[Any, Any, list[str]]:
async def dns_seed_lookup(self, host: str) -> list[str]:
""" Run a DNS lookup for TXT, A, and AAAA records and return a list of connection strings.
"""
if self.test_mode:
Expand All @@ -97,7 +97,7 @@ def dns_seed_lookup(self, host: str) -> Generator[Any, Any, list[str]]:
d2.addErrback(self.errback),

d = defer.gatherResults([d1, d2])
results = yield d
results = await d
unique_urls: set[str] = set()
for urls in results:
unique_urls.update(urls)
Expand Down
10 changes: 4 additions & 6 deletions hathor/p2p/peer_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@
import hashlib
from enum import Enum
from math import inf
from typing import TYPE_CHECKING, Any, Generator, Optional, cast
from typing import TYPE_CHECKING, Any, Optional, cast

from cryptography import x509
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding, rsa
from OpenSSL.crypto import X509, PKey
from twisted.internet.defer import inlineCallbacks
from twisted.internet.interfaces import ISSLTransport
from twisted.internet.ssl import Certificate, CertificateOptions, TLSVersion, trustRootFromCertificates

Expand Down Expand Up @@ -324,8 +323,7 @@ def _get_certificate_options(self) -> CertificateOptions:
)
return certificate_options

@inlineCallbacks
def validate_entrypoint(self, protocol: 'HathorProtocol') -> Generator[Any, Any, bool]:
async def validate_entrypoint(self, protocol: 'HathorProtocol') -> bool:
""" Validates if connection entrypoint is one of the peer entrypoints
"""
found_entrypoint = False
Expand All @@ -349,7 +347,7 @@ def validate_entrypoint(self, protocol: 'HathorProtocol') -> Generator[Any, Any,
host = connection_string_to_host(entrypoint)
# TODO: don't use `daa.TEST_MODE` for this
test_mode = not_none(DifficultyAdjustmentAlgorithm.singleton).TEST_MODE
result = yield discover_dns(host, test_mode)
result = await discover_dns(host, test_mode)
if protocol.connection_string in result:
# Found the entrypoint
found_entrypoint = True
Expand All @@ -369,7 +367,7 @@ def validate_entrypoint(self, protocol: 'HathorProtocol') -> Generator[Any, Any,
found_entrypoint = True
break
test_mode = not_none(DifficultyAdjustmentAlgorithm.singleton).TEST_MODE
result = yield discover_dns(host, test_mode)
result = await discover_dns(host, test_mode)
if connection_host in [connection_string_to_host(x) for x in result]:
# Found the entrypoint
found_entrypoint = True
Expand Down
5 changes: 3 additions & 2 deletions hathor/p2p/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import time
from enum import Enum
from typing import TYPE_CHECKING, Any, Generator, Optional, cast
from typing import TYPE_CHECKING, Any, Coroutine, Generator, Optional, cast

from structlog import get_logger
from twisted.internet.defer import Deferred
Expand Down Expand Up @@ -311,7 +311,8 @@ def recv_message(self, cmd: ProtocolMessages, payload: str) -> Optional[Deferred
fn = self.state.cmd_map.get(cmd)
if fn is not None:
try:
return fn(payload)
result = fn(payload)
return Deferred.fromCoroutine(result) if isinstance(result, Coroutine) else result
except Exception:
self.log.warn('recv_message processing error', exc_info=True)
raise
Expand Down
8 changes: 6 additions & 2 deletions hathor/p2p/states/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import TYPE_CHECKING, Callable, Optional, Union
from collections.abc import Coroutine
from typing import TYPE_CHECKING, Any, Callable, Optional

from structlog import get_logger
from twisted.internet.defer import Deferred
Expand All @@ -27,7 +28,10 @@

class BaseState:
protocol: 'HathorProtocol'
cmd_map: dict[ProtocolMessages, Union[Callable[[str], None], Callable[[str], Deferred[None]]]]
cmd_map: dict[
ProtocolMessages,
Callable[[str], None] | Callable[[str], Deferred[None]] | Callable[[str], Coroutine[Deferred[None], Any, None]]
]

def __init__(self, protocol: 'HathorProtocol'):
self.log = logger.new(**protocol.get_logger_context())
Expand Down
Loading