Skip to content

Commit

Permalink
tests(side-dag): implement missing side-dag related tests
Browse files Browse the repository at this point in the history
  • Loading branch information
glevco committed Jul 18, 2024
1 parent 06a93b8 commit 59295e8
Show file tree
Hide file tree
Showing 13 changed files with 1,350 additions and 214 deletions.
25 changes: 25 additions & 0 deletions hathor/builder/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from hathor.conf.get_settings import get_global_settings
from hathor.conf.settings import HathorSettings as HathorSettingsType
from hathor.consensus import ConsensusAlgorithm
from hathor.consensus.poa import PoaBlockProducer, PoaSigner
from hathor.daa import DifficultyAdjustmentAlgorithm
from hathor.event import EventManager
from hathor.event.storage import EventMemoryStorage, EventRocksDBStorage, EventStorage
Expand Down Expand Up @@ -195,6 +196,8 @@ def __init__(self) -> None:
self._vertex_parser: VertexParser | None = None
self._consensus: ConsensusAlgorithm | None = None
self._p2p_manager: ConnectionsManager | None = None
self._poa_signer: PoaSigner | None = None
self._poa_block_producer: PoaBlockProducer | None = None

def build(self) -> BuildArtifacts:
if self.artifacts is not None:
Expand Down Expand Up @@ -228,6 +231,7 @@ def build(self) -> BuildArtifacts:
cpu_mining_service = self._get_or_create_cpu_mining_service()
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()

if self._enable_address_index:
indexes.enable_address_index(pubsub)
Expand Down Expand Up @@ -268,10 +272,13 @@ def build(self) -> BuildArtifacts:
execution_manager=execution_manager,
vertex_handler=vertex_handler,
vertex_parser=vertex_parser,
poa_block_producer=poa_block_producer,
**kwargs
)

p2p_manager.set_manager(manager)
if poa_block_producer:
poa_block_producer.manager = manager

stratum_factory: Optional[StratumFactory] = None
if self._enable_stratum_server:
Expand Down Expand Up @@ -623,6 +630,19 @@ def _get_or_create_vertex_parser(self) -> VertexParser:

return self._vertex_parser

def _get_or_create_poa_block_producer(self) -> PoaBlockProducer | None:
if not self._poa_signer:
return None

if self._poa_block_producer is None:
self._poa_block_producer = PoaBlockProducer(
settings=self._get_or_create_settings(),
reactor=self._get_reactor(),
poa_signer=self._poa_signer,
)

return self._poa_block_producer

def use_memory(self) -> 'Builder':
self.check_if_can_modify()
self._storage_type = StorageType.MEMORY
Expand Down Expand Up @@ -818,3 +838,8 @@ def set_settings(self, settings: HathorSettingsType) -> 'Builder':
self.check_if_can_modify()
self._settings = settings
return self

def set_poa_signer(self, signer: PoaSigner) -> 'Builder':
self.check_if_can_modify()
self._poa_signer = signer
return self
27 changes: 15 additions & 12 deletions hathor/builder/cli_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,18 @@ def create_manager(self, reactor: Reactor) -> HathorManager:
log_vertex_bytes=self._args.log_vertex_bytes,
)

from hathor.consensus.poa import PoaBlockProducer, PoaSignerFile
poa_block_producer: PoaBlockProducer | None = None
if settings.CONSENSUS_ALGORITHM.is_poa():
assert isinstance(self._args, SideDagArgs)
if self._args.poa_signer_file:
poa_signer_file = PoaSignerFile.parse_file(self._args.poa_signer_file)
poa_block_producer = PoaBlockProducer(
settings=settings,
reactor=reactor,
poa_signer=poa_signer_file.get_signer(),
)

self.manager = HathorManager(
reactor,
settings=settings,
Expand All @@ -340,26 +352,17 @@ def create_manager(self, reactor: Reactor) -> HathorManager:
execution_manager=execution_manager,
vertex_handler=vertex_handler,
vertex_parser=vertex_parser,
poa_block_producer=poa_block_producer,
)

if settings.CONSENSUS_ALGORITHM.is_poa():
assert isinstance(self._args, SideDagArgs)
if self._args.poa_signer_file:
from hathor.consensus.poa import PoaBlockProducer, PoaSignerFile
poa_signer_file = PoaSignerFile.parse_file(self._args.poa_signer_file)
self.manager.poa_block_producer = PoaBlockProducer(
settings=settings,
reactor=reactor,
manager=self.manager,
poa_signer=poa_signer_file.get_signer(),
)

if self._args.x_ipython_kernel:
self.check_or_raise(self._args.x_asyncio_reactor,
'--x-ipython-kernel must be used with --x-asyncio-reactor')
self._start_ipykernel()

p2p_manager.set_manager(self.manager)
if poa_block_producer:
poa_block_producer.manager = self.manager

