diff --git a/hathor/cli/events_simulator/__init__.py b/hathor/cli/events_simulator/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/hathor/cli/events_simulator/events_simulator.py b/hathor/cli/events_simulator/events_simulator.py new file mode 100644 index 000000000..207618de8 --- /dev/null +++ b/hathor/cli/events_simulator/events_simulator.py @@ -0,0 +1,54 @@ +# Copyright 2023 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 argparse import ArgumentParser, Namespace + +from hathor.cli.events_simulator.scenario import Scenario + +DEFAULT_PORT = 8080 + + +def create_parser() -> ArgumentParser: + from hathor.cli.util import create_parser + + parser = create_parser() + possible_scenarios = [scenario.value for scenario in Scenario] + + parser.add_argument('--scenario', help=f'One of {possible_scenarios}', type=Scenario, required=True) + parser.add_argument('--port', help='Port to run the WebSocket server', type=int, default=DEFAULT_PORT) + + return parser + + +def execute(args: Namespace) -> None: + from hathor.event.storage import EventMemoryStorage + from hathor.event.websocket import EventWebsocketFactory + from hathor.util import reactor + + storage = EventMemoryStorage() + + for event in args.scenario.get_events(): + storage.save_event(event) + + factory = EventWebsocketFactory(reactor, storage) + + factory.start() + reactor.listenTCP(args.port, factory) + reactor.run() + + +def main(): + parser = create_parser() + args = parser.parse_args() + execute(args) diff --git a/hathor/cli/events_simulator/scenario.py b/hathor/cli/events_simulator/scenario.py new file mode 100644 index 000000000..aff5da2e0 --- /dev/null +++ b/hathor/cli/events_simulator/scenario.py @@ -0,0 +1,76 @@ +# Copyright 2023 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 enum import Enum + +from hathor.event.model.base_event import BaseEvent +from hathor.event.model.event_data import TxData, TxMetadata +from hathor.pubsub import HathorEvents + + +class Scenario(Enum): + SINGLE_CHAIN = 'SINGLE_CHAIN' + BEST_CHAIN_WITH_SIDE_CHAINS = 'BEST_CHAIN_WITH_SIDE_CHAINS' + MULTIPLE_FORKS = 'MULTIPLE_FORKS' + + def get_events(self): + return _SCENARIO_EVENTS[self] + + +_TRANSACTION_DATA_1 = TxData( + hash='123', + nonce=456, + timestamp=0, + version=1, + weight=2, + inputs=[], + outputs=[], + parents=[], + tokens=[], + metadata=TxMetadata( + hash='123', + spent_outputs=[], + conflict_with=[], + voided_by=[], + received_by=[], + children=[], + twins=[], + accumulated_weight=2, + score=2, + height=0, + validation='' + ) +) + +_TRANSACTION_1 = BaseEvent( + peer_id='123', + id=0, + timestamp=0, + type=HathorEvents.NETWORK_NEW_TX_ACCEPTED, + data=_TRANSACTION_DATA_1 +) + + +# TODO: We still have to actually populate the list of events for each scenario. Pending on design discussions. +_SCENARIO_EVENTS = { + Scenario.SINGLE_CHAIN: [ + _TRANSACTION_1 + ], + Scenario.BEST_CHAIN_WITH_SIDE_CHAINS: [ + _TRANSACTION_1 + ], + Scenario.MULTIPLE_FORKS: [ + _TRANSACTION_1 + ], +} diff --git a/hathor/cli/main.py b/hathor/cli/main.py index 798cfa22f..d1a81c4b9 100644 --- a/hathor/cli/main.py +++ b/hathor/cli/main.py @@ -55,6 +55,7 @@ def __init__(self) -> None: tx_generator, wallet, ) + from .events_simulator import events_simulator self.add_cmd('mining', 'run_miner', mining, 'Run a mining process (running node required)') self.add_cmd('mining', 'run_merged_mining', merged_mining, @@ -80,6 +81,7 @@ def __init__(self) -> None: self.add_cmd('dev', 'shell', shell, 'Run a Python shell') self.add_cmd('dev', 'quick_test', quick_test, 'Similar to run_node but will quit after receiving a tx') self.add_cmd('dev', 'generate_nginx_config', nginx_config, 'Generate nginx config from OpenAPI json') + self.add_cmd('dev', 'events_simulator', events_simulator, 'Simulate integration events via websocket') self.add_cmd('dev', 'x-export', db_export, 'EXPERIMENTAL: Export database to a simple format.') self.add_cmd('dev', 'x-import', db_import, 'EXPERIMENTAL: Import database from exported format.') self.add_cmd('dev', 'replay-logs', replay_logs, 'EXPERIMENTAL: re-play json logs as console printted')