diff --git a/requirements-core.txt b/requirements-core.txt index 451c2f5b3d2..134300c179d 100644 --- a/requirements-core.txt +++ b/requirements-core.txt @@ -23,3 +23,4 @@ libtorrent==1.2.19 file-read-backwards==3.0.0 Brotli==1.0.9 # to prevent AttributeError on macOs: module 'brotli' has no attribute 'error' (in urllib3.response) human-readable==1.3.2 +typing_extensions==4.7.1 diff --git a/src/tribler/core/components/bandwidth_accounting/bandwidth_accounting_component.py b/src/tribler/core/components/bandwidth_accounting/bandwidth_accounting_component.py index 9686af225e9..7e29fc31f11 100644 --- a/src/tribler/core/components/bandwidth_accounting/bandwidth_accounting_component.py +++ b/src/tribler/core/components/bandwidth_accounting/bandwidth_accounting_component.py @@ -1,6 +1,7 @@ from tribler.core.components.bandwidth_accounting.community.bandwidth_accounting_community import ( BandwidthAccountingCommunity, BandwidthAccountingTestnetCommunity, + BandwidthCommunitySettings, ) from tribler.core.components.bandwidth_accounting.db.database import BandwidthDatabase from tribler.core.components.component import Component @@ -40,12 +41,14 @@ async def run(self): store_all_transactions=store_all_transactions) kwargs = {"max_peers": -1} if unlimited_peers else {} - self.community = bandwidth_cls(self._ipv8_component.peer, - self._ipv8_component.ipv8.endpoint, - self._ipv8_component.ipv8.network, - settings=config.bandwidth_accounting, - database=self.database, - **kwargs) + self.community = bandwidth_cls(BandwidthCommunitySettings( + my_peer=self._ipv8_component.peer, + endpoint=self._ipv8_component.ipv8.endpoint, + network=self._ipv8_component.ipv8.network, + settings=config.bandwidth_accounting, + database=self.database, + **kwargs + )) self._ipv8_component.initialise_community_by_default(self.community) diff --git a/src/tribler/core/components/bandwidth_accounting/community/bandwidth_accounting_community.py b/src/tribler/core/components/bandwidth_accounting/community/bandwidth_accounting_community.py index 4c3dd4df1a7..7d55565ad62 100644 --- a/src/tribler/core/components/bandwidth_accounting/community/bandwidth_accounting_community.py +++ b/src/tribler/core/components/bandwidth_accounting/community/bandwidth_accounting_community.py @@ -16,10 +16,14 @@ ) from tribler.core.components.bandwidth_accounting.db.database import BandwidthDatabase from tribler.core.components.bandwidth_accounting.db.transaction import BandwidthTransactionData, EMPTY_SIGNATURE -from tribler.core.components.ipv8.tribler_community import TriblerCommunity +from tribler.core.components.ipv8.tribler_community import TriblerCommunity, TriblerSettings from tribler.core.utilities.unicode import hexlify +class BandwidthCommunitySettings(TriblerSettings): + database: BandwidthDatabase | None = None + + class BandwidthAccountingCommunity(TriblerCommunity): """ Community around bandwidth accounting and payouts. @@ -27,17 +31,18 @@ class BandwidthAccountingCommunity(TriblerCommunity): community_id = unhexlify('79b25f2867739261780faefede8f25038de9975d') DB_NAME = 'bandwidth' version = b'\x02' + settings_class = BandwidthCommunitySettings - def __init__(self, *args, **kwargs) -> None: + def __init__(self, settings: BandwidthCommunitySettings) -> None: """ Initialize the community. :param persistence: The database that stores transactions, will be created if not provided. :param database_path: The path at which the database will be created. Defaults to the current working directory. """ - self.database: BandwidthDatabase = kwargs.pop('database', None) + self.database = settings.database self.random = Random() - super().__init__(*args, **kwargs) + super().__init__(settings) self.request_cache = RequestCache() self.my_pk = self.my_peer.public_key.key_to_bin() diff --git a/src/tribler/core/components/bandwidth_accounting/tests/test_bandwidth_endpoint.py b/src/tribler/core/components/bandwidth_accounting/tests/test_bandwidth_endpoint.py index 05cb22574e1..39567310d41 100644 --- a/src/tribler/core/components/bandwidth_accounting/tests/test_bandwidth_endpoint.py +++ b/src/tribler/core/components/bandwidth_accounting/tests/test_bandwidth_endpoint.py @@ -4,7 +4,7 @@ from ipv8.test.mocking.ipv8 import MockIPv8 from tribler.core.components.bandwidth_accounting.community.bandwidth_accounting_community import ( - BandwidthAccountingCommunity, + BandwidthAccountingCommunity, BandwidthCommunitySettings, ) from tribler.core.components.bandwidth_accounting.db.database import BandwidthDatabase from tribler.core.components.bandwidth_accounting.db.transaction import BandwidthTransactionData, EMPTY_SIGNATURE @@ -27,9 +27,10 @@ def bandwidth_database(tmp_path, peer): @pytest.fixture async def bw_community(bandwidth_database, peer): - ipv8 = MockIPv8(peer, BandwidthAccountingCommunity, - database=bandwidth_database, - settings=BandwidthAccountingSettings()) + ipv8 = MockIPv8(peer, BandwidthAccountingCommunity, BandwidthCommunitySettings( + database=bandwidth_database, + settings=BandwidthAccountingSettings() + )) community = ipv8.get_overlay(BandwidthAccountingCommunity) yield community await ipv8.stop() diff --git a/src/tribler/core/components/bandwidth_accounting/tests/test_community.py b/src/tribler/core/components/bandwidth_accounting/tests/test_community.py index 3b92360fa49..daa2a51a3b1 100644 --- a/src/tribler/core/components/bandwidth_accounting/tests/test_community.py +++ b/src/tribler/core/components/bandwidth_accounting/tests/test_community.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from ipv8.keyvault.crypto import default_eccrypto from ipv8.peer import Peer from ipv8.test.base import TestBase @@ -5,6 +7,7 @@ from tribler.core.components.bandwidth_accounting.community.bandwidth_accounting_community import ( BandwidthAccountingCommunity, + BandwidthCommunitySettings, ) from tribler.core.components.bandwidth_accounting.community.cache import BandwidthTransactionSignCache from tribler.core.components.bandwidth_accounting.db.database import BandwidthDatabase @@ -21,11 +24,17 @@ def setUp(self): super().setUp() self.initialize(BandwidthAccountingCommunity, 2) - def create_node(self): + def create_node(self, settings: BandwidthCommunitySettings | None = None, # pylint: disable=unused-argument + create_dht: bool = False, enable_statistics: bool = False): # pylint: disable=unused-argument peer = Peer(default_eccrypto.generate_key("curve25519"), address=("1.2.3.4", 5)) - db = BandwidthDatabase(db_path=MEMORY_DB, my_pub_key=peer.public_key.key_to_bin()) - ipv8 = MockIPv8(peer, BandwidthAccountingCommunity, database=db, - settings=BandwidthAccountingSettings()) + db = BandwidthDatabase(db_path=MEMORY_DB, + my_pub_key=peer.public_key.key_to_bin()) + ipv8 = MockIPv8(peer, + BandwidthAccountingCommunity, + BandwidthCommunitySettings( + database=db, + settings=BandwidthAccountingSettings() + )) return ipv8 def database(self, i): diff --git a/src/tribler/core/components/gigachannel/community/gigachannel_community.py b/src/tribler/core/components/gigachannel/community/gigachannel_community.py index f00d939535c..7c0cc55e3a7 100644 --- a/src/tribler/core/components/gigachannel/community/gigachannel_community.py +++ b/src/tribler/core/components/gigachannel/community/gigachannel_community.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import time import uuid from binascii import unhexlify @@ -13,7 +15,10 @@ from tribler.core.components.ipv8.discovery_booster import DiscoveryBooster from tribler.core.components.metadata_store.db.serialization import CHANNEL_TORRENT from tribler.core.components.metadata_store.remote_query_community.payload_checker import ObjState -from tribler.core.components.metadata_store.remote_query_community.remote_query_community import RemoteQueryCommunity +from tribler.core.components.metadata_store.remote_query_community.remote_query_community import ( + RemoteCommunitySettings, + RemoteQueryCommunity +) from tribler.core.components.metadata_store.utils import NoChannelSourcesException from tribler.core.utilities.notifier import Notifier from tribler.core.utilities.simpledefs import CHANNELS_VIEW_UUID @@ -70,8 +75,13 @@ def get_last_seen_peers_for_channel(self, channel_pk: bytes, channel_id: int, li return sorted(channel_peers, key=lambda x: x.last_response, reverse=True)[0:limit] +class GigaCommunitySettings(RemoteCommunitySettings): + notifier: Notifier | None = None + + class GigaChannelCommunity(RemoteQueryCommunity): community_id = unhexlify('d3512d0ff816d8ac672eab29a9c1a3a32e17cb13') + settings_class = GigaCommunitySettings def create_introduction_response( self, @@ -94,14 +104,12 @@ def create_introduction_response( new_style=new_style, ) - def __init__( - self, *args, notifier: Notifier = None, **kwargs - ): # pylint: disable=unused-argument + def __init__(self, settings: GigaCommunitySettings): # pylint: disable=unused-argument # ACHTUNG! We create a separate instance of Network for this community because it # walks aggressively and wants lots of peers, which can interfere with other communities - super().__init__(*args, **kwargs) + super().__init__(settings) - self.notifier = notifier + self.notifier = settings.notifier # This set contains all the peers that we queried for subscribed channels over time. # It is emptied regularly. The purpose of this set is to work as a filter so we never query the same diff --git a/src/tribler/core/components/gigachannel/community/tests/test_gigachannel_community.py b/src/tribler/core/components/gigachannel/community/tests/test_gigachannel_community.py index a4938f05fb9..5df19605ccc 100644 --- a/src/tribler/core/components/gigachannel/community/tests/test_gigachannel_community.py +++ b/src/tribler/core/components/gigachannel/community/tests/test_gigachannel_community.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import time from collections.abc import Mapping from dataclasses import asdict, dataclass, fields @@ -5,6 +7,8 @@ from unittest.mock import AsyncMock, Mock import pytest + +from ipv8.community import CommunitySettings from ipv8.keyvault.crypto import default_eccrypto from ipv8.peer import Peer from ipv8.test.base import TestBase @@ -13,7 +17,7 @@ from tribler.core.components.gigachannel.community.gigachannel_community import ( ChannelsPeersMapping, GigaChannelCommunity, - NoChannelSourcesException, + GigaCommunitySettings, NoChannelSourcesException, happy_eyeballs_delay ) from tribler.core.components.gigachannel.community.settings import ChantSettings @@ -66,7 +70,8 @@ async def tearDown(self): metadata_store.shutdown() await super().tearDown() - def create_node(self, *args, **kwargs): + def create_node(self, settings: CommunitySettings | None = None, # pylint: disable=unused-argument + create_dht: bool = False, enable_statistics: bool = False): # pylint: disable=unused-argument metadata_store = MetadataStore( Path(self.temporary_directory()) / f"{self.count}.db", Path(self.temporary_directory()), @@ -74,10 +79,11 @@ def create_node(self, *args, **kwargs): disable_sync=True, ) self.metadata_store_set.add(metadata_store) - kwargs['metadata_store'] = metadata_store - kwargs['settings'] = ChantSettings() - kwargs['rqc_settings'] = RemoteQueryCommunitySettings() - node = super().create_node(*args, **kwargs) + node = super().create_node(GigaCommunitySettings( + metadata_store=metadata_store, + settings=ChantSettings(), + rqc_settings=RemoteQueryCommunitySettings() + )) node.overlay.discovery_booster.finish() notifier = Notifier(loop=self.loop) diff --git a/src/tribler/core/components/gigachannel/gigachannel_component.py b/src/tribler/core/components/gigachannel/gigachannel_component.py index 527f57a75d9..9f5f3e8f7ed 100644 --- a/src/tribler/core/components/gigachannel/gigachannel_component.py +++ b/src/tribler/core/components/gigachannel/gigachannel_component.py @@ -4,7 +4,7 @@ from tribler.core.components.database.database_component import DatabaseComponent from tribler.core.components.gigachannel.community.gigachannel_community import ( GigaChannelCommunity, - GigaChannelTestnetCommunity, + GigaChannelTestnetCommunity, GigaCommunitySettings, ) from tribler.core.components.gigachannel.community.sync_strategy import RemovePeers from tribler.core.components.ipv8.ipv8_component import INFINITE, Ipv8Component @@ -29,17 +29,17 @@ async def run(self): db_component = await self.get_component(DatabaseComponent) giga_channel_cls = GigaChannelTestnetCommunity if config.general.testnet else GigaChannelCommunity - community = giga_channel_cls( - self._ipv8_component.peer, - self._ipv8_component.ipv8.endpoint, - Network(), + community = giga_channel_cls(GigaCommunitySettings( + my_peer=self._ipv8_component.peer, + endpoint=self._ipv8_component.ipv8.endpoint, + network=Network(), notifier=notifier, settings=config.chant, rqc_settings=config.remote_query_community, metadata_store=metadata_store_component.mds, max_peers=50, tribler_db=db_component.db if db_component else None - ) + )) self.community = community self._ipv8_component.initialise_community_by_default(community, default_random_walk_max_peers=30) self._ipv8_component.ipv8.add_strategy(community, RemovePeers(community), INFINITE) diff --git a/src/tribler/core/components/ipv8/ipv8_component.py b/src/tribler/core/components/ipv8/ipv8_component.py index 7b07d4a332e..d123f2c980e 100644 --- a/src/tribler/core/components/ipv8/ipv8_component.py +++ b/src/tribler/core/components/ipv8/ipv8_component.py @@ -1,6 +1,7 @@ from typing import Optional from ipv8.bootstrapping.dispersy.bootstrapper import DispersyBootstrapper +from ipv8.community import CommunitySettings from ipv8.configuration import ConfigBuilder, DISPERSY_BOOTSTRAPPER from ipv8.dht.churn import PingChurn from ipv8.dht.discovery import DHTDiscoveryCommunity @@ -112,7 +113,12 @@ def make_bootstrapper(self) -> DispersyBootstrapper: def _init_peer_discovery_community(self): ipv8 = self.ipv8 - community = DiscoveryCommunity(self.peer, ipv8.endpoint, ipv8.network, max_peers=100) + community = DiscoveryCommunity(CommunitySettings( + my_peer=self.peer, + endpoint=ipv8.endpoint, + network=ipv8.network, + max_peers=100 + )) self.initialise_community_by_default(community) ipv8.add_strategy(community, RandomChurn(community), INFINITE) ipv8.add_strategy(community, PeriodicSimilarity(community), INFINITE) @@ -120,7 +126,12 @@ def _init_peer_discovery_community(self): def _init_dht_discovery_community(self): ipv8 = self.ipv8 - community = DHTDiscoveryCommunity(self.peer, ipv8.endpoint, ipv8.network, max_peers=60) + community = DHTDiscoveryCommunity(CommunitySettings( + my_peer=self.peer, + endpoint=ipv8.endpoint, + network=ipv8.network, + max_peers=60 + )) self.initialise_community_by_default(community) ipv8.add_strategy(community, PingChurn(community), INFINITE) self.dht_discovery_community = community @@ -136,4 +147,4 @@ async def shutdown(self): await self.ipv8.unload_overlay(overlay) await self._task_manager.shutdown_task_manager() - await self.ipv8.stop(stop_loop=False) + await self.ipv8.stop() diff --git a/src/tribler/core/components/ipv8/tribler_community.py b/src/tribler/core/components/ipv8/tribler_community.py index 018d4ecdd56..a8a9779dc79 100644 --- a/src/tribler/core/components/ipv8/tribler_community.py +++ b/src/tribler/core/components/ipv8/tribler_community.py @@ -1,13 +1,21 @@ -from ipv8.community import Community +from __future__ import annotations + +from ipv8.community import Community, CommunitySettings from tribler.core.config.tribler_config_section import TriblerConfigSection +class TriblerSettings(CommunitySettings): + settings: TriblerConfigSection | None = None + + class TriblerCommunity(Community): """Base class for Tribler communities. """ - def __init__(self, *args, settings: TriblerConfigSection = None, **kwargs): - super().__init__(*args, **kwargs) - self.settings = settings + settings_class = TriblerSettings + + def __init__(self, settings: TriblerSettings): + super().__init__(settings) + self.settings = settings.settings self.logger.info(f'Init. Settings: {settings}.') diff --git a/src/tribler/core/components/knowledge/community/knowledge_community.py b/src/tribler/core/components/knowledge/community/knowledge_community.py index 6f276fc7962..4eac8a6083a 100644 --- a/src/tribler/core/components/knowledge/community/knowledge_community.py +++ b/src/tribler/core/components/knowledge/community/knowledge_community.py @@ -7,7 +7,7 @@ from ipv8.types import Key from pony.orm import db_session -from tribler.core.components.ipv8.tribler_community import TriblerCommunity +from tribler.core.components.ipv8.tribler_community import TriblerCommunity, TriblerSettings from tribler.core.components.knowledge.community.knowledge_payload import ( RawStatementOperationMessage, RequestStatementOperationMessage, @@ -26,6 +26,12 @@ CLEAR_ALL_REQUESTS_INTERVAL = 10 * 60 # 10 minutes +class KnowledgeSettings(TriblerSettings): + db: TriblerDatabase + key: LibNaCLSK + request_interval = REQUEST_INTERVAL + + class KnowledgeCommunity(TriblerCommunity): """ Community for disseminating tags across the network. @@ -33,18 +39,18 @@ class KnowledgeCommunity(TriblerCommunity): """ community_id = unhexlify('d7f7bdc8bcd3d9ad23f06f25aa8aab6754eb23a0') + settings_class = KnowledgeSettings - def __init__(self, *args, db: TriblerDatabase, key: LibNaCLSK, request_interval=REQUEST_INTERVAL, - **kwargs): - super().__init__(*args, **kwargs) - self.db = db - self.key = key + def __init__(self, settings: KnowledgeSettings): + super().__init__(settings) + self.db = settings.db + self.key = settings.key self.requests = OperationsRequests() self.add_message_handler(RawStatementOperationMessage, self.on_message) self.add_message_handler(RequestStatementOperationMessage, self.on_request) - self.register_task("request_operations", self.request_operations, interval=request_interval) + self.register_task("request_operations", self.request_operations, interval=settings.request_interval) self.register_task("clear_requests", self.requests.clear_requests, interval=CLEAR_ALL_REQUESTS_INTERVAL) self.logger.info('Knowledge community initialized') diff --git a/src/tribler/core/components/knowledge/community/tests/test_knowledge_community.py b/src/tribler/core/components/knowledge/community/tests/test_knowledge_community.py index 4f8d94ebd66..cf0dc3f0182 100644 --- a/src/tribler/core/components/knowledge/community/tests/test_knowledge_community.py +++ b/src/tribler/core/components/knowledge/community/tests/test_knowledge_community.py @@ -1,12 +1,15 @@ +from __future__ import annotations + import datetime from unittest.mock import MagicMock, Mock +from ipv8.community import CommunitySettings from ipv8.keyvault.private.libnaclkey import LibNaCLSK from ipv8.test.base import TestBase from ipv8.test.mocking.ipv8 import MockIPv8 from pony.orm import db_session -from tribler.core.components.knowledge.community.knowledge_community import KnowledgeCommunity +from tribler.core.components.knowledge.community.knowledge_community import KnowledgeCommunity, KnowledgeSettings from tribler.core.components.knowledge.community.knowledge_payload import StatementOperation from tribler.core.components.database.db.tribler_database import TriblerDatabase, Operation, ResourceType @@ -21,9 +24,13 @@ def setUp(self): async def tearDown(self): await super().tearDown() - def create_node(self, *args, **kwargs): - return MockIPv8("curve25519", KnowledgeCommunity, db=TriblerDatabase(), key=LibNaCLSK(), - request_interval=REQUEST_INTERVAL_FOR_RANDOM_OPERATIONS) + def create_node(self, settings: CommunitySettings | None = None, # pylint: disable=unused-argument + create_dht: bool = False, enable_statistics: bool = False): # pylint: disable=unused-argument + return MockIPv8("curve25519", KnowledgeCommunity, KnowledgeSettings( + db=TriblerDatabase(), + key=LibNaCLSK(), + request_interval=REQUEST_INTERVAL_FOR_RANDOM_OPERATIONS + )) def create_operation(self, subject='1' * 20, obj=''): community = self.overlay(0) diff --git a/src/tribler/core/components/knowledge/knowledge_component.py b/src/tribler/core/components/knowledge/knowledge_component.py index d1cfc487853..9f6a6e568f5 100644 --- a/src/tribler/core/components/knowledge/knowledge_component.py +++ b/src/tribler/core/components/knowledge/knowledge_component.py @@ -3,7 +3,7 @@ from tribler.core.components.database.database_component import DatabaseComponent from tribler.core.components.ipv8.ipv8_component import Ipv8Component from tribler.core.components.key.key_component import KeyComponent -from tribler.core.components.knowledge.community.knowledge_community import KnowledgeCommunity +from tribler.core.components.knowledge.community.knowledge_community import KnowledgeCommunity, KnowledgeSettings from tribler.core.components.knowledge.rules.knowledge_rules_processor import KnowledgeRulesProcessor from tribler.core.components.metadata_store.utils import generate_test_channels @@ -23,13 +23,13 @@ async def run(self): mds_component = await self.require_component(metadata_store_component.MetadataStoreComponent) db_component = await self.require_component(DatabaseComponent) - self.community = KnowledgeCommunity( - self._ipv8_component.peer, - self._ipv8_component.ipv8.endpoint, - self._ipv8_component.ipv8.network, + self.community = KnowledgeCommunity(KnowledgeSettings( + my_peer=self._ipv8_component.peer, + endpoint=self._ipv8_component.ipv8.endpoint, + network=self._ipv8_component.ipv8.network, db=db_component.db, key=key_component.secondary_key - ) + )) self.rules_processor = KnowledgeRulesProcessor( notifier=self.session.notifier, db=db_component.db, diff --git a/src/tribler/core/components/metadata_store/remote_query_community/remote_query_community.py b/src/tribler/core/components/metadata_store/remote_query_community/remote_query_community.py index 71d2e459875..367f5d021b8 100644 --- a/src/tribler/core/components/metadata_store/remote_query_community/remote_query_community.py +++ b/src/tribler/core/components/metadata_store/remote_query_community/remote_query_community.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import json import struct import time @@ -14,7 +16,7 @@ from tribler.core.components.ipv8.eva.protocol import EVAProtocol from tribler.core.components.ipv8.eva.result import TransferResult -from tribler.core.components.ipv8.tribler_community import TriblerCommunity +from tribler.core.components.ipv8.tribler_community import TriblerCommunity, TriblerSettings from tribler.core.components.knowledge.community.knowledge_validator import is_valid_resource from tribler.core.components.database.db.tribler_database import ResourceType from tribler.core.components.metadata_store.db.orm_bindings.channel_metadata import LZ4_EMPTY_ARCHIVE, entries_to_chunk @@ -128,21 +130,24 @@ def on_timeout(self): pass +class RemoteCommunitySettings(TriblerSettings): + rqc_settings: RemoteQueryCommunitySettings | None = None + metadata_store: MetadataStore | None = None + tribler_db = None + + class RemoteQueryCommunity(TriblerCommunity): """ Community for general purpose SELECT-like queries into remote Channels database """ + settings_class = RemoteCommunitySettings - def __init__(self, my_peer, endpoint, network, - rqc_settings: RemoteQueryCommunitySettings = None, - metadata_store=None, - tribler_db=None, - **kwargs): - super().__init__(my_peer, endpoint, network=network, **kwargs) + def __init__(self, settings: RemoteCommunitySettings): + super().__init__(settings) - self.rqc_settings = rqc_settings - self.mds: MetadataStore = metadata_store - self.tribler_db = tribler_db + self.rqc_settings = settings.rqc_settings + self.mds = settings.metadata_store + self.tribler_db = settings.tribler_db # This object stores requests for "select" queries that we sent to other hosts. # We keep track of peers we actually requested for data so people can't randomly push spam at us. # Also, this keeps track of hosts we responded to. There is a possibility that diff --git a/src/tribler/core/components/metadata_store/remote_query_community/tests/test_remote_query_community.py b/src/tribler/core/components/metadata_store/remote_query_community/tests/test_remote_query_community.py index a279b6ffaa3..ed565f8f66e 100644 --- a/src/tribler/core/components/metadata_store/remote_query_community/tests/test_remote_query_community.py +++ b/src/tribler/core/components/metadata_store/remote_query_community/tests/test_remote_query_community.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import asyncio import random import string @@ -9,6 +11,8 @@ from unittest.mock import Mock, patch import pytest + +from ipv8.community import CommunitySettings from ipv8.keyvault.crypto import default_eccrypto from ipv8.test.base import TestBase from pony.orm import db_session @@ -18,6 +22,7 @@ from tribler.core.components.metadata_store.db.serialization import CHANNEL_THUMBNAIL, CHANNEL_TORRENT, REGULAR_TORRENT from tribler.core.components.metadata_store.db.store import MetadataStore from tribler.core.components.metadata_store.remote_query_community.remote_query_community import ( + RemoteCommunitySettings, RemoteQueryCommunity, sanitize_query, ) @@ -73,7 +78,8 @@ async def tearDown(self): metadata_store.shutdown() await super().tearDown() - def create_node(self, *args, **kwargs): + def create_node(self, settings: CommunitySettings | None = None, # pylint: disable=unused-argument + create_dht: bool = False, enable_statistics: bool = False): # pylint: disable=unused-argument metadata_store = MetadataStore( Path(self.temporary_directory()) / f"{self.count}.db", Path(self.temporary_directory()), @@ -81,9 +87,8 @@ def create_node(self, *args, **kwargs): disable_sync=True, ) self.metadata_store_set.add(metadata_store) - kwargs['metadata_store'] = metadata_store - kwargs['rqc_settings'] = RemoteQueryCommunitySettings() - node = super().create_node(*args, **kwargs) + node = super().create_node(RemoteCommunitySettings(metadata_store=metadata_store, + rqc_settings=RemoteQueryCommunitySettings())) self.count += 1 return node diff --git a/src/tribler/core/components/metadata_store/remote_query_community/tests/test_remote_search_by_tags.py b/src/tribler/core/components/metadata_store/remote_query_community/tests/test_remote_search_by_tags.py index 6fcf1134af4..30a264796f8 100644 --- a/src/tribler/core/components/metadata_store/remote_query_community/tests/test_remote_search_by_tags.py +++ b/src/tribler/core/components/metadata_store/remote_query_community/tests/test_remote_search_by_tags.py @@ -1,6 +1,9 @@ +from __future__ import annotations + import os from unittest.mock import AsyncMock, Mock, PropertyMock, patch +from ipv8.community import CommunitySettings from ipv8.keyvault.crypto import default_eccrypto from ipv8.test.base import TestBase from pony.orm import db_session @@ -9,7 +12,10 @@ from tribler.core.components.database.db.tests.test_tribler_database import Resource, TestTagDB from tribler.core.components.metadata_store.db.orm_bindings.channel_node import NEW from tribler.core.components.metadata_store.db.store import MetadataStore -from tribler.core.components.metadata_store.remote_query_community.remote_query_community import RemoteQueryCommunity +from tribler.core.components.metadata_store.remote_query_community.remote_query_community import ( + RemoteCommunitySettings, + RemoteQueryCommunity +) from tribler.core.components.metadata_store.remote_query_community.settings import RemoteQueryCommunitySettings from tribler.core.components.metadata_store.remote_query_community.tests.test_remote_query_community import ( BasicRemoteQueryCommunity, @@ -37,7 +43,8 @@ async def tearDown(self): await super().tearDown() - def create_node(self, *args, **kwargs): + def create_node(self, settings: CommunitySettings | None = None, # pylint: disable=unused-argument + create_dht: bool = False, enable_statistics: bool = False): # pylint: disable=unused-argument self.metadata_store = MetadataStore( Path(self.temporary_directory()) / "mds.db", Path(self.temporary_directory()), @@ -46,10 +53,11 @@ def create_node(self, *args, **kwargs): ) self.tribler_db = TriblerDatabase(str(Path(self.temporary_directory()) / "tags.db")) - kwargs['metadata_store'] = self.metadata_store - kwargs['tribler_db'] = self.tribler_db - kwargs['rqc_settings'] = RemoteQueryCommunitySettings() - return super().create_node(*args, **kwargs) + return super().create_node(RemoteCommunitySettings( + metadata_store=self.metadata_store, + tribler_db=self.tribler_db, + rqc_settings=RemoteQueryCommunitySettings() + )) @property def rqc(self) -> RemoteQueryCommunity: diff --git a/src/tribler/core/components/popularity/community/popularity_community.py b/src/tribler/core/components/popularity/community/popularity_community.py index 4e7e31c90c4..6a22bc9ad88 100644 --- a/src/tribler/core/components/popularity/community/popularity_community.py +++ b/src/tribler/core/components/popularity/community/popularity_community.py @@ -7,7 +7,10 @@ from ipv8.lazy_community import lazy_wrapper from pony.orm import db_session -from tribler.core.components.metadata_store.remote_query_community.remote_query_community import RemoteQueryCommunity +from tribler.core.components.metadata_store.remote_query_community.remote_query_community import ( + RemoteCommunitySettings, + RemoteQueryCommunity +) from tribler.core.components.popularity.community.payload import PopularTorrentsRequest, TorrentsHealthPayload from tribler.core.components.popularity.community.version_community_mixin import VersionCommunityMixin from tribler.core.components.torrent_checker.torrent_checker.dataclasses import HealthInfo @@ -19,6 +22,10 @@ from tribler.core.components.torrent_checker.torrent_checker.torrent_checker import TorrentChecker +class PopularityCommunitySettings(RemoteCommunitySettings): + torrent_checker: TorrentChecker | None = None + + class PopularityCommunity(RemoteQueryCommunity, VersionCommunityMixin): """ Community for disseminating the content across the network. @@ -36,11 +43,12 @@ class PopularityCommunity(RemoteQueryCommunity, VersionCommunityMixin): GOSSIP_RANDOM_TORRENT_COUNT = 10 community_id = unhexlify('9aca62f878969c437da9844cba29a134917e1648') + settings_class = PopularityCommunitySettings - def __init__(self, *args, torrent_checker=None, **kwargs): + def __init__(self, settings: PopularityCommunitySettings): # Creating a separate instance of Network for this community to find more peers - super().__init__(*args, **kwargs) - self.torrent_checker: TorrentChecker = torrent_checker + super().__init__(settings) + self.torrent_checker = settings.torrent_checker self.add_message_handler(TorrentsHealthPayload, self.on_torrents_health) self.add_message_handler(PopularTorrentsRequest, self.on_popular_torrents_request) diff --git a/src/tribler/core/components/popularity/community/tests/test_popularity_community.py b/src/tribler/core/components/popularity/community/tests/test_popularity_community.py index 78415f61ed8..f1e04c92a66 100644 --- a/src/tribler/core/components/popularity/community/tests/test_popularity_community.py +++ b/src/tribler/core/components/popularity/community/tests/test_popularity_community.py @@ -1,8 +1,11 @@ +from __future__ import annotations + import time from random import randint from typing import List from unittest.mock import Mock +from ipv8.community import CommunitySettings from ipv8.keyvault.crypto import default_eccrypto from ipv8.test.base import TestBase from ipv8.test.mocking.ipv8 import MockIPv8 @@ -10,7 +13,10 @@ from tribler.core.components.metadata_store.db.store import MetadataStore from tribler.core.components.metadata_store.remote_query_community.settings import RemoteQueryCommunitySettings -from tribler.core.components.popularity.community.popularity_community import PopularityCommunity +from tribler.core.components.popularity.community.popularity_community import ( + PopularityCommunity, + PopularityCommunitySettings +) from tribler.core.components.torrent_checker.torrent_checker.torrentchecker_session import HealthInfo from tribler.core.tests.tools.base_test import MockObject from tribler.core.utilities.path_util import Path @@ -53,7 +59,8 @@ async def tearDown(self): metadata_store.shutdown() await super().tearDown() - def create_node(self, *args, **kwargs): + def create_node(self, settings: CommunitySettings | None = None, # pylint: disable=unused-argument + create_dht: bool = False, enable_statistics: bool = False): # pylint: disable=unused-argument mds = MetadataStore(Path(self.temporary_directory()) / f"{self.count}", Path(self.temporary_directory()), default_eccrypto.generate_key("curve25519")) @@ -64,10 +71,12 @@ def create_node(self, *args, **kwargs): self.count += 1 rqc_settings = RemoteQueryCommunitySettings() - return MockIPv8("curve25519", PopularityCommunity, metadata_store=mds, - torrent_checker=torrent_checker, - rqc_settings=rqc_settings - ) + return MockIPv8("curve25519", PopularityCommunity, + PopularityCommunitySettings( + metadata_store=mds, + torrent_checker=torrent_checker, + rqc_settings=rqc_settings + )) @db_session def fill_database(self, metadata_store, last_check_now=False): diff --git a/src/tribler/core/components/popularity/popularity_component.py b/src/tribler/core/components/popularity/popularity_component.py index bbc54a5ac86..7e64bbe458a 100644 --- a/src/tribler/core/components/popularity/popularity_component.py +++ b/src/tribler/core/components/popularity/popularity_component.py @@ -4,7 +4,10 @@ from tribler.core.components.gigachannel.community.sync_strategy import RemovePeers from tribler.core.components.ipv8.ipv8_component import INFINITE, Ipv8Component from tribler.core.components.metadata_store.metadata_store_component import MetadataStoreComponent -from tribler.core.components.popularity.community.popularity_community import PopularityCommunity +from tribler.core.components.popularity.community.popularity_community import ( + PopularityCommunity, + PopularityCommunitySettings +) from tribler.core.components.reporter.reporter_component import ReporterComponent from tribler.core.components.torrent_checker.torrent_checker_component import TorrentCheckerComponent @@ -23,13 +26,15 @@ async def run(self): torrent_checker_component = await self.require_component(TorrentCheckerComponent) config = self.session.config - community = PopularityCommunity(self._ipv8_component.peer, - self._ipv8_component.ipv8.endpoint, - Network(), - settings=config.popularity_community, - rqc_settings=config.remote_query_community, - metadata_store=metadata_store_component.mds, - torrent_checker=torrent_checker_component.torrent_checker) + community = PopularityCommunity(PopularityCommunitySettings( + my_peer=self._ipv8_component.peer, + endpoint=self._ipv8_component.ipv8.endpoint, + network=Network(), + settings=config.popularity_community, + rqc_settings=config.remote_query_community, + metadata_store=metadata_store_component.mds, + torrent_checker=torrent_checker_component.torrent_checker + )) self.community = community self._ipv8_component.initialise_community_by_default(community, default_random_walk_max_peers=30) diff --git a/src/tribler/core/components/restapi/rest/tests/test_statistics_endpoint.py b/src/tribler/core/components/restapi/rest/tests/test_statistics_endpoint.py index 0f227d082f1..a1832df55f3 100644 --- a/src/tribler/core/components/restapi/rest/tests/test_statistics_endpoint.py +++ b/src/tribler/core/components/restapi/rest/tests/test_statistics_endpoint.py @@ -1,14 +1,14 @@ from unittest.mock import Mock import pytest -from aiohttp.web_app import Application from ipv8.test.mocking.ipv8 import MockIPv8 -from tribler.core.components.bandwidth_accounting.community.bandwidth_accounting_community \ - import BandwidthAccountingCommunity +from tribler.core.components.bandwidth_accounting.community.bandwidth_accounting_community import ( + BandwidthAccountingCommunity, + BandwidthCommunitySettings +) from tribler.core.components.bandwidth_accounting.settings import BandwidthAccountingSettings from tribler.core.components.restapi.rest.base_api_test import do_request -from tribler.core.components.restapi.rest.rest_manager import error_middleware from tribler.core.components.restapi.rest.statistics_endpoint import StatisticsEndpoint @@ -17,8 +17,10 @@ @pytest.fixture async def endpoint(metadata_store): - ipv8 = MockIPv8("low", BandwidthAccountingCommunity, database=Mock(), - settings=BandwidthAccountingSettings()) + ipv8 = MockIPv8("low", BandwidthAccountingCommunity, BandwidthCommunitySettings( + database=Mock(), + settings=BandwidthAccountingSettings()) + ) ipv8.overlays = [ipv8.overlay] ipv8.endpoint.bytes_up = 100 ipv8.endpoint.bytes_down = 20 diff --git a/src/tribler/core/components/tunnel/community/tunnel_community.py b/src/tribler/core/components/tunnel/community/tunnel_community.py index c9896ec31fa..32422cc873e 100644 --- a/src/tribler/core/components/tunnel/community/tunnel_community.py +++ b/src/tribler/core/components/tunnel/community/tunnel_community.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import hashlib import math import sys @@ -11,7 +13,7 @@ import async_timeout from ipv8.messaging.anonymization.caches import CreateRequestCache from ipv8.messaging.anonymization.community import unpack_cell -from ipv8.messaging.anonymization.hidden_services import HiddenTunnelCommunity +from ipv8.messaging.anonymization.hidden_services import HiddenTunnelCommunity, HiddenTunnelSettings from ipv8.messaging.anonymization.payload import EstablishIntroPayload, NO_CRYPTO_PACKETS from ipv8.messaging.anonymization.tunnel import ( CIRCUIT_STATE_CLOSING, @@ -34,6 +36,7 @@ from tribler.core import notifications from tribler.core.components.bandwidth_accounting.db.transaction import BandwidthTransactionData +from tribler.core.components.ipv8.tribler_community import TriblerSettings from tribler.core.components.socks_servers.socks5.server import Socks5Server from tribler.core.components.tunnel.community.caches import BalanceRequestCache, HTTPRequestCache from tribler.core.components.tunnel.community.discovery import GoldenRatioStrategy @@ -61,24 +64,34 @@ MAX_HTTP_PACKET_SIZE = 1400 +class TriblerTunnelCommunitySettings(HiddenTunnelSettings, TriblerSettings): + bandwidth_community = None + exitnode_cache: Optional[Path] = None + config = None + notifier = None + dlmgr = None + socks_servers: List[Socks5Server] = [] + + class TriblerTunnelCommunity(HiddenTunnelCommunity): """ This community is built upon the anonymous messaging layer in IPv8. It adds support for libtorrent anonymous downloads and bandwidth token payout when closing circuits. """ community_id = unhexlify('a3591a6bd89bbaca0974062a1287afcfbc6fd6bb') - - def __init__(self, *args, **kwargs): - self.bandwidth_community = kwargs.pop('bandwidth_community', None) - self.exitnode_cache: Optional[Path] = kwargs.pop('exitnode_cache', None) - self.config = kwargs.pop('config', None) - self.notifier = kwargs.pop('notifier', None) - self.download_manager = kwargs.pop('dlmgr', None) - self.socks_servers: List[Socks5Server] = kwargs.pop('socks_servers', []) + settings_class = TriblerTunnelCommunitySettings + + def __init__(self, settings: TriblerTunnelCommunitySettings): + self.bandwidth_community = settings.bandwidth_community + self.exitnode_cache = settings.exitnode_cache + self.config = settings.config + self.notifier = settings.notifier + self.download_manager = settings.dlmgr + self.socks_servers = settings.socks_servers num_competing_slots = self.config.competing_slots num_random_slots = self.config.random_slots - super().__init__(*args, **kwargs) + super().__init__(settings) self._use_main_thread = True if self.config.exitnode_enabled: @@ -382,7 +395,8 @@ def clean_from_slots(self, circuit_id): if tup[1] == circuit_id: self.competing_slots[ind] = (0, None) - def remove_circuit(self, circuit_id, additional_info='', remove_now=False, destroy=False): + def remove_circuit(self, circuit_id: int, additional_info: str = '', remove_now: bool = False, + destroy: bool | int = False): if circuit_id not in self.circuits: self.logger.warning("Circuit %d not found when trying to remove it", circuit_id) return succeed(None) @@ -423,14 +437,12 @@ def remove_circuit(self, circuit_id, additional_info='', remove_now=False, destr remove_now=remove_now, destroy=destroy) @task - async def remove_relay(self, circuit_id, additional_info='', remove_now=False, destroy=False, - got_destroy_from=None, both_sides=True): + async def remove_relay(self, circuit_id: int, additional_info: str = '', remove_now: bool = False, + destroy: bool = False): removed_relays = await super().remove_relay(circuit_id, additional_info=additional_info, remove_now=remove_now, - destroy=destroy, - got_destroy_from=got_destroy_from, - both_sides=both_sides) + destroy=destroy) self.clean_from_slots(circuit_id) @@ -438,7 +450,8 @@ async def remove_relay(self, circuit_id, additional_info='', remove_now=False, d for removed_relay in removed_relays: self.notifier[notifications.circuit_removed](removed_relay, additional_info) - def remove_exit_socket(self, circuit_id, additional_info='', remove_now=False, destroy=False): + def remove_exit_socket(self, circuit_id: int, additional_info: str = '', remove_now: bool = False, + destroy: bool = False): if circuit_id in self.exit_sockets and self.notifier: exit_socket = self.exit_sockets[circuit_id] self.notifier[notifications.circuit_removed](exit_socket, additional_info) diff --git a/src/tribler/core/components/tunnel/tests/test_full_session/test_tunnel_community.py b/src/tribler/core/components/tunnel/tests/test_full_session/test_tunnel_community.py index 69021280ff4..840a336aa2d 100644 --- a/src/tribler/core/components/tunnel/tests/test_full_session/test_tunnel_community.py +++ b/src/tribler/core/components/tunnel/tests/test_full_session/test_tunnel_community.py @@ -26,7 +26,10 @@ from tribler.core.components.libtorrent.torrentdef import TorrentDef from tribler.core.components.socks_servers.socks5.server import Socks5Server from tribler.core.components.socks_servers.socks_servers_component import NUM_SOCKS_PROXIES -from tribler.core.components.tunnel.community.tunnel_community import TriblerTunnelCommunity +from tribler.core.components.tunnel.community.tunnel_community import ( + TriblerTunnelCommunity, + TriblerTunnelCommunitySettings +) from tribler.core.components.tunnel.settings import TunnelCommunitySettings from tribler.core.tests.tools.common import TESTS_DATA_DIR from tribler.core.utilities.simpledefs import DownloadStatus @@ -135,10 +138,12 @@ async def create_tunnel_community(temp_path_factory: TempPathFactory, ipv8 = MockIPv8("curve25519", TriblerTunnelCommunity, - settings={"max_circuits": 1}, - config=config, - socks_servers=socks_servers, - dlmgr=download_manager) + TriblerTunnelCommunitySettings( + settings={"max_circuits": 1}, + config=config, + socks_servers=socks_servers, + dlmgr=download_manager + )) if start_lt: download_manager.peer_mid = ipv8.my_peer.mid download_manager.initialize() diff --git a/src/tribler/core/components/tunnel/tests/test_triblertunnel_community.py b/src/tribler/core/components/tunnel/tests/test_triblertunnel_community.py index d8ccdde5d79..707732abe61 100644 --- a/src/tribler/core/components/tunnel/tests/test_triblertunnel_community.py +++ b/src/tribler/core/components/tunnel/tests/test_triblertunnel_community.py @@ -1,10 +1,15 @@ +from __future__ import annotations + import os from asyncio import Future, TimeoutError as AsyncTimeoutError, sleep, wait_for from collections import defaultdict from random import random -from unittest.mock import MagicMock, Mock, patch +from unittest.mock import Mock import pytest + +from ipv8.community import CommunitySettings +from ipv8.keyvault.public.libnaclkey import LibNaCLPK from ipv8.messaging.anonymization.payload import EstablishIntroPayload from ipv8.messaging.anonymization.tunnel import ( CIRCUIT_STATE_READY, @@ -12,8 +17,8 @@ CIRCUIT_TYPE_RP_SEEDER, PEER_FLAG_EXIT_BT, ) +from ipv8.messaging.serialization import ADDRESS_TYPE_IPV4 from ipv8.peer import Peer -from ipv8.peerdiscovery.network import Network from ipv8.test.base import TestBase from ipv8.test.messaging.anonymization import test_community from ipv8.test.messaging.anonymization.test_community import MockDHTProvider @@ -23,11 +28,16 @@ from tribler.core.components.bandwidth_accounting.community.bandwidth_accounting_community import ( BandwidthAccountingCommunity, + BandwidthCommunitySettings, ) from tribler.core.components.bandwidth_accounting.db.database import BandwidthDatabase from tribler.core.components.bandwidth_accounting.settings import BandwidthAccountingSettings from tribler.core.components.tunnel.community.payload import BandwidthTransactionPayload -from tribler.core.components.tunnel.community.tunnel_community import PEER_FLAG_EXIT_HTTP, TriblerTunnelCommunity +from tribler.core.components.tunnel.community.tunnel_community import ( + PEER_FLAG_EXIT_HTTP, + TriblerTunnelCommunity, + TriblerTunnelCommunitySettings +) from tribler.core.components.tunnel.settings import TunnelCommunitySettings from tribler.core.tests.tools.base_test import MockObject from tribler.core.tests.tools.tracker.http_tracker import HTTPTracker @@ -37,29 +47,16 @@ from tribler.core.utilities.utilities import MEMORY_DB -# pylint: disable=redefined-outer-name - -@pytest.fixture() -async def tunnel_community(): - community = TriblerTunnelCommunity(MagicMock(), - MagicMock(), - MagicMock(), - socks_servers=MagicMock(), - config=MagicMock(), - notifier=MagicMock(), - dlmgr=MagicMock(), - bandwidth_community=MagicMock(), - dht_provider=MagicMock(), - exitnode_cache=MagicMock(), - settings=MagicMock()) - yield community - await community.unload() - - +@pytest.mark.usefixtures("tmp_path") class TestTriblerTunnelCommunity(TestBase): # pylint: disable=too-many-public-methods + @pytest.fixture(autouse=True) + def init_tmp(self, tmp_path): + self.tmp_path = tmp_path + def setUp(self): self.initialize(TriblerTunnelCommunity, 1) + self.tmp_path = self.tmp_path async def tearDown(self): test_community.global_dht_services = defaultdict(list) # Reset the global_dht_services variable @@ -67,21 +64,25 @@ async def tearDown(self): await node.overlay.bandwidth_community.unload() await super().tearDown() - def create_node(self): + def create_node(self, settings: CommunitySettings | None = None, # pylint: disable=unused-argument + create_dht: bool = False, enable_statistics: bool = False): # pylint: disable=unused-argument config = TunnelCommunitySettings() mock_ipv8 = MockIPv8("curve25519", TriblerTunnelCommunity, - settings={'remove_tunnel_delay': 0}, - config=config, - exitnode_cache=Path(self.temporary_directory()) / "exitnode_cache.dat" - ) - mock_ipv8.overlay.settings.max_circuits = 1 - - db = BandwidthDatabase(db_path=MEMORY_DB, my_pub_key=mock_ipv8.my_peer.public_key.key_to_bin()) + TriblerTunnelCommunitySettings( + settings={'remove_tunnel_delay': 0}, + config=config, + exitnode_cache=Path(self.temporary_directory()) / "exitnode_cache.dat", + max_circuits=1 + )) # Load the bandwidth accounting community - mock_ipv8.overlay.bandwidth_community = BandwidthAccountingCommunity( - mock_ipv8.my_peer, mock_ipv8.endpoint, mock_ipv8.network, - settings=BandwidthAccountingSettings(), database=db) + mock_ipv8.overlay.bandwidth_community = BandwidthAccountingCommunity(BandwidthCommunitySettings( + my_peer=mock_ipv8.my_peer, + endpoint=mock_ipv8.endpoint, + network=mock_ipv8.network, + settings=BandwidthAccountingSettings(), + database=BandwidthDatabase(db_path=MEMORY_DB, my_pub_key=mock_ipv8.my_peer.public_key.key_to_bin()) + )) mock_ipv8.overlay.dht_provider = MockDHTProvider(Peer(mock_ipv8.overlay.my_peer.key, mock_ipv8.overlay.my_estimated_wan)) @@ -345,11 +346,10 @@ async def test_payouts(self): self.assertEqual(self.nodes[0].overlay.tunnels_ready(2), 1.0) # Destroy the circuit - for circuit_id, circuit in self.nodes[0].overlay.circuits.items(): + for circuit_id, circuit in list(self.nodes[0].overlay.circuits.items()): circuit.bytes_down = 250 * 1024 * 1024 - self.nodes[0].overlay.remove_circuit(circuit_id, destroy=1) - - await sleep(0.5) + await self.nodes[0].overlay.remove_circuit(circuit_id, destroy=1) + await self.deliver_messages() # Verify whether the downloader (node 0) correctly paid the relay and exit nodes. self.assertTrue(self.nodes[0].overlay.bandwidth_community.database.get_my_balance() < 0) @@ -672,20 +672,18 @@ async def test_perform_http_request_failed(self): b'GET /scrape?info_hash=0 HTTP/1.1\r\n\r\n'), timeout=.3) + def test_cache_exitnodes_to_disk(self): + """ Test whether we can cache exit nodes to disk """ + self.overlay(0).candidates = {Peer(LibNaCLPK(b'\x00'*64), ("0.1.2.3", 1029)): {PEER_FLAG_EXIT_BT}} + self.overlay(0).exitnode_cache = self.tmp_path / 'exitnode_cache.dat' + self.overlay(0).cache_exitnodes_to_disk() -@patch.object(Network, 'snapshot', Mock(return_value=b'snapshot')) -def test_cache_exitnodes_to_disk(tunnel_community: TriblerTunnelCommunity, tmp_path): - """ Test whether we can cache exit nodes to disk """ - tunnel_community.exitnode_cache = tmp_path / 'exitnode_cache.dat' - tunnel_community.cache_exitnodes_to_disk() - - assert tunnel_community.exitnode_cache.read_bytes() == b'snapshot' - + assert self.overlay(0).exitnode_cache.read_bytes() == bytes([ADDRESS_TYPE_IPV4]) + bytes(range(6)) -@patch.object(Network, 'snapshot', Mock(return_value=b'snapshot')) -def test_cache_exitnodes_to_disk_os_error(tunnel_community: TriblerTunnelCommunity): - """ Test whether we can handle an OSError when caching exit nodes to disk and raise no errors """ - tunnel_community.exitnode_cache = Mock(write_bytes=Mock(side_effect=FileNotFoundError)) - tunnel_community.cache_exitnodes_to_disk() + def test_cache_exitnodes_to_disk_os_error(self): + """ Test whether we can handle an OSError when caching exit nodes to disk and raise no errors """ + self.overlay(0).candidates = {Peer(LibNaCLPK(b'\x00'*64), ("0.1.2.3", 1029)): {PEER_FLAG_EXIT_BT}} + self.overlay(0).exitnode_cache = Mock(write_bytes=Mock(side_effect=FileNotFoundError)) + self.overlay(0).cache_exitnodes_to_disk() - assert tunnel_community.exitnode_cache.write_bytes.called + assert self.overlay(0).exitnode_cache.write_bytes.called diff --git a/src/tribler/core/components/tunnel/tunnel_component.py b/src/tribler/core/components/tunnel/tunnel_component.py index ae89702fb95..28d86dd7fdd 100644 --- a/src/tribler/core/components/tunnel/tunnel_component.py +++ b/src/tribler/core/components/tunnel/tunnel_component.py @@ -9,7 +9,7 @@ from tribler.core.components.tunnel.community.discovery import GoldenRatioStrategy from tribler.core.components.tunnel.community.tunnel_community import ( TriblerTunnelCommunity, - TriblerTunnelTestnetCommunity, + TriblerTunnelCommunitySettings, TriblerTunnelTestnetCommunity, ) @@ -47,17 +47,19 @@ async def run(self): exitnode_cache = config.state_dir / "exitnode_cache.dat" # TODO: decouple bandwidth community and dlmgr to initiate later - self.community = tunnel_cls(self._ipv8_component.peer, - self._ipv8_component.ipv8.endpoint, - self._ipv8_component.ipv8.network, - socks_servers=socks_servers, - config=config.tunnel_community, - notifier=self.session.notifier, - dlmgr=download_manager, - bandwidth_community=bandwidth_community, - dht_provider=provider, - exitnode_cache=exitnode_cache, - settings=settings) + self.community = tunnel_cls(TriblerTunnelCommunitySettings( + my_peer=self._ipv8_component.peer, + endpoint=self._ipv8_component.ipv8.endpoint, + network=self._ipv8_component.ipv8.network, + socks_servers=socks_servers, + config=config.tunnel_community, + notifier=self.session.notifier, + dlmgr=download_manager, + bandwidth_community=bandwidth_community, + dht_provider=provider, + exitnode_cache=exitnode_cache, + settings=settings + )) self._ipv8_component.initialise_community_by_default(self.community) self._ipv8_component.ipv8.add_strategy(self.community, GoldenRatioStrategy(self.community), INFINITE)