if self._args.stratum:
stratum_factory = StratumFactory(self.manager, reactor=reactor)
Expand Down
8 changes: 4 additions & 4 deletions hathor/cli/side_dag.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,18 +97,18 @@ def main(capture_stdout: bool) -> None:
to the non-side-dag full node, which runs in a background process and is commonly just a Hathor full node.
Whenever one of the full nodes fail, the other is automatically terminated.
By default, both full nodes output logs to stdout, but logs can be configured independently. Here's an example:
The only exception is log configuration, which is set using a single option. By default, both full nodes output
logs to stdout. Here's an example changing both logs to json:
```bash
$ python -m hathor side_dag
$ python -m hathor run_node_with_side_dag
--testnet
--procname-prefix testnet-
--memory-storage
--disable-logs
--side-dag-config-yaml ./my-side-dag.yml
--side-dag-procname-prefix my-side-dag-
--side-dag-memory-storage
--side-dag-json-logs
--json-logs both
```
In this example, Hathor testnet logs would be disabled, while side-dag logs would be outputted to stdout as json.
Expand Down
34 changes: 18 additions & 16 deletions hathor/consensus/poa/poa_block_producer.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,20 +59,13 @@ class PoaBlockProducer:
'_last_seen_best_block',
)

def __init__(
self,
*,
settings: HathorSettings,
reactor: ReactorProtocol,
manager: 'HathorManager',
poa_signer: PoaSigner,
) -> None:
def __init__(self, *, settings: HathorSettings, reactor: ReactorProtocol, poa_signer: PoaSigner) -> None:
assert isinstance(settings.CONSENSUS_ALGORITHM, PoaSettings)
self._log = logger.new()
self._settings = settings
self._poa_settings = settings.CONSENSUS_ALGORITHM
self._reactor = reactor
self._manager = manager
self._manager: HathorManager | None = None
self._poa_signer = poa_signer
self._signer_index = self._calculate_signer_index(self._poa_settings, self._poa_signer)
self._last_seen_best_block: Block | None = None
Expand All @@ -84,6 +77,15 @@ def __init__(
self._schedule_block_lc = LoopingCall(self._schedule_block)
self._schedule_block_lc.clock = self._reactor

@property
def manager(self) -> HathorManager:
assert self._manager is not None
return self._manager

@manager.setter
def manager(self, manager: HathorManager) -> None:
self._manager = manager

def start(self) -> None:
self._start_producing_lc.start(_WAIT_SYNC_DELAY)
self._schedule_block_lc.start(self._settings.AVG_TIME_BETWEEN_BLOCKS)
Expand All @@ -108,7 +110,7 @@ def _calculate_signer_index(settings: PoaSettings, poa_signer: PoaSigner) -> int

def _start_producing(self) -> None:
"""Start producing new blocks."""
if not self._manager.can_start_mining():
if not self.manager.can_start_mining():
# We're syncing, so we'll try again later
self._log.warn('cannot start producing new blocks, node not synced')
return
Expand All @@ -119,7 +121,7 @@ def _start_producing(self) -> None:

def _schedule_block(self) -> None:
"""Schedule propagation of a new block."""
previous_block = self._manager.tx_storage.get_best_block()
previous_block = self.manager.tx_storage.get_best_block()
if not self._started_producing or previous_block == self._last_seen_best_block:
return

Expand All @@ -139,16 +141,16 @@ def _schedule_block(self) -> None:
def _produce_block(self, previous_block: PoaBlock) -> None:
"""Create and propagate a new block."""
from hathor.transaction.poa import PoaBlock
block_templates = self._manager.get_block_templates(parent_block_hash=previous_block.hash)
block = block_templates.generate_mining_block(self._manager.rng, cls=PoaBlock)
block_templates = self.manager.get_block_templates(parent_block_hash=previous_block.hash)
block = block_templates.generate_mining_block(self.manager.rng, cls=PoaBlock)
assert isinstance(block, PoaBlock)
block.weight = poa.calculate_weight(self._poa_settings, block, self._signer_index)
self._poa_signer.sign_block(block)
block.update_hash()

self._manager.on_new_tx(block, propagate_to_peers=False, fails_silently=False)
self.manager.on_new_tx(block, propagate_to_peers=False, fails_silently=False)
if not block.get_metadata().voided_by:
self._manager.connections.send_tx_to_peers(block)
self.manager.connections.send_tx_to_peers(block)

self._log.debug(
'produced new block',
Expand All @@ -169,5 +171,5 @@ def _expected_block_timestamp(self, previous_block: Block) -> int:

signer_count = len(self._poa_settings.signers)
assert signer_count >= 1
random_offset = self._manager.rng.choice(range(signer_count * _RANDOM_DELAY_MULTIPLIER)) + 1
random_offset = self.manager.rng.choice(range(signer_count * _RANDOM_DELAY_MULTIPLIER)) + 1
return timestamp + random_offset
3 changes: 2 additions & 1 deletion hathor/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ def __init__(
environment_info: Optional[EnvironmentInfo] = None,
full_verification: bool = False,
enable_event_queue: bool = False,
poa_block_producer: PoaBlockProducer | None = None,
) -> None:
"""
:param reactor: Twisted reactor which handles the mainloop and the events.
Expand Down Expand Up @@ -235,7 +236,7 @@ def __init__(
# This is included in some logs to provide more context
self.environment_info = environment_info

self.poa_block_producer: PoaBlockProducer | None = None
self.poa_block_producer = poa_block_producer

# Task that will count the total sync time
self.lc_check_sync_state = LoopingCall(self.check_sync_state)
Expand Down
Empty file added tests/poa/__init__.py
Empty file.
Loading

0 comments on commit 59295e8

Please sign in to comment.