Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
e1aefa8
refactor(event-queue): improve event ordering (#738)
glevco Jul 31, 2023
48a64d6
Merge branch 'release' into master
jansegre Aug 2, 2023
366a2ca
chore(feature-activation): update feature endpoint visibility to public
glevco Aug 2, 2023
4e97384
chore(feature-activation): PR suggestions
glevco Aug 2, 2023
de0d612
Merge pull request #743 from HathorNetwork/chore/feature-activation/e…
jansegre Aug 3, 2023
c95834d
chore(event-queue): update event endpoints visibility to public
glevco Aug 3, 2023
afddefe
chore: improve merkle path log
glevco Aug 3, 2023
32c9671
Merge pull request #745 from HathorNetwork/chore/improve-merkle-log
jansegre Aug 3, 2023
a909ab2
fix(event-queue): improve memory usage during the load phase
glevco Aug 2, 2023
21505bc
fix(sync-v2): compare to local bytes broke in some cases
jansegre Aug 3, 2023
a63ab5f
Merge pull request #747 from HathorNetwork/fix/compare-with-partial
jansegre Aug 8, 2023
4277cc2
refactor(sync-v2): rename SyncAgent module from manager to agent
jansegre Aug 4, 2023
97f2471
Merge pull request #748 from HathorNetwork/refactor/sync-v2-agent
jansegre Aug 8, 2023
3b02e6c
feat: add best_blockchain in /status payload (#704)
alexruzenhack Aug 10, 2023
480cbe1
fix(tests): make simulator test not flaky on sync-v2
jansegre Aug 10, 2023
6df0ca3
Merge pull request #750 from HathorNetwork/fix/sync-v2-flaky-tests
jansegre Aug 23, 2023
f89cd71
feat(feature-activation): implement signal bits in mining blocks
glevco Jul 18, 2023
88eeb5c
Merge pull request #703 from HathorNetwork/feat/feature-activation/bi…
jansegre Aug 23, 2023
bd5311f
chore: improve miner simulator flakiness
glevco Aug 23, 2023
4c664ff
Merge pull request #753 from HathorNetwork/chore/miner-simulator-flak…
jansegre Aug 24, 2023
dac9430
chore: bump version to v0.56.0
jansegre Aug 25, 2023
f83614a
Merge pull request #757 from HathorNetwork/chore/v0.56.0
jansegre Aug 25, 2023
3135fd0
chore: add deprecation warning for Python 3.9
jansegre Aug 25, 2023
e748f2a
Merge pull request #759 from HathorNetwork/chore/deprecation-warnings…
jansegre Aug 25, 2023
2f70ef1
feat(feature-activation): add logging of NOP features
glevco Aug 25, 2023
ca5ac69
refactor: extract SysctlRunner from SysctlProtocol
alexruzenhack Jul 28, 2023
3acc0cc
Merge pull request #739 from HathorNetwork/refactor/sysctl-protocol
jansegre Aug 28, 2023
fd5941d
feat(feature-activation): configure NOP features on testnet
glevco Aug 25, 2023
376c55b
Merge pull request #761 from HathorNetwork/feat/feature-activation/co…
jansegre Aug 28, 2023
7265310
fix: imports
glevco Aug 28, 2023
99ba548
Merge pull request #762 from HathorNetwork/fix/imports
jansegre Aug 29, 2023
78229b7
chore: improve pubsub
glevco Jul 11, 2023
dfab19f
Merge pull request #764 from HathorNetwork/master
jansegre Aug 30, 2023
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
80 changes: 66 additions & 14 deletions hathor/builder/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
from hathor.event import EventManager
from hathor.event.storage import EventMemoryStorage, EventRocksDBStorage, EventStorage
from hathor.event.websocket import EventWebsocketFactory
from hathor.feature_activation.bit_signaling_service import BitSignalingService
from hathor.feature_activation.feature import Feature
from hathor.feature_activation.feature_service import FeatureService
from hathor.indexes import IndexesManager, MemoryIndexesManager, RocksDBIndexesManager
from hathor.manager import HathorManager
Expand Down Expand Up @@ -64,7 +66,6 @@ class BuildArtifacts(NamedTuple):
wallet: Optional[BaseWallet]
rocksdb_storage: Optional[RocksDBStorage]
stratum_factory: Optional[StratumFactory]
feature_service: FeatureService


class Builder:
Expand All @@ -80,7 +81,7 @@ def __init__(self) -> None:
self.log = logger.new()
self.artifacts: Optional[BuildArtifacts] = None

self._settings: HathorSettingsType = HathorSettings()
self._settings: Optional[HathorSettingsType] = None
self._rng: Random = Random()
self._checkpoints: Optional[list[Checkpoint]] = None
self._capabilities: Optional[list[str]] = None
Expand All @@ -95,6 +96,11 @@ def __init__(self) -> None:
self._event_manager: Optional[EventManager] = None
self._enable_event_queue: Optional[bool] = None

self._support_features: set[Feature] = set()
self._not_support_features: set[Feature] = set()
self._feature_service: Optional[FeatureService] = None
self._bit_signaling_service: Optional[BitSignalingService] = None

self._rocksdb_path: Optional[str] = None
self._rocksdb_storage: Optional[RocksDBStorage] = None
self._rocksdb_cache_capacity: Optional[int] = None
Expand Down Expand Up @@ -134,7 +140,7 @@ def build(self) -> BuildArtifacts:
if self._network is None:
raise TypeError('you must set a network')

settings = self._get_settings()
settings = self._get_or_create_settings()
reactor = self._get_reactor()
pubsub = self._get_or_create_pubsub()

Expand All @@ -149,6 +155,8 @@ def build(self) -> BuildArtifacts:
event_manager = self._get_or_create_event_manager()
indexes = self._get_or_create_indexes_manager()
tx_storage = self._get_or_create_tx_storage(indexes)
feature_service = self._get_or_create_feature_service(tx_storage)
bit_signaling_service = self._get_or_create_bit_signaling_service(tx_storage)

if self._enable_address_index:
indexes.enable_address_index(pubsub)
Expand Down Expand Up @@ -181,6 +189,8 @@ def build(self) -> BuildArtifacts:
checkpoints=self._checkpoints,
capabilities=self._capabilities,
environment_info=get_environment_info(self._cmdline, peer_id.id),
feature_service=feature_service,
bit_signaling_service=bit_signaling_service,
**kwargs
)

Expand All @@ -190,8 +200,6 @@ def build(self) -> BuildArtifacts:
if self._enable_stratum_server:
stratum_factory = self._create_stratum_server(manager)

feature_service = self._create_feature_service(tx_storage)

self.artifacts = BuildArtifacts(
peer_id=peer_id,
settings=settings,
Expand All @@ -206,7 +214,6 @@ def build(self) -> BuildArtifacts:
wallet=wallet,
rocksdb_storage=self._rocksdb_storage,
stratum_factory=stratum_factory,
feature_service=feature_service
)

return self.artifacts
Expand All @@ -220,6 +227,16 @@ def set_event_manager(self, event_manager: EventManager) -> 'Builder':
self._event_manager = event_manager
return self

def set_feature_service(self, feature_service: FeatureService) -> 'Builder':
self.check_if_can_modify()
self._feature_service = feature_service
return self

def set_bit_signaling_service(self, bit_signaling_service: BitSignalingService) -> 'Builder':
self.check_if_can_modify()
self._bit_signaling_service = bit_signaling_service
return self

def set_rng(self, rng: Random) -> 'Builder':
self.check_if_can_modify()
self._rng = rng
Expand All @@ -240,7 +257,9 @@ def set_peer_id(self, peer_id: PeerId) -> 'Builder':
self._peer_id = peer_id
return self

def _get_settings(self) -> HathorSettingsType:
def _get_or_create_settings(self) -> HathorSettingsType:
if self._settings is None:
self._settings = HathorSettings()
return self._settings

def _get_reactor(self) -> Reactor:
Expand All @@ -252,7 +271,7 @@ def _get_soft_voided_tx_ids(self) -> set[bytes]:
if self._soft_voided_tx_ids is not None:
return self._soft_voided_tx_ids

settings = self._get_settings()
settings = self._get_or_create_settings()

return set(settings.SOFT_VOIDED_TX_IDS)

Expand All @@ -272,12 +291,6 @@ def _create_stratum_server(self, manager: HathorManager) -> StratumFactory:
manager.metrics.stratum_factory = stratum_factory
return stratum_factory

def _create_feature_service(self, tx_storage: TransactionStorage) -> FeatureService:
return FeatureService(
feature_settings=self._settings.FEATURE_ACTIVATION,
tx_storage=tx_storage
)

def _get_or_create_rocksdb_storage(self) -> RocksDBStorage:
assert self._rocksdb_path is not None

Expand Down Expand Up @@ -388,6 +401,29 @@ def _get_or_create_event_manager(self) -> EventManager:

return self._event_manager

def _get_or_create_feature_service(self, tx_storage: TransactionStorage) -> FeatureService:
if self._feature_service is None:
settings = self._get_or_create_settings()
self._feature_service = FeatureService(
feature_settings=settings.FEATURE_ACTIVATION,
tx_storage=tx_storage
)

return self._feature_service

def _get_or_create_bit_signaling_service(self, tx_storage: TransactionStorage) -> BitSignalingService:
if self._bit_signaling_service is None:
settings = self._get_or_create_settings()
self._bit_signaling_service = BitSignalingService(
feature_settings=settings.FEATURE_ACTIVATION,
feature_service=self._get_or_create_feature_service(tx_storage),
tx_storage=tx_storage,
support_features=self._support_features,
not_support_features=self._not_support_features,
)

return self._bit_signaling_service

def use_memory(self) -> 'Builder':
self.check_if_can_modify()
self._storage_type = StorageType.MEMORY
Expand Down Expand Up @@ -559,3 +595,19 @@ def set_soft_voided_tx_ids(self, soft_voided_tx_ids: set[bytes]) -> 'Builder':
self.check_if_can_modify()
self._soft_voided_tx_ids = soft_voided_tx_ids
return self

def set_features(
self,
*,
support_features: Optional[set[Feature]],
not_support_features: Optional[set[Feature]]
) -> 'Builder':
self.check_if_can_modify()
self._support_features = support_features or set()
self._not_support_features = not_support_features or set()
return self

def set_settings(self, settings: HathorSettingsType) -> 'Builder':
self.check_if_can_modify()
self._settings = settings
return self
24 changes: 20 additions & 4 deletions hathor/builder/cli_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,21 @@
from typing import Any, Optional

from structlog import get_logger
from twisted.internet.posixbase import PosixReactorBase

from hathor.cli.run_node import RunNodeArgs
from hathor.consensus import ConsensusAlgorithm
from hathor.event import EventManager
from hathor.exception import BuilderError
from hathor.feature_activation.bit_signaling_service import BitSignalingService
from hathor.feature_activation.feature_service import FeatureService
from hathor.indexes import IndexesManager, MemoryIndexesManager, RocksDBIndexesManager
from hathor.manager import HathorManager
from hathor.p2p.manager import ConnectionsManager
from hathor.p2p.peer_id import PeerId
from hathor.p2p.utils import discover_hostname
from hathor.pubsub import PubSubManager
from hathor.stratum import StratumFactory
from hathor.util import Random
from hathor.util import Random, Reactor
from hathor.wallet import BaseWallet, HDWallet, Wallet

logger = get_logger()
Expand All @@ -53,7 +54,7 @@ def check_or_raise(self, condition: bool, message: str) -> None:
if not condition:
raise BuilderError(message)

def create_manager(self, reactor: PosixReactorBase) -> HathorManager:
def create_manager(self, reactor: Reactor) -> HathorManager:
import hathor
from hathor.conf import HathorSettings
from hathor.conf.get_settings import get_settings_source
Expand Down Expand Up @@ -189,6 +190,19 @@ def create_manager(self, reactor: PosixReactorBase) -> HathorManager:
self.log.info('--x-enable-event-queue flag provided. '
'The events detected by the full node will be stored and can be retrieved by clients')

self.feature_service = FeatureService(
feature_settings=settings.FEATURE_ACTIVATION,
tx_storage=tx_storage
)

bit_signaling_service = BitSignalingService(
feature_settings=settings.FEATURE_ACTIVATION,
feature_service=self.feature_service,
tx_storage=tx_storage,
support_features=self._args.signal_support,
not_support_features=self._args.signal_not_support
)

p2p_manager = ConnectionsManager(
reactor,
network=network,
Expand Down Expand Up @@ -216,7 +230,9 @@ def create_manager(self, reactor: PosixReactorBase) -> HathorManager:
checkpoints=settings.CHECKPOINTS,
environment_info=get_environment_info(args=str(self._args), peer_id=peer_id.id),
full_verification=full_verification,
enable_event_queue=self._args.x_enable_event_queue
enable_event_queue=self._args.x_enable_event_queue,
feature_service=self.feature_service,
bit_signaling_service=bit_signaling_service
)

p2p_manager.set_manager(self.manager)
Expand Down
16 changes: 16 additions & 0 deletions hathor/cli/nginx_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,15 @@ def generate_nginx_config(openapi: dict[str, Any], *, out_file: TextIO, rate_k:
websocket_max_conn_per_ip = 10000
mining_websocket_max_conn_global = 1000
mining_websocket_max_conn_per_ip = 1000
event_websocket_max_conn_global = 1000
event_websocket_max_conn_per_ip = 1000
else:
websocket_max_conn_global = 4000
websocket_max_conn_per_ip = 10
mining_websocket_max_conn_global = 100
mining_websocket_max_conn_per_ip = 4
event_websocket_max_conn_global = 100
event_websocket_max_conn_per_ip = 4

header = f'''# THIS FILE WAS AUTOGENERATED BY THE `hathor-cli nginx-config` TOOL AT {datetime.now()}

Expand Down Expand Up @@ -231,6 +235,8 @@ def generate_nginx_config(openapi: dict[str, Any], *, out_file: TextIO, rate_k:
limit_conn_zone $per_ip_key zone=per_ip__ws:10m;
limit_conn_zone $global_key zone=global__mining_ws:32k;
limit_conn_zone $per_ip_key zone=per_ip__mining_ws:10m;
limit_conn_zone $global_key zone=global__event_ws:32k;
limit_conn_zone $per_ip_key zone=per_ip__event_ws:10m;
'''

server_open = f'''
Expand Down Expand Up @@ -282,6 +288,16 @@ def generate_nginx_config(openapi: dict[str, Any], *, out_file: TextIO, rate_k:
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://backend;
}}
location ~ ^/{api_prefix}/event_ws/?$ {{
limit_conn global__event_ws {event_websocket_max_conn_global};
limit_conn per_ip__event_ws {event_websocket_max_conn_per_ip};
include cors_params;
include proxy_params;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://backend;
}}'''
# TODO: maybe return 403 instead?
server_close = f'''
Expand Down
2 changes: 1 addition & 1 deletion hathor/cli/openapi_files/openapi_base.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
],
"info": {
"title": "Hathor API",
"version": "0.55.0"
"version": "0.56.0"
},
"consumes": [
"application/json"
Expand Down
2 changes: 2 additions & 0 deletions hathor/cli/openapi_files/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ def register_resource(resource_class: ResourceClass) -> ResourceClass:
def get_registered_resources() -> list[type[Resource]]:
""" Returns a list with all the resources registered for the docs
"""
import hathor.event.resources.event # noqa: 401
import hathor.feature_activation.resources.feature # noqa: 401
import hathor.p2p.resources # noqa: 401
import hathor.profiler.resources # noqa: 401
import hathor.stratum.resources # noqa: 401
Expand Down
40 changes: 28 additions & 12 deletions hathor/cli/run_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,21 +156,22 @@ def prepare(self, *, register_resources: bool = True) -> None:
self.start_manager()

if self._args.stratum:
assert self.manager.stratum_factory is not None
self.reactor.listenTCP(self._args.stratum, self.manager.stratum_factory)

from hathor.conf import HathorSettings
from hathor.feature_activation.feature_service import FeatureService
settings = HathorSettings()

feature_service = FeatureService(
feature_settings=settings.FEATURE_ACTIVATION,
tx_storage=self.manager.tx_storage
)

if register_resources:
resources_builder = ResourcesBuilder(self.manager, self._args, builder.event_ws_factory, feature_service)
resources_builder = ResourcesBuilder(
self.manager,
self._args,
builder.event_ws_factory,
builder.feature_service
)
status_server = resources_builder.build()
if self._args.status:
assert status_server is not None
self.reactor.listenTCP(self._args.status, status_server)

from hathor.builder.builder import BuildArtifacts
Expand All @@ -188,7 +189,6 @@ def prepare(self, *, register_resources: bool = True) -> None:
wallet=self.manager.wallet,
rocksdb_storage=getattr(builder, 'rocksdb_storage', None),
stratum_factory=self.manager.stratum_factory,
feature_service=feature_service
)

def start_sentry_if_possible(self) -> None:
Expand Down Expand Up @@ -312,11 +312,14 @@ def check_unsafe_arguments(self) -> None:
sys.exit(-1)

def check_python_version(self) -> None:
MIN_VER = (3, 8)
RECOMMENDED_VER = (3, 9)
# comments to help grep's
MIN_VER = (3, 9) # Python-3.9
MIN_STABLE = (3, 10) # Python-3.10
RECOMMENDED_VER = (3, 10) # Python-3.10
cur = sys.version_info
min_pretty = '.'.join(map(str, MIN_VER))
cur_pretty = '.'.join(map(str, cur))
min_pretty = '.'.join(map(str, MIN_VER))
min_stable_pretty = '.'.join(map(str, MIN_STABLE))
recommended_pretty = '.'.join(map(str, RECOMMENDED_VER))
if cur < MIN_VER:
self.log.critical('\n'.join([
Expand All @@ -329,6 +332,17 @@ def check_python_version(self) -> None:
'',
]))
sys.exit(-1)
elif cur < MIN_STABLE:
self.log.warning('\n'.join([
'',
'********************************************************',
f'The detected Python version {cur_pretty} is deprecated and support for it will be removed in the'
' next release.',
f'The minimum supported Python version will be {min_stable_pretty}',
f'The recommended Python version is {recommended_pretty}',
'********************************************************',
'',
]))

def __init__(self, *, argv=None):
self.log = logger.new()
Expand Down Expand Up @@ -375,11 +389,13 @@ def init_sysctl(self, description: str) -> None:

from hathor.builder.sysctl_builder import SysctlBuilder
from hathor.sysctl.factory import SysctlFactory
from hathor.sysctl.runner import SysctlRunner

builder = SysctlBuilder(self.artifacts)
root = builder.build()

factory = SysctlFactory(root)
runner = SysctlRunner(root)
factory = SysctlFactory(runner)
endpoint = serverFromString(self.reactor, description)
endpoint.listen(factory)

Expand Down
Loading