diff --git a/hathor/builder/builder.py b/hathor/builder/builder.py index b2d7e2890..30c22fc15 100644 --- a/hathor/builder/builder.py +++ b/hathor/builder/builder.py @@ -66,21 +66,14 @@ def add_factories( cls, settings: HathorSettingsType, p2p_manager: ConnectionsManager, - 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 from hathor.p2p.sync_v2.factory import SyncV2Factory from hathor.p2p.sync_version import SyncVersion - # sync-v1 support: - if sync_v1_support > cls.UNAVAILABLE: - p2p_manager.add_sync_factory(SyncVersion.V1_1, SyncV11Factory(p2p_manager, vertex_parser=vertex_parser)) - 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( @@ -185,8 +178,7 @@ def __init__(self) -> None: self._enable_tokens_index: bool = False self._enable_utxo_index: bool = False - self._sync_v1_support: SyncSupportLevel = SyncSupportLevel.UNAVAILABLE - self._sync_v2_support: SyncSupportLevel = SyncSupportLevel.UNAVAILABLE + self._sync_v2_support: SyncSupportLevel = SyncSupportLevel.ENABLED self._enable_stratum_server: Optional[bool] = None @@ -209,7 +201,7 @@ def build(self) -> BuildArtifacts: if self.artifacts is not None: raise ValueError('cannot call build twice') - if SyncSupportLevel.ENABLED not in {self._sync_v1_support, self._sync_v2_support}: + if SyncSupportLevel.ENABLED not in {self._sync_v2_support}: raise TypeError('you must enable at least one sync version') settings = self._get_or_create_settings() @@ -435,7 +427,6 @@ def _get_or_create_p2p_manager(self) -> ConnectionsManager: SyncSupportLevel.add_factories( self._get_or_create_settings(), self._p2p_manager, - self._sync_v1_support, self._sync_v2_support, self._get_or_create_vertex_parser(), self._get_or_create_vertex_handler(), @@ -772,26 +763,11 @@ def set_pubsub(self, pubsub: PubSubManager) -> 'Builder': self._pubsub = pubsub return self - def set_sync_v1_support(self, support_level: SyncSupportLevel) -> 'Builder': - self.check_if_can_modify() - self._sync_v1_support = support_level - return self - def set_sync_v2_support(self, support_level: SyncSupportLevel) -> 'Builder': self.check_if_can_modify() self._sync_v2_support = support_level return self - def enable_sync_v1(self) -> 'Builder': - self.check_if_can_modify() - self._sync_v1_support = SyncSupportLevel.ENABLED - return self - - def disable_sync_v1(self) -> 'Builder': - self.check_if_can_modify() - self._sync_v1_support = SyncSupportLevel.DISABLED - return self - def enable_sync_v2(self) -> 'Builder': self.check_if_can_modify() self._sync_v2_support = SyncSupportLevel.ENABLED diff --git a/hathor/builder/cli_builder.py b/hathor/builder/cli_builder.py index 059007190..cc4e3870a 100644 --- a/hathor/builder/cli_builder.py +++ b/hathor/builder/cli_builder.py @@ -198,46 +198,20 @@ def create_manager(self, reactor: Reactor) -> HathorManager: hostname = self.get_hostname() - sync_choice: SyncChoice if self._args.sync_bridge: - self.log.warn('--sync-bridge is deprecated and will be removed') - sync_choice = SyncChoice.BRIDGE_DEFAULT + raise BuilderError('--sync-bridge was removed') elif self._args.sync_v1_only: - self.log.warn('--sync-v1-only is deprecated and will be removed') - sync_choice = SyncChoice.V1_DEFAULT + raise BuilderError('--sync-v1-only was removed') elif self._args.sync_v2_only: self.log.warn('--sync-v2-only is the default, this parameter has no effect') - sync_choice = SyncChoice.V2_DEFAULT elif self._args.x_remove_sync_v1: - sync_choice = SyncChoice.V2_ONLY + self.log.warn('--x-remove-sync-v1 is deprecated and has no effect') elif self._args.x_sync_bridge: - self.log.warn('--x-sync-bridge is deprecated and will be removed') - sync_choice = SyncChoice.BRIDGE_DEFAULT + raise BuilderError('--x-sync-bridge was removed') elif self._args.x_sync_v1_only: - self.log.warn('--x-sync-v1-only is deprecated and will be removed') - sync_choice = SyncChoice.V1_DEFAULT + raise BuilderError('--x-sync-v1-only was removed') elif self._args.x_sync_v2_only: self.log.warn('--x-sync-v2-only is deprecated and will be removed') - sync_choice = SyncChoice.V2_DEFAULT - else: - # XXX: this is the default behavior when no parameter is given - sync_choice = SyncChoice.V2_DEFAULT - - sync_v1_support: SyncSupportLevel - sync_v2_support: SyncSupportLevel - match sync_choice: - case SyncChoice.V1_DEFAULT: - sync_v1_support = SyncSupportLevel.ENABLED - sync_v2_support = SyncSupportLevel.DISABLED - case SyncChoice.V2_DEFAULT: - sync_v1_support = SyncSupportLevel.DISABLED - sync_v2_support = SyncSupportLevel.ENABLED - case SyncChoice.BRIDGE_DEFAULT: - sync_v1_support = SyncSupportLevel.ENABLED - sync_v2_support = SyncSupportLevel.ENABLED - case SyncChoice.V2_ONLY: - sync_v1_support = SyncSupportLevel.UNAVAILABLE - sync_v2_support = SyncSupportLevel.ENABLED pubsub = PubSubManager(reactor) @@ -345,14 +319,7 @@ def create_manager(self, reactor: Reactor) -> HathorManager: log_vertex_bytes=self._args.log_vertex_bytes, ) - SyncSupportLevel.add_factories( - settings, - p2p_manager, - sync_v1_support, - sync_v2_support, - vertex_parser, - vertex_handler, - ) + SyncSupportLevel.add_factories(settings, p2p_manager, SyncSupportLevel.ENABLED, vertex_parser, vertex_handler) from hathor.consensus.poa import PoaBlockProducer, PoaSignerFile poa_block_producer: PoaBlockProducer | None = None diff --git a/hathor/cli/run_node.py b/hathor/cli/run_node.py index ba4f40816..24ee77390 100644 --- a/hathor/cli/run_node.py +++ b/hathor/cli/run_node.py @@ -135,14 +135,13 @@ def create_parser(cls) -> ArgumentParser: parser.add_argument('--enable-debug-api', action='store_true', help='Enable _debug/* endpoints') parser.add_argument('--enable-crash-api', action='store_true', help='Enable _crash/* endpoints') sync_args = parser.add_mutually_exclusive_group() - sync_args.add_argument('--sync-bridge', action='store_true', help=SUPPRESS) # moved to --x-sync-bridge - sync_args.add_argument('--sync-v1-only', action='store_true', help=SUPPRESS) # moved to --x-sync-v1-only - sync_args.add_argument('--sync-v2-only', action='store_true', help=SUPPRESS) # already default - sync_args.add_argument('--x-remove-sync-v1', action='store_true', help='Make sync-v1 unavailable, thus ' - 'impossible to be enabled in runtime.') - sync_args.add_argument('--x-sync-v1-only', action='store_true', help='Disable support for running sync-v2.') - sync_args.add_argument('--x-sync-v2-only', action='store_true', help=SUPPRESS) # old argument - sync_args.add_argument('--x-sync-bridge', action='store_true', help='Enable running both sync protocols.') + sync_args.add_argument('--sync-bridge', action='store_true', help=SUPPRESS) # deprecated + sync_args.add_argument('--sync-v1-only', action='store_true', help=SUPPRESS) # deprecated + sync_args.add_argument('--sync-v2-only', action='store_true', help=SUPPRESS) # deprecated + sync_args.add_argument('--x-remove-sync-v1', action='store_true', help=SUPPRESS) # deprecated + sync_args.add_argument('--x-sync-v1-only', action='store_true', help=SUPPRESS) # deprecated + sync_args.add_argument('--x-sync-v2-only', action='store_true', help=SUPPRESS) # deprecated + sync_args.add_argument('--x-sync-bridge', action='store_true', help=SUPPRESS) # deprecated parser.add_argument('--x-localhost-only', action='store_true', help='Only connect to peers on localhost') parser.add_argument('--x-rocksdb-indexes', action='store_true', help=SUPPRESS) parser.add_argument('--x-enable-event-queue', action='store_true', diff --git a/hathor/cli/util.py b/hathor/cli/util.py index 3e11b83c5..4fbd7cf12 100644 --- a/hathor/cli/util.py +++ b/hathor/cli/util.py @@ -269,11 +269,6 @@ def setup_logging( 'level': 'INFO' if logging_options.debug else 'WARN', 'propagate': False, }, - 'hathor.p2p.sync_v1': { - 'handlers': handlers, - 'level': 'DEBUG' if debug_sync else 'INFO', - 'propagate': False, - }, 'hathor.p2p.sync_v2': { 'handlers': handlers, 'level': 'DEBUG' if debug_sync else 'INFO', diff --git a/hathor/p2p/sync_v1/__init__.py b/hathor/p2p/sync_v1/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/hathor/p2p/sync_v1/agent.py b/hathor/p2p/sync_v1/agent.py deleted file mode 100644 index 68fe401ec..000000000 --- a/hathor/p2p/sync_v1/agent.py +++ /dev/null @@ -1,715 +0,0 @@ -# Copyright 2021 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. - -import base64 -import struct -from math import inf -from typing import TYPE_CHECKING, Any, Callable, Generator, Iterator, Optional -from weakref import WeakSet - -from structlog import get_logger -from twisted.internet.defer import CancelledError, Deferred, inlineCallbacks -from twisted.internet.interfaces import IDelayedCall - -from hathor.conf.get_settings import get_global_settings -from hathor.p2p.messages import GetNextPayload, GetTipsPayload, NextPayload, ProtocolMessages, TipsPayload -from hathor.p2p.sync_agent import SyncAgent -from hathor.p2p.sync_v1.downloader import Downloader -from hathor.reactor import ReactorProtocol as Reactor -from hathor.transaction import BaseTransaction -from hathor.transaction.storage.exceptions import TransactionDoesNotExist -from hathor.transaction.vertex_parser import VertexParser -from hathor.util import json_dumps, json_loads - -logger = get_logger() - -if TYPE_CHECKING: - from twisted.python.failure import Failure # noqa: F401 - - from hathor.p2p.protocol import HathorProtocol # noqa: F401 - from hathor.p2p.rate_limiter import RateLimiter - - -def _get_deps(tx: BaseTransaction) -> Iterator[bytes]: - """ Method to get dependencies of a block/transaction. - """ - for h in tx.parents: - yield h - for txin in tx.inputs: - yield txin.tx_id - - -class NodeSyncTimestamp(SyncAgent): - """ An algorithm to sync the DAG between two peers using the timestamp of the transactions. - - This algorithm must assume that a new item may arrive while it is running. The item's timestamp - may be recent or old, changing the tips of any timestamp. - """ - name: str = 'node-sync-timestamp' - - MAX_HASHES: int = 40 - - def __init__( - self, - protocol: 'HathorProtocol', - downloader: Downloader, - reactor: Reactor, - *, - vertex_parser: VertexParser, - ) -> None: - """ - :param protocol: Protocol of the connection. - :type protocol: HathorProtocol - - :param reactor: Reactor to schedule later calls. (default=twisted.internet.reactor) - :type reactor: Reactor - """ - self._settings = get_global_settings() - self.vertex_parser = vertex_parser - self.protocol = protocol - self.manager = protocol.node - self.downloader = downloader - - self.reactor: Reactor = reactor - - # Rate limit for this connection. - assert protocol.connections is not None - self.global_rate_limiter: 'RateLimiter' = protocol.connections.rate_limiter - self.GlobalRateLimiter = protocol.connections.GlobalRateLimiter - - self.call_later_id: Optional[IDelayedCall] = None - self.call_later_interval: int = 1 # seconds - - # Keep track of call laters. - self._send_tips_call_later: list[IDelayedCall] = [] - - # Timestamp of the peer's latest block (according to the peer itself) - self.peer_timestamp: int = 0 - - # Latest timestamp in which we're synced. - # This number may decrease if a new transaction/block arrives in a timestamp smaller than it. - self.synced_timestamp: int = 0 - - # Latest data timestamp of the peer. - self.previous_timestamp: int = 0 - - # Latest deferred waiting for a reply. - self.deferred_by_key: dict[str, Deferred[Any]] = {} - - # Maximum difference between our latest timestamp and synced timestamp to consider - # that the peer is synced (in seconds). - self.sync_threshold: int = self._settings.P2P_SYNC_THRESHOLD - - # Indicate whether the sync manager has been started. - self._started: bool = False - - # Indicate whether the synchronization is enabled. - # When the sync is disabled, it will keep the last synced_timestamp. - self.is_enabled: bool = False - - # Indicate whether the synchronization is running. - self.is_running: bool = False - - # Create logger with context - self.log = logger.new(**self.protocol.get_logger_context()) - - def get_status(self): - """ Return the status of the sync. - """ - return { - 'is_enabled': self.is_enabled, - 'latest_timestamp': self.peer_timestamp, - 'synced_timestamp': self.synced_timestamp, - } - - def get_cmd_dict(self) -> dict[ProtocolMessages, Callable[[str], None]]: - """ Return a dict of messages. - """ - return { - ProtocolMessages.GET_DATA: self.handle_get_data, - ProtocolMessages.DATA: self.handle_data, - ProtocolMessages.GET_TIPS: self.handle_get_tips, - ProtocolMessages.TIPS: self.handle_tips, - ProtocolMessages.GET_NEXT: self.handle_get_next, - ProtocolMessages.NEXT: self.handle_next, - ProtocolMessages.NOT_FOUND: self.handle_not_found, - } - - def is_started(self) -> bool: - return self._started - - def start(self) -> None: - """ Start sync. - """ - if self._started: - raise Exception('NodeSyncTimestamp is already running') - self._started = True - self.next_step() - - def stop(self) -> None: - """ Stop sync. - """ - if not self._started: - raise Exception('NodeSyncTimestamp is already stopped') - self._started = False - if self.call_later_id and self.call_later_id.active(): - self.call_later_id.cancel() - for call_later in self._send_tips_call_later: - if call_later.active(): - call_later.cancel() - # XXX: force remove this connection from _all_ pending downloads - self.downloader.drop_connection(self) - - # XXX[jansegre]: maybe we should rename this to `out_of_sync` and invert the condition, would be easier to - # understand its usage on `send_tx_to_peer_if_possible` IMO - def is_synced(self) -> bool: - """ Test whether we have sent (or received) txs in storage to/from the remote peer up a certain threshold. - - When `True` we will send any new tx to the remote peer, since we're confident it can process it. When `False` - we will have to explicitly check if we have synced up to the parents of the new tx to determine if we will send - it. - - This condition is used to decide if we will send a new tx to that peer, but this isn't the only requirement. - See the `send_tx_to_peer_if_possible` method for the exact process and to understand why this condition has to - be this way. - """ - return self.manager.tx_storage.latest_timestamp - self.synced_timestamp <= self.sync_threshold - - def is_errored(self) -> bool: - # XXX: this sync manager does not have an error state, this method exists for API parity with sync-v2 - return False - - def send_tx_to_peer_if_possible(self, tx: BaseTransaction) -> None: - if not self.is_enabled: - return - if self.peer_timestamp is None: - return - if self.synced_timestamp is None: - return - - if not self.is_synced(): - # When a peer has not synced yet, we just propagate the transactions whose - # parents' timestamps are below synced_timestamp, i.e., we know that the peer - # has all the parents. - for parent_hash in tx.parents: - parent = self.protocol.node.tx_storage.get_transaction(parent_hash) - if parent.timestamp > self.synced_timestamp: - return - - self.send_data(tx) - - def get_peer_next(self, timestamp: Optional[int] = None, offset: int = 0) -> Deferred[NextPayload]: - """ A helper that returns a deferred that is called when the peer replies. - - :param timestamp: Timestamp of the GET-NEXT message - :type timestamp: int - - :rtype: Deferred - """ - key = 'next' - if self.deferred_by_key.get(key, None) is not None: - raise Exception('latest_deferred is not None') - self.send_get_next(timestamp, offset) - deferred: Deferred[NextPayload] = Deferred() - self.deferred_by_key[key] = deferred - return deferred - - def get_peer_tips(self, timestamp: Optional[int] = None, include_hashes: bool = False, - offset: int = 0) -> Deferred[TipsPayload]: - """ A helper that returns a deferred that is called when the peer replies. - - :param timestamp: Timestamp of the GET-TIPS message - :type timestamp: int - - :param include_hashes: Indicates whether the tx/blk hashes should be included - :type include_hashes: bool - - :rtype: Deferred - """ - key = 'tips' - if self.deferred_by_key.get(key, None) is not None: - raise Exception('latest_deferred is not None') - self.send_get_tips(timestamp, include_hashes, offset) - deferred: Deferred[TipsPayload] = Deferred() - self.deferred_by_key[key] = deferred - return deferred - - def get_data(self, hash_bytes: bytes) -> Deferred: - """ A helper that returns a deferred that is called when the peer replies. - - :param hash_bytes: Hash of the data to be downloaded - :type hash_bytes: bytes(hash) - - :rtype: Deferred - """ - d = self.downloader.get_tx(hash_bytes, self) - d.addCallback(self.on_tx_success) - d.addErrback(self.on_get_data_failed, hash_bytes) - return d - - def request_data(self, hash_bytes: bytes) -> Deferred[BaseTransaction]: - key = self.get_data_key(hash_bytes) - if self.deferred_by_key.get(key, None) is not None: - raise Exception('latest_deferred is not None') - self.send_get_data(hash_bytes.hex()) - deferred: Deferred[BaseTransaction] = Deferred() - self.deferred_by_key[key] = deferred - # In case the deferred fails we just remove it from the dictionary - deferred.addErrback(self.remove_deferred, hash_bytes) - return deferred - - @inlineCallbacks - def sync_from_timestamp(self, next_timestamp: int) -> Generator[Deferred, Any, None]: - """ Download all unknown hashes until synced timestamp reaches `timestamp`. - It assumes that we're synced in all timestamps smaller than `next_timestamp`. - - :param next_timestamp: Timestamp to start the sync - """ - self.log.debug('sync start', ts=next_timestamp) - assert next_timestamp < inf - pending: WeakSet[Deferred] = WeakSet() - next_offset = 0 - while True: - payload: NextPayload = (yield self.get_peer_next(next_timestamp, offset=next_offset)) - self.log.debug('next payload', ts=payload.timestamp, next_ts=payload.next_timestamp, - next_offset=payload.next_offset, hashes=len(payload.hashes)) - count = 0 - for h in payload.hashes: - if not self.manager.tx_storage.transaction_exists(h): - pending.add(self.get_data(h)) - count += 1 - self.log.debug('...', next_ts=next_timestamp, count=count, pending=len(pending)) - if next_timestamp != payload.next_timestamp and count == 0: - break - next_timestamp = payload.next_timestamp - next_offset = payload.next_offset - if next_timestamp == inf: - break - if next_timestamp > self.peer_timestamp: - break - for deferred in pending: - yield deferred - - @inlineCallbacks - def find_synced_timestamp(self) -> Generator[Deferred, Any, Optional[int]]: - """ Search for the highest timestamp in which we are synced. - - It uses an exponential search followed by a binary search. - """ - self.log.debug('find synced timestamp') - tips: TipsPayload = (yield self.get_peer_tips()) - if self.peer_timestamp: - # Peer's timestamp cannot go backwards. - assert tips.timestamp >= self.peer_timestamp, '{} < {}'.format(tips.timestamp, self.peer_timestamp) - self.peer_timestamp = tips.timestamp - - # Assumption: Both exponential search and binary search are safe to run even when new - # items are arriving in the network. - - # Exponential search to find an interval. - # Maximum of ceil(log(k)), where k is the number of items between the new one and the latest item. - prev_cur = None - cur = self.peer_timestamp - local_merkle_tree, _ = self.manager.tx_storage.get_merkle_tree(cur) - step = 1 - while tips.merkle_tree != local_merkle_tree: - if cur <= self.manager.tx_storage.first_timestamp: - raise Exception( - 'We cannot go before genesis. Peer is probably running with wrong configuration or database.' - ) - prev_cur = cur - assert self.manager.tx_storage.first_timestamp > 0 - cur = max(cur - step, self.manager.tx_storage.first_timestamp) - tips = (yield self.get_peer_tips(cur)) - local_merkle_tree, _ = self.manager.tx_storage.get_merkle_tree(cur) - step *= 2 - - # Here, both nodes are synced at timestamp `cur` and not synced at timestamp `prev_cur`. - if prev_cur is None: - self.synced_timestamp = cur - return None - - # Binary search to find inside the interval. - # Maximum of ceil(log(k)) - 1, where k is the number of items between the new one and the latest item. - # During the binary search, we are synced at `low` and not synced at `high`. - low = cur - high = prev_cur - while high - low > 1: - mid = (low + high + 1) // 2 - tips = (yield self.get_peer_tips(mid)) - local_merkle_tree, _ = self.manager.tx_storage.get_merkle_tree(mid) - if tips.merkle_tree == local_merkle_tree: - low = mid - else: - high = mid - - # Synced timestamp found. - self.synced_timestamp = low - assert self.synced_timestamp <= self.peer_timestamp - - if low == high: - assert low == tips.timestamp - return None - - assert low + 1 == high - self.log.debug('synced', latest_ts=self.peer_timestamp, synced_at=self.synced_timestamp) - return self.synced_timestamp + 1 - - @inlineCallbacks - def _next_step(self) -> Generator[Deferred, Any, None]: - """ Run the next step to keep nodes synced. - """ - if not self.is_enabled: - self.log.debug('sync is disabled') - return - if not self.is_running or not self._started: - self.log.debug('already stopped') - return - next_timestamp: int = (yield self.find_synced_timestamp()) - self.log.debug('_next_step', next_timestamp=next_timestamp) - if next_timestamp is None: - return - yield self.sync_from_timestamp(next_timestamp) - - @inlineCallbacks - def next_step(self) -> Generator[Deferred, Any, None]: - """ Execute next step and schedule next execution. - """ - if self.is_running: - # Already running... - self.log.debug('already running') - return - - if not self.is_enabled: - self.log.debug('sync is disabled') - self.schedule_next_step_call() - return - - try: - self.is_running = True - yield self._next_step() - except Exception: - self.log.warn('_next_step error', exc_info=True) - raise - else: - self.schedule_next_step_call() - finally: - self.is_running = False - - def schedule_next_step_call(self) -> None: - """Schedule `next_step()` call.""" - if self.call_later_id and self.call_later_id.active(): - self.call_later_id.cancel() - self.call_later_id = self.reactor.callLater(self.call_later_interval, self.next_step) - - def send_message(self, cmd: ProtocolMessages, payload: Optional[str] = None) -> None: - """ Helper to send a message. - """ - assert self.protocol.state is not None - self.protocol.state.send_message(cmd, payload) - - def send_get_next(self, timestamp: Optional[int], offset: int = 0) -> None: - """ Send a GET-NEXT message. - """ - # XXX: is `timestamp = None` actually valid? - payload = json_dumps(dict( - timestamp=timestamp, - offset=offset, - )) - self.send_message(ProtocolMessages.GET_NEXT, payload) - - def handle_get_next(self, payload: str) -> None: - """ Handle a received GET-NEXT message. - """ - data = json_loads(payload) - args = GetNextPayload(**data) - self.send_next(args.timestamp, args.offset) - - def send_next(self, timestamp: int, offset: int = 0) -> None: - """ Send a NEXT message. - """ - from hathor.indexes.timestamp_index import RangeIdx - count = self.MAX_HASHES - - assert self.manager.tx_storage.indexes is not None - from_idx = RangeIdx(timestamp, offset) - hashes, next_idx = self.manager.tx_storage.indexes.sorted_all.get_hashes_and_next_idx(from_idx, count) - if next_idx is None: - # this means we've reached the end and there's nothing else to sync - next_timestamp, next_offset = inf, 0 - else: - next_timestamp, next_offset = next_idx - - data = { - 'timestamp': timestamp, - 'next_timestamp': next_timestamp, - 'next_offset': next_offset, - 'hashes': [i.hex() for i in hashes], - } - self.send_message(ProtocolMessages.NEXT, json_dumps(data)) - - def handle_next(self, payload: str) -> None: - """ Handle a received NEXT messages. - """ - data = json_loads(payload) - data['hashes'] = [bytes.fromhex(h) for h in data['hashes']] - args = NextPayload(**data) - - key = 'next' - deferred = self.deferred_by_key.pop(key, None) - if deferred: - deferred.callback(args) - - def send_get_tips(self, timestamp: Optional[int] = None, include_hashes: bool = False, offset: int = 0) -> None: - """ Send a GET-TIPS message. - """ - if timestamp is None: - self.send_message(ProtocolMessages.GET_TIPS) - else: - payload = json_dumps(dict( - timestamp=timestamp, - include_hashes=include_hashes, - offset=offset, - )) - self.send_message(ProtocolMessages.GET_TIPS, payload) - - def handle_get_tips(self, payload: str) -> None: - """ Handle a received GET-TIPS message. - """ - if not payload: - self.send_tips() - else: - data = json_loads(payload) - args = GetTipsPayload(**data) - self.send_tips(args.timestamp, args.include_hashes, args.offset) - - def send_tips(self, timestamp: Optional[int] = None, include_hashes: bool = False, offset: int = 0) -> None: - """Try to send a TIPS message. If rate limit has been reached, it schedules to send it later.""" - - # Filter for active delayed calls once one is executing - self._send_tips_call_later = [ - call_later - for call_later in self._send_tips_call_later - if call_later.active() - ] - - if not self.global_rate_limiter.add_hit(self.GlobalRateLimiter.SEND_TIPS): - self.log.debug('send_tips throttled') - if len(self._send_tips_call_later) >= self._settings.MAX_GET_TIPS_DELAYED_CALLS: - self.protocol.send_error_and_close_connection( - 'Too many GET_TIPS message' - ) - return - self._send_tips_call_later.append( - self.reactor.callLater( - 1, self.send_tips, timestamp, include_hashes, offset - ) - ) - return - - self._send_tips(timestamp, include_hashes, offset) - - def _send_tips(self, timestamp: Optional[int] = None, include_hashes: bool = False, offset: int = 0) -> None: - """ Send a TIPS message. - """ - if timestamp is None: - timestamp = self.manager.tx_storage.latest_timestamp - - # All tips - # intervals = self.manager.tx_storage.get_all_tips(timestamp) - # if len(intervals) == 0: - # raise Exception('No tips for timestamp {}'.format(timestamp)) - - # Calculate list of hashes to be sent - merkle_tree, hashes = self.manager.tx_storage.get_merkle_tree(timestamp) - has_more = False - - if not include_hashes: - hashes = [] - else: - hashes = hashes[offset:] - if len(hashes) > self.MAX_HASHES: - hashes = hashes[:self.MAX_HASHES] - has_more = True - - data = { - 'length': 0, # len(intervals), - 'timestamp': timestamp, - 'merkle_tree': merkle_tree.hex(), - 'hashes': [h.hex() for h in hashes], - 'has_more': has_more, - } - - self.send_message(ProtocolMessages.TIPS, json_dumps(data)) - - def handle_tips(self, payload: str) -> None: - """ Handle a received TIPS messages. - """ - data = json_loads(payload) - data['merkle_tree'] = bytes.fromhex(data['merkle_tree']) - data['hashes'] = [bytes.fromhex(h) for h in data['hashes']] - args = TipsPayload(**data) - - key = 'tips' - deferred = self.deferred_by_key.pop(key, None) - if deferred: - deferred.callback(args) - - def send_get_data(self, hash_hex: str) -> None: - """ Send a GET-DATA message, requesting the data of a given hash. - """ - self.send_message(ProtocolMessages.GET_DATA, hash_hex) - - def handle_get_data(self, payload: str) -> None: - """ Handle a received GET-DATA message. - """ - hash_hex = payload - # self.log.debug('handle_get_data', payload=hash_hex) - try: - tx = self.protocol.node.tx_storage.get_transaction(bytes.fromhex(hash_hex)) - self.send_data(tx) - except TransactionDoesNotExist: - # In case the tx does not exist we send a NOT-FOUND message - self.send_message(ProtocolMessages.NOT_FOUND, hash_hex) - - def handle_not_found(self, payload: str) -> None: - """ Handle a received NOT-FOUND message. - """ - hash_hex = payload - # We ask for the downloader to retry the request - self.downloader.retry(bytes.fromhex(hash_hex)) - - def send_data(self, tx: BaseTransaction) -> None: - """ Send a DATA message. - """ - self.log.debug('send tx', tx=tx.hash_hex) - payload = base64.b64encode(tx.get_struct()).decode('ascii') - self.send_message(ProtocolMessages.DATA, payload) - - def handle_data(self, payload: str) -> None: - """ Handle a received DATA message. - """ - if not payload: - return - data = base64.b64decode(payload) - - try: - tx = self.vertex_parser.deserialize(data) - except struct.error: - # Invalid data for tx decode - return - - assert tx is not None - - self.log.debug('tx received from peer', tx=tx.hash_hex, peer=self.protocol.get_peer_id()) - - if self.protocol.node.tx_storage.get_genesis(tx.hash): - # We just got the data of a genesis tx/block. What should we do? - # Will it reduce peer reputation score? - return - tx.storage = self.protocol.node.tx_storage - - key = self.get_data_key(tx.hash) - deferred = self.deferred_by_key.pop(key, None) - if deferred: - # Adding to the DAG will be done after the downloader validates the correct order - assert tx.timestamp is not None - self.requested_data_arrived(tx.timestamp) - deferred.callback(tx) - elif self.manager.tx_storage.transaction_exists(tx.hash): - # transaction already added to the storage, ignore it - # XXX: maybe we could add a hash blacklist and punish peers propagating known bad txs - self.manager.tx_storage.compare_bytes_with_local_tx(tx) - return - else: - self.log.info('tx received in real time from peer', tx=tx.hash_hex, peer=self.protocol.get_peer_id()) - # If we have not requested the data, it is a new transaction being propagated - # in the network, thus, we propagate it as well. - success = self.manager.vertex_handler.on_new_vertex(tx) - if success: - self.protocol.connections.send_tx_to_peers(tx) - self.update_received_stats(tx, success) - - def update_received_stats(self, tx: 'BaseTransaction', result: bool) -> None: - """ Update protocol metrics when receiving a new tx - """ - # Update statistics. - if result: - if tx.is_block: - self.protocol.metrics.received_blocks += 1 - else: - self.protocol.metrics.received_txs += 1 - else: - if tx.is_block: - self.protocol.metrics.discarded_blocks += 1 - else: - self.protocol.metrics.discarded_txs += 1 - - def requested_data_arrived(self, timestamp: int) -> None: - """ Update synced timestamp when a requested data arrives - """ - if timestamp - 1 > self.synced_timestamp: - self.synced_timestamp = timestamp - 1 - - def get_data_key(self, hash_bytes: bytes) -> str: - """ Return data key corresponding a tx to be used in the deferred dict - """ - key = 'get-data-{}'.format(hash_bytes.hex()) - return key - - def remove_deferred(self, reason: 'Failure', hash_bytes: bytes) -> None: - """ Remove the deferred from the deferred_by_key - Used when a requested tx deferred fails for some reason (not found, or timeout) - """ - key = self.get_data_key(hash_bytes) - self.deferred_by_key.pop(key, None) - - def on_tx_success(self, tx: 'BaseTransaction') -> 'BaseTransaction': - """ Callback for the deferred when we add a new tx to the DAG - """ - # When we have multiple callbacks in a deferred - # the parameter of the second callback is the return of the first - # so I need to return the same tx to guarantee that all peers will receive it - if tx: - if self.manager.tx_storage.transaction_exists(tx.hash): - self.manager.tx_storage.compare_bytes_with_local_tx(tx) - success = True - else: - # Add tx to the DAG. - success = self.manager.vertex_handler.on_new_vertex(tx) - if success: - self.protocol.connections.send_tx_to_peers(tx) - # Updating stats data - self.update_received_stats(tx, success) - return tx - - def on_get_data_failed(self, failure: 'Failure', hash_bytes: bytes) -> None: - """ Method called when get_data deferred fails. - We need this errback because otherwise the sync crashes when the deferred is canceled. - We should just log a warning because it will continue the sync and will try to get this tx again. - """ - log_func = self.log.debug if isinstance(failure.value, CancelledError) else self.log.warn - log_func('failed to download tx', tx=hash_bytes.hex(), reason=failure) - - def is_sync_enabled(self) -> bool: - """Return True if sync is enabled for this connection.""" - return self.is_enabled - - def enable_sync(self) -> None: - """Enable sync for this connection.""" - self.is_enabled = True - - def disable_sync(self) -> None: - """Disable sync for this connection.""" - self.is_enabled = False diff --git a/hathor/p2p/sync_v1/downloader.py b/hathor/p2p/sync_v1/downloader.py deleted file mode 100644 index d8b3c12cf..000000000 --- a/hathor/p2p/sync_v1/downloader.py +++ /dev/null @@ -1,334 +0,0 @@ -# Copyright 2021 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 collections import deque -from functools import partial -from typing import TYPE_CHECKING, Any, Optional - -from structlog import get_logger -from twisted.internet import defer -from twisted.internet.defer import Deferred -from twisted.python.failure import Failure - -from hathor.conf.get_settings import get_global_settings -from hathor.transaction.storage.exceptions import TransactionDoesNotExist - -if TYPE_CHECKING: - from hathor.manager import HathorManager - from hathor.p2p.sync_v1.agent import NodeSyncTimestamp - from hathor.transaction import BaseTransaction - -logger = get_logger() - - -class TxDetails: - # Hash of the transaction. - tx_id: bytes - - # This will be resolved after the transactions has been added to - # the DAG. - deferred: Deferred - - # List of connections that requested this transaction. - connections: list['NodeSyncTimestamp'] - - # This will be resolved after the transaction has been downloaded, - # but not necessarily added to the DAG. - downloading_deferred: Optional[Deferred] - - # Index of the list of connections that requested the data - # Useful when we need to retry the request and want to select a new connection - requested_index: int - - def __init__(self, tx_id: bytes, deferred: Deferred, connections: list['NodeSyncTimestamp']): - self._settings = get_global_settings() - self.log = logger.new() - self.tx_id = tx_id - self.deferred = deferred - self.connections = connections - self.downloading_deferred = None - self.requested_index = 0 - self.retry_count = 0 - - def drop_connection(self, connection: 'NodeSyncTimestamp') -> bool: - """Called by the downloader to remove a connection from the tx_details connections, returns a bool. - - It will return True if after the drop there are no more viable connections to download the tx from, which means - the _remove_pending_tx should be called for this tx, returns False otherwise.""" - try: - connection_index = self.connections.index(connection) - except ValueError: - return False - if self.requested_index > connection_index: - self.requested_index -= 1 - self.connections.pop(connection_index) - if not self.has_available_connection(): - if self.downloading_deferred is not None: - self.log.debug('cancel downloading deferred', tx=self.tx_id.hex()) - self.downloading_deferred.cancel() - self.downloading_deferred = None - return True - return False - - def has_available_connection(self) -> bool: - """ Whether there is any valid connection which the tx can be downloaded from.""" - for conn in self.connections: - if not conn.protocol.aborting: - return True - return False - - def get_connection(self) -> Optional['NodeSyncTimestamp']: - """ Get a connection to start the download for this tx detail - - We start from the first connection because it's the first one that requested - so it's supposed to be the one with lowest rtt that is available this time - - We tried to do a random choice but it was getting too slow because sometimes - we were choosing a peer that is far - - We use the requested_index to get the next connection, in case of a retry - """ - connection = None - while connection is None: - if len(self.connections) <= self.requested_index: - # We don't have more connections available - break - - connection = self.connections[self.requested_index] - self.retry_count += 1 - - # only try next peer if we reach max retries on the current one - if self.retry_count >= self._settings.GET_DATA_RETRIES: - self.requested_index += 1 - self.retry_count = 0 - - if connection.protocol.aborting: - # Connection was already closed, so try the next one - connection = None - - return connection - - -class Downloader: - """ It manages the download of all transactions from peers. It is used to do - several optimizations instead of downloading the same transactions multiple times, - one from each peer. - - TODO: Should we have a flag to sync only the best blockchain? Or to sync the - best blockchain first? - """ - - # All transactions that must be downloaded. - pending_transactions: dict[bytes, TxDetails] - - # Transactions waiting to be downloaded. - waiting_deque: deque[bytes] - - # Transactions that are being downloaded. - downloading_deque: deque[bytes] - - # Transactions that have been downloaded but are not ready to be - # added to the DAG. - downloading_buffer: dict[bytes, 'BaseTransaction'] - - # Size of the sliding window used to download transactions. - window_size: int - - def __init__(self, manager: 'HathorManager', window_size: int = 100): - self._settings = get_global_settings() - self.log = logger.new() - self.manager = manager - - self.pending_transactions = {} - self.waiting_deque = deque() - self.downloading_deque = deque() - self.downloading_buffer = {} - self.window_size = window_size - - def drop_connection(self, connection: 'NodeSyncTimestamp') -> None: - """ Called when a peer is disconnected to remove that connection from all the affected pending transactions.""" - to_remove: list[bytes] = [] - for tx_details in self.pending_transactions.values(): - if tx_details.drop_connection(connection): - to_remove.append(tx_details.tx_id) - for tx_id in to_remove: - self._remove_pending_tx(tx_id) - - def get_tx(self, tx_id: bytes, connection: 'NodeSyncTimestamp') -> Deferred: - """ Add a transaction to be downloaded and add to the DAG. - """ - try: - # If I already have this tx in the storage just return a defer already success - # In the node_sync code we already handle this case but in a race condition situation - # we might get here but it's not common - tx = self.manager.tx_storage.get_transaction(tx_id) - self.log.debug('requesting to download a tx that is already in the storage', tx=tx_id.hex()) - return defer.succeed(tx) - except TransactionDoesNotExist: - # This tx does not exist in our storage - details = self.pending_transactions.get(tx_id, None) - if details is not None: - # Some peer already requested this tx and is waiting for the download to finish - # so we just return the same deferred that will be resolved to all of them - details.connections.append(connection) - return details.deferred - - # Creating a new deferred to handle the download of this tx - deferred: Deferred = Deferred() - details = TxDetails(tx_id, deferred, [connection]) - self.pending_transactions[tx_id] = details - self.waiting_deque.append(tx_id) - self.download_next_if_possible() - return details.deferred - - def download_next_if_possible(self) -> None: - """ Start as many downloads as the number of available slots in the sliding window. - """ - while self.waiting_deque and len(self.downloading_deque) < self.window_size: - self.start_next_download() - - def start_next_download(self) -> None: - """ Start the next download from the waiting queue. - The tx_id is moved from the waiting queue to the downloading queue. - """ - tx_id = self.waiting_deque.popleft() - - details = self.pending_transactions[tx_id] - connection = details.get_connection() - - if connection is None: - self._remove_pending_tx(tx_id) - else: - # Setting downloading deferred - self.add_get_downloading_deferred(tx_id, details, connection) - - # Adding to download deque - self.downloading_deque.append(tx_id) - - def add_get_downloading_deferred(self, tx_id: bytes, details: TxDetails, connection: 'NodeSyncTimestamp') -> None: - """ Getting a downloading deferred when requesting data from a connection - """ - self.log.debug('requesting tx to peer', tx=tx_id.hex(), peer=connection.protocol.get_peer_id()) - assert details.downloading_deferred is None - details.downloading_deferred = connection.request_data(tx_id) - details.downloading_deferred.addCallback(self.on_new_tx) - details.downloading_deferred.addErrback(self.on_error) - - # Adding timeout to callback - fn_timeout = partial(self.on_deferred_timeout, tx_id=tx_id) - details.downloading_deferred.addTimeout( - self._settings.GET_DATA_TIMEOUT, - connection.reactor, - onTimeoutCancel=fn_timeout - ) - - def on_deferred_timeout(self, result: Any, timeout: int, *, tx_id: bytes) -> None: - """ Timeout handler for the downloading deferred - It just calls the retry method - """ - self.retry(tx_id) - - def on_error(self, failure: Failure) -> None: - """ Errback for downloading deferred. - """ - self.log.error('failed to download tx', err=failure, traceback=failure.getTraceback()) - - def on_new_tx(self, tx: 'BaseTransaction') -> None: - """ This is called when a new transaction arrives. - """ - self.log.debug('new tx/block', tx=tx.hash_hex) - - details = self.pending_transactions.get(tx.hash, None) - if not details: - # Something is wrong! It should never happen. - self.log.warn('new tx/block arrived but tx detail does not exist', tx=tx.hash_hex) - return - - assert len(self.downloading_deque) > 0 - self.downloading_buffer[tx.hash] = tx - self.check_downloading_queue() - - def check_downloading_queue(self) -> None: - """ Check whether the transactions of the downloading queue - have already been downloaded. Those that were are added to the DAG. - - downloading_deque is a list of transactions that are being downloaded - downloading_buffer is a dict with transactions already downloaded - - We need to add to the DAG in the same order as the downloading_deque - so we iterate in this order and add to the DAG if it the download was already done - """ - count = 0 - while self.downloading_deque: - tx_id = self.downloading_deque[0] - tx = self.downloading_buffer.pop(tx_id, None) - if not tx: - # If we still don't have this tx in the downloading_buffer - # means that we need to wait until its download is finished to add to the DAG - break - - self.downloading_deque.popleft() - count += 1 - - # Run the deferred. - details = self.pending_transactions.pop(tx_id) - details.deferred.callback(tx) - - if count > 0: - self.download_next_if_possible() - - def retry(self, tx_id: bytes) -> None: - """ Retry a failed download - It will try up to settings.GET_DATA_RETRIES per connection - """ - self.log.warn('retry tx', tx=tx_id.hex()) - - details = self.pending_transactions.get(tx_id, None) - - if details is None: - self.log.error('nothing to retry', tx=tx_id.hex()) - # XXX: Nothing to retry but should never enter here - # Maybe a race condition in which the timeout has triggered and the tx has arrived. - return - - # Failing old downloading deferred - if details.downloading_deferred: - details.downloading_deferred.cancel() - details.downloading_deferred = None - - # Get new connection - new_connection = details.get_connection() - - if new_connection is None: - self._remove_pending_tx(tx_id) - return - - # Start new download - self.add_get_downloading_deferred(tx_id, details, new_connection) - - def _remove_pending_tx(self, tx_id: bytes) -> None: - """ Cancel tx deferred and remove it from the pending dict and download deque - """ - self.log.warn('no new connections available to download the tx from', tx=tx_id.hex()) - # remove this tx_id from pending_transactions and cancel the deferred - details = self.pending_transactions.pop(tx_id) - details.deferred.cancel() - - # also remove from downloading queue - if tx_id in self.downloading_deque: - self.downloading_deque.remove(tx_id) - - # also remove from waiting queue - if tx_id in self.waiting_deque: - self.waiting_deque.remove(tx_id) diff --git a/hathor/p2p/sync_v1/factory.py b/hathor/p2p/sync_v1/factory.py deleted file mode 100644 index 2a205d728..000000000 --- a/hathor/p2p/sync_v1/factory.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2021 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 typing import TYPE_CHECKING, Optional - -from hathor.p2p.manager import ConnectionsManager -from hathor.p2p.sync_agent import SyncAgent -from hathor.p2p.sync_factory import SyncAgentFactory -from hathor.p2p.sync_v1.agent import NodeSyncTimestamp -from hathor.p2p.sync_v1.downloader import Downloader -from hathor.reactor import ReactorProtocol as Reactor -from hathor.transaction.vertex_parser import VertexParser - -if TYPE_CHECKING: - from hathor.p2p.protocol import HathorProtocol - - -class SyncV11Factory(SyncAgentFactory): - def __init__(self, connections: ConnectionsManager, *, vertex_parser: VertexParser): - self.connections = connections - self.vertex_parser = vertex_parser - self._downloader: Optional[Downloader] = None - - def get_downloader(self) -> Downloader: - if self._downloader is None: - assert self.connections.manager is not None - self._downloader = Downloader(self.connections.manager) - return self._downloader - - def create_sync_agent(self, protocol: 'HathorProtocol', reactor: Reactor) -> SyncAgent: - return NodeSyncTimestamp( - protocol, - downloader=self.get_downloader(), - reactor=reactor, - vertex_parser=self.vertex_parser - ) diff --git a/hathor/simulator/simulator.py b/hathor/simulator/simulator.py index a31862909..c776b7da7 100644 --- a/hathor/simulator/simulator.py +++ b/hathor/simulator/simulator.py @@ -82,7 +82,6 @@ def get_default_builder(self) -> Builder: .set_peer(PrivatePeer.auto_generated()) \ .set_soft_voided_tx_ids(set()) \ .enable_full_verification() \ - .enable_sync_v1() \ .enable_sync_v2() \ .use_memory() \ .set_settings(self.settings) diff --git a/tests/cli/test_multisig_signature.py b/tests/cli/test_multisig_signature.py index 9fb802b0a..46b8051e0 100644 --- a/tests/cli/test_multisig_signature.py +++ b/tests/cli/test_multisig_signature.py @@ -15,9 +15,7 @@ from tests.utils import add_blocks_unlock_reward, add_new_transactions -class BaseSignatureTest(unittest.TestCase): - __test__ = False - +class SignatureTest(unittest.TestCase): def setUp(self): super().setUp() @@ -61,16 +59,3 @@ def test_generate_signature(self): data_to_sign = tx.get_sighash_all() hashed_data = hashlib.sha256(data_to_sign).digest() self.assertIsNone(public_key.verify(signature, hashed_data, ec.ECDSA(hashes.SHA256()))) - - -class SyncV1SignatureTest(unittest.SyncV1Params, BaseSignatureTest): - __test__ = True - - -class SyncV2SignatureTest(unittest.SyncV2Params, BaseSignatureTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeSignatureTest(unittest.SyncBridgeParams, SyncV2SignatureTest): - pass diff --git a/tests/cli/test_multisig_spend.py b/tests/cli/test_multisig_spend.py index 9a152fdad..7b427ed78 100644 --- a/tests/cli/test_multisig_spend.py +++ b/tests/cli/test_multisig_spend.py @@ -14,9 +14,7 @@ from tests.utils import add_blocks_unlock_reward -class BaseMultiSigSpendTest(unittest.TestCase): - __test__ = False - +class MultiSigSpendTest(unittest.TestCase): def setUp(self): super().setUp() @@ -121,16 +119,3 @@ def test_spend_multisig(self): tx = Transaction.create_from_struct(bytes.fromhex(tx_raw)) self.assertTrue(self.manager.propagate_tx(tx, False)) - - -class SyncV1MultiSigSpendTest(unittest.SyncV1Params, BaseMultiSigSpendTest): - __test__ = True - - -class SyncV2MultiSigSpendTest(unittest.SyncV2Params, BaseMultiSigSpendTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeMultiSigSpendTest(unittest.SyncBridgeParams, SyncV2MultiSigSpendTest): - pass diff --git a/tests/cli/test_twin_tx.py b/tests/cli/test_twin_tx.py index 0ae5ee723..1696c2625 100644 --- a/tests/cli/test_twin_tx.py +++ b/tests/cli/test_twin_tx.py @@ -19,9 +19,7 @@ ) -class BaseTwinTxTest(unittest.TestCase): - __test__ = False - +class TwinTxTest(unittest.TestCase): def setUp(self): super().setUp() @@ -167,16 +165,3 @@ def test_parameter_error(self): output = f.getvalue().strip().splitlines() self.assertEqual('The command expects raw_tx or hash and url as parameters', output[0]) - - -class SyncV1TwinTxTest(unittest.SyncV1Params, BaseTwinTxTest): - __test__ = True - - -class SyncV2TwinTxTest(unittest.SyncV2Params, BaseTwinTxTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeTwinTxTest(unittest.SyncBridgeParams, SyncV2TwinTxTest): - pass diff --git a/tests/consensus/test_consensus.py b/tests/consensus/test_consensus.py index 7a4eef49d..db68ace72 100644 --- a/tests/consensus/test_consensus.py +++ b/tests/consensus/test_consensus.py @@ -8,9 +8,7 @@ from tests.utils import add_blocks_unlock_reward, add_new_double_spending, add_new_transactions -class BaseConsensusTestCase(unittest.TestCase): - __test__ = False - +class ConsensusTestCase(unittest.TestCase): def setUp(self) -> None: super().setUp() self.tx_storage = TransactionMemoryStorage(settings=self._settings) @@ -269,16 +267,3 @@ def test_dont_revert_block_high_weight_verify_both(self) -> None: self.assertIsNone(meta.voided_by) self.assertConsensusValid(manager) - - -class SyncV1ConsensusTestCase(unittest.SyncV1Params, BaseConsensusTestCase): - __test__ = True - - -class SyncV2ConsensusTestCase(unittest.SyncV2Params, BaseConsensusTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeConsensusTestCase(unittest.SyncBridgeParams, SyncV2ConsensusTestCase): - pass diff --git a/tests/consensus/test_consensus2.py b/tests/consensus/test_consensus2.py index da40a5703..82fa9be60 100644 --- a/tests/consensus/test_consensus2.py +++ b/tests/consensus/test_consensus2.py @@ -3,12 +3,11 @@ from hathor.simulator.utils import gen_new_tx from hathor.transaction import Transaction from hathor.util import not_none -from tests import unittest from tests.simulation.base import SimulatorTestCase from tests.utils import add_custom_tx -class BaseConsensusSimulatorTestCase(SimulatorTestCase): +class ConsensusSimulatorTestCase(SimulatorTestCase): def checkConflict(self, tx1: Transaction, tx2: Transaction) -> None: meta1 = tx1.get_metadata() meta2 = tx2.get_metadata() @@ -130,16 +129,3 @@ def test_two_conflicts_intertwined_multiple_times(self) -> None: # Uncomment lines below to visualize the DAG and the blockchain. # dot = self.graphviz.dot() # dot.render('dot0') - - -class SyncV1ConsensusSimulatorTestCase(unittest.SyncV1Params, BaseConsensusSimulatorTestCase): - __test__ = True - - -class SyncV2ConsensusSimulatorTestCase(unittest.SyncV2Params, BaseConsensusSimulatorTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeConsensusSimulatorTestCase(unittest.SyncBridgeParams, SyncV2ConsensusSimulatorTestCase): - __test__ = True diff --git a/tests/consensus/test_consensus3.py b/tests/consensus/test_consensus3.py index dad7ca70b..8990b5967 100644 --- a/tests/consensus/test_consensus3.py +++ b/tests/consensus/test_consensus3.py @@ -10,7 +10,7 @@ def setUp(self) -> None: super().setUp() self.network = 'testnet' - self.manager1 = self.create_peer(self.network, unlock_wallet=True, enable_sync_v1=True, enable_sync_v2=False) + self.manager1 = self.create_peer(self.network, unlock_wallet=True) @pytest.mark.xfail(strict=True) def test_double_spending_attempt_1(self) -> None: diff --git a/tests/consensus/test_consensus4.py b/tests/consensus/test_consensus4.py index 906a82b10..46097857d 100644 --- a/tests/consensus/test_consensus4.py +++ b/tests/consensus/test_consensus4.py @@ -2,13 +2,11 @@ from hathor.manager import HathorManager from hathor.transaction import Block from hathor.types import VertexId -from tests import unittest from tests.simulation.base import SimulatorTestCase from tests.utils import gen_custom_tx -class BaseConsensusSimulatorTestCase(SimulatorTestCase): - +class ConsensusSimulatorTestCase(SimulatorTestCase): def create_chain( self, manager: HathorManager, @@ -82,16 +80,3 @@ def test_conflict_with_parent_tx(self) -> None: # Uncomment lines below to visualize the DAG and the blockchain. # dot = self.graphviz.dot() # dot.render('dot0') - - -class SyncV1ConsensusSimulatorTestCase(unittest.SyncV1Params, BaseConsensusSimulatorTestCase): - __test__ = True - - -class SyncV2ConsensusSimulatorTestCase(unittest.SyncV2Params, BaseConsensusSimulatorTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeConsensusSimulatorTestCase(unittest.SyncBridgeParams, SyncV2ConsensusSimulatorTestCase): - __test__ = True diff --git a/tests/consensus/test_consensus5.py b/tests/consensus/test_consensus5.py index 19feaded3..fa40dfd29 100644 --- a/tests/consensus/test_consensus5.py +++ b/tests/consensus/test_consensus5.py @@ -2,13 +2,11 @@ from hathor.manager import HathorManager from hathor.transaction import Block from hathor.types import VertexId -from tests import unittest from tests.simulation.base import SimulatorTestCase from tests.utils import gen_custom_tx -class BaseConsensusSimulatorTestCase(SimulatorTestCase): - +class ConsensusSimulatorTestCase(SimulatorTestCase): def create_chain( self, manager: HathorManager, @@ -84,16 +82,3 @@ def test_conflict_with_parent_tx(self) -> None: # Uncomment lines below to visualize the DAG and the blockchain. # dot = self.graphviz.dot() # dot.render('dot0') - - -class SyncV1ConsensusSimulatorTestCase(unittest.SyncV1Params, BaseConsensusSimulatorTestCase): - __test__ = True - - -class SyncV2ConsensusSimulatorTestCase(unittest.SyncV2Params, BaseConsensusSimulatorTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeConsensusSimulatorTestCase(unittest.SyncBridgeParams, SyncV2ConsensusSimulatorTestCase): - __test__ = True diff --git a/tests/consensus/test_first_block.py b/tests/consensus/test_first_block.py index 3544b2e7a..1b63e2555 100644 --- a/tests/consensus/test_first_block.py +++ b/tests/consensus/test_first_block.py @@ -2,9 +2,6 @@ class FirstBlockTestCase(unittest.TestCase): - _enable_sync_v1 = True - _enable_sync_v2 = True - def setUp(self) -> None: super().setUp() diff --git a/tests/consensus/test_soft_voided.py b/tests/consensus/test_soft_voided.py index fd43b0f7e..a1bc57a19 100644 --- a/tests/consensus/test_soft_voided.py +++ b/tests/consensus/test_soft_voided.py @@ -6,12 +6,11 @@ from hathor.simulator.utils import gen_new_tx from hathor.transaction import Block from hathor.types import VertexId -from tests import unittest from tests.simulation.base import SimulatorTestCase from tests.utils import add_custom_tx -class BaseSoftVoidedTestCase(SimulatorTestCase): +class SoftVoidedTestCase(SimulatorTestCase): seed_config = 5988775361793628170 def assertNoParentsAreSoftVoided(self, tx: Block) -> None: @@ -156,16 +155,3 @@ def test_soft_voided(self) -> None: ]) for _ in self._run_test(self.simulator, soft_voided_tx_ids): pass - - -class SyncV1SoftVoidedTestCase(unittest.SyncV1Params, BaseSoftVoidedTestCase): - __test__ = True - - -class SyncV2SoftVoidedTestCase(unittest.SyncV2Params, BaseSoftVoidedTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeSoftVoidedTestCase(unittest.SyncBridgeParams, SyncV2SoftVoidedTestCase): - __test__ = True diff --git a/tests/consensus/test_soft_voided2.py b/tests/consensus/test_soft_voided2.py index 116761235..70881c627 100644 --- a/tests/consensus/test_soft_voided2.py +++ b/tests/consensus/test_soft_voided2.py @@ -7,12 +7,11 @@ from hathor.transaction import Block, Transaction from hathor.types import VertexId from hathor.wallet import HDWallet -from tests import unittest from tests.simulation.base import SimulatorTestCase from tests.utils import BURN_ADDRESS, add_custom_tx -class BaseConsensusSimulatorTestCase(SimulatorTestCase): +class ConsensusSimulatorTestCase(SimulatorTestCase): seed_config = 5988775361793628169 def assertValidConflictResolution(self, tx1: Transaction, tx2: Transaction) -> None: @@ -209,16 +208,3 @@ def test_soft_voided(self) -> None: self.assertEqual(10, len(soft_voided_tx_ids)) for _ in self._run_test(self.simulator, soft_voided_tx_ids): pass - - -class SyncV1ConsensusSimulatorTestCase(unittest.SyncV1Params, BaseConsensusSimulatorTestCase): - __test__ = True - - -class SyncV2ConsensusSimulatorTestCase(unittest.SyncV2Params, BaseConsensusSimulatorTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeConsensusSimulatorTestCase(unittest.SyncBridgeParams, SyncV2ConsensusSimulatorTestCase): - __test__ = True diff --git a/tests/consensus/test_soft_voided3.py b/tests/consensus/test_soft_voided3.py index 807d6fe8c..bdb8c0a7c 100644 --- a/tests/consensus/test_soft_voided3.py +++ b/tests/consensus/test_soft_voided3.py @@ -6,12 +6,11 @@ from hathor.simulator.utils import gen_new_tx from hathor.transaction import BaseTransaction from hathor.types import VertexId -from tests import unittest from tests.simulation.base import SimulatorTestCase from tests.utils import add_custom_tx, gen_custom_tx -class BaseSoftVoidedTestCase(SimulatorTestCase): +class SoftVoidedTestCase(SimulatorTestCase): seed_config = 5988775361793628169 def assertNoParentsAreSoftVoided(self, tx: BaseTransaction) -> None: @@ -138,16 +137,3 @@ def test_soft_voided(self) -> None: ]) for _ in self._run_test(self.simulator, soft_voided_tx_ids): pass - - -class SyncV1SoftVoidedTestCase(unittest.SyncV1Params, BaseSoftVoidedTestCase): - __test__ = True - - -class SyncV2SoftVoidedTestCase(unittest.SyncV2Params, BaseSoftVoidedTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeSoftVoidedTestCase(unittest.SyncBridgeParams, SyncV2SoftVoidedTestCase): - __test__ = True diff --git a/tests/consensus/test_soft_voided4.py b/tests/consensus/test_soft_voided4.py index cb9e1db7d..f60dab477 100644 --- a/tests/consensus/test_soft_voided4.py +++ b/tests/consensus/test_soft_voided4.py @@ -6,12 +6,11 @@ from hathor.simulator.utils import gen_new_double_spending from hathor.transaction import Transaction from hathor.types import VertexId -from tests import unittest from tests.simulation.base import SimulatorTestCase from tests.utils import add_custom_tx -class BaseSoftVoidedTestCase(SimulatorTestCase): +class SoftVoidedTestCase(SimulatorTestCase): seed_config = 5988775361793628169 def _run_test( @@ -173,16 +172,3 @@ def test_soft_voided(self) -> None: ] for _ in self._run_test(self.simulator, soft_voided_tx_ids): pass - - -class SyncV1SoftVoidedTestCase(unittest.SyncV1Params, BaseSoftVoidedTestCase): - __test__ = True - - -class SyncV2SoftVoidedTestCase(unittest.SyncV2Params, BaseSoftVoidedTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeSoftVoidedTestCase(unittest.SyncBridgeParams, SyncV2SoftVoidedTestCase): - __test__ = True diff --git a/tests/dag_builder/test_dag_builter.py b/tests/dag_builder/test_dag_builter.py index b059f6e4b..6683b25cc 100644 --- a/tests/dag_builder/test_dag_builter.py +++ b/tests/dag_builder/test_dag_builter.py @@ -3,9 +3,6 @@ class DAGCreatorTestCase(unittest.TestCase): - _enable_sync_v1 = False - _enable_sync_v2 = True - def setUp(self): super().setUp() diff --git a/tests/event/test_event_manager.py b/tests/event/test_event_manager.py index 289d5b0f5..cebd50ae3 100644 --- a/tests/event/test_event_manager.py +++ b/tests/event/test_event_manager.py @@ -5,9 +5,7 @@ from tests import unittest -class BaseEventManagerTest(unittest.TestCase): - __test__ = False - +class EventManagerTest(unittest.TestCase): def setUp(self) -> None: super().setUp() self.network = 'testnet' @@ -86,16 +84,3 @@ def test_cannot_finish_group_twice(self) -> None: with self.assertRaises(AssertionError): self._fake_reorg_finished() self.run_to_completion() - - -class SyncV1EventManager(unittest.SyncV1Params, BaseEventManagerTest): - __test__ = True - - -class SyncV2EventManager(unittest.SyncV1Params, BaseEventManagerTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeEventManagerTest(unittest.SyncBridgeParams, SyncV2EventManager): - pass diff --git a/tests/event/test_event_reorg.py b/tests/event/test_event_reorg.py index 5c4a64b8c..873aeea88 100644 --- a/tests/event/test_event_reorg.py +++ b/tests/event/test_event_reorg.py @@ -5,9 +5,7 @@ from tests.utils import BURN_ADDRESS, get_genesis_key -class BaseEventReorgTest(unittest.TestCase): - __test__ = False - +class EventReorgTest(unittest.TestCase): def setUp(self) -> None: super().setUp() self.network = 'testnet' @@ -87,16 +85,3 @@ def test_reorg_events(self) -> None: for expected_data_key, expected_data_value in expected_partial_data.items(): self.assertEqual(actual_event.data.dict()[expected_data_key], expected_data_value) - - -class SyncV1EventReorgTest(unittest.SyncV1Params, BaseEventReorgTest): - __test__ = True - - -class SyncV2EventReorgTest(unittest.SyncV1Params, BaseEventReorgTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeEventReorgTest(unittest.SyncBridgeParams, SyncV2EventReorgTest): - pass diff --git a/tests/feature_activation/test_feature_simulation.py b/tests/feature_activation/test_feature_simulation.py index 30dd9c77e..b00e5f32d 100644 --- a/tests/feature_activation/test_feature_simulation.py +++ b/tests/feature_activation/test_feature_simulation.py @@ -29,13 +29,14 @@ from hathor.simulator.utils import add_new_blocks, gen_new_tx from hathor.transaction.exceptions import BlockMustSignalError from hathor.util import not_none -from tests import unittest from tests.resources.base_resource import StubSite from tests.simulation.base import SimulatorTestCase from tests.utils import HAS_ROCKSDB class BaseFeatureSimulationTest(SimulatorTestCase): + __test__ = False + def get_simulator_builder(self) -> Builder: """Return a pre-configured builder to be used in tests.""" raise NotImplementedError @@ -663,13 +664,17 @@ def test_reorg(self) -> None: assert artifacts.bit_signaling_service.get_not_support_features() == [Feature.NOP_FEATURE_1] -class BaseMemoryStorageFeatureSimulationTest(BaseFeatureSimulationTest): +class MemoryStorageFeatureSimulationTest(BaseFeatureSimulationTest): + __test__ = True + def get_simulator_builder(self) -> Builder: return self.simulator.get_default_builder() @pytest.mark.skipif(not HAS_ROCKSDB, reason='requires python-rocksdb') -class BaseRocksDBStorageFeatureSimulationTest(BaseFeatureSimulationTest): +class RocksDBStorageFeatureSimulationTest(BaseFeatureSimulationTest): + __test__ = True + def get_rocksdb_directory(self) -> str: import tempfile tmp_dir = tempfile.mkdtemp() @@ -806,32 +811,3 @@ def test_feature_from_existing_storage(self) -> None: assert get_ancestor_iteratively_mock.call_count == 0 assert artifacts2.tx_storage.get_vertices_count() == 67 calculate_new_state_mock.reset_mock() - - -class SyncV1MemoryStorageFeatureSimulationTest(unittest.SyncV1Params, BaseMemoryStorageFeatureSimulationTest): - __test__ = True - - -class SyncV2MemoryStorageFeatureSimulationTest(unittest.SyncV2Params, BaseMemoryStorageFeatureSimulationTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeMemoryStorageFeatureSimulationTest(unittest.SyncBridgeParams, BaseMemoryStorageFeatureSimulationTest): - __test__ = True - - -class SyncV1RocksDBStorageFeatureSimulationTest(unittest.SyncV1Params, BaseRocksDBStorageFeatureSimulationTest): - __test__ = True - - -class SyncV2RocksDBStorageFeatureSimulationTest(unittest.SyncV2Params, BaseRocksDBStorageFeatureSimulationTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeRocksDBStorageFeatureSimulationTest( - unittest.SyncBridgeParams, - BaseRocksDBStorageFeatureSimulationTest -): - __test__ = True diff --git a/tests/feature_activation/test_mining_simulation.py b/tests/feature_activation/test_mining_simulation.py index cf4c7a626..ff61f9328 100644 --- a/tests/feature_activation/test_mining_simulation.py +++ b/tests/feature_activation/test_mining_simulation.py @@ -29,12 +29,11 @@ from hathor.transaction.resources import GetBlockTemplateResource from hathor.transaction.util import unpack, unpack_len from hathor.util import json_loadb -from tests import unittest from tests.resources.base_resource import StubSite from tests.simulation.base import SimulatorTestCase -class BaseMiningSimulationTest(SimulatorTestCase): +class MiningSimulationTest(SimulatorTestCase): def test_signal_bits_in_mining(self) -> None: settings_dict = get_settings()._asdict() settings_dict.update( @@ -188,15 +187,3 @@ def _decode_values(values: bytes) -> Iterable[dict[str, Any]]: yield json_loadb(value) buf = new_buf - - -class SyncV1MiningSimulationTest(unittest.SyncV1Params, BaseMiningSimulationTest): - __test__ = True - - -class SyncV2MiningSimulationTest(unittest.SyncV2Params, BaseMiningSimulationTest): - __test__ = True - - -class SyncBridgeMiningSimulationTest(unittest.SyncBridgeParams, BaseMiningSimulationTest): - __test__ = True diff --git a/tests/others/test_cli_builder.py b/tests/others/test_cli_builder.py index d1a95c6e6..59818c573 100644 --- a/tests/others/test_cli_builder.py +++ b/tests/others/test_cli_builder.py @@ -109,14 +109,10 @@ def test_sync_default(self): self.assertTrue(manager.connections.is_sync_version_enabled(SyncVersion.V2)) def test_sync_bridge(self): - manager = self._build(['--memory-storage', '--x-sync-bridge']) - self.assertTrue(manager.connections.is_sync_version_enabled(SyncVersion.V1_1)) - self.assertTrue(manager.connections.is_sync_version_enabled(SyncVersion.V2)) + self._build_with_error(['--memory-storage', '--x-sync-bridge'], '--x-sync-bridge was removed') def test_sync_bridge2(self): - manager = self._build(['--memory-storage', '--sync-bridge']) - self.assertTrue(manager.connections.is_sync_version_enabled(SyncVersion.V1_1)) - self.assertTrue(manager.connections.is_sync_version_enabled(SyncVersion.V2)) + self._build_with_error(['--memory-storage', '--sync-bridge'], '--sync-bridge was removed') def test_sync_v2_only(self): manager = self._build(['--memory-storage', '--x-sync-v2-only']) @@ -129,9 +125,7 @@ def test_sync_v2_only2(self): self.assertTrue(manager.connections.is_sync_version_enabled(SyncVersion.V2)) def test_sync_v1_only(self): - manager = self._build(['--memory-storage', '--sync-v1-only']) - self.assertTrue(manager.connections.is_sync_version_enabled(SyncVersion.V1_1)) - self.assertFalse(manager.connections.is_sync_version_enabled(SyncVersion.V2)) + self._build_with_error(['--memory-storage', '--sync-v1-only'], '--sync-v1-only was removed') def test_keypair_wallet(self): manager = self._build(['--memory-storage', '--wallet', 'keypair']) diff --git a/tests/others/test_init_manager.py b/tests/others/test_init_manager.py index a4211f136..7d60ed8fb 100644 --- a/tests/others/test_init_manager.py +++ b/tests/others/test_init_manager.py @@ -42,12 +42,16 @@ def test_invalid_arguments(self): manager = artifacts.manager del manager - # disabling all sync versions should be invalid - with self.assertRaises(TypeError): - builder = TestBuilder() - builder.set_tx_storage(self.tx_storage) + builder = TestBuilder() + builder.set_tx_storage(self.tx_storage) + + # removed method + with self.assertRaises(AttributeError): builder.disable_sync_v1() - builder.disable_sync_v2() + + # but also it should still be impossible to build with no sync + builder.disable_sync_v2() + with self.assertRaises(TypeError): builder.build() def tests_init_with_stratum(self): @@ -82,9 +86,7 @@ def test_wrong_stop(self): manager.stop() -class BaseManagerInitializationTestCase(unittest.TestCase): - __test__ = False - +class ManagerInitializationTestCase(unittest.TestCase): def setUp(self): super().setUp() self.tx_storage = ModifiedTransactionMemoryStorage(settings=self._settings) @@ -178,16 +180,3 @@ def test_init_not_voided_tips(self): all_tips = manager.generate_parent_txs(None).get_all_tips() iter_tips_meta = map(manager.tx_storage.get_metadata, all_tips) self.assertFalse(any(tx_meta.voided_by for tx_meta in iter_tips_meta)) - - -class SyncV1ManagerInitializationTestCase(unittest.SyncV1Params, BaseManagerInitializationTestCase): - __test__ = True - - -class SyncV2ManagerInitializationTestCase(unittest.SyncV2Params, BaseManagerInitializationTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeManagerInitializationTestCase(unittest.SyncBridgeParams, SyncV2ManagerInitializationTestCase): - pass diff --git a/tests/others/test_metrics.py b/tests/others/test_metrics.py index 0fb201377..03b117cd0 100644 --- a/tests/others/test_metrics.py +++ b/tests/others/test_metrics.py @@ -15,9 +15,7 @@ from tests.utils import HAS_ROCKSDB -class BaseMetricsTest(unittest.TestCase): - __test__ = False - +class MetricsTest(unittest.TestCase): def test_p2p_network_events(self): """Simulates publishing an event to pubsub the same way as done by the ConnectionsManager class. @@ -281,16 +279,3 @@ def test_cache_data_collection(self): # Assertion self.assertEquals(manager.metrics.transaction_cache_hits, 10) self.assertEquals(manager.metrics.transaction_cache_misses, 20) - - -class SyncV1MetricsTest(unittest.SyncV1Params, BaseMetricsTest): - __test__ = True - - -class SyncV2MetricsTest(unittest.SyncV2Params, BaseMetricsTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeMetricsTest(unittest.SyncBridgeParams, SyncV2MetricsTest): - pass diff --git a/tests/p2p/netfilter/test_match.py b/tests/p2p/netfilter/test_match.py index ad3929d85..f0aca9342 100644 --- a/tests/p2p/netfilter/test_match.py +++ b/tests/p2p/netfilter/test_match.py @@ -196,10 +196,6 @@ def test_match_peer_id_empty_context(self) -> None: context = NetfilterContext() self.assertFalse(matcher.match(context)) - -class BaseNetfilterMatchTest(unittest.TestCase): - __test__ = False - def test_match_peer_id(self) -> None: network = 'testnet' peer1 = PrivatePeer.auto_generated() @@ -232,16 +228,3 @@ def test_match_peer_id(self) -> None: json = matcher.to_json() self.assertEqual(json['type'], 'NetfilterMatchPeerId') self.assertEqual(json['match_params']['peer_id'], str(peer1.id)) - - -class SyncV1NetfilterMatchTest(unittest.SyncV1Params, BaseNetfilterMatchTest): - __test__ = True - - -class SyncV2NetfilterMatchTest(unittest.SyncV2Params, BaseNetfilterMatchTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeNetfilterMatchTest(unittest.SyncBridgeParams, SyncV2NetfilterMatchTest): - pass diff --git a/tests/p2p/test_capabilities.py b/tests/p2p/test_capabilities.py index 022fb1fc6..0d200a131 100644 --- a/tests/p2p/test_capabilities.py +++ b/tests/p2p/test_capabilities.py @@ -1,50 +1,10 @@ from hathor.p2p.states import ReadyState -from hathor.p2p.sync_v1.agent import NodeSyncTimestamp from hathor.p2p.sync_v2.agent import NodeBlockSync from hathor.simulator import FakeConnection from tests import unittest -class SyncV1HathorCapabilitiesTestCase(unittest.SyncV1Params, unittest.TestCase): - def test_capabilities(self) -> None: - network = 'testnet' - manager1 = self.create_peer(network, capabilities=[self._settings.CAPABILITY_WHITELIST]) - manager2 = self.create_peer(network, capabilities=[]) - - conn = FakeConnection(manager1, manager2) - - # Run the p2p protocol. - for _ in range(100): - conn.run_one_step(debug=True) - self.clock.advance(0.1) - - # Even if we don't have the capability we must connect because the whitelist url conf is None - assert isinstance(conn._proto1.state, ReadyState) - assert isinstance(conn._proto2.state, ReadyState) - self.assertEqual(conn._proto1.state.state_name, 'READY') - self.assertEqual(conn._proto2.state.state_name, 'READY') - self.assertIsInstance(conn._proto1.state.sync_agent, NodeSyncTimestamp) - self.assertIsInstance(conn._proto2.state.sync_agent, NodeSyncTimestamp) - - manager3 = self.create_peer(network, capabilities=[self._settings.CAPABILITY_WHITELIST]) - manager4 = self.create_peer(network, capabilities=[self._settings.CAPABILITY_WHITELIST]) - - conn2 = FakeConnection(manager3, manager4) - - # Run the p2p protocol. - for _ in range(100): - conn2.run_one_step(debug=True) - self.clock.advance(0.1) - - assert isinstance(conn2._proto1.state, ReadyState) - assert isinstance(conn2._proto2.state, ReadyState) - self.assertEqual(conn2._proto1.state.state_name, 'READY') - self.assertEqual(conn2._proto2.state.state_name, 'READY') - self.assertIsInstance(conn2._proto1.state.sync_agent, NodeSyncTimestamp) - self.assertIsInstance(conn2._proto2.state.sync_agent, NodeSyncTimestamp) - - -class SyncV2HathorCapabilitiesTestCase(unittest.SyncV2Params, unittest.TestCase): +class CapabilitiesTestCase(unittest.TestCase): def test_capabilities(self) -> None: network = 'testnet' manager1 = self.create_peer(network, capabilities=[self._settings.CAPABILITY_WHITELIST, @@ -84,8 +44,3 @@ def test_capabilities(self) -> None: self.assertEqual(conn2._proto2.state.state_name, 'READY') self.assertIsInstance(conn2._proto1.state.sync_agent, NodeBlockSync) self.assertIsInstance(conn2._proto2.state.sync_agent, NodeBlockSync) - - -# sync-bridge should behave like sync-v2 -class SyncBridgeHathorCapabilitiesTestCase(unittest.SyncBridgeParams, SyncV2HathorCapabilitiesTestCase): - pass diff --git a/tests/p2p/test_connections.py b/tests/p2p/test_connections.py index a0c910dda..1d07f3e91 100644 --- a/tests/p2p/test_connections.py +++ b/tests/p2p/test_connections.py @@ -15,7 +15,7 @@ def test_connections(self) -> None: process3.terminate() def test_manager_connections(self) -> None: - manager: HathorManager = self.create_peer('testnet', enable_sync_v1=True, enable_sync_v2=False) + manager: HathorManager = self.create_peer('testnet') endpoint = PeerEndpoint.parse('tcp://127.0.0.1:8005') manager.connections.connect_to_endpoint(endpoint, use_ssl=True) @@ -27,13 +27,7 @@ def test_manager_connections(self) -> None: def test_manager_disabled_ipv6(self) -> None: """Should not try to connect to ipv6 peers if ipv6 is disabled""" - manager = self.create_peer( - 'testnet', - enable_sync_v1=False, - enable_sync_v2=True, - enable_ipv6=False, - disable_ipv4=False - ) + manager = self.create_peer('testnet', enable_ipv6=False, disable_ipv4=False) endpoint = PeerEndpoint.parse('tcp://[::1]:8005') manager.connections.connect_to_endpoint(endpoint, use_ssl=True) @@ -45,13 +39,7 @@ def test_manager_disabled_ipv6(self) -> None: def test_manager_enabled_ipv6_and_ipv4(self) -> None: """Should connect to both ipv4 and ipv6 peers if both are enabled""" - manager = self.create_peer( - 'testnet', - enable_sync_v1=False, - enable_sync_v2=True, - enable_ipv6=True, - disable_ipv4=False - ) + manager = self.create_peer('testnet', enable_ipv6=True, disable_ipv4=False) endpoint_ipv6 = PeerEndpoint.parse('tcp://[::3:2:1]:8005') manager.connections.connect_to_endpoint(endpoint_ipv6, use_ssl=True) @@ -75,13 +63,7 @@ def test_manager_enabled_ipv6_and_ipv4(self) -> None: def test_manager_disabled_ipv4(self) -> None: """Should not try to connect to ipv4 peers if ipv4 is disabled""" - manager = self.create_peer( - 'testnet', - enable_sync_v1=False, - enable_sync_v2=True, - enable_ipv6=True, - disable_ipv4=True, - ) + manager = self.create_peer('testnet', enable_ipv6=True, disable_ipv4=True) endpoint = PeerEndpoint.parse('tcp://127.0.0.1:8005') manager.connections.connect_to_endpoint(endpoint, use_ssl=True) diff --git a/tests/p2p/test_double_spending.py b/tests/p2p/test_double_spending.py index 21b74d620..1cfedead8 100644 --- a/tests/p2p/test_double_spending.py +++ b/tests/p2p/test_double_spending.py @@ -9,9 +9,7 @@ from tests.utils import add_blocks_unlock_reward, add_new_tx -class BaseHathorSyncMethodsTestCase(unittest.TestCase): - __test__ = False - +class SyncMethodsTestCase(unittest.TestCase): def setUp(self) -> None: super().setUp() @@ -324,16 +322,3 @@ def test_double_spending_propagation(self) -> None: # dot2 = self.manager1.tx_storage.graphviz_funds(format='pdf', acc_weight=True) # dot2.render('dot2') - - -class SyncV1HathorSyncMethodsTestCase(unittest.SyncV1Params, BaseHathorSyncMethodsTestCase): - __test__ = True - - -class SyncV2HathorSyncMethodsTestCase(unittest.SyncV2Params, BaseHathorSyncMethodsTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeHathorSyncMethodsTestCase(unittest.SyncBridgeParams, SyncV2HathorSyncMethodsTestCase): - pass diff --git a/tests/p2p/test_get_best_blockchain.py b/tests/p2p/test_get_best_blockchain.py index ff0d95149..72fe42b81 100644 --- a/tests/p2p/test_get_best_blockchain.py +++ b/tests/p2p/test_get_best_blockchain.py @@ -8,13 +8,21 @@ from hathor.simulator import FakeConnection from hathor.simulator.trigger import StopAfterNMinedBlocks from hathor.util import json_dumps -from tests import unittest from tests.resources.base_resource import StubSite from tests.simulation.base import SimulatorTestCase -class BaseGetBestBlockchainTestCase(SimulatorTestCase): +def check_decreasing_monotonicity(sequence: list[int]) -> bool: + """Check if a sequence is monotonic and is decreasing. Raise an exception otherwise. + """ + n = len(sequence) + for i in range(1, n): + if sequence[i] >= sequence[i-1]: + raise ValueError(f'Sequence not monotonic. Value {sequence[i]} >= {sequence[i-1]}. Index: {i}.') + return True + +class GetBestBlockchainTestCase(SimulatorTestCase): seed_config = 6 def _send_cmd(self, proto: Protocol, cmd: str, payload: str | None = None) -> None: @@ -428,26 +436,3 @@ async def test_best_blockchain_from_status_resource(self) -> None: self.assertTrue(check_decreasing_monotonicity(height_sequence)) except ValueError as e: self.fail(str(e)) - - -def check_decreasing_monotonicity(sequence: list[int]) -> bool: - """Check if a sequence is monotonic and is decreasing. Raise an exception otherwise. - """ - n = len(sequence) - for i in range(1, n): - if sequence[i] >= sequence[i-1]: - raise ValueError(f'Sequence not monotonic. Value {sequence[i]} >= {sequence[i-1]}. Index: {i}.') - return True - - -class SyncV1GetBestBlockchainTestCase(unittest.SyncV1Params, BaseGetBestBlockchainTestCase): - __test__ = True - - -class SyncV2GetBestBlockchainTestCase(unittest.SyncV2Params, BaseGetBestBlockchainTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeGetBestBlockchainTestCase(unittest.SyncBridgeParams, BaseGetBestBlockchainTestCase): - __test__ = True diff --git a/tests/p2p/test_peer_id.py b/tests/p2p/test_peer_id.py index 75030843b..110688de4 100644 --- a/tests/p2p/test_peer_id.py +++ b/tests/p2p/test_peer_id.py @@ -258,10 +258,6 @@ def test_unverified_peer_to_json_roundtrip(self) -> None: UnverifiedPeer.create_from_json(peer_json_with_conflicting_ids) assert str(e.value) == f'conflicting peer_id: {other_peer_id} != {peer_id}' - -class BasePeerIdTest(unittest.TestCase): - __test__ = False - async def test_validate_entrypoint(self) -> None: manager = self.create_peer('testnet', unlock_wallet=False) peer = manager.my_peer @@ -306,16 +302,3 @@ def getPeer(self) -> DummyPeer: peer.entrypoints = [PeerEndpoint.parse('tcp://[2001:db8::ff00:42:8329]:40403')] result = await peer.info.validate_entrypoint(protocol) self.assertTrue(result) - - -class SyncV1PeerIdTest(unittest.SyncV1Params, BasePeerIdTest): - __test__ = True - - -class SyncV2PeerIdTest(unittest.SyncV2Params, BasePeerIdTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgePeerIdTest(unittest.SyncBridgeParams, SyncV2PeerIdTest): - pass diff --git a/tests/p2p/test_protocol.py b/tests/p2p/test_protocol.py index 7a054b578..ac3c9b95a 100644 --- a/tests/p2p/test_protocol.py +++ b/tests/p2p/test_protocol.py @@ -18,9 +18,7 @@ from tests import unittest -class BaseHathorProtocolTestCase(unittest.TestCase): - __test__ = False - +class HathorProtocolTestCase(unittest.TestCase): def setUp(self) -> None: super().setUp() self.network = 'testnet' @@ -587,104 +585,6 @@ async def error() -> None: assert self.conn.peek_tr1_value() == b'ERROR Error processing "READY" command\r\n' self.assertTrue(self.conn.tr1.disconnecting) - -class SyncV1HathorProtocolTestCase(unittest.SyncV1Params, BaseHathorProtocolTestCase): - __test__ = True - - def test_two_connections(self) -> None: - self.conn.run_one_step() # HELLO - self.conn.run_one_step() # PEER-ID - self.conn.run_one_step() # READY - self.conn.run_one_step() # GET-PEERS - self.conn.run_one_step() # GET-TIPS - - manager3 = self.create_peer(self.network) - conn = FakeConnection(self.manager1, manager3) - conn.run_one_step() # HELLO - conn.run_one_step() # PEER-ID - conn.run_one_step() # READY - conn.run_one_step() # GET-PEERS - - self._check_result_only_cmd(self.conn.peek_tr1_value(), b'PEERS') - self.conn.run_one_step() - - def test_get_data(self) -> None: - self.conn.run_one_step() # HELLO - self.conn.run_one_step() # PEER-ID - self.conn.run_one_step() # READY - self.conn.run_one_step() # GET-PEERS - self.conn.run_one_step() # GET-TIPS - self.conn.run_one_step() # PEERS - self.conn.run_one_step() # TIPS - self.assertIsConnected() - missing_tx = '00000000228dfcd5dec1c9c6263f6430a5b4316bb9e3decb9441a6414bfd8697' - self._send_cmd(self.conn.proto1, 'GET-DATA', missing_tx) - self._check_result_only_cmd(self.conn.peek_tr1_value(), b'NOT-FOUND') - self.conn.run_one_step() - - def test_valid_hello_and_peer_id(self) -> None: - self._check_result_only_cmd(self.conn.peek_tr1_value(), b'HELLO') - self._check_result_only_cmd(self.conn.peek_tr2_value(), b'HELLO') - self.conn.run_one_step() # HELLO - self._check_result_only_cmd(self.conn.peek_tr1_value(), b'PEER-ID') - self._check_result_only_cmd(self.conn.peek_tr2_value(), b'PEER-ID') - self.conn.run_one_step() # PEER-ID - self._check_result_only_cmd(self.conn.peek_tr1_value(), b'READY') - self._check_result_only_cmd(self.conn.peek_tr2_value(), b'READY') - self.conn.run_one_step() # READY - self._check_result_only_cmd(self.conn.peek_tr1_value(), b'GET-PEERS') - self._check_result_only_cmd(self.conn.peek_tr2_value(), b'GET-PEERS') - self.conn.run_one_step() # GET-PEERS - self._check_result_only_cmd(self.conn.peek_tr1_value(), b'GET-TIPS') - self._check_result_only_cmd(self.conn.peek_tr2_value(), b'GET-TIPS') - self.conn.run_one_step() # GET-TIPS - self.assertIsConnected() - self._check_result_only_cmd(self.conn.peek_tr1_value(), b'PEERS') - self._check_result_only_cmd(self.conn.peek_tr2_value(), b'PEERS') - self.conn.run_one_step() # PEERS - self._check_result_only_cmd(self.conn.peek_tr1_value(), b'TIPS') - self._check_result_only_cmd(self.conn.peek_tr2_value(), b'TIPS') - self.conn.run_one_step() # TIPS - self.assertIsConnected() - - def test_send_ping(self) -> None: - self.conn.run_one_step() # HELLO - self.conn.run_one_step() # PEER-ID - self.conn.run_one_step() # READY - self.conn.run_one_step() # GET-PEERS - self.conn.run_one_step() # GET-TIPS - self.conn.run_one_step() # PEERS - self.conn.run_one_step() # TIPS - self.assertIsConnected() - self.clock.advance(5) - self.assertRegex(self.conn.peek_tr1_value(), b'^PING .*\r\n') - self.assertRegex(self.conn.peek_tr2_value(), b'^PING .*\r\n') - self.conn.run_one_step() # PING - self.conn.run_one_step() # GET-TIPS - self.conn.run_one_step() # GET-BEST-BLOCKCHAIN - self.assertRegex(self.conn.peek_tr1_value(), b'PONG .*\r\n') - self.assertRegex(self.conn.peek_tr2_value(), b'PONG .*\r\n') - while b'PONG ' in self.conn.peek_tr1_value(): - self.conn.run_one_step() - self.assertEqual(self.clock.seconds(), self.conn.proto1.last_message) - - def test_invalid_peer_id(self) -> None: - self.conn.run_one_step() # HELLO - self.conn.run_one_step() # PEER-ID - self.conn.run_one_step() # READY - self.conn.run_one_step() # GET-PEERS - self.conn.run_one_step() # GET-TIPS - self.conn.run_one_step() # PEERS - self.conn.run_one_step() # TIPS - invalid_payload = {'id': '123', 'entrypoints': ['tcp://localhost:1234']} - self._send_cmd(self.conn.proto1, 'PEER-ID', json_dumps(invalid_payload)) - self._check_result_only_cmd(self.conn.peek_tr1_value(), b'ERROR') - self.assertTrue(self.conn.tr1.disconnecting) - - -class SyncV2HathorProtocolTestCase(unittest.SyncV2Params, BaseHathorProtocolTestCase): - __test__ = True - def test_two_connections(self) -> None: self.assertAndStepConn(self.conn, b'^HELLO') self.assertAndStepConn(self.conn, b'^PEER-ID') @@ -699,7 +599,7 @@ def test_two_connections(self) -> None: # disable timeout because we will make several steps on a new conn and this might get left behind self.conn.disable_idle_timeout() - manager3 = self.create_peer(self.network, enable_sync_v2=True) + manager3 = self.create_peer(self.network) conn = FakeConnection(self.manager1, manager3) self.assertAndStepConn(conn, b'^HELLO') self.assertAndStepConn(conn, b'^PEER-ID') @@ -787,8 +687,3 @@ def test_send_ping(self) -> None: while b'PONG\r\n' in self.conn.peek_tr1_value(): self.conn.run_one_step() self.assertEqual(self.clock.seconds(), self.conn.proto1.last_message) - - -# sync-bridge should behave like sync-v2 -class SyncBridgeHathorProtocolTestCase(unittest.SyncBridgeParams, SyncV2HathorProtocolTestCase): - pass diff --git a/tests/p2p/test_split_brain.py b/tests/p2p/test_split_brain.py index 3a2352853..f5d2f00f1 100644 --- a/tests/p2p/test_split_brain.py +++ b/tests/p2p/test_split_brain.py @@ -12,9 +12,7 @@ from tests.utils import add_blocks_unlock_reward, add_new_double_spending, add_new_transactions -class BaseHathorSyncMethodsTestCase(unittest.TestCase): - __test__ = False - +class SyncMethodsTestCase(unittest.TestCase): def setUp(self) -> None: super().setUp() @@ -393,16 +391,3 @@ def test_split_brain_no_double_spending(self) -> None: winners2.add(tx.hash) self.assertEqual(len(winners2), winner_blocks + winner_txs) - - -class SyncV1HathorSyncMethodsTestCase(unittest.SyncV1Params, BaseHathorSyncMethodsTestCase): - __test__ = True - - -class SyncV2HathorSyncMethodsTestCase(unittest.SyncV2Params, BaseHathorSyncMethodsTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeHathorSyncMethodsTestCase(unittest.SyncBridgeParams, SyncV2HathorSyncMethodsTestCase): - pass diff --git a/tests/p2p/test_split_brain2.py b/tests/p2p/test_split_brain2.py index e1622fb8a..7b3e5fc2b 100644 --- a/tests/p2p/test_split_brain2.py +++ b/tests/p2p/test_split_brain2.py @@ -2,13 +2,10 @@ from hathor.graphviz import GraphvizVisualizer from hathor.simulator import FakeConnection -from tests import unittest from tests.simulation.base import SimulatorTestCase -class BaseHathorSyncMethodsTestCase(SimulatorTestCase): - __test__ = False - +class SyncMethodsTestCase(SimulatorTestCase): @pytest.mark.flaky(max_runs=3, min_passes=1) def test_split_brain(self) -> None: debug_pdf = False @@ -73,16 +70,3 @@ def test_split_brain(self) -> None: self.assertConsensusEqual(manager1, manager2) self.assertConsensusValid(manager1) self.assertConsensusValid(manager2) - - -class SyncV1HathorSyncMethodsTestCase(unittest.SyncV1Params, BaseHathorSyncMethodsTestCase): - __test__ = True - - -class SyncV2HathorSyncMethodsTestCase(unittest.SyncV2Params, BaseHathorSyncMethodsTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeHathorSyncMethodsTestCase(unittest.SyncBridgeParams, SyncV2HathorSyncMethodsTestCase): - pass diff --git a/tests/p2p/test_sync.py b/tests/p2p/test_sync.py index fc7712495..38439ed29 100644 --- a/tests/p2p/test_sync.py +++ b/tests/p2p/test_sync.py @@ -1,9 +1,5 @@ -from twisted.python.failure import Failure - from hathor.checkpoint import Checkpoint as cp from hathor.crypto.util import decode_address -from hathor.p2p.protocol import PeerIdState -from hathor.p2p.sync_version import SyncVersion from hathor.simulator import FakeConnection from hathor.transaction import Block, Transaction from hathor.transaction.storage.exceptions import TransactionIsNotABlock @@ -12,9 +8,7 @@ from tests.utils import add_blocks_unlock_reward -class BaseHathorSyncMethodsTestCase(unittest.TestCase): - __test__ = False - +class SyncMethodsTestCase(unittest.TestCase): def setUp(self) -> None: super().setUp() @@ -89,90 +83,6 @@ def test_get_blocks_before(self) -> None: expected_result = expected_result[::-1] self.assertEqual(result, expected_result) - def test_block_sync_only_genesis(self) -> None: - manager2 = self.create_peer(self.network) - self.assertEqual(manager2.state, manager2.NodeState.READY) - - conn = FakeConnection(self.manager1, manager2) - - conn.run_one_step() # HELLO - conn.run_one_step() # PEER-ID - conn.run_one_step() # READY - - node_sync = conn.proto1.state.sync_agent - self.assertEqual(node_sync.synced_timestamp, node_sync.peer_timestamp) - self.assertTipsEqual(self.manager1, manager2) - - def test_block_sync_new_blocks(self) -> None: - self._add_new_blocks(15) - - manager2 = self.create_peer(self.network) - self.assertEqual(manager2.state, manager2.NodeState.READY) - - conn = FakeConnection(self.manager1, manager2) - - for _ in range(10000): - if conn.is_empty(): - break - conn.run_one_step(debug=True) - self.clock.advance(0.1) - - node_sync = conn.proto1.state.sync_agent - self.assertEqual(node_sync.synced_timestamp, node_sync.peer_timestamp) - self.assertTipsEqual(self.manager1, manager2) - self.assertConsensusEqual(self.manager1, manager2) - self.assertConsensusValid(self.manager1) - self.assertConsensusValid(manager2) - - def test_block_sync_many_new_blocks(self) -> None: - self._add_new_blocks(150) - - manager2 = self.create_peer(self.network) - self.assertEqual(manager2.state, manager2.NodeState.READY) - - conn = FakeConnection(self.manager1, manager2) - conn.disable_idle_timeout() - - while not conn.is_empty(): - conn.run_one_step(debug=True) - self.clock.advance(0.1) - - node_sync = conn.proto1.state.sync_agent - self.assertEqual(node_sync.synced_timestamp, node_sync.peer_timestamp) - self.assertTipsEqual(self.manager1, manager2) - self.assertConsensusEqual(self.manager1, manager2) - self.assertConsensusValid(self.manager1) - self.assertConsensusValid(manager2) - - def test_block_sync_new_blocks_and_txs(self) -> None: - self._add_new_blocks(25) - self._add_new_transactions(3) - self._add_new_blocks(4) - self._add_new_transactions(5) - - manager2 = self.create_peer(self.network) - self.assertEqual(manager2.state, manager2.NodeState.READY) - - conn = FakeConnection(self.manager1, manager2) - - for _ in range(1000): - conn.run_one_step() - self.clock.advance(0.1) - - # dot1 = self.manager1.tx_storage.graphviz(format='pdf') - # dot1.render('dot1') - - # dot2 = manager2.tx_storage.graphviz(format='pdf') - # dot2.render('dot2') - - node_sync = conn.proto1.state.sync_agent - self.assertEqual(self.manager1.tx_storage.latest_timestamp, manager2.tx_storage.latest_timestamp) - self.assertEqual(node_sync.synced_timestamp, node_sync.peer_timestamp) - self.assertTipsEqual(self.manager1, manager2) - self.assertConsensusEqual(self.manager1, manager2) - self.assertConsensusValid(self.manager1) - self.assertConsensusValid(manager2) - def test_tx_propagation_nat_peers(self) -> None: """ manager1 <- manager2 <- manager3 """ @@ -230,6 +140,18 @@ def test_tx_propagation_nat_peers(self) -> None: self.assertConsensusValid(self.manager2) self.assertConsensusValid(self.manager3) + node_sync1 = self.conn1.proto1.state.sync_agent + self.assertEqual(self.manager1.tx_storage.latest_timestamp, self.manager2.tx_storage.latest_timestamp) + self.assertEqual(node_sync1.peer_best_block, node_sync1.synced_block) + self.assertEqual(node_sync1.peer_best_block.height, self.manager1.tx_storage.get_height_best_block()) + self.assertConsensusEqual(self.manager1, self.manager2) + + node_sync2 = self.conn2.proto1.state.sync_agent + self.assertEqual(self.manager2.tx_storage.latest_timestamp, self.manager3.tx_storage.latest_timestamp) + self.assertEqual(node_sync2.peer_best_block, node_sync2.synced_block) + self.assertEqual(node_sync2.peer_best_block.height, self.manager2.tx_storage.get_height_best_block()) + self.assertConsensusEqual(self.manager2, self.manager3) + def test_check_sync_state(self) -> None: """Tests if the LoopingCall to check the sync state works""" # Initially it should do nothing, since there is no recent activity @@ -246,239 +168,6 @@ def test_check_sync_state(self) -> None: self.assertTrue(hasattr(self.manager1, "first_time_fully_synced")) self.assertFalse(self.manager1.lc_check_sync_state.running) - -class SyncV1HathorSyncMethodsTestCase(unittest.SyncV1Params, BaseHathorSyncMethodsTestCase): - __test__ = True - - def test_downloader(self) -> None: - from hathor.p2p.sync_v1.agent import NodeSyncTimestamp - - blocks = self._add_new_blocks(3) - - manager2 = self.create_peer(self.network) - self.assertEqual(manager2.state, manager2.NodeState.READY) - - conn = FakeConnection(self.manager1, manager2) - - # Get to PEER-ID state only because when it gets to READY it will automatically sync - conn.run_one_step() - - self.assertTrue(isinstance(conn.proto1.state, PeerIdState)) - self.assertTrue(isinstance(conn.proto2.state, PeerIdState)) - - downloader = conn.proto2.connections.get_sync_factory(SyncVersion.V1_1).get_downloader() - - node_sync1 = NodeSyncTimestamp( - conn.proto1, downloader, reactor=conn.proto1.node.reactor, vertex_parser=self.manager1.vertex_parser - ) - node_sync1.start() - node_sync2 = NodeSyncTimestamp( - conn.proto2, downloader, reactor=conn.proto2.node.reactor, vertex_parser=manager2.vertex_parser - ) - node_sync2.start() - - self.assertTrue(isinstance(conn.proto1.state, PeerIdState)) - self.assertTrue(isinstance(conn.proto2.state, PeerIdState)) - - deferred1 = downloader.get_tx(blocks[0].hash, node_sync1) - deferred1.addCallback(node_sync1.on_tx_success) - - self.assertEqual(len(downloader.pending_transactions), 1) - - details = downloader.pending_transactions[blocks[0].hash] - self.assertEqual(len(details.connections), 1) - self.assertEqual(len(downloader.downloading_deque), 1) - - deferred2 = downloader.get_tx(blocks[0].hash, node_sync2) - deferred2.addCallback(node_sync2.on_tx_success) - - self.assertEqual(len(downloader.pending_transactions), 1) - self.assertEqual(len(downloader.pending_transactions[blocks[0].hash].connections), 2) - self.assertEqual(len(downloader.downloading_deque), 1) - self.assertEqual(deferred1, deferred2) - - details.downloading_deferred.callback(blocks[0]) - - self.assertEqual(len(downloader.downloading_deque), 0) - self.assertEqual(len(downloader.pending_transactions), 0) - - # Getting tx already downloaded - downloader.get_tx(blocks[0].hash, node_sync1) - - self.assertEqual(len(downloader.downloading_deque), 0) - - # Adding fake tx_id to downloading deque - downloader.downloading_deque.append('1') - - # Getting new tx - downloader.get_tx(blocks[1].hash, node_sync1) - - self.assertEqual(len(downloader.pending_transactions), 1) - - details = downloader.pending_transactions[blocks[1].hash] - self.assertEqual(len(details.connections), 1) - self.assertEqual(len(downloader.downloading_deque), 2) - - details.downloading_deferred.callback(blocks[1]) - - # Still 2 elements because the first one is not downloaded yet - self.assertEqual(len(downloader.downloading_deque), 2) - - # Remove it - downloader.downloading_deque.popleft() - - # And try again - downloader.check_downloading_queue() - self.assertEqual(len(downloader.downloading_deque), 0) - - def _downloader_bug_setup(self) -> None: - """ This is an auxiliary method to setup a bug scenario.""" - from hathor.p2p.sync_version import SyncVersion - - # ## premise setup - # - # - peer_X will be self.manager - # - peer_Y will be manager2 - # - and manager_bug will be where the bug will happen - # add blocks - self.blocks = self._add_new_blocks(10) - self.tx_A = self.blocks[0] - self.tx_B = self.blocks[1] - - # create second peer - self.manager2 = self.create_peer(self.network) - - # connect them and sync all blocks - self.conn0 = FakeConnection(self.manager1, self.manager2) - for _ in range(1000): - if self.conn0.is_empty(): - break - self.conn0.run_one_step() - self.clock.advance(0.1) - else: - self.fail('expected to break out of loop') - self.assertTipsEqual(self.manager1, self.manager2) - self.assertEqual(self.manager1.tx_storage.get_best_block(), self.blocks[-1]) - self.assertEqual(self.manager2.tx_storage.get_best_block(), self.blocks[-1]) - - # create the peer that will experience the bug - self.manager_bug = self.create_peer(self.network) - self.downloader = self.manager_bug.connections.get_sync_factory(SyncVersion.V1_1).get_downloader() - self.downloader.window_size = 1 - self.conn1 = FakeConnection(self.manager_bug, self.manager1) - self.conn2 = FakeConnection(self.manager_bug, self.manager2) - - # put that peer in a situation where sync advanced to the point that tx_A and tx_B are requested - for _ in range(50): - self.conn1.run_one_step() - if self.tx_A.hash in self.downloader.pending_transactions and \ - self.tx_B.hash in self.downloader.pending_transactions: - break - else: - self.fail('expected to break out of loop') - - # force second download after clock is advanced, this will give us enough time in between the timeouts - self.clock.advance(10.0) - self.downloader.start_next_download() - - for _ in range(50): - self.conn2.run_one_step() - details_A = self.downloader.pending_transactions.get(self.tx_A.hash) - details_B = self.downloader.pending_transactions.get(self.tx_B.hash) - details_A_has_conns = details_A is not None and len(details_A.connections) >= 2 - details_B_has_conns = details_B is not None and len(details_B.connections) >= 2 - if details_A_has_conns and details_B_has_conns: - break - else: - self.fail('expected to break out of loop') - - # by this point everything should be set to so we can trigger the bug, any issues that happen before this - # comment are an issue in setting up the scenario, not related to the problem itself - - def test_downloader_retry_reorder(self) -> None: - """ Reproduce the bug that causes a reorder in the downloader queue. - - The tracking issue for this bug is #465 - - - In order for the bug to be triggered, the following events must happen in the following order: - - - premise: - - be connected to two nodes which are ahead of our node (we'll call them peer_X and peer_Y) - - sync timestamp must have requested two transactions, tx_A and tx_B, of which tx_B depends on tx_A (tx_A can - be parent of tx_B) - - while tx_A and tx_B are in the downloader, these are the key events that trigger the issue: - - tx_A is requested for download to peer_X - - tx_B is requested for download to peer_X - - peer_X disconnects - - peer_Y disconnects - - download of tx_A timeouts, since there are no nodes to download it from it is removed from the downloader, - and it is not retried - - peer_X re-connects, sync starts and tx_A and tx_B are added to the downloader - - peer_Y re-connects, sync starts and tx_A and tx_B are added to the downloader - - download of tx_B timeouts, since now there are peers to download it from, it isn't removed and a retry is - triggered - - tx_B is downloaded, and now it will be processed before tx_A - - tx_A is eventually downloaded (or not, this doesn't have to happen) - - tx_B is processed, but it will fail because tx_A has not been added yet - """ - self._downloader_bug_setup() - - # disconnect and wait for the download of tx_A to timeout but not yet the download of tx_B - self.conn1.disconnect(Failure(Exception('testing'))) - self.conn2.disconnect(Failure(Exception('testing'))) - self.clock.advance(self._settings.GET_DATA_TIMEOUT - 10.0) - - # reconnect peer_X and peer_Y - self.conn1 = FakeConnection(self.manager_bug, self.manager1) - self.conn2 = FakeConnection(self.manager_bug, self.manager2) - - # proceed as normal until both peers are back to the connections list - for _ in range(50): - self.conn1.run_one_step() - self.conn2.run_one_step() - self.clock.advance(0.1) - details_A = self.downloader.pending_transactions.get(self.tx_A.hash) - details_B = self.downloader.pending_transactions.get(self.tx_B.hash) - details_A_has_conns = details_A is not None and len(details_A.connections) >= 2 - details_B_has_conns = details_B is not None and len(details_B.connections) >= 2 - if details_A_has_conns and details_B_has_conns: - break - else: - self.fail('expected to break out of loop') - - # wait for the download of B to be retried - self.clock.advance(11.0) - - # this situation should cause the bug before the fix - # just advancing the connection a little bit should be enough to finish syncing without the bug - for _ in range(20): - self.conn2.run_one_step() - self.clock.advance(0.1) - - # if the fix is applied, we would see tx_A in storage by this point - self.assertTrue(self.manager_bug.tx_storage.transaction_exists(self.tx_A.hash)) - - def test_downloader_disconnect(self) -> None: - """ This is related to test_downloader_retry_reorder, but it basically tests the change in behavior instead. - - When a peer disconnects it should be immediately removed from the tx-detail's connections list. - """ - self._downloader_bug_setup() - - # disconnect and check if the connections were removed from the tx-details (which also means the tx-details - # will be removed from pending_transactions) - self.assertIn(self.tx_A.hash, self.downloader.pending_transactions) - self.assertIn(self.tx_B.hash, self.downloader.pending_transactions) - self.conn1.disconnect(Failure(Exception('testing'))) - self.conn2.disconnect(Failure(Exception('testing'))) - self.assertNotIn(self.tx_A.hash, self.downloader.pending_transactions) - self.assertNotIn(self.tx_B.hash, self.downloader.pending_transactions) - - -class SyncV2HathorSyncMethodsTestCase(unittest.SyncV2Params, BaseHathorSyncMethodsTestCase): - __test__ = True - def test_sync_metadata(self) -> None: # test if the synced peer will build all tx metadata correctly @@ -524,21 +213,6 @@ def test_sync_metadata(self) -> None: self.assertCountEqual(meta1.conflict_with or [], meta2.conflict_with or []) self.assertCountEqual(meta1.twins or [], meta2.twins or []) - def test_tx_propagation_nat_peers(self) -> None: - super().test_tx_propagation_nat_peers() - - node_sync1 = self.conn1.proto1.state.sync_agent - self.assertEqual(self.manager1.tx_storage.latest_timestamp, self.manager2.tx_storage.latest_timestamp) - self.assertEqual(node_sync1.peer_best_block, node_sync1.synced_block) - self.assertEqual(node_sync1.peer_best_block.height, self.manager1.tx_storage.get_height_best_block()) - self.assertConsensusEqual(self.manager1, self.manager2) - - node_sync2 = self.conn2.proto1.state.sync_agent - self.assertEqual(self.manager2.tx_storage.latest_timestamp, self.manager3.tx_storage.latest_timestamp) - self.assertEqual(node_sync2.peer_best_block, node_sync2.synced_block) - self.assertEqual(node_sync2.peer_best_block.height, self.manager2.tx_storage.get_height_best_block()) - self.assertConsensusEqual(self.manager2, self.manager3) - def test_block_sync_new_blocks_and_txs(self) -> None: self._add_new_blocks(25) self._add_new_transactions(3) @@ -745,10 +419,3 @@ def test_block_sync_only_genesis(self) -> None: self.assertEqual(self.manager1.tx_storage.get_vertices_count(), 3) self.assertEqual(manager2.tx_storage.get_vertices_count(), 3) - - # TODO: an equivalent test to test_downloader, could be something like test_checkpoint_sync - - -# sync-bridge should behave like sync-v2 -class SyncBridgeHathorSyncMethodsTestCase(unittest.SyncBridgeParams, SyncV2HathorSyncMethodsTestCase): - pass diff --git a/tests/p2p/test_sync_bridge.py b/tests/p2p/test_sync_bridge.py deleted file mode 100644 index 9c9024be0..000000000 --- a/tests/p2p/test_sync_bridge.py +++ /dev/null @@ -1,82 +0,0 @@ -from hathor.simulator import FakeConnection -from tests.simulation.base import SimulatorTestCase - - -class MixedSyncRandomSimulatorTestCase(SimulatorTestCase): - __test__ = True - - def test_the_three_transacting_miners(self) -> None: - manager1 = self.create_peer(enable_sync_v1=True, enable_sync_v2=False) - manager2 = self.create_peer(enable_sync_v1=True, enable_sync_v2=True) - manager3 = self.create_peer(enable_sync_v1=False, enable_sync_v2=True) - - managers = [manager1, manager2, manager3] - all_managers = managers - miners = [] - tx_gens = [] - - for manager in managers: - miner = self.simulator.create_miner(manager, hashpower=100e6) - miner.start() - miners.append(miner) - tx_gen = self.simulator.create_tx_generator(manager, rate=2 / 60., hashpower=1e6, ignore_no_funds=True) - tx_gen.start() - tx_gens.append(tx_gen) - - self.simulator.run(2000) - - self.simulator.add_connection(FakeConnection(manager1, manager2, latency=0.300)) - self.simulator.add_connection(FakeConnection(manager1, manager3, latency=0.300)) - self.simulator.add_connection(FakeConnection(manager2, manager3, latency=0.300)) - - for tx_gen in tx_gens: - tx_gen.stop() - for miner in miners: - miner.stop() - - self.simulator.run_until_complete(2000, 600) - - for idx, node in enumerate(all_managers): - self.log.debug(f'checking node {idx}') - self.assertConsensusValid(manager) - - for manager_a, manager_b in zip(all_managers[:-1], all_managers[1:]): - # sync-v2 consensus test is more lenient (if sync-v1 assert passes sync-v2 assert will pass too) - self.assertConsensusEqualSyncV2(manager_a, manager_b, strict_sync_v2_indexes=False) - - def test_bridge_with_late_v2(self) -> None: - manager1 = self.create_peer(enable_sync_v1=True, enable_sync_v2=False) - manager2 = self.create_peer(enable_sync_v1=True, enable_sync_v2=True) - manager3 = self.create_peer(enable_sync_v1=False, enable_sync_v2=True) - - managers = [manager1, manager2] - all_managers = [manager1, manager2, manager3] - miners = [] - tx_gens = [] - - for manager in managers: - miner = self.simulator.create_miner(manager, hashpower=100e6) - miner.start() - miners.append(miner) - tx_gen = self.simulator.create_tx_generator(manager, rate=2 / 60., hashpower=1e6, ignore_no_funds=True) - tx_gen.start() - tx_gens.append(tx_gen) - - self.simulator.add_connection(FakeConnection(manager1, manager2, latency=0.300)) - self.simulator.run(2000) - - for tx_gen in tx_gens: - tx_gen.stop() - for miner in miners: - miner.stop() - - self.simulator.add_connection(FakeConnection(manager2, manager3, latency=0.300)) - self.simulator.run_until_complete(2000, 600) - - for idx, node in enumerate(all_managers): - self.log.debug(f'checking node {idx}') - self.assertConsensusValid(manager) - - for manager_a, manager_b in zip(all_managers[:-1], all_managers[1:]): - # sync-v2 consensus test is more lenient (if sync-v1 assert passes sync-v2 assert will pass too) - self.assertConsensusEqualSyncV2(manager_a, manager_b, strict_sync_v2_indexes=False) diff --git a/tests/p2p/test_sync_enabled.py b/tests/p2p/test_sync_enabled.py index f681f90a0..1e3bfd46f 100644 --- a/tests/p2p/test_sync_enabled.py +++ b/tests/p2p/test_sync_enabled.py @@ -1,10 +1,9 @@ from hathor.simulator import FakeConnection from hathor.simulator.trigger import StopAfterNMinedBlocks -from tests import unittest from tests.simulation.base import SimulatorTestCase -class BaseRandomSimulatorTestCase(SimulatorTestCase): +class RandomSimulatorTestCase(SimulatorTestCase): def test_new_node_disabled(self) -> None: manager1 = self.create_peer() manager1.allow_mining_without_peers() @@ -67,16 +66,3 @@ def test_sync_rotate(self) -> None: self.assertEqual(len(enabled2), 3) # Chance of false positive: (1/comb(15, 3))**2 = 0.00000483 self.assertNotEqual(enabled, enabled2) - - -class SyncV1RandomSimulatorTestCase(unittest.SyncV1Params, BaseRandomSimulatorTestCase): - __test__ = True - - -class SyncV2RandomSimulatorTestCase(unittest.SyncV2Params, BaseRandomSimulatorTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeRandomSimulatorTestCase(unittest.SyncBridgeParams, SyncV2RandomSimulatorTestCase): - __test__ = True diff --git a/tests/p2p/test_sync_mempool.py b/tests/p2p/test_sync_mempool.py index 87bf3edde..f8680f417 100644 --- a/tests/p2p/test_sync_mempool.py +++ b/tests/p2p/test_sync_mempool.py @@ -10,9 +10,7 @@ from tests.utils import add_blocks_unlock_reward -class BaseHathorSyncMempoolTestCase(unittest.TestCase): - __test__ = False - +class SyncMempoolTestCase(unittest.TestCase): def setUp(self) -> None: super().setUp() @@ -83,7 +81,7 @@ def test_mempool_basic(self) -> None: dot1 = GraphvizVisualizer(self.manager1.tx_storage, include_verifications=True, include_funds=True).dot() dot1.render('mempool-test') - self.manager2 = self.create_peer(self.network, enable_sync_v1=True) + self.manager2 = self.create_peer(self.network) self.assertEqual(self.manager2.state, self.manager2.NodeState.READY) conn = FakeConnection(self.manager1, self.manager2) @@ -97,17 +95,6 @@ def test_mempool_basic(self) -> None: self.assertConsensusValid(self.manager2) self.assertConsensusEqual(self.manager1, self.manager2) - -class SyncV1HathorSyncMempoolTestCase(unittest.SyncV1Params, BaseHathorSyncMempoolTestCase): - __test__ = True - - -class SyncV2HathorSyncMempoolTestCase(unittest.SyncV2Params, BaseHathorSyncMempoolTestCase): - __test__ = True - - def test_mempool_basic(self) -> None: - super().test_mempool_basic() - # 3 genesis # 25 blocks # Unlock reward blocks @@ -128,7 +115,7 @@ def test_mempool_invalid_new_tx(self) -> None: # 30 transactions in the mempool txs = self._add_new_transactions(30) - self.manager2 = self.create_peer(self.network, enable_sync_v1=True) + self.manager2 = self.create_peer(self.network) self.assertEqual(self.manager2.state, self.manager2.NodeState.READY) conn = FakeConnection(self.manager1, self.manager2) @@ -182,8 +169,3 @@ def test_mempool_invalid_new_tx(self) -> None: self.assertFalse(conn.tr2.disconnecting) conn.run_one_step(debug=True) self.assertTrue(conn.tr2.disconnecting) - - -# sync-bridge should behave like sync-v2 -class SyncBridgeHathorSyncMempoolTestCase(unittest.SyncBridgeParams, SyncV2HathorSyncMempoolTestCase): - pass diff --git a/tests/p2p/test_sync_rate_limiter.py b/tests/p2p/test_sync_rate_limiter.py deleted file mode 100644 index 04d091c27..000000000 --- a/tests/p2p/test_sync_rate_limiter.py +++ /dev/null @@ -1,191 +0,0 @@ -from unittest.mock import Mock, patch - -from twisted.python.failure import Failure - -from hathor.p2p.states import ReadyState -from hathor.p2p.sync_v1.agent import NodeSyncTimestamp -from hathor.simulator import FakeConnection -from hathor.simulator.trigger import StopAfterNMinedBlocks -from tests import unittest -from tests.simulation.base import SimulatorTestCase - - -class SyncV1RandomSimulatorTestCase(unittest.SyncV1Params, SimulatorTestCase): - __test__ = True - - def test_sync_rate_limiter(self) -> None: - manager1 = self.create_peer() - - miner1 = self.simulator.create_miner(manager1, hashpower=10e6) - miner1.start() - trigger = StopAfterNMinedBlocks(miner1, quantity=20) - self.simulator.run(3600, trigger=trigger) - - manager2 = self.create_peer() - manager2.connections.MAX_ENABLED_SYNC = 0 - conn12 = FakeConnection(manager1, manager2, latency=0.05) - self.simulator.add_connection(conn12) - self.simulator.run(3600) - - # Disable to reset all previous hits to the rate limiter. - manager2.connections.disable_rate_limiter() - manager2.connections.enable_rate_limiter(8, 2) - - connected_peers2 = list(manager2.connections.connected_peers.values()) - self.assertEqual(1, len(connected_peers2)) - protocol1 = connected_peers2[0] - assert isinstance(protocol1.state, ReadyState) - sync2 = protocol1.state.sync_agent - assert isinstance(sync2, NodeSyncTimestamp) - - with patch.object(sync2, '_send_tips') as mock: - for i in range(100): - sync2.send_tips() - self.assertEqual(mock.call_count, min(i + 1, 8)) - self.assertEqual(mock.call_count, 8) - - sync2.send_tips() - self.assertEqual(mock.call_count, 8) - - self.simulator._clock.advance(2000) - self.assertTrue(mock.call_count, 16) - - def test_sync_rate_limiter_disconnect(self) -> None: - # Test send_tips delayed calls cancelation with disconnection - manager1 = self.create_peer() - manager2 = self.create_peer() - manager2.connections.MAX_ENABLED_SYNC = 0 - - conn12 = FakeConnection(manager1, manager2, latency=0.05) - self.simulator.add_connection(conn12) - self.simulator.run(3600) - - connections = manager2.connections - connections.rate_limiter.reset(connections.GlobalRateLimiter.SEND_TIPS) - connections.enable_rate_limiter(1, 1) - - connected_peers2 = list(manager2.connections.connected_peers.values()) - self.assertEqual(1, len(connected_peers2)) - - protocol1 = connected_peers2[0] - assert isinstance(protocol1.state, ReadyState) - sync1 = protocol1.state.sync_agent - assert isinstance(sync1, NodeSyncTimestamp) - mock = Mock(wraps=sync1._send_tips) - - with patch.object(sync1, '_send_tips', new=mock): - sync1.send_tips() - self.assertEqual(mock.call_count, 1) - self.assertEqual(len(sync1._send_tips_call_later), 0) - - sync1.send_tips() - self.assertEqual(mock.call_count, 1) - self.assertEqual(len(sync1._send_tips_call_later), 1) - - sync1.send_tips() - self.assertEqual(mock.call_count, 1) - self.assertEqual(len(sync1._send_tips_call_later), 2) - - # Close the connection. - conn12.disconnect(Failure(Exception('testing'))) - self.simulator.remove_connection(conn12) - - self.simulator.run(30) - - # Send tips should not be called any further since the connection has already been closed. - self.assertEqual(mock.call_count, 1) - # Residual delayed calls - self.assertEqual(len(sync1._send_tips_call_later), 2) - # The residual delayed calls should have been canceled - for call_later in sync1._send_tips_call_later: - self.assertFalse(call_later.active()) - - def test_sync_rate_limiter_delayed_calls_draining(self) -> None: - # Test the draining of delayed calls from _send_tips_call_later list - manager1 = self.create_peer() - manager2 = self.create_peer() - manager2.connections.MAX_ENABLED_SYNC = 0 - - conn12 = FakeConnection(manager1, manager2, latency=0.05) - self.simulator.add_connection(conn12) - self.simulator.run(3600) - - connections = manager2.connections - connections.rate_limiter.reset(connections.GlobalRateLimiter.SEND_TIPS) - connections.enable_rate_limiter(1, 1) - - connected_peers2 = list(manager2.connections.connected_peers.values()) - self.assertEqual(1, len(connected_peers2)) - - protocol1 = connected_peers2[0] - assert isinstance(protocol1.state, ReadyState) - sync1 = protocol1.state.sync_agent - assert isinstance(sync1, NodeSyncTimestamp) - - sync1.send_tips() - self.assertEqual(len(sync1._send_tips_call_later), 0) - - sync1.send_tips() - self.assertEqual(len(sync1._send_tips_call_later), 1) - - sync1.send_tips() - self.assertEqual(len(sync1._send_tips_call_later), 2) - - sync1.send_tips() - self.assertEqual(len(sync1._send_tips_call_later), 3) - - self.simulator.run(30) - - # Without disconnection, all the delayed calls - # should have been executed - self.assertEqual(len(sync1._send_tips_call_later), 0) - - def test_sync_rate_limiter_delayed_calls_stop(self) -> None: - # Test the draining of delayed calls from _send_tips_call_later list - manager1 = self.create_peer() - manager2 = self.create_peer() - manager2.connections.MAX_ENABLED_SYNC = 0 - - conn12 = FakeConnection(manager1, manager2, latency=0.05) - self.simulator.add_connection(conn12) - self.simulator.run(3600) - - connections = manager2.connections - connections.rate_limiter.reset(connections.GlobalRateLimiter.SEND_TIPS) - connections.enable_rate_limiter(1, 1) - - connected_peers2 = list(manager2.connections.connected_peers.values()) - self.assertEqual(1, len(connected_peers2)) - - protocol1 = connected_peers2[0] - assert isinstance(protocol1.state, ReadyState) - sync1 = protocol1.state.sync_agent - assert isinstance(sync1, NodeSyncTimestamp) - - sync1.send_tips() - self.assertEqual(len(sync1._send_tips_call_later), 0) - - # add delayed calls to the maximum - max_delayed_calls = self._settings.MAX_GET_TIPS_DELAYED_CALLS - for count in range(max_delayed_calls): - sync1.send_tips() - - # we should have the maxinum delayed calls - self.assertEqual(len(sync1._send_tips_call_later), max_delayed_calls) - # Transport connection is still open - self.assertFalse(conn12.tr2.disconnecting) - - # add one delayed call beyond the maximum - sync1.send_tips() - # we keep the maximum delayed calls allowed - self.assertEqual(len(sync1._send_tips_call_later), max_delayed_calls) - # Transport connection is aborted - self.assertTrue(conn12.tr2.disconnecting) - - self.simulator.run(30) - - # A residual delayed calls is kept when connection closes - self.assertEqual(len(sync1._send_tips_call_later), max_delayed_calls) - # All residual tasks should have been canceled - for call_later in sync1._send_tips_call_later: - self.assertEqual(call_later.active(), False) diff --git a/tests/p2p/test_sync_v2.py b/tests/p2p/test_sync_v2.py index 842f75bda..c8db309f1 100644 --- a/tests/p2p/test_sync_v2.py +++ b/tests/p2p/test_sync_v2.py @@ -44,7 +44,7 @@ def _get_partial_blocks(self, tx_storage: TransactionStorage) -> set[VertexId]: return partial_blocks def _run_restart_test(self, *, full_verification: bool, use_tx_storage_cache: bool) -> None: - manager1 = self.create_peer(enable_sync_v1=False, enable_sync_v2=True) + manager1 = self.create_peer() manager1.allow_mining_without_peers() miner1 = self.simulator.create_miner(manager1, hashpower=10e6) @@ -69,8 +69,6 @@ def _run_restart_test(self, *, full_verification: bool, use_tx_storage_cache: bo peer = PrivatePeer.auto_generated() builder2 = self.simulator.get_default_builder() \ .set_peer(peer) \ - .disable_sync_v1() \ - .enable_sync_v2() \ .use_rocksdb(path) manager2 = self.simulator.create_peer(builder2) @@ -108,8 +106,6 @@ def _run_restart_test(self, *, full_verification: bool, use_tx_storage_cache: bo # Restart full node using the same db. builder3 = self.simulator.get_default_builder() \ .set_peer(peer) \ - .disable_sync_v1() \ - .enable_sync_v2() \ .use_rocksdb(path) if full_verification: @@ -169,7 +165,7 @@ def test_restart_fullnode_full_verification_with_cache(self) -> None: self._run_restart_test(full_verification=True, use_tx_storage_cache=True) def test_exceeds_streaming_and_mempool_limits(self) -> None: - manager1 = self.create_peer(enable_sync_v1=False, enable_sync_v2=True) + manager1 = self.create_peer() manager1.allow_mining_without_peers() # Find 50 blocks. @@ -223,8 +219,6 @@ def test_exceeds_streaming_and_mempool_limits(self) -> None: peer = PrivatePeer.auto_generated() builder2 = self.simulator.get_default_builder() \ .set_peer(peer) \ - .disable_sync_v1() \ - .enable_sync_v2() \ manager2 = self.simulator.create_peer(builder2) conn12 = FakeConnection(manager1, manager2, latency=0.05) @@ -263,7 +257,7 @@ def test_receiving_tips_limit(self) -> None: from hathor.wallet.base_wallet import WalletOutputInfo from tests.utils import BURN_ADDRESS - manager1 = self.create_peer(enable_sync_v1=False, enable_sync_v2=True) + manager1 = self.create_peer() manager1.allow_mining_without_peers() # Find 100 blocks. @@ -313,9 +307,7 @@ def custom_gen_new_tx(manager: HathorManager, _address: str, value: int) -> Tran # Create a new peer and run sync for a while (but stop before getting synced). peer = PrivatePeer.auto_generated() builder2 = self.simulator.get_default_builder() \ - .set_peer(peer) \ - .disable_sync_v1() \ - .enable_sync_v2() \ + .set_peer(peer) manager2 = self.simulator.create_peer(builder2) conn12 = FakeConnection(manager1, manager2, latency=0.05) @@ -344,14 +336,14 @@ def custom_gen_new_tx(manager: HathorManager, _address: str, value: int) -> Tran self.assertTrue(conn12.proto2.aborting) def _prepare_sync_v2_find_best_common_block_reorg(self) -> FakeConnection: - manager1 = self.create_peer(enable_sync_v1=False, enable_sync_v2=True) + manager1 = self.create_peer() manager1.allow_mining_without_peers() miner1 = self.simulator.create_miner(manager1, hashpower=10e6) miner1.start() self.assertTrue(self.simulator.run(24 * 3600)) miner1.stop() - manager2 = self.create_peer(enable_sync_v1=False, enable_sync_v2=True) + manager2 = self.create_peer() conn12 = FakeConnection(manager1, manager2, latency=0.05) self.simulator.add_connection(conn12) @@ -427,7 +419,7 @@ def fake_get_peer_block_hashes(heights: list[int]) -> Deferred[list[_HeightInfo] self.assertIsNone(common_block_info) def test_multiple_unexpected_txs(self) -> None: - manager1 = self.create_peer(enable_sync_v1=False, enable_sync_v2=True) + manager1 = self.create_peer() manager1.allow_mining_without_peers() # mine some blocks (10, could be any amount) @@ -448,7 +440,7 @@ def test_multiple_unexpected_txs(self) -> None: miner1.stop() # create a new peer and run sync and stop when it requests transactions, so we can inject it with invalid ones - manager2 = self.create_peer(enable_sync_v1=False, enable_sync_v2=True) + manager2 = self.create_peer() conn12 = FakeConnection(manager1, manager2, latency=0.05) self.simulator.add_connection(conn12) regex = re.compile(rf'{ProtocolMessages.GET_TRANSACTIONS_BFS.value} '.encode('ascii')) diff --git a/tests/p2p/test_twin_tx.py b/tests/p2p/test_twin_tx.py index ae2339cb5..3c62e7c22 100644 --- a/tests/p2p/test_twin_tx.py +++ b/tests/p2p/test_twin_tx.py @@ -7,9 +7,7 @@ from tests.utils import add_blocks_unlock_reward, add_new_double_spending -class BaseTwinTransactionTestCase(unittest.TestCase): - __test__ = False - +class TwinTransactionTestCase(unittest.TestCase): def setUp(self) -> None: super().setUp() self.network = 'testnet' @@ -84,16 +82,3 @@ def test_twin_tx(self) -> None: self.assertEqual(meta3.conflict_with, [tx1.hash, tx2.hash]) self.assertConsensusValid(self.manager) - - -class SyncV1TwinTransactionTestCase(unittest.SyncV1Params, BaseTwinTransactionTestCase): - __test__ = True - - -class SyncV2TwinTransactionTestCase(unittest.SyncV2Params, BaseTwinTransactionTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeTwinTransactionTestCase(unittest.SyncBridgeParams, SyncV2TwinTransactionTestCase): - pass diff --git a/tests/p2p/test_whitelist.py b/tests/p2p/test_whitelist.py index db854ff63..29fb10e7d 100644 --- a/tests/p2p/test_whitelist.py +++ b/tests/p2p/test_whitelist.py @@ -13,16 +13,16 @@ from tests import unittest -class WhitelistTestCase(unittest.SyncV1Params, unittest.TestCase): - def test_sync_v11_whitelist_no_no(self) -> None: +class WhitelistTestCase(unittest.TestCase): + def test_whitelist_no_no(self) -> None: network = 'testnet' self._settings = get_global_settings()._replace(ENABLE_PEER_WHITELIST=True) manager1 = self.create_peer(network) - self.assertEqual(manager1.connections.get_enabled_sync_versions(), {SyncVersion.V1_1}) + self.assertEqual(manager1.connections.get_enabled_sync_versions(), {SyncVersion.V2}) manager2 = self.create_peer(network) - self.assertEqual(manager2.connections.get_enabled_sync_versions(), {SyncVersion.V1_1}) + self.assertEqual(manager2.connections.get_enabled_sync_versions(), {SyncVersion.V2}) conn = FakeConnection(manager1, manager2) self.assertFalse(conn.tr1.disconnecting) @@ -36,15 +36,15 @@ def test_sync_v11_whitelist_no_no(self) -> None: self.assertTrue(conn.tr1.disconnecting) self.assertTrue(conn.tr2.disconnecting) - def test_sync_v11_whitelist_yes_no(self) -> None: + def test_whitelist_yes_no(self) -> None: network = 'testnet' self._settings = get_global_settings()._replace(ENABLE_PEER_WHITELIST=True) manager1 = self.create_peer(network) - self.assertEqual(manager1.connections.get_enabled_sync_versions(), {SyncVersion.V1_1}) + self.assertEqual(manager1.connections.get_enabled_sync_versions(), {SyncVersion.V2}) manager2 = self.create_peer(network) - self.assertEqual(manager2.connections.get_enabled_sync_versions(), {SyncVersion.V1_1}) + self.assertEqual(manager2.connections.get_enabled_sync_versions(), {SyncVersion.V2}) manager1.peers_whitelist.append(manager2.my_peer.id) @@ -60,15 +60,15 @@ def test_sync_v11_whitelist_yes_no(self) -> None: self.assertFalse(conn.tr1.disconnecting) self.assertTrue(conn.tr2.disconnecting) - def test_sync_v11_whitelist_yes_yes(self) -> None: + def test_whitelist_yes_yes(self) -> None: network = 'testnet' self._settings = get_global_settings()._replace(ENABLE_PEER_WHITELIST=True) manager1 = self.create_peer(network) - self.assertEqual(manager1.connections.get_enabled_sync_versions(), {SyncVersion.V1_1}) + self.assertEqual(manager1.connections.get_enabled_sync_versions(), {SyncVersion.V2}) manager2 = self.create_peer(network) - self.assertEqual(manager2.connections.get_enabled_sync_versions(), {SyncVersion.V1_1}) + self.assertEqual(manager2.connections.get_enabled_sync_versions(), {SyncVersion.V2}) manager1.peers_whitelist.append(manager2.my_peer.id) manager2.peers_whitelist.append(manager1.my_peer.id) diff --git a/tests/poa/test_poa_simulation.py b/tests/poa/test_poa_simulation.py index 096a93fd1..9baf296ee 100644 --- a/tests/poa/test_poa_simulation.py +++ b/tests/poa/test_poa_simulation.py @@ -37,7 +37,6 @@ from hathor.transaction.scripts import P2PKH from hathor.transaction.token_creation_tx import TokenCreationTransaction from hathor.util import not_none -from tests import unittest from tests.poa.utils import get_settings, get_signer from tests.simulation.base import SimulatorTestCase from tests.utils import HAS_ROCKSDB @@ -76,7 +75,7 @@ def _assert_height_weight_signer_id( assert sorted(non_voided_blocks) == expected -class BasePoaSimulationTest(SimulatorTestCase): +class PoaSimulationTest(SimulatorTestCase): def _get_manager(self, signer: PoaSigner | None = None) -> HathorManager: builder = self.simulator.get_default_builder().disable_full_verification() if signer: @@ -574,16 +573,3 @@ def test_use_case(self) -> None: token_tx.update_hash() assert manager.on_new_tx(token_tx, fails_silently=False) - - -class SyncV1PoaSimulationTest(unittest.SyncV1Params, BasePoaSimulationTest): - __test__ = True - - -class SyncV2PoaSimulationTest(unittest.SyncV2Params, BasePoaSimulationTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgePoaSimulationTest(unittest.SyncBridgeParams, SyncV2PoaSimulationTest): - pass diff --git a/tests/poa/test_poa_verification.py b/tests/poa/test_poa_verification.py index e82512878..5ff4e1def 100644 --- a/tests/poa/test_poa_verification.py +++ b/tests/poa/test_poa_verification.py @@ -27,9 +27,7 @@ from tests import unittest -class BasePoaVerificationTest(unittest.TestCase): - __test__ = False - +class PoaVerificationTest(unittest.TestCase): def setUp(self) -> None: super().setUp() @@ -272,16 +270,3 @@ def test_poa_block_validate_full(self) -> None: verify_reward_wrapped.assert_called_once() verify_mandatory_signaling_wrapped.assert_called_once() verify_poa_wrapped.assert_called_once() - - -class SyncV1PoaVerificationTest(unittest.SyncV1Params, BasePoaVerificationTest): - __test__ = True - - -class SyncV2PoaVerificationTest(unittest.SyncV2Params, BasePoaVerificationTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgePoaVerificationTest(unittest.SyncBridgeParams, SyncV2PoaVerificationTest): - pass diff --git a/tests/resources/healthcheck/test_healthcheck.py b/tests/resources/healthcheck/test_healthcheck.py index c857e5877..969d99899 100644 --- a/tests/resources/healthcheck/test_healthcheck.py +++ b/tests/resources/healthcheck/test_healthcheck.py @@ -7,13 +7,10 @@ from hathor.manager import HathorManager from hathor.simulator import FakeConnection from hathor.simulator.utils import add_new_blocks -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest -class BaseHealthcheckReadinessTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class HealthcheckReadinessTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(HealthcheckResource(self.manager)) @@ -206,16 +203,3 @@ def test_get_ready(self): }] } }) - - -class SyncV1StatusTest(unittest.SyncV1Params, BaseHealthcheckReadinessTest): - __test__ = True - - -class SyncV2StatusTest(unittest.SyncV2Params, BaseHealthcheckReadinessTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeStatusTest(unittest.SyncBridgeParams, SyncV2StatusTest): - pass diff --git a/tests/resources/p2p/test_add_peer.py b/tests/resources/p2p/test_add_peer.py index f70f3aefe..cae3a4bae 100644 --- a/tests/resources/p2p/test_add_peer.py +++ b/tests/resources/p2p/test_add_peer.py @@ -3,13 +3,10 @@ from hathor.p2p.peer import PrivatePeer from hathor.p2p.peer_endpoint import PeerAddress from hathor.p2p.resources import AddPeersResource -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest -class BaseAddPeerTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class AddPeerTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(AddPeersResource(self.manager)) @@ -40,16 +37,3 @@ def test_invalid_data(self): response = yield self.web.post('p2p/peers', {'a': 'tcp://localhost:8006'}) data = response.json_value() self.assertFalse(data['success']) - - -class SyncV1AddPeerTest(unittest.SyncV1Params, BaseAddPeerTest): - __test__ = True - - -class SyncV2AddPeerTest(unittest.SyncV2Params, BaseAddPeerTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeAddPeerTest(unittest.SyncBridgeParams, SyncV2AddPeerTest): - pass diff --git a/tests/resources/p2p/test_mining.py b/tests/resources/p2p/test_mining.py index b0d559f90..ae3ae605f 100644 --- a/tests/resources/p2p/test_mining.py +++ b/tests/resources/p2p/test_mining.py @@ -4,13 +4,10 @@ from hathor.p2p.resources import MiningResource from hathor.transaction import Block -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest -class BaseMiningTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class MiningTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(MiningResource(self.manager)) @@ -72,16 +69,3 @@ def test_post_invalid_data(self): # invalid base64 response_post = yield self.web.post('mining', {'block_bytes': 'YWFha'}) self.assertEqual(response_post.written[0], b'0') - - -class SyncV1MiningTest(unittest.SyncV1Params, BaseMiningTest): - __test__ = True - - -class SyncV2MiningTest(unittest.SyncV2Params, BaseMiningTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeMiningTest(unittest.SyncBridgeParams, SyncV2MiningTest): - pass diff --git a/tests/resources/p2p/test_netfilter.py b/tests/resources/p2p/test_netfilter.py index 3574abf8d..27dc73f77 100644 --- a/tests/resources/p2p/test_netfilter.py +++ b/tests/resources/p2p/test_netfilter.py @@ -2,13 +2,10 @@ from hathor.p2p.netfilter import get_table from hathor.p2p.resources import NetfilterRuleResource -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest -class BaseNetfilterTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class NetfilterTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(NetfilterRuleResource(self.manager)) @@ -185,16 +182,3 @@ def test_netfilter_rule(self): response = yield self.web.get('netfilter', {b'chain': bytes('post_peerid', 'utf-8')}) data_get = response.json_value() self.assertEqual(len(data_get['rules']), 2) - - -class SyncV1NetfilterTest(unittest.SyncV1Params, BaseNetfilterTest): - __test__ = True - - -class SyncV2NetfilterTest(unittest.SyncV2Params, BaseNetfilterTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeNetfilterTest(unittest.SyncBridgeParams, SyncV2NetfilterTest): - pass diff --git a/tests/resources/p2p/test_status.py b/tests/resources/p2p/test_status.py index e7c322f74..44da55eab 100644 --- a/tests/resources/p2p/test_status.py +++ b/tests/resources/p2p/test_status.py @@ -7,13 +7,10 @@ from hathor.p2p.peer_endpoint import PeerAddress from hathor.p2p.resources import StatusResource from hathor.simulator import FakeConnection -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest -class BaseStatusTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class StatusTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(StatusResource(self.manager)) @@ -111,16 +108,3 @@ def test_connecting_peers(self): self.assertEqual(len(connecting), 1) self.assertEqual(connecting[0]['address'], address) self.assertIsNotNone(connecting[0]['deferred']) - - -class SyncV1StatusTest(unittest.SyncV1Params, BaseStatusTest): - __test__ = True - - -class SyncV2StatusTest(unittest.SyncV2Params, BaseStatusTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeStatusTest(unittest.SyncBridgeParams, SyncV2StatusTest): - pass diff --git a/tests/resources/test_mining_info.py b/tests/resources/test_mining_info.py index 2f028f624..4eb51bbba 100644 --- a/tests/resources/test_mining_info.py +++ b/tests/resources/test_mining_info.py @@ -2,13 +2,10 @@ from hathor.p2p.resources import MiningInfoResource from hathor.simulator.utils import add_new_blocks -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest -class BaseGetMiningInfoTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class GetMiningInfoTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(MiningInfoResource(self.manager)) @@ -61,16 +58,3 @@ def test_mined_tokens(self): data = response.json_value() self.assertEqual(data['blocks'], self._settings.BLOCKS_PER_HALVING + 20) self.assertEqual(data['mined_tokens'], mined_tokens) - - -class SyncV1GetMiningInfoTest(unittest.SyncV1Params, BaseGetMiningInfoTest): - __test__ = True - - -class SyncV2GetMiningInfoTest(unittest.SyncV2Params, BaseGetMiningInfoTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeGetMiningInfoTest(unittest.SyncBridgeParams, SyncV2GetMiningInfoTest): - pass diff --git a/tests/resources/test_profiler.py b/tests/resources/test_profiler.py index 8dfa5c333..f961705aa 100644 --- a/tests/resources/test_profiler.py +++ b/tests/resources/test_profiler.py @@ -6,13 +6,10 @@ from twisted.internet.defer import inlineCallbacks from hathor.profiler.resources import ProfilerResource -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest -class BaseProfilerTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class ProfilerTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(ProfilerResource(self.manager)) @@ -60,16 +57,3 @@ def test_dump_file(self): filename_arr = filename.split('/') self.assertEqual(filename_arr[0], 'profiles') self.assertTrue(re.search(r'^profile\d{3}\.prof$', filename_arr[1])) - - -class SyncV1ProfilerTest(unittest.SyncV1Params, BaseProfilerTest): - __test__ = True - - -class SyncV2ProfilerTest(unittest.SyncV2Params, BaseProfilerTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeProfilerTest(unittest.SyncBridgeParams, SyncV2ProfilerTest): - pass diff --git a/tests/resources/test_version.py b/tests/resources/test_version.py index f5c5e121d..9c0bac278 100644 --- a/tests/resources/test_version.py +++ b/tests/resources/test_version.py @@ -8,13 +8,10 @@ import hathor from hathor.version import BASE_VERSION, DEFAULT_VERSION_SUFFIX, _get_version from hathor.version_resource import VersionResource -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest -class BaseVersionTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class VersionTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(VersionResource(self.manager)) @@ -73,16 +70,3 @@ def test_build_version(self): with open(file_path, 'w') as build_version_file: build_version_file.write('1.2.3-beta') self.assertEqual(_get_version(), f"{BASE_VERSION}-{git_head}-{DEFAULT_VERSION_SUFFIX}") - - -class SyncV1VersionTest(unittest.SyncV1Params, BaseVersionTest): - __test__ = True - - -class SyncV2VersionTest(unittest.SyncV2Params, BaseVersionTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeVersionTest(unittest.SyncBridgeParams, SyncV2VersionTest): - pass diff --git a/tests/resources/transaction/test_block_at_height.py b/tests/resources/transaction/test_block_at_height.py index c7c006e8e..71856bb39 100644 --- a/tests/resources/transaction/test_block_at_height.py +++ b/tests/resources/transaction/test_block_at_height.py @@ -2,14 +2,11 @@ from hathor.simulator.utils import add_new_block, add_new_blocks from hathor.transaction.resources import BlockAtHeightResource -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest from tests.utils import add_blocks_unlock_reward, add_new_tx -class BaseBlockAtHeightTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class BlockAtHeightTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(BlockAtHeightResource(self.manager)) @@ -108,16 +105,3 @@ def test_get(self): response6 = yield self.web.get("block_at_height", {b'height': b'5'}) data6 = response6.json_value() self.assertFalse(data6['success']) - - -class SyncV1BlockAtHeightTest(unittest.SyncV1Params, BaseBlockAtHeightTest): - __test__ = True - - -class SyncV2BlockAtHeightTest(unittest.SyncV2Params, BaseBlockAtHeightTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeBlockAtHeightTest(unittest.SyncBridgeParams, SyncV2BlockAtHeightTest): - pass diff --git a/tests/resources/transaction/test_create_tx.py b/tests/resources/transaction/test_create_tx.py index e52b9c1f3..62bda2f24 100644 --- a/tests/resources/transaction/test_create_tx.py +++ b/tests/resources/transaction/test_create_tx.py @@ -7,14 +7,11 @@ from hathor.transaction import Transaction from hathor.transaction.resources import CreateTxResource from hathor.transaction.scripts import P2PKH, create_base_script -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest from tests.utils import add_blocks_unlock_reward, add_new_tx -class BaseTransactionTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class TransactionTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(CreateTxResource(self.manager)) @@ -361,16 +358,3 @@ def test_invalid_address(self): }) # TODO: tests that use the tokens field (i.e. not only HTR) - - -class SyncV1TransactionTest(unittest.SyncV1Params, BaseTransactionTest): - __test__ = True - - -class SyncV2TransactionTest(unittest.SyncV2Params, BaseTransactionTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeTransactionTest(unittest.SyncBridgeParams, SyncV2TransactionTest): - pass diff --git a/tests/resources/transaction/test_dashboard.py b/tests/resources/transaction/test_dashboard.py index c67a139a4..7775f7f95 100644 --- a/tests/resources/transaction/test_dashboard.py +++ b/tests/resources/transaction/test_dashboard.py @@ -1,13 +1,10 @@ from twisted.internet.defer import inlineCallbacks from hathor.transaction.resources import DashboardTransactionResource -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest -class BaseDashboardTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class DashboardTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(DashboardTransactionResource(self.manager)) @@ -77,16 +74,3 @@ def test_negative_count(self): response = yield self.web.get("dashboard_tx", {b'block': b'6', b'tx': b'-1'}) data = response.json_value() self.assertFalse(data['success']) - - -class SyncV1DashboardTest(unittest.SyncV1Params, BaseDashboardTest): - __test__ = True - - -class SyncV2DashboardTest(unittest.SyncV2Params, BaseDashboardTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeDashboardTest(unittest.SyncBridgeParams, SyncV2DashboardTest): - pass diff --git a/tests/resources/transaction/test_decodetx.py b/tests/resources/transaction/test_decodetx.py index 35519afc4..9cdeedb29 100644 --- a/tests/resources/transaction/test_decodetx.py +++ b/tests/resources/transaction/test_decodetx.py @@ -2,14 +2,11 @@ from hathor.transaction.resources import DecodeTxResource from hathor.transaction.scripts import parse_address_script -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest from tests.utils import add_blocks_unlock_reward, create_tokens -class BaseDecodeTxTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class DecodeTxTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(DecodeTxResource(self.manager)) @@ -54,16 +51,3 @@ def test_get(self): response = yield self.web.get('decode_tx', {b'hex_tx': bytes(tx2.get_struct().hex(), 'utf-8')}) data = response.json_value() self.assertTrue(data['success']) - - -class SyncV1DecodeTxTest(unittest.SyncV1Params, BaseDecodeTxTest): - __test__ = True - - -class SyncV2DecodeTxTest(unittest.SyncV2Params, BaseDecodeTxTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeDecodeTxTest(unittest.SyncBridgeParams, SyncV2DecodeTxTest): - pass diff --git a/tests/resources/transaction/test_get_tx_parents.py b/tests/resources/transaction/test_get_tx_parents.py index aa65490a0..fc1502e1a 100644 --- a/tests/resources/transaction/test_get_tx_parents.py +++ b/tests/resources/transaction/test_get_tx_parents.py @@ -1,13 +1,10 @@ from twisted.internet.defer import inlineCallbacks from hathor.transaction.resources import TxParentsResource -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest -class BaseDecodeTxTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class DecodeTxTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(TxParentsResource(self.manager)) @@ -28,16 +25,3 @@ def test_get_syncing(self): data = resp.json_value() self.assertFalse(data['success']) - - -class SyncV1DecodeTxTest(unittest.SyncV1Params, BaseDecodeTxTest): - __test__ = True - - -class SyncV2DecodeTxTest(unittest.SyncV2Params, BaseDecodeTxTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeDecodeTxTest(unittest.SyncBridgeParams, SyncV2DecodeTxTest): - pass diff --git a/tests/resources/transaction/test_graphviz.py b/tests/resources/transaction/test_graphviz.py index 4c3f0d498..5f29bc07f 100644 --- a/tests/resources/transaction/test_graphviz.py +++ b/tests/resources/transaction/test_graphviz.py @@ -3,7 +3,6 @@ from hathor.simulator.utils import add_new_blocks from hathor.transaction import Transaction from hathor.transaction.resources import GraphvizFullResource, GraphvizNeighboursResource -from tests import unittest from tests.resources.base_resource import StubSite, TestDummyRequest, _BaseResourceTest from tests.utils import add_blocks_unlock_reward, add_new_transactions @@ -35,7 +34,9 @@ def create_resource(self): raise NotImplementedError -class BaseGraphvizFullTest(BaseGraphvizTest): +class GraphvizFullTest(BaseGraphvizTest): + __test__ = True + def create_resource(self): return GraphvizFullResource(self.manager, format='dot') @@ -80,20 +81,9 @@ def test_error_request(self): self.assertIsNone(request._finishedDeferreds) -class SyncV1GraphvizFullTest(unittest.SyncV1Params, BaseGraphvizFullTest): - __test__ = True - - -class SyncV2GraphvizFullTest(unittest.SyncV2Params, BaseGraphvizFullTest): +class GraphvizNeigboursTest(BaseGraphvizTest): __test__ = True - -# sync-bridge should behave like sync-v2 -class SyncBridgeGraphvizFullTest(unittest.SyncBridgeParams, SyncV2GraphvizFullTest): - pass - - -class BaseGraphvizNeigboursTest(BaseGraphvizTest): def create_resource(self): return GraphvizNeighboursResource(self.manager, format='dot') @@ -111,16 +101,3 @@ def test_error_request(self): self.assertIsNotNone(request._finishedDeferreds) self.resource._err_tx_resolve('Error', request) self.assertIsNone(request._finishedDeferreds) - - -class SyncV1GraphvizNeigboursTest(unittest.SyncV1Params, BaseGraphvizNeigboursTest): - __test__ = True - - -class SyncV2GraphvizNeigboursTest(unittest.SyncV2Params, BaseGraphvizNeigboursTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeGraphvizNeigboursTest(unittest.SyncBridgeParams, SyncV2GraphvizNeigboursTest): - pass diff --git a/tests/resources/transaction/test_mempool.py b/tests/resources/transaction/test_mempool.py index 45e29d1ab..b9d54ca2e 100644 --- a/tests/resources/transaction/test_mempool.py +++ b/tests/resources/transaction/test_mempool.py @@ -2,14 +2,11 @@ from hathor.simulator.utils import add_new_blocks from hathor.transaction.resources import MempoolResource -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest from tests.utils import add_blocks_unlock_reward, add_new_transactions -class BaseMempoolTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class MempoolTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(MempoolResource(self.manager)) @@ -60,16 +57,3 @@ def test_get(self): self.assertTrue(data5['success']) # default limit is 100 self.assertEqual(len(data5['transactions']), self._settings.MEMPOOL_API_TX_LIMIT) - - -class SyncV1MempoolTest(unittest.SyncV1Params, BaseMempoolTest): - __test__ = True - - -class SyncV2MempoolTest(unittest.SyncV2Params, BaseMempoolTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeMempoolTest(unittest.SyncBridgeParams, SyncV2MempoolTest): - pass diff --git a/tests/resources/transaction/test_mining.py b/tests/resources/transaction/test_mining.py index 64df41444..94b0d45e7 100644 --- a/tests/resources/transaction/test_mining.py +++ b/tests/resources/transaction/test_mining.py @@ -2,13 +2,10 @@ from hathor.mining.cpu_mining_service import CpuMiningService from hathor.transaction.resources import mining -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest -class BaseMiningApiTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class MiningApiTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.get_block_template = StubSite(mining.GetBlockTemplateResource(self.manager, self.manager._settings)) @@ -102,16 +99,3 @@ def test_get_block_template_and_submit_block(self): block = create_tx_from_dict(data) CpuMiningService().resolve(block, update_time=False) self.assertTrue(self.manager.propagate_tx(block)) - - -class SyncV1MiningApiTest(unittest.SyncV1Params, BaseMiningApiTest): - __test__ = True - - -class SyncV2MiningApiTest(unittest.SyncV2Params, BaseMiningApiTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeMiningApiTest(unittest.SyncBridgeParams, SyncV2MiningApiTest): - pass diff --git a/tests/resources/transaction/test_pushtx.py b/tests/resources/transaction/test_pushtx.py index 25d5e6976..174ee3586 100644 --- a/tests/resources/transaction/test_pushtx.py +++ b/tests/resources/transaction/test_pushtx.py @@ -9,7 +9,6 @@ from hathor.transaction.scripts import P2PKH, parse_address_script from hathor.wallet.base_wallet import WalletInputInfo, WalletOutputInfo from hathor.wallet.resources import SendTokensResource -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest from tests.utils import add_blocks_unlock_reward, add_tx_with_data_script, create_tokens @@ -304,41 +303,18 @@ def test_push_standard_script_data(self) -> Generator: expected = 'Transaction is non standard.' self.assertEqual(expected, data['message']) + # GET -class BasePushTxGetTest(BasePushTxTest): +class PushTxGetTest(BasePushTxTest): is_post = False - - -class SyncV1PushTxGetTest(unittest.SyncV1Params, BasePushTxGetTest): - __test__ = True - - -class SyncV2PushTxGetTest(unittest.SyncV2Params, BasePushTxGetTest): __test__ = True -# sync-bridge should behave like sync-v2 -class SyncBridgePushTxGetTest(unittest.SyncBridgeParams, SyncV2PushTxGetTest): - pass - - # POST -class BasePushTxPostTest(BasePushTxTest): +class PushTxPostTest(BasePushTxTest): is_post = True - - -class SyncV1PushTxPostTest(unittest.SyncV1Params, BasePushTxPostTest): __test__ = True - - -class SyncV2PushTxPostTest(unittest.SyncV2Params, BasePushTxPostTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgePushTxPostTest(unittest.SyncBridgeParams, SyncV2PushTxPostTest): - pass diff --git a/tests/resources/transaction/test_transaction_confirmation.py b/tests/resources/transaction/test_transaction_confirmation.py index a04eeb641..02e91f91d 100644 --- a/tests/resources/transaction/test_transaction_confirmation.py +++ b/tests/resources/transaction/test_transaction_confirmation.py @@ -2,14 +2,11 @@ from hathor.simulator.utils import add_new_blocks from hathor.transaction.resources import TransactionAccWeightResource -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest from tests.utils import add_blocks_unlock_reward, add_new_transactions -class BaseTransactionTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class TransactionTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(TransactionAccWeightResource(self.manager)) @@ -62,16 +59,3 @@ def test_blocks_are_blocked(self): ) data_success = response_success.json_value() self.assertFalse(data_success['success']) - - -class SyncV1TransactionTest(unittest.SyncV1Params, BaseTransactionTest): - __test__ = True - - -class SyncV2TransactionTest(unittest.SyncV2Params, BaseTransactionTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeTransactionTest(unittest.SyncBridgeParams, SyncV2TransactionTest): - pass diff --git a/tests/resources/transaction/test_tx.py b/tests/resources/transaction/test_tx.py index 52f776cf0..9419ae494 100644 --- a/tests/resources/transaction/test_tx.py +++ b/tests/resources/transaction/test_tx.py @@ -6,14 +6,11 @@ from hathor.transaction.static_metadata import TransactionStaticMetadata from hathor.transaction.token_creation_tx import TokenCreationTransaction from hathor.transaction.validation_state import ValidationState -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest from tests.utils import add_blocks_unlock_reward, add_new_transactions -class BaseTransactionTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class TransactionTest(_BaseResourceTest._ResourceTest): # XXX: using memory storage so that we can more easily manipulate the tokens-index for a test use_memory_storage = True @@ -529,16 +526,3 @@ def test_partially_validated_not_found(self): response = yield self.web.get("transaction", {b'id': bytes(tx.hash_hex, 'utf-8')}) data = response.json_value() self.assertFalse(data['success']) - - -class SyncV1TransactionTest(unittest.SyncV1Params, BaseTransactionTest): - __test__ = True - - -class SyncV2TransactionTest(unittest.SyncV2Params, BaseTransactionTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeTransactionTest(unittest.SyncBridgeParams, SyncV2TransactionTest): - pass diff --git a/tests/resources/transaction/test_utxo_search.py b/tests/resources/transaction/test_utxo_search.py index e906c1592..b2c02cb83 100644 --- a/tests/resources/transaction/test_utxo_search.py +++ b/tests/resources/transaction/test_utxo_search.py @@ -3,14 +3,11 @@ from hathor.crypto.util import decode_address from hathor.simulator.utils import add_new_blocks from hathor.transaction.resources import UtxoSearchResource -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest from tests.utils import add_blocks_unlock_reward -class BaseUtxoSearchTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class UtxoSearchTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp(utxo_index=True) self.web = StubSite(UtxoSearchResource(self.manager)) @@ -100,16 +97,3 @@ def test_simple_gets(self): 'timelock': None, 'heightlock': b.static_metadata.height + self._settings.REWARD_SPEND_MIN_BLOCKS, } for b in blocks[::-1]]) - - -class SyncV1UtxoSearchTest(unittest.SyncV1Params, BaseUtxoSearchTest): - __test__ = True - - -class SyncV2UtxoSearchTest(unittest.SyncV2Params, BaseUtxoSearchTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeUtxoSearchTest(unittest.SyncBridgeParams, SyncV2UtxoSearchTest): - pass diff --git a/tests/resources/transaction/test_validate_address.py b/tests/resources/transaction/test_validate_address.py index 0c2884a37..24dec4b87 100644 --- a/tests/resources/transaction/test_validate_address.py +++ b/tests/resources/transaction/test_validate_address.py @@ -1,13 +1,10 @@ from twisted.internet.defer import inlineCallbacks from hathor.transaction.resources import ValidateAddressResource -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest -class BaseTransactionTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class TransactionTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(ValidateAddressResource(self.manager)) @@ -66,16 +63,3 @@ def test_gibberish(self): 'error': 'InvalidAddress', 'msg': 'Invalid base58 address', }) - - -class SyncV1TransactionTest(unittest.SyncV1Params, BaseTransactionTest): - __test__ = True - - -class SyncV2TransactionTest(unittest.SyncV2Params, BaseTransactionTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeTransactionTest(unittest.SyncBridgeParams, SyncV2TransactionTest): - pass diff --git a/tests/resources/wallet/test_address.py b/tests/resources/wallet/test_address.py index 2ead8d9df..290b629d2 100644 --- a/tests/resources/wallet/test_address.py +++ b/tests/resources/wallet/test_address.py @@ -1,13 +1,10 @@ from twisted.internet.defer import inlineCallbacks from hathor.wallet.resources import AddressResource -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest -class BaseAddressTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class AddressTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(AddressResource(self.manager)) @@ -34,16 +31,3 @@ def test_get(self): self.assertEqual(new_address1, same_address) self.assertEqual(same_address, same_address2) self.assertNotEqual(new_address1, new_address2) - - -class SyncV1AddressTest(unittest.SyncV1Params, BaseAddressTest): - __test__ = True - - -class SyncV2AddressTest(unittest.SyncV2Params, BaseAddressTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeAddressTest(unittest.SyncBridgeParams, SyncV2AddressTest): - pass diff --git a/tests/resources/wallet/test_balance.py b/tests/resources/wallet/test_balance.py index 42532c7e7..63b883771 100644 --- a/tests/resources/wallet/test_balance.py +++ b/tests/resources/wallet/test_balance.py @@ -5,14 +5,11 @@ from hathor.mining.cpu_mining_service import CpuMiningService from hathor.p2p.resources import MiningResource from hathor.wallet.resources import BalanceResource -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest from tests.utils import resolve_block_bytes -class BaseBalanceTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class BalanceTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(BalanceResource(self.manager)) @@ -40,16 +37,3 @@ def test_get(self): self.assertTrue(data2['success']) tokens = self.manager.get_tokens_issued_per_block(1) self.assertEqual(data2['balance'], {'available': tokens, 'locked': 0}) - - -class SyncV1BalanceTest(unittest.SyncV1Params, BaseBalanceTest): - __test__ = True - - -class SyncV2BalanceTest(unittest.SyncV2Params, BaseBalanceTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeBalanceTest(unittest.SyncBridgeParams, SyncV2BalanceTest): - pass diff --git a/tests/resources/wallet/test_history.py b/tests/resources/wallet/test_history.py index 7b7e398c7..cce60475a 100644 --- a/tests/resources/wallet/test_history.py +++ b/tests/resources/wallet/test_history.py @@ -5,14 +5,11 @@ from hathor.mining.cpu_mining_service import CpuMiningService from hathor.p2p.resources import MiningResource from hathor.wallet.resources import HistoryResource -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest from tests.utils import resolve_block_bytes -class BaseHistoryTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class HistoryTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(HistoryResource(self.manager)) @@ -34,16 +31,3 @@ def test_get(self): data = response.json_value() self.assertEqual(len(data['history']), 1) self.assertEqual(data['total_pages'], 1) - - -class SyncV1HistoryTest(unittest.SyncV1Params, BaseHistoryTest): - __test__ = True - - -class SyncV2HistoryTest(unittest.SyncV2Params, BaseHistoryTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeHistoryTest(unittest.SyncBridgeParams, SyncV2HistoryTest): - pass diff --git a/tests/resources/wallet/test_lock.py b/tests/resources/wallet/test_lock.py index d4ec2f404..356d05ffb 100644 --- a/tests/resources/wallet/test_lock.py +++ b/tests/resources/wallet/test_lock.py @@ -1,13 +1,10 @@ from twisted.internet.defer import inlineCallbacks from hathor.wallet.resources import LockWalletResource, StateWalletResource, UnlockWalletResource -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest -class BaseLockTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class LockTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp(unlock_wallet=False) self.web = StubSite(LockWalletResource(self.manager)) @@ -44,16 +41,3 @@ def test_locking(self): response_locked = yield self.web_state.get('wallet/state') data_locked = response_locked.json_value() self.assertTrue(data_locked['is_locked']) - - -class SyncV1LockTest(unittest.SyncV1Params, BaseLockTest): - __test__ = True - - -class SyncV2LockTest(unittest.SyncV2Params, BaseLockTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeLockTest(unittest.SyncBridgeParams, SyncV2LockTest): - pass diff --git a/tests/resources/wallet/test_nano_contract.py b/tests/resources/wallet/test_nano_contract.py index f5d6e345a..66228ff4a 100644 --- a/tests/resources/wallet/test_nano_contract.py +++ b/tests/resources/wallet/test_nano_contract.py @@ -10,14 +10,11 @@ NanoContractExecuteResource, NanoContractMatchValueResource, ) -from tests import unittest from tests.resources.base_resource import StubSite, TestDummyRequest, _BaseResourceTest from tests.utils import add_blocks_unlock_reward -class BaseNanoContractsTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class NanoContractsTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.manager.wallet.unlock(b"MYPASS") @@ -218,16 +215,3 @@ def test_decode_error(self): response_match_put = match_resource.render_PUT(request_match_put) data_response_match_put = json_loadb(response_match_put) self.assertFalse(data_response_match_put['success']) - - -class SyncV1NanoContractsTest(unittest.SyncV1Params, BaseNanoContractsTest): - __test__ = True - - -class SyncV2NanoContractsTest(unittest.SyncV2Params, BaseNanoContractsTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeNanoContractsTest(unittest.SyncBridgeParams, SyncV2NanoContractsTest): - pass diff --git a/tests/resources/wallet/test_search_address.py b/tests/resources/wallet/test_search_address.py index 37d6908b3..bee2a3b8d 100644 --- a/tests/resources/wallet/test_search_address.py +++ b/tests/resources/wallet/test_search_address.py @@ -4,14 +4,11 @@ from hathor.simulator.utils import add_new_blocks from hathor.transaction.scripts import parse_address_script from hathor.wallet.resources.thin_wallet import AddressBalanceResource, AddressSearchResource -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest from tests.utils import add_blocks_unlock_reward, create_tokens -class BaseSearchAddressTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class SearchAddressTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() @@ -141,16 +138,3 @@ def test_negative_count(self): ) data = response.json_value() self.assertFalse(data['success']) - - -class SyncV1SearchAddressTest(unittest.SyncV1Params, BaseSearchAddressTest): - __test__ = True - - -class SyncV2SearchAddressTest(unittest.SyncV2Params, BaseSearchAddressTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeSearchAddressTest(unittest.SyncBridgeParams, SyncV2SearchAddressTest): - pass diff --git a/tests/resources/wallet/test_send_tokens.py b/tests/resources/wallet/test_send_tokens.py index f0eb54427..34c4026a5 100644 --- a/tests/resources/wallet/test_send_tokens.py +++ b/tests/resources/wallet/test_send_tokens.py @@ -7,14 +7,11 @@ from hathor.p2p.resources import MiningResource from hathor.simulator.utils import add_new_blocks from hathor.wallet.resources import BalanceResource, HistoryResource, SendTokensResource -from tests import unittest from tests.resources.base_resource import StubSite, TestDummyRequest, _BaseResourceTest from tests.utils import add_blocks_unlock_reward, resolve_block_bytes -class BaseSendTokensTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class SendTokensTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() self.web = StubSite(SendTokensResource(self.manager, self._settings)) @@ -200,16 +197,3 @@ def test_error_request(self): self.assertIsNotNone(request._finishedDeferreds) resource._err_tx_resolve('Error', request) self.assertIsNone(request._finishedDeferreds) - - -class SyncV1SendTokensTest(unittest.SyncV1Params, BaseSendTokensTest): - __test__ = True - - -class SyncV2SendTokensTest(unittest.SyncV2Params, BaseSendTokensTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeSendTokensTest(unittest.SyncBridgeParams, SyncV2SendTokensTest): - pass diff --git a/tests/resources/wallet/test_thin_wallet.py b/tests/resources/wallet/test_thin_wallet.py index 393599c13..43d288d57 100644 --- a/tests/resources/wallet/test_thin_wallet.py +++ b/tests/resources/wallet/test_thin_wallet.py @@ -12,14 +12,11 @@ TokenHistoryResource, TokenResource, ) -from tests import unittest from tests.resources.base_resource import StubSite, TestDummyRequest, _BaseResourceTest from tests.utils import add_blocks_unlock_reward, add_new_tx, create_tokens -class BaseSendTokensTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class SendTokensTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() @@ -682,16 +679,3 @@ def test_token_history_invalid_params(self): }) data = response.json_value() self.assertFalse(data['success']) - - -class SyncV1SendTokensTest(unittest.SyncV1Params, BaseSendTokensTest): - __test__ = True - - -class SyncV2SendTokensTest(unittest.SyncV2Params, BaseSendTokensTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeSendTokensTest(unittest.SyncBridgeParams, SyncV2SendTokensTest): - pass diff --git a/tests/resources/wallet/test_unlock.py b/tests/resources/wallet/test_unlock.py index 246ad1919..29c86078f 100644 --- a/tests/resources/wallet/test_unlock.py +++ b/tests/resources/wallet/test_unlock.py @@ -2,13 +2,10 @@ from hathor.wallet import HDWallet from hathor.wallet.resources import LockWalletResource, StateWalletResource, UnlockWalletResource -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest -class BaseUnlockTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class UnlockTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp(unlock_wallet=False) self.web = StubSite(UnlockWalletResource(self.manager)) @@ -82,16 +79,3 @@ def test_unlocking_hd_wallet(self): response_words = yield self.web.post("wallet/unlock", {'words': data_success['words'], 'passphrase': ''}) data_words = response_words.json_value() self.assertTrue(data_words['success']) - - -class SyncV1UnlockTest(unittest.SyncV1Params, BaseUnlockTest): - __test__ = True - - -class SyncV2UnlockTest(unittest.SyncV2Params, BaseUnlockTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeUnlockTest(unittest.SyncBridgeParams, SyncV2UnlockTest): - pass diff --git a/tests/simulation/base.py b/tests/simulation/base.py index e3de5b68e..413594612 100644 --- a/tests/simulation/base.py +++ b/tests/simulation/base.py @@ -1,6 +1,5 @@ from typing import Optional -from hathor.builder import SyncSupportLevel from hathor.manager import HathorManager from hathor.simulator import Simulator from hathor.types import VertexId @@ -28,29 +27,14 @@ def tearDown(self) -> None: def create_peer( # type: ignore[override] self, - enable_sync_v1: bool | None = None, - enable_sync_v2: bool | None = None, soft_voided_tx_ids: set[VertexId] = set(), simulator: Simulator | None = None ) -> HathorManager: - if enable_sync_v1 is None: - assert hasattr(self, '_enable_sync_v1'), ('`_enable_sync_v1` has no default by design, either set one on ' - 'the test class or pass `enable_sync_v1` by argument') - enable_sync_v1 = self._enable_sync_v1 - if enable_sync_v2 is None: - assert hasattr(self, '_enable_sync_v2'), ('`_enable_sync_v2` has no default by design, either set one on ' - 'the test class or pass `enable_sync_v2` by argument') - enable_sync_v2 = self._enable_sync_v2 - assert enable_sync_v1 or enable_sync_v2, 'enable at least one sync version' - sync_v1_support = SyncSupportLevel.ENABLED if enable_sync_v1 else SyncSupportLevel.DISABLED - sync_v2_support = SyncSupportLevel.ENABLED if enable_sync_v2 else SyncSupportLevel.DISABLED if simulator is None: simulator = self.simulator builder = simulator.get_default_builder() \ .set_peer(self.get_random_peer_from_pool(rng=simulator.rng)) \ - .set_soft_voided_tx_ids(soft_voided_tx_ids) \ - .set_sync_v1_support(sync_v1_support) \ - .set_sync_v2_support(sync_v2_support) + .set_soft_voided_tx_ids(soft_voided_tx_ids) return simulator.create_peer(builder) diff --git a/tests/simulation/test_simulator.py b/tests/simulation/test_simulator.py index b2f8083ce..dfe9161c8 100644 --- a/tests/simulation/test_simulator.py +++ b/tests/simulation/test_simulator.py @@ -4,11 +4,10 @@ from hathor.simulator import FakeConnection from hathor.simulator.trigger import All as AllTriggers, StopWhenSynced, Trigger from hathor.verification.vertex_verifier import VertexVerifier -from tests import unittest from tests.simulation.base import SimulatorTestCase -class BaseRandomSimulatorTestCase(SimulatorTestCase): +class RandomSimulatorTestCase(SimulatorTestCase): def test_verify_pow(self) -> None: manager1 = self.create_peer() # just get one of the genesis, we don't really need to create any transaction @@ -149,59 +148,3 @@ def test_new_syncing_peer(self) -> None: self.log.debug(f'checking node {idx}') self.assertConsensusValid(node) self.assertConsensusEqual(node, late_manager) - - -class SyncV1RandomSimulatorTestCase(unittest.SyncV1Params, BaseRandomSimulatorTestCase): - __test__ = True - - -class SyncV2RandomSimulatorTestCase(unittest.SyncV2Params, BaseRandomSimulatorTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeRandomSimulatorTestCase(unittest.SyncBridgeParams, SyncV2RandomSimulatorTestCase): - __test__ = True - - def test_compare_mempool_implementations(self) -> None: - manager1 = self.create_peer() - manager2 = self.create_peer() - - # XXX: make sure we have both indexes - tx_storage = manager1.tx_storage - assert tx_storage.indexes is not None - assert tx_storage.indexes.mempool_tips is not None - assert manager1.tx_storage.indexes and manager1.tx_storage.indexes.tx_tips is not None - mempool_tips = tx_storage.indexes.mempool_tips - - miner1 = self.simulator.create_miner(manager1, hashpower=10e6) - miner1.start() - self.simulator.run(10) - - gen_tx1 = self.simulator.create_tx_generator(manager1, rate=3 / 60., hashpower=1e6, ignore_no_funds=True) - gen_tx1.start() - self.simulator.run(10) - - conn12 = FakeConnection(manager1, manager2, latency=0.150) - self.simulator.add_connection(conn12) - self.simulator.run(10) - - miner2 = self.simulator.create_miner(manager2, hashpower=100e6) - miner2.start() - self.simulator.run(10) - - gen_tx2 = self.simulator.create_tx_generator(manager2, rate=10 / 60., hashpower=1e6, ignore_no_funds=True) - gen_tx2.start() - - for _ in range(200): - # mempool tips - self.assertEqual( - set(mempool_tips.iter(tx_storage)), - set(tx_storage.iter_mempool_tips_from_tx_tips()), - ) - # and the complete mempool - self.assertEqual( - set(mempool_tips.iter_all(tx_storage)), - set(tx_storage.iter_mempool_from_tx_tips()), - ) - self.simulator.run(10) diff --git a/tests/simulation/test_simulator_itself.py b/tests/simulation/test_simulator_itself.py index 45b8046de..d557c77a3 100644 --- a/tests/simulation/test_simulator_itself.py +++ b/tests/simulation/test_simulator_itself.py @@ -1,19 +1,16 @@ import pytest -from hathor.builder import SyncSupportLevel from hathor.manager import HathorManager from hathor.p2p.peer import PrivatePeer from hathor.simulator import FakeConnection, Simulator from tests import unittest -class BaseSimulatorSelfTestCase(unittest.TestCase): +class SimulatorSelfTestCase(unittest.TestCase): """These tests will basically setup two independent simulator instances and assert that they generate the same blocks and transactions to the hash throughout the execution. """ - __test__ = False - def setUp(self) -> None: super().setUp() @@ -43,25 +40,9 @@ def create_simulator_peer( self, simulator: Simulator, peer_pool: list[PrivatePeer], - enable_sync_v1: bool | None = None, - enable_sync_v2: bool | None = None ) -> HathorManager: - if enable_sync_v1 is None: - assert hasattr(self, '_enable_sync_v1'), ('`_enable_sync_v1` has no default by design, either set one on ' - 'the test class or pass `enable_sync_v1` by argument') - enable_sync_v1 = self._enable_sync_v1 - if enable_sync_v2 is None: - assert hasattr(self, '_enable_sync_v2'), ('`_enable_sync_v2` has no default by design, either set one on ' - 'the test class or pass `enable_sync_v2` by argument') - enable_sync_v2 = self._enable_sync_v2 - assert enable_sync_v1 or enable_sync_v2, 'enable at least one sync version' - sync_v1_support = SyncSupportLevel.ENABLED if enable_sync_v1 else SyncSupportLevel.DISABLED - sync_v2_support = SyncSupportLevel.ENABLED if enable_sync_v2 else SyncSupportLevel.DISABLED - builder = simulator.get_default_builder() \ - .set_peer(self.get_random_peer_from_pool()) \ - .set_sync_v1_support(sync_v1_support) \ - .set_sync_v2_support(sync_v2_support) + .set_peer(self.get_random_peer_from_pool()) return simulator.create_peer(builder) @@ -262,16 +243,3 @@ def test_determinism_interleaved(self) -> None: for idx, (node1, node2) in enumerate(zip(nodes1, nodes2)): self.log.debug(f'checking node {idx}') self.assertConsensusEqual(node1, node2) - - -class SyncV1SimulatorSelfTestCase(unittest.SyncV1Params, BaseSimulatorSelfTestCase): - __test__ = True - - -class SyncV2SimulatorSelfTestCase(unittest.SyncV2Params, BaseSimulatorSelfTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeSimulatorSelfTestCase(unittest.SyncBridgeParams, SyncV2SimulatorSelfTestCase): - __test__ = True diff --git a/tests/sysctl/test_core.py b/tests/sysctl/test_core.py index 4c3c8543b..d8c76fbe9 100644 --- a/tests/sysctl/test_core.py +++ b/tests/sysctl/test_core.py @@ -6,8 +6,6 @@ class HathorManagerSysctlTestCase(SimulatorTestCase): __test__ = True - _enable_sync_v1 = True - _enable_sync_v2 = True def test_profiler(self): manager = self.create_peer() diff --git a/tests/sysctl/test_p2p.py b/tests/sysctl/test_p2p.py index ec0366888..0550939e0 100644 --- a/tests/sysctl/test_p2p.py +++ b/tests/sysctl/test_p2p.py @@ -5,11 +5,12 @@ from hathor.p2p.peer_id import PeerId from hathor.sysctl import ConnectionsManagerSysctl from hathor.sysctl.exception import SysctlException -from tests import unittest from tests.simulation.base import SimulatorTestCase -class BaseRandomSimulatorTestCase(SimulatorTestCase): +class RandomSimulatorTestCase(SimulatorTestCase): + __test__ = True + def test_max_enabled_sync(self): manager = self.create_peer() connections = manager.connections @@ -134,26 +135,21 @@ def test_available_sync_versions(self): connections = manager.connections sysctl = ConnectionsManagerSysctl(connections) - self.assertEqual(sysctl.get('available_sync_versions'), ['v1', 'v2']) + self.assertEqual(sysctl.get('available_sync_versions'), ['v2']) del connections._sync_factories[SyncVersion.V2] - self.assertEqual(sysctl.get('available_sync_versions'), ['v1']) - - def _default_enabled_sync_versions(self) -> list[str]: - raise NotImplementedError + self.assertEqual(sysctl.get('available_sync_versions'), []) def test_enabled_sync_versions(self): manager = self.create_peer() connections = manager.connections sysctl = ConnectionsManagerSysctl(connections) - self.assertEqual(sysctl.get('enabled_sync_versions'), self._default_enabled_sync_versions()) - sysctl.unsafe_set('enabled_sync_versions', ['v1', 'v2']) - self.assertEqual(sysctl.get('enabled_sync_versions'), ['v1', 'v2']) + self.assertEqual(sysctl.get('enabled_sync_versions'), ['v2']) + sysctl.unsafe_set('enabled_sync_versions', []) + self.assertEqual(sysctl.get('enabled_sync_versions'), []) sysctl.unsafe_set('enabled_sync_versions', ['v2']) self.assertEqual(sysctl.get('enabled_sync_versions'), ['v2']) - sysctl.unsafe_set('enabled_sync_versions', ['v1']) - self.assertEqual(sysctl.get('enabled_sync_versions'), ['v1']) def test_kill_all_connections(self): manager = self.create_peer() @@ -184,25 +180,3 @@ def test_kill_connection_unknown_peer_id(self): with self.assertRaises(SysctlException): sysctl.unsafe_set('kill_connection', 'unknown-peer-id') - - -class SyncV1RandomSimulatorTestCase(unittest.SyncV1Params, BaseRandomSimulatorTestCase): - __test__ = True - - def _default_enabled_sync_versions(self) -> list[str]: - return ['v1'] - - -class SyncV2RandomSimulatorTestCase(unittest.SyncV2Params, BaseRandomSimulatorTestCase): - __test__ = True - - def _default_enabled_sync_versions(self) -> list[str]: - return ['v2'] - - -# sync-bridge should behave like sync-v2 -class SyncBridgeRandomSimulatorTestCase(unittest.SyncBridgeParams, SyncV2RandomSimulatorTestCase): - __test__ = True - - def _default_enabled_sync_versions(self) -> list[str]: - return ['v1', 'v2'] diff --git a/tests/sysctl/test_websocket.py b/tests/sysctl/test_websocket.py index 920eb3b87..14e7fd6e4 100644 --- a/tests/sysctl/test_websocket.py +++ b/tests/sysctl/test_websocket.py @@ -5,9 +5,6 @@ class WebsocketSysctlTestCase(unittest.TestCase): - _enable_sync_v1 = True - _enable_sync_v2 = True - def setUp(self): super().setUp() self.manager = self.create_peer('testnet') diff --git a/tests/tx/test_accumulated_weight.py b/tests/tx/test_accumulated_weight.py index 746bcaf30..783a5b07d 100644 --- a/tests/tx/test_accumulated_weight.py +++ b/tests/tx/test_accumulated_weight.py @@ -5,9 +5,7 @@ from tests.utils import add_blocks_unlock_reward, add_new_transactions -class BaseAccumulatedWeightTestCase(unittest.TestCase): - __test__ = False - +class AccumulatedWeightTestCase(unittest.TestCase): def setUp(self): super().setUp() self.tx_storage = TransactionMemoryStorage(settings=self._settings) @@ -45,16 +43,3 @@ def test_accumulated_weight_indirect_block(self): meta = tx0.update_accumulated_weight() self.assertAlmostEqual(meta.accumulated_weight, expected) - - -class SyncV1AccumulatedWeightTestCase(unittest.SyncV1Params, BaseAccumulatedWeightTestCase): - __test__ = True - - -class SyncV2AccumulatedWeightTestCase(unittest.SyncV2Params, BaseAccumulatedWeightTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeAccumulatedWeightTestCase(unittest.SyncBridgeParams, SyncV2AccumulatedWeightTestCase): - pass diff --git a/tests/tx/test_blockchain.py b/tests/tx/test_blockchain.py index ae0af3c50..0aaa420a6 100644 --- a/tests/tx/test_blockchain.py +++ b/tests/tx/test_blockchain.py @@ -8,9 +8,7 @@ from tests.utils import add_new_transactions -class BaseBlockchainTestCase(unittest.TestCase): - __test__ = False - +class BlockchainTestCase(unittest.TestCase): """ Thus, there are eight cases to be handled when a new block arrives, which are: (i) Single best chain, connected to the head of the best chain @@ -22,6 +20,7 @@ class BaseBlockchainTestCase(unittest.TestCase): (vii) Multiple best chains, connected to the head of a side chain (viii) Multiple best chains, connected to the tail of a side chain """ + def setUp(self): super().setUp() self.tx_storage = TransactionMemoryStorage(settings=self._settings) @@ -469,16 +468,3 @@ def test_daa_weight_decay_blocks(self): manager.reactor.advance(1) weight = manager.generate_mining_block().weight self.assertAlmostEqual(weight, manager.daa.MIN_BLOCK_WEIGHT) - - -class SyncV1BlockchainTestCase(unittest.SyncV1Params, BaseBlockchainTestCase): - __test__ = True - - -class SyncV2BlockchainTestCase(unittest.SyncV2Params, BaseBlockchainTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeBlockchainTestCase(unittest.SyncBridgeParams, SyncV2BlockchainTestCase): - pass diff --git a/tests/tx/test_cache_storage.py b/tests/tx/test_cache_storage.py index f6457cd01..789011e22 100644 --- a/tests/tx/test_cache_storage.py +++ b/tests/tx/test_cache_storage.py @@ -8,9 +8,7 @@ CACHE_SIZE = 5 -class BaseCacheStorageTest(unittest.TestCase): - __test__ = False - +class CacheStorageTest(unittest.TestCase): def setUp(self): super().setUp() @@ -154,16 +152,3 @@ def test_topological_sort_dfs(self): for tx in self.cache_storage._run_topological_sort_dfs(root=tx, visited=dict()): total += 1 self.assertEqual(total, 5) - - -class SyncV1CacheStorageTest(unittest.SyncV1Params, BaseCacheStorageTest): - __test__ = True - - -class SyncV2CacheStorageTest(unittest.SyncV2Params, BaseCacheStorageTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeCacheStorageTest(unittest.SyncBridgeParams, SyncV2CacheStorageTest): - pass diff --git a/tests/tx/test_indexes.py b/tests/tx/test_indexes.py index 15f238ea4..bbf41748a 100644 --- a/tests/tx/test_indexes.py +++ b/tests/tx/test_indexes.py @@ -689,7 +689,9 @@ def test_height_index(self): self.assertEqual(height_index.get_n_height_tips(103), height_index.get_n_height_tips(104)) -class BaseMemoryIndexesTest(BaseIndexesTest): +class MemoryIndexesTest(BaseIndexesTest): + __test__ = True + def setUp(self): from hathor.transaction.storage import TransactionMemoryStorage @@ -714,7 +716,9 @@ def setUp(self): @pytest.mark.skipif(not HAS_ROCKSDB, reason='requires python-rocksdb') -class BaseRocksDBIndexesTest(BaseIndexesTest): +class RocksDBIndexesTest(BaseIndexesTest): + __test__ = True + def setUp(self): import tempfile @@ -742,29 +746,3 @@ def setUp(self): self.last_block = self.blocks[-1] self.graphviz = GraphvizVisualizer(self.tx_storage, include_verifications=True, include_funds=True) - - -class SyncV1MemoryIndexesTest(unittest.SyncV1Params, BaseMemoryIndexesTest): - __test__ = True - - -class SyncV2MemoryIndexesTest(unittest.SyncV2Params, BaseMemoryIndexesTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeMemoryIndexesTest(unittest.SyncBridgeParams, SyncV2MemoryIndexesTest): - pass - - -class SyncV1RocksDBIndexesTest(unittest.SyncV1Params, BaseRocksDBIndexesTest): - __test__ = True - - -class SyncV2RocksDBIndexesTest(unittest.SyncV2Params, BaseRocksDBIndexesTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeRocksDBIndexesTest(unittest.SyncBridgeParams, SyncV2RocksDBIndexesTest): - pass diff --git a/tests/tx/test_indexes3.py b/tests/tx/test_indexes3.py index c7a513acf..b0c47ba00 100644 --- a/tests/tx/test_indexes3.py +++ b/tests/tx/test_indexes3.py @@ -1,11 +1,10 @@ import pytest from hathor.simulator import FakeConnection -from tests import unittest from tests.simulation.base import SimulatorTestCase -class BaseSimulatorIndexesTestCase(SimulatorTestCase): +class SimulatorIndexesTestCase(SimulatorTestCase): def _build_randomized_blockchain(self): manager = self.create_peer() @@ -108,16 +107,3 @@ def test_topological_iterators(self): self.assertEqual(len(txs), total_count, f'iterator "{name}" does not cover all txs') # must be topological self.assertIsTopological(iter(txs), f'iterator "{name}" is not topological') - - -class SyncV1SimulatorIndexesTestCase(unittest.SyncV1Params, BaseSimulatorIndexesTestCase): - __test__ = True - - -class SyncV2SimulatorIndexesTestCase(unittest.SyncV2Params, BaseSimulatorIndexesTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeSimulatorIndexesTestCase(unittest.SyncBridgeParams, SyncV2SimulatorIndexesTestCase): - __test__ = True diff --git a/tests/tx/test_indexes4.py b/tests/tx/test_indexes4.py index 4fee7ca40..8a5a98111 100644 --- a/tests/tx/test_indexes4.py +++ b/tests/tx/test_indexes4.py @@ -7,9 +7,7 @@ from tests.utils import add_blocks_unlock_reward -class BaseSimulatorIndexesTestCase(unittest.TestCase): - __test__ = False - +class SimulatorIndexesTestCase(unittest.TestCase): def _build_randomized_blockchain(self, *, utxo_index=False): tx_storage = TransactionMemoryStorage(settings=self._settings) manager = self.create_peer('testnet', tx_storage=tx_storage, unlock_wallet=True, wallet_index=True, @@ -139,16 +137,3 @@ def test_topological_iterators(self): self.assertEqual(len(txs), total_count, f'iterator "{name}" does not cover all txs') # must be topological self.assertIsTopological(iter(txs), f'iterator "{name}" is not topological') - - -class SyncV1SimulatorIndexesTestCase(unittest.SyncV1Params, BaseSimulatorIndexesTestCase): - __test__ = True - - -class SyncV2SimulatorIndexesTestCase(unittest.SyncV2Params, BaseSimulatorIndexesTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeSimulatorIndexesTestCase(unittest.SyncBridgeParams, SyncV2SimulatorIndexesTestCase): - __test__ = True diff --git a/tests/tx/test_merged_mining.py b/tests/tx/test_merged_mining.py index ebf032bb1..38721170f 100644 --- a/tests/tx/test_merged_mining.py +++ b/tests/tx/test_merged_mining.py @@ -16,9 +16,7 @@ def test_flip80_odd_length(self): flip80(i) -class BaseMergedMiningTest(unittest.TestCase): - __test__ = False - +class MergedMiningTest(unittest.TestCase): @ensure_deferred async def test_coordinator(self): from cryptography.hazmat.backends import default_backend @@ -1412,16 +1410,3 @@ async def submit_block(self, block: bytes) -> str: stub = 'high-hash' await asyncio.sleep(self.response_delay) return stub - - -class SyncV1MergedMiningTest(unittest.SyncV1Params, BaseMergedMiningTest): - __test__ = True - - -class SyncV2MergedMiningTest(unittest.SyncV2Params, BaseMergedMiningTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeMergedMiningTest(unittest.SyncBridgeParams, SyncV2MergedMiningTest): - pass diff --git a/tests/tx/test_mining.py b/tests/tx/test_mining.py index 49e6d1c41..17d77450d 100644 --- a/tests/tx/test_mining.py +++ b/tests/tx/test_mining.py @@ -8,7 +8,7 @@ from tests import unittest -class BaseMiningTest(unittest.TestCase): +class MiningTest(unittest.TestCase): """ Thus, there are eight cases to be handled when a new block arrives, which are: (i) Single best chain, connected to the head of the best chain @@ -21,8 +21,6 @@ class BaseMiningTest(unittest.TestCase): (viii) Multiple best chains, connected to the tail of a side chain """ - __test__ = False - def setUp(self): super().setUp() self.tx_storage = TransactionMemoryStorage(settings=self._settings) @@ -119,16 +117,3 @@ def test_minimally_valid_block(self) -> None: self.assertTrue(isinstance(block, Block)) self.assertEqual(json, expected) - - -class SyncV1MiningTest(unittest.SyncV1Params, BaseMiningTest): - __test__ = True - - -class SyncV2MiningTest(unittest.SyncV2Params, BaseMiningTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeMiningTest(unittest.SyncBridgeParams, SyncV2MiningTest): - pass diff --git a/tests/tx/test_multisig.py b/tests/tx/test_multisig.py index 22748266e..25222b90d 100644 --- a/tests/tx/test_multisig.py +++ b/tests/tx/test_multisig.py @@ -11,9 +11,7 @@ from tests.utils import add_blocks_unlock_reward -class BaseMultisigTestCase(unittest.TestCase): - __test__ = False - +class MultisigTestCase(unittest.TestCase): def setUp(self): super().setUp() @@ -139,16 +137,3 @@ def test_spend_multisig(self): # Script error with self.assertRaises(ScriptError): create_output_script(base58.b58decode('55d14K5jMqsN2uwUEFqiPG5SoD7Vr1BfnH')) - - -class SyncV1MultisigTestCase(unittest.SyncV1Params, BaseMultisigTestCase): - __test__ = True - - -class SyncV2MultisigTestCase(unittest.SyncV2Params, BaseMultisigTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeMultisigTestCase(unittest.SyncBridgeParams, SyncV2MultisigTestCase): - pass diff --git a/tests/tx/test_prometheus.py b/tests/tx/test_prometheus.py index 5783db6ca..d7784de18 100644 --- a/tests/tx/test_prometheus.py +++ b/tests/tx/test_prometheus.py @@ -8,9 +8,7 @@ from tests.utils import add_new_transactions -class BasePrometheusTest(unittest.TestCase): - __test__ = False - +class PrometheusTest(unittest.TestCase): def setUp(self): super().setUp() @@ -60,16 +58,3 @@ def test_wallet(self): # Removing tmpdir shutil.rmtree(tmpdir) - - -class SyncV1PrometheusTest(unittest.SyncV1Params, BasePrometheusTest): - __test__ = True - - -class SyncV2PrometheusTest(unittest.SyncV2Params, BasePrometheusTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgePrometheusTest(unittest.SyncBridgeParams, SyncV2PrometheusTest): - pass diff --git a/tests/tx/test_reward_lock.py b/tests/tx/test_reward_lock.py index 1a56d7e6a..55f062f56 100644 --- a/tests/tx/test_reward_lock.py +++ b/tests/tx/test_reward_lock.py @@ -13,10 +13,8 @@ from tests.utils import add_blocks_unlock_reward, get_genesis_key -class BaseTransactionTest(unittest.TestCase): - __test__ = False - - def setUp(self) -> None: +class TransactionTest(unittest.TestCase): + def setUp(self): super().setUp() self.wallet = Wallet() @@ -219,16 +217,3 @@ def test_classic_reward_lock_timestamp_expected_to_fail(self) -> None: self.assertEqual(tx.static_metadata.min_height, unlock_height) with self.assertRaises(RewardLocked): self.manager.verification_service.verify(tx) - - -class SyncV1TransactionTest(unittest.SyncV1Params, BaseTransactionTest): - __test__ = True - - -class SyncV2TransactionTest(unittest.SyncV2Params, BaseTransactionTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeTransactionTest(unittest.SyncBridgeParams, SyncV2TransactionTest): - pass diff --git a/tests/tx/test_stratum.py b/tests/tx/test_stratum.py index 1445684b4..6a2811111 100644 --- a/tests/tx/test_stratum.py +++ b/tests/tx/test_stratum.py @@ -61,8 +61,8 @@ def _get_latest_message(self): return json_loads(data) -class BaseStratumServerTest(_BaseStratumTest): - __test__ = False +class StratumServerTest(_BaseStratumTest): + __test__ = True def test_parse_error(self): self.protocol.lineReceived(b'{]') @@ -144,20 +144,9 @@ def test_subscribe(self): self.assertEqual(job['method'], 'job') -class SyncV1StratumServerTest(unittest.SyncV1Params, BaseStratumServerTest): +class StratumJobTest(_BaseStratumTest): __test__ = True - -class SyncV2StratumServerTest(unittest.SyncV2Params, BaseStratumServerTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeStratumServerTest(unittest.SyncBridgeParams, SyncV2StratumServerTest): - pass - - -class BaseStratumJobTest(_BaseStratumTest): def _get_nonce(self, valid=True): target = 2**(256 - self.job['weight']) - 1 base = sha256(bytes.fromhex(self.job['data'])) @@ -235,22 +224,7 @@ def test_min_share_weight(self): self.assertTrue(job.weight >= 1, f'job weight of {job.weight} is too small') -class SyncV1StratumJobTest(unittest.SyncV1Params, BaseStratumJobTest): - __test__ = True - - -class SyncV2StratumJobTest(unittest.SyncV2Params, BaseStratumJobTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeStratumJobTest(unittest.SyncBridgeParams, SyncV2StratumJobTest): - pass - - -class BaseStratumClientTest(unittest.TestCase): - __test__ = False - +class StratumClientTest(unittest.TestCase): def setUp(self): super().setUp() storage = TransactionMemoryStorage(settings=self._settings) @@ -294,16 +268,3 @@ def test_n_core_mining(self): self.block.nonce = int(nonce, 16) self.block.update_hash() self.block.verify_pow() - - -class SyncV1StratumClientTest(unittest.SyncV1Params, BaseStratumClientTest): - __test__ = True - - -class SyncV2StratumClientTest(unittest.SyncV2Params, BaseStratumClientTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeStratumClientTest(unittest.SyncBridgeParams, SyncV2StratumClientTest): - pass diff --git a/tests/tx/test_timelock.py b/tests/tx/test_timelock.py index 609248d07..638da9038 100644 --- a/tests/tx/test_timelock.py +++ b/tests/tx/test_timelock.py @@ -7,9 +7,7 @@ from tests.utils import add_blocks_unlock_reward -class BaseTimelockTransactionTestCase(unittest.TestCase): - __test__ = False - +class TimelockTransactionTestCase(unittest.TestCase): def setUp(self): super().setUp() self.network = 'testnet' @@ -152,16 +150,3 @@ def test_choose_inputs(self): self.assertEqual(self.manager.wallet.balance[self._settings.HATHOR_TOKEN_UID], WalletBalance(0, blocks_tokens[0])) - - -class SyncV1TimelockTransactionTestCase(unittest.SyncV1Params, BaseTimelockTransactionTestCase): - __test__ = True - - -class SyncV2TimelockTransactionTestCase(unittest.SyncV2Params, BaseTimelockTransactionTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeTimelockTransactionTestCase(unittest.SyncBridgeParams, SyncV2TimelockTransactionTestCase): - pass diff --git a/tests/tx/test_tips.py b/tests/tx/test_tips.py index c1ae8bfad..d3f99ef70 100644 --- a/tests/tx/test_tips.py +++ b/tests/tx/test_tips.py @@ -4,9 +4,7 @@ from tests.utils import add_blocks_unlock_reward, add_new_double_spending, add_new_transactions -class BaseTipsTestCase(unittest.TestCase): - __test__ = False - +class TipsTestCase(unittest.TestCase): def setUp(self): super().setUp() @@ -14,7 +12,9 @@ def setUp(self): self.manager = self.create_peer(self.network, unlock_wallet=True) def get_tips(self): - raise NotImplementedError + assert self.manager.tx_storage.indexes is not None + assert self.manager.tx_storage.indexes.mempool_tips is not None + return self.manager.tx_storage.indexes.mempool_tips.get() def test_tips_back(self): add_new_block(self.manager, advance_clock=1) @@ -160,24 +160,3 @@ def test_tips_twin(self): # tx6 is the only one left self.assertCountEqual(self.get_tips(), set([tx6.hash])) - - -class SyncV1TipsTestCase(unittest.SyncV1Params, BaseTipsTestCase): - __test__ = True - - def get_tips(self): - return {tx.hash for tx in self.manager.tx_storage.iter_mempool_tips_from_tx_tips()} - - -class SyncV2TipsTestCase(unittest.SyncV2Params, BaseTipsTestCase): - __test__ = True - - def get_tips(self): - assert self.manager.tx_storage.indexes is not None - assert self.manager.tx_storage.indexes.mempool_tips is not None - return self.manager.tx_storage.indexes.mempool_tips.get() - - -# sync-bridge should behave like sync-v2 -class SyncBridgeTipsTestCase(unittest.SyncBridgeParams, SyncV2TipsTestCase): - pass diff --git a/tests/tx/test_tokens.py b/tests/tx/test_tokens.py index ebcb4aafd..cfd2a8ecc 100644 --- a/tests/tx/test_tokens.py +++ b/tests/tx/test_tokens.py @@ -14,9 +14,7 @@ from tests.utils import add_blocks_unlock_reward, add_new_double_spending, create_tokens, get_genesis_key -class BaseTokenTest(unittest.TestCase): - __test__ = False - +class TokenTest(unittest.TestCase): def setUp(self): super().setUp() self.manager = self.create_peer('testnet', unlock_wallet=True, wallet_index=True) @@ -619,32 +617,6 @@ def test_voided_token_creation(self): print(tokens_index) -class SyncV1TokenTest(unittest.SyncV1Params, BaseTokenTest): - __test__ = True - - -class SyncV2TokenTest(unittest.SyncV2Params, BaseTokenTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeTokenTest(unittest.SyncBridgeParams, SyncV2TokenTest): - pass - - @pytest.mark.skipif(unittest.USE_MEMORY_STORAGE, reason='previous tests already use memory, avoid duplication') -class BaseMemoryTokenTest(BaseTokenTest): +class MemoryTokenTest(TokenTest): use_memory_storage = True - - -class SyncV1MemoryTokenTest(unittest.SyncV1Params, BaseMemoryTokenTest): - __test__ = True - - -class SyncV2MemoryTokenTest(unittest.SyncV2Params, BaseMemoryTokenTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeMemoryTokenTest(unittest.SyncBridgeParams, SyncV2MemoryTokenTest): - pass diff --git a/tests/tx/test_traversal.py b/tests/tx/test_traversal.py index 9f730c545..0631f2ee7 100644 --- a/tests/tx/test_traversal.py +++ b/tests/tx/test_traversal.py @@ -6,7 +6,7 @@ from tests.utils import add_blocks_unlock_reward, add_new_transactions, add_new_tx -class _TraversalTestCase(unittest.TestCase): +class BaseTraversalTestCase(unittest.TestCase): __test__ = False def setUp(self): @@ -87,7 +87,9 @@ def test_right_to_left(self): self.assertTrue(seen_v.union(seen_f).issubset(seen_vf)) -class BaseBFSTimestampWalkTestCase(_TraversalTestCase): +class BFSTimestampWalkTestCase(BaseTraversalTestCase): + __test__ = True + def gen_walk(self, **kwargs): return BFSTimestampWalk(self.manager.tx_storage, **kwargs) @@ -110,15 +112,9 @@ def _run_rl(self, walk): return seen -class SyncV1BFSTimestampWalkTestCase(unittest.SyncV1Params, BaseBFSTimestampWalkTestCase): - __test__ = True - - -class SyncV2BFSTimestampWalkTestCase(unittest.SyncV2Params, BaseBFSTimestampWalkTestCase): +class BFSOrderWalkTestCase(BaseTraversalTestCase): __test__ = True - -class BaseBFSOrderWalkTestCase(_TraversalTestCase): def gen_walk(self, **kwargs): return BFSOrderWalk(self.manager.tx_storage, **kwargs) @@ -153,20 +149,9 @@ def _run_rl(self, walk): return seen -class SyncV1BFSOrderWalkTestCase(unittest.SyncV1Params, BaseBFSOrderWalkTestCase): +class DFSWalkTestCase(BaseTraversalTestCase): __test__ = True - -class SyncV2BFSOrderWalkTestCase(unittest.SyncV2Params, BaseBFSOrderWalkTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeBFSOrderWalkTestCase(unittest.SyncBridgeParams, SyncV2BFSOrderWalkTestCase): - pass - - -class BaseDFSWalkTestCase(_TraversalTestCase): def gen_walk(self, **kwargs): return DFSWalk(self.manager.tx_storage, **kwargs) @@ -181,16 +166,3 @@ def _run_rl(self, walk): for tx in walk.run(self.root_tx, skip_root=True): seen.add(tx.hash) return seen - - -class SyncV1DFSWalkTestCase(unittest.SyncV1Params, BaseDFSWalkTestCase): - __test__ = True - - -class SyncV2DFSWalkTestCase(unittest.SyncV2Params, BaseDFSWalkTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeDFSWalkTestCase(unittest.SyncBridgeParams, SyncV2DFSWalkTestCase): - pass diff --git a/tests/tx/test_tx.py b/tests/tx/test_tx.py index 833d158d2..6c842d656 100644 --- a/tests/tx/test_tx.py +++ b/tests/tx/test_tx.py @@ -41,9 +41,7 @@ from tests.utils import add_blocks_unlock_reward, add_new_transactions, create_script_with_sigops, get_genesis_key -class BaseTransactionTest(unittest.TestCase): - __test__ = False - +class TransactionTest(unittest.TestCase): def setUp(self): super().setUp() self.wallet = Wallet() @@ -1244,16 +1242,3 @@ def test_compare_bytes_partially_validated_different(self) -> None: # the storage already has block1 and should correctly return False self.assertFalse(self.tx_storage.compare_bytes_with_local_tx(block2)) - - -class SyncV1TransactionTest(unittest.SyncV1Params, BaseTransactionTest): - __test__ = True - - -class SyncV2TransactionTest(unittest.SyncV2Params, BaseTransactionTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeTransactionTest(unittest.SyncBridgeParams, SyncV2TransactionTest): - pass diff --git a/tests/tx/test_tx_serialization.py b/tests/tx/test_tx_serialization.py index c32986025..eebe37162 100644 --- a/tests/tx/test_tx_serialization.py +++ b/tests/tx/test_tx_serialization.py @@ -6,7 +6,7 @@ from tests.utils import add_blocks_unlock_reward -class _SerializationTest(unittest.TestCase): +class BaseSerializationTest(unittest.TestCase): __test__ = False def setUp(self): @@ -63,68 +63,38 @@ def test_serialization_genesis(self): self._assertTxEq(tx, tx_re) -class _SerializationV2OnlyTest(unittest.TestCase): - __test__ = False - - def test_serialization_tips(self): - from itertools import chain - it_mempool_tips = (x.hash for x in self.manager.tx_storage.indexes.mempool_tips.iter(self.manager.tx_storage)) - it_block_height_entries = iter([self.tx_storage.indexes.height.get_tip()]) - for tx_hash in chain(it_mempool_tips, it_block_height_entries): - tx = self.tx_storage.get_transaction(tx_hash) - tx_re = self._reserialize(tx) - self._assertTxEq(tx, tx_re) - +class NoSerializationTest(BaseSerializationTest): + """This should absolutely not fail, or the tests are wrong.""" -class _SerializationWithoutMetadataTest(_SerializationTest): - def _assertTxEq(self, tx1, tx2): - self.log.info('assertEqual tx without metadata', a=tx1.to_json(), b=tx2.to_json()) - self.assertEqual(tx1, tx2) + __test__ = True + def _reserialize(self, tx): + return tx -class _SerializationWithMetadataTest(_SerializationTest): def _assertTxEq(self, tx1, tx2): self.log.info('assertEqual tx with metadata', a=tx1.to_json(), b=tx2.to_json()) self.assertEqual(tx1, tx2) self.log.info('assertEqual tx metadata', a=tx1.get_metadata().to_json(), b=tx2.get_metadata().to_json()) self.assertEqual(tx1.get_metadata(), tx2.get_metadata()) - -class BaseNoSerializationTest(_SerializationWithMetadataTest): - """This should absolutely not fail, or the tests are wrong.""" - - def _reserialize(self, tx): - return tx - - -class SyncV1NoSerializationTest(unittest.SyncV1Params, BaseNoSerializationTest): - __test__ = True + def test_serialization_tips(self): + from itertools import chain + it_mempool_tips = (x.hash for x in self.manager.tx_storage.indexes.mempool_tips.iter(self.manager.tx_storage)) + it_block_height_entries = iter([self.tx_storage.indexes.height.get_tip()]) + for tx_hash in chain(it_mempool_tips, it_block_height_entries): + tx = self.tx_storage.get_transaction(tx_hash) + tx_re = self._reserialize(tx) + self._assertTxEq(tx, tx_re) -class SyncV2NoSerializationTest(unittest.SyncV2Params, BaseNoSerializationTest, _SerializationV2OnlyTest): +class StructSerializationTest(BaseSerializationTest): __test__ = True - -# sync-bridge should behave like sync-v2 -class SyncBridgeNoSerializationTest(unittest.SyncBridgeParams, SyncV2NoSerializationTest): - pass - - -class BaseStructSerializationTest(_SerializationWithoutMetadataTest): def _reserialize(self, tx): cls = tx.__class__ tx_struct = tx.get_struct() return cls.create_from_struct(tx_struct) - -class SyncV1StructSerializationTest(unittest.SyncV1Params, BaseStructSerializationTest): - __test__ = True - - -class SyncV2StructSerializationTest(unittest.SyncV2Params, BaseStructSerializationTest, _SerializationV2OnlyTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeStructSerializationTest(unittest.SyncBridgeParams, SyncV2StructSerializationTest): - pass + def _assertTxEq(self, tx1, tx2): + self.log.info('assertEqual tx without metadata', a=tx1.to_json(), b=tx2.to_json()) + self.assertEqual(tx1, tx2) diff --git a/tests/tx/test_verification.py b/tests/tx/test_verification.py index ee92a3f22..15a6fa3f7 100644 --- a/tests/tx/test_verification.py +++ b/tests/tx/test_verification.py @@ -29,13 +29,12 @@ from tests.utils import add_blocks_unlock_reward, create_tokens, get_genesis_key -class BaseVerificationTest(unittest.TestCase): +class VerificationTest(unittest.TestCase): """ This module implements simple tests related to vertex verification. It does not test the implementation of verification methods, but rather simply asserts that each verification method is called when it is supposed to be called. This guarantee is mostly useful during the verification refactors. """ - __test__ = False def setUp(self) -> None: super().setUp() @@ -1089,16 +1088,3 @@ def test_token_creation_transaction_validate_full(self) -> None: # TokenCreationTransaction methods verify_token_info_wrapped.assert_called_once() verify_minted_tokens_wrapped.assert_called_once() - - -class SyncV1VerificationTest(unittest.SyncV1Params, BaseVerificationTest): - __test__ = True - - -class SyncV2VerificationTest(unittest.SyncV2Params, BaseVerificationTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeVerificationTest(unittest.SyncBridgeParams, SyncV2VerificationTest): - pass diff --git a/tests/unittest.py b/tests/unittest.py index 4a659f6bd..0992b636b 100644 --- a/tests/unittest.py +++ b/tests/unittest.py @@ -19,9 +19,7 @@ from hathor.event.storage import EventStorage from hathor.manager import HathorManager from hathor.p2p.peer import PrivatePeer -from hathor.p2p.sync_v1.agent import NodeSyncTimestamp from hathor.p2p.sync_v2.agent import NodeBlockSync -from hathor.p2p.sync_version import SyncVersion from hathor.pubsub import PubSubManager from hathor.reactor import ReactorProtocol as Reactor, get_global_reactor from hathor.simulator.clock import MemoryReactorHeapClock @@ -64,23 +62,6 @@ def _get_default_peer_id_pool_filepath() -> str: PEER_ID_POOL = list(_load_peer_pool()) -# XXX: Sync*Params classes should be inherited before the TestCase class when a sync version is needed - - -class SyncV1Params: - _enable_sync_v1 = True - _enable_sync_v2 = False - - -class SyncV2Params: - _enable_sync_v1 = False - _enable_sync_v2 = True - - -class SyncBridgeParams: - _enable_sync_v1 = True - _enable_sync_v2 = True - class TestBuilder(Builder): __test__ = False @@ -110,8 +91,6 @@ def _get_reactor(self) -> Reactor: class TestCase(unittest.TestCase): - _enable_sync_v1: bool - _enable_sync_v2: bool use_memory_storage: bool = USE_MEMORY_STORAGE seed_config: Optional[int] = None @@ -216,8 +195,6 @@ def create_peer( # type: ignore[no-untyped-def] wallet_index: bool = False, capabilities: list[str] | None = None, full_verification: bool = True, - enable_sync_v1: bool | None = None, - enable_sync_v2: bool | None = None, checkpoints: list[Checkpoint] | None = None, utxo_index: bool = False, event_manager: EventManager | None = None, @@ -230,7 +207,6 @@ def create_peer( # type: ignore[no-untyped-def] enable_ipv6: bool = False, disable_ipv4: bool = False, ): # TODO: Add -> HathorManager here. It breaks the lint in a lot of places. - enable_sync_v1, enable_sync_v2 = self._syncVersionFlags(enable_sync_v1, enable_sync_v2) settings = self._settings._replace(NETWORK_NAME=network) builder = self.get_builder() \ @@ -276,16 +252,6 @@ def create_peer( # type: ignore[no-untyped-def] if use_memory_index is True: builder.force_memory_index() - if enable_sync_v1 is True: - builder.enable_sync_v1() - elif enable_sync_v1 is False: - builder.disable_sync_v1() - - if enable_sync_v2 is True: - builder.enable_sync_v2() - elif enable_sync_v2 is False: - builder.disable_sync_v2() - if wallet_index: builder.enable_wallet_index() @@ -305,10 +271,6 @@ def create_peer( # type: ignore[no-untyped-def] builder.set_daa(daa) manager = self.create_peer_from_builder(builder, start_manager=start_manager) - # XXX: just making sure that tests set this up correctly - assert manager.connections.is_sync_version_enabled(SyncVersion.V2) == enable_sync_v2 - assert manager.connections.is_sync_version_enabled(SyncVersion.V1_1) == enable_sync_v1 - return manager def run_to_completion(self) -> None: @@ -333,45 +295,14 @@ def assertIsTopological(self, tx_sequence: Iterator[BaseTransaction], message: O self.assertIn(dep, valid_deps, message) valid_deps.add(tx.hash) - def _syncVersionFlags( - self, - enable_sync_v1: bool | None = None, - enable_sync_v2: bool | None = None - ) -> tuple[bool, bool]: - """Internal: use this to check and get the flags and optionally provide override values.""" - if enable_sync_v1 is None: - assert hasattr(self, '_enable_sync_v1'), ('`_enable_sync_v1` has no default by design, either set one on ' - 'the test class or pass `enable_sync_v1` by argument') - enable_sync_v1 = self._enable_sync_v1 - if enable_sync_v2 is None: - assert hasattr(self, '_enable_sync_v2'), ('`_enable_sync_v2` has no default by design, either set one on ' - 'the test class or pass `enable_sync_v2` by argument') - enable_sync_v2 = self._enable_sync_v2 - assert enable_sync_v1 or enable_sync_v2, 'enable at least one sync version' - return enable_sync_v1, enable_sync_v2 - def assertTipsEqual(self, manager1: HathorManager, manager2: HathorManager) -> None: - _, enable_sync_v2 = self._syncVersionFlags() - if enable_sync_v2: - self.assertTipsEqualSyncV2(manager1, manager2) - else: - self.assertTipsEqualSyncV1(manager1, manager2) + self.assertTipsEqualSyncV2(manager1, manager2) def assertTipsNotEqual(self, manager1: HathorManager, manager2: HathorManager) -> None: s1 = set(manager1.tx_storage.get_all_tips()) s2 = set(manager2.tx_storage.get_all_tips()) self.assertNotEqual(s1, s2) - def assertTipsEqualSyncV1(self, manager1: HathorManager, manager2: HathorManager) -> None: - # XXX: this is the original implementation of assertTipsEqual - s1 = set(manager1.tx_storage.get_all_tips()) - s2 = set(manager2.tx_storage.get_all_tips()) - self.assertEqual(s1, s2) - - s1 = set(manager1.tx_storage.get_tx_tips()) - s2 = set(manager2.tx_storage.get_tx_tips()) - self.assertEqual(s1, s2) - def assertTipsEqualSyncV2( self, manager1: HathorManager, @@ -404,32 +335,7 @@ def assertTipsEqualSyncV2( self.assertIn(b2, s1) def assertConsensusEqual(self, manager1: HathorManager, manager2: HathorManager) -> None: - _, enable_sync_v2 = self._syncVersionFlags() - if enable_sync_v2: - self.assertConsensusEqualSyncV2(manager1, manager2) - else: - self.assertConsensusEqualSyncV1(manager1, manager2) - - def assertConsensusEqualSyncV1(self, manager1: HathorManager, manager2: HathorManager) -> None: - self.assertEqual(manager1.tx_storage.get_vertices_count(), manager2.tx_storage.get_vertices_count()) - for tx1 in manager1.tx_storage.get_all_transactions(): - tx2 = manager2.tx_storage.get_transaction(tx1.hash) - tx1_meta = tx1.get_metadata() - tx2_meta = tx2.get_metadata() - # conflict_with's type is Optional[list[bytes]], so we convert to a set because order does not matter. - self.assertEqual(set(tx1_meta.conflict_with or []), set(tx2_meta.conflict_with or [])) - # Soft verification - if tx1_meta.voided_by is None: - # If tx1 is not voided, then tx2 must be not voided. - self.assertIsNone(tx2_meta.voided_by) - else: - # If tx1 is voided, then tx2 must be voided. - assert tx1_meta.voided_by is not None - assert tx2_meta.voided_by is not None - self.assertGreaterEqual(len(tx1_meta.voided_by), 1) - self.assertGreaterEqual(len(tx2_meta.voided_by), 1) - # Hard verification - # self.assertEqual(tx1_meta.voided_by, tx2_meta.voided_by) + self.assertConsensusEqualSyncV2(manager1, manager2) def assertConsensusEqualSyncV2( self, @@ -530,18 +436,9 @@ def assertTransactionConsensusValid(self, tx: Transaction) -> None: self.assertTrue(meta.voided_by) self.assertTrue(parent_meta.voided_by.issubset(meta.voided_by)) - def assertSyncedProgress(self, node_sync: NodeSyncTimestamp | NodeBlockSync) -> None: + def assertSyncedProgress(self, node_sync: NodeBlockSync) -> None: """Check "synced" status of p2p-manager, uses self._enable_sync_vX to choose which check to run.""" - enable_sync_v1, enable_sync_v2 = self._syncVersionFlags() - if enable_sync_v2: - assert isinstance(node_sync, NodeBlockSync) - self.assertV2SyncedProgress(node_sync) - elif enable_sync_v1: - assert isinstance(node_sync, NodeSyncTimestamp) - self.assertV1SyncedProgress(node_sync) - - def assertV1SyncedProgress(self, node_sync: NodeSyncTimestamp) -> None: - self.assertEqual(node_sync.synced_timestamp, node_sync.peer_timestamp) + self.assertV2SyncedProgress(node_sync) def assertV2SyncedProgress(self, node_sync: NodeBlockSync) -> None: self.assertEqual(node_sync.synced_block, node_sync.peer_best_block) diff --git a/tests/wallet/test_balance_update.py b/tests/wallet/test_balance_update.py index c4e5981e0..c7148546c 100644 --- a/tests/wallet/test_balance_update.py +++ b/tests/wallet/test_balance_update.py @@ -8,9 +8,7 @@ from tests.utils import add_blocks_unlock_reward, create_tokens -class BaseHathorSyncMethodsTestCase(unittest.TestCase): - __test__ = False - +class HathorSyncMethodsTestCase(unittest.TestCase): def setUp(self): super().setUp() @@ -435,16 +433,3 @@ def test_tokens_balance(self): balances_per_address = self.manager.wallet.get_balance_per_address(self._settings.HATHOR_TOKEN_UID) self.assertEqual(hathor_balance.available, sum(x for x in balances_per_address.values())) - - -class SyncV1HathorSyncMethodsTestCase(unittest.SyncV1Params, BaseHathorSyncMethodsTestCase): - __test__ = True - - -class SyncV2HathorSyncMethodsTestCase(unittest.SyncV2Params, BaseHathorSyncMethodsTestCase): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeHathorSyncMethodsTestCase(unittest.SyncBridgeParams, SyncV2HathorSyncMethodsTestCase): - pass diff --git a/tests/wallet/test_index.py b/tests/wallet/test_index.py index 3a4fb7935..803ae3129 100644 --- a/tests/wallet/test_index.py +++ b/tests/wallet/test_index.py @@ -6,9 +6,7 @@ from tests.utils import add_blocks_unlock_reward -class BaseWalletIndexTest(unittest.TestCase): - __test__ = False - +class WalletIndexTest(unittest.TestCase): def setUp(self): super().setUp() @@ -54,16 +52,3 @@ def test_twin_tx(self): wallet_data = self.manager.tx_storage.indexes.addresses.get_from_address(address) self.assertEqual(len(wallet_data), 2) self.assertEqual(set(wallet_data), set([tx1.hash, tx2.hash])) - - -class SyncV1WalletIndexTest(unittest.SyncV1Params, BaseWalletIndexTest): - __test__ = True - - -class SyncV2WalletIndexTest(unittest.SyncV2Params, BaseWalletIndexTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeWalletIndexTest(unittest.SyncBridgeParams, SyncV2WalletIndexTest): - pass diff --git a/tests/wallet/test_wallet.py b/tests/wallet/test_wallet.py index 72d6bf698..48d1890b8 100644 --- a/tests/wallet/test_wallet.py +++ b/tests/wallet/test_wallet.py @@ -19,9 +19,7 @@ PASSWORD = b'passwd' -class BaseBasicWalletTest(unittest.TestCase): - __test__ = False - +class BasicWalletTest(unittest.TestCase): def setUp(self): super().setUp() self.directory = tempfile.mkdtemp() @@ -270,16 +268,3 @@ def test_maybe_spent_txs(self): self.assertTrue(self.manager.on_new_tx(tx2, fails_silently=False)) self.clock.advance(2) self.assertEqual(0, len(w.maybe_spent_txs[self._settings.HATHOR_TOKEN_UID])) - - -class SyncV1BasicWalletTest(unittest.SyncV1Params, BaseBasicWalletTest): - __test__ = True - - -class SyncV2BasicWalletTest(unittest.SyncV2Params, BaseBasicWalletTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeBasicWalletTest(unittest.SyncBridgeParams, SyncV2BasicWalletTest): - pass diff --git a/tests/wallet/test_wallet_hd.py b/tests/wallet/test_wallet_hd.py index 3366df47c..398b3767b 100644 --- a/tests/wallet/test_wallet_hd.py +++ b/tests/wallet/test_wallet_hd.py @@ -8,9 +8,7 @@ from tests.utils import add_blocks_unlock_reward -class BaseWalletHDTest(unittest.TestCase): - __test__ = False - +class WalletHDTest(unittest.TestCase): def setUp(self): super().setUp() self.wallet = HDWallet(gap_limit=2) @@ -110,16 +108,3 @@ def test_lock(self): def test_exceptions(self): with self.assertRaises(ValueError): HDWallet(word_count=3) - - -class SyncV1WalletHDTest(unittest.SyncV1Params, BaseWalletHDTest): - __test__ = True - - -class SyncV2WalletHDTest(unittest.SyncV2Params, BaseWalletHDTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeWalletHDTest(unittest.SyncBridgeParams, SyncV2WalletHDTest): - pass diff --git a/tests/websocket/test_async_iterators.py b/tests/websocket/test_async_iterators.py index a3435e723..0cab7af54 100644 --- a/tests/websocket/test_async_iterators.py +++ b/tests/websocket/test_async_iterators.py @@ -27,9 +27,6 @@ async def async_islice(iterable: AsyncIterator[T], stop: int) -> AsyncIterator[T class AsyncIteratorsTestCase(TestCase): - _enable_sync_v1 = True - _enable_sync_v2 = True - def setUp(self) -> None: super().setUp() diff --git a/tests/websocket/test_streamer.py b/tests/websocket/test_streamer.py index 87c4a5407..9436c6215 100644 --- a/tests/websocket/test_streamer.py +++ b/tests/websocket/test_streamer.py @@ -12,9 +12,6 @@ class AsyncIteratorsTestCase(TestCase): - _enable_sync_v1 = True - _enable_sync_v2 = True - WS_PROTOCOL_MESSAGE_SEPARATOR = b'\x81' def test_streamer(self) -> None: diff --git a/tests/websocket/test_websocket.py b/tests/websocket/test_websocket.py index 3b1df54cd..9ee0e44a5 100644 --- a/tests/websocket/test_websocket.py +++ b/tests/websocket/test_websocket.py @@ -9,13 +9,10 @@ from hathor.wallet.base_wallet import SpentTx, UnspentTx, WalletBalance from hathor.websocket import WebsocketStatsResource from hathor.websocket.factory import HathorAdminWebsocketFactory, HathorAdminWebsocketProtocol -from tests import unittest from tests.resources.base_resource import StubSite, _BaseResourceTest -class BaseWebsocketTest(_BaseResourceTest._ResourceTest): - __test__ = False - +class WebsocketTest(_BaseResourceTest._ResourceTest): def setUp(self): super().setUp() @@ -228,16 +225,3 @@ def test_get_stats(self): data = response.json_value() self.assertEqual(data['connections'], 1) self.assertEqual(data['subscribed_addresses'], 2) - - -class SyncV1WebsocketTest(unittest.SyncV1Params, BaseWebsocketTest): - __test__ = True - - -class SyncV2WebsocketTest(unittest.SyncV2Params, BaseWebsocketTest): - __test__ = True - - -# sync-bridge should behave like sync-v2 -class SyncBridgeWebsocketTest(unittest.SyncBridgeParams, SyncV2WebsocketTest): - pass