From 3926fa5e0e77a20f08de265b99e96eb4372b471d Mon Sep 17 00:00:00 2001 From: Gabriel Levcovitz Date: Fri, 3 Nov 2023 15:52:24 -0300 Subject: [PATCH] refactor(daa): remove global daa test mode --- hathor/builder/cli_builder.py | 15 ++++++------ hathor/daa.py | 23 ++++++++----------- hathor/p2p/peer_id.py | 9 +++++--- hathor/simulator/simulator.py | 5 +--- tests/p2p/test_split_brain.py | 4 ++-- tests/resources/base_resource.py | 4 ++-- tests/resources/transaction/test_create_tx.py | 6 ++--- tests/resources/wallet/test_send_tokens.py | 4 ++-- tests/tx/test_blockchain.py | 8 +++---- tests/tx/test_cache_storage.py | 4 ++-- tests/tx/test_genesis.py | 6 ++--- tests/tx/test_tx.py | 4 ++-- tests/tx/test_tx_storage.py | 8 +++---- tests/unittest.py | 10 ++++---- 14 files changed, 52 insertions(+), 58 deletions(-) diff --git a/hathor/builder/cli_builder.py b/hathor/builder/cli_builder.py index b9e12c7b8..416c933ab 100644 --- a/hathor/builder/cli_builder.py +++ b/hathor/builder/cli_builder.py @@ -59,7 +59,7 @@ def check_or_raise(self, condition: bool, message: str) -> None: def create_manager(self, reactor: Reactor) -> HathorManager: import hathor from hathor.conf.get_settings import get_settings, get_settings_source - from hathor.daa import TestMode, _set_test_mode + from hathor.daa import TestMode from hathor.event.storage import EventMemoryStorage, EventRocksDBStorage, EventStorage from hathor.event.websocket.factory import EventWebsocketFactory from hathor.p2p.netfilter.utils import add_peer_id_blacklist @@ -208,7 +208,13 @@ def create_manager(self, reactor: Reactor) -> HathorManager: not_support_features=self._args.signal_not_support ) - daa = DifficultyAdjustmentAlgorithm(settings=settings) + test_mode = TestMode.DISABLED + if self._args.test_mode_tx_weight: + test_mode = TestMode.TEST_TX_WEIGHT + if self.wallet: + self.wallet.test_mode = True + + daa = DifficultyAdjustmentAlgorithm(settings=settings, test_mode=test_mode) vertex_verifiers = VertexVerifiers.create_defaults( settings=settings, @@ -281,11 +287,6 @@ def create_manager(self, reactor: Reactor) -> HathorManager: if self._args.bootstrap: p2p_manager.add_peer_discovery(BootstrapPeerDiscovery(self._args.bootstrap)) - if self._args.test_mode_tx_weight: - _set_test_mode(TestMode.TEST_TX_WEIGHT) - if self.wallet: - self.wallet.test_mode = True - if self._args.x_rocksdb_indexes: self.log.warn('--x-rocksdb-indexes is now the default, no need to specify it') if self._args.memory_indexes: diff --git a/hathor/daa.py b/hathor/daa.py index ece55766a..4d8fc7413 100644 --- a/hathor/daa.py +++ b/hathor/daa.py @@ -21,7 +21,7 @@ from enum import IntFlag from math import log -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, ClassVar, Optional from structlog import get_logger @@ -45,26 +45,21 @@ class TestMode(IntFlag): TEST_ALL_WEIGHT = 3 -TEST_MODE = TestMode.DISABLED - - -def _set_test_mode(mode: TestMode) -> None: - global TEST_MODE - logger.debug('change DAA test mode', from_mode=TEST_MODE.name, to_mode=mode.name) - TEST_MODE = mode - - class DifficultyAdjustmentAlgorithm: + # TODO: This singleton is temporary, and only used in PeerId. It should be removed from there, and then from here. + singleton: ClassVar[Optional['DifficultyAdjustmentAlgorithm']] = None - def __init__(self, *, settings: HathorSettings) -> None: + def __init__(self, *, settings: HathorSettings, test_mode: TestMode = TestMode.DISABLED) -> None: self._settings = settings self.AVG_TIME_BETWEEN_BLOCKS = self._settings.AVG_TIME_BETWEEN_BLOCKS self.MIN_BLOCK_WEIGHT = self._settings.MIN_BLOCK_WEIGHT + self.TEST_MODE = test_mode + DifficultyAdjustmentAlgorithm.singleton = self @cpu.profiler(key=lambda _, block: 'calculate_block_difficulty!{}'.format(block.hash.hex())) def calculate_block_difficulty(self, block: 'Block') -> float: """ Calculate block weight according to the ascendents of `block`, using calculate_next_weight.""" - if TEST_MODE & TestMode.TEST_BLOCK_WEIGHT: + if self.TEST_MODE & TestMode.TEST_BLOCK_WEIGHT: return 1.0 if block.is_genesis: @@ -79,7 +74,7 @@ def calculate_next_weight(self, parent_block: 'Block', timestamp: int) -> float: The weight must not be less than `MIN_BLOCK_WEIGHT`. """ - if TEST_MODE & TestMode.TEST_BLOCK_WEIGHT: + if self.TEST_MODE & TestMode.TEST_BLOCK_WEIGHT: return 1.0 from hathor.transaction import sum_weights @@ -166,7 +161,7 @@ def minimum_tx_weight(self, tx: 'Transaction') -> float: """ # In test mode we don't validate the minimum weight for tx # We do this to allow generating many txs for testing - if TEST_MODE & TestMode.TEST_TX_WEIGHT: + if self.TEST_MODE & TestMode.TEST_TX_WEIGHT: return 1.0 if tx.is_genesis: diff --git a/hathor/p2p/peer_id.py b/hathor/p2p/peer_id.py index 532502ab8..711fd1f5c 100644 --- a/hathor/p2p/peer_id.py +++ b/hathor/p2p/peer_id.py @@ -28,9 +28,10 @@ from twisted.internet.interfaces import ISSLTransport from twisted.internet.ssl import Certificate, CertificateOptions, TLSVersion, trustRootFromCertificates -from hathor import daa from hathor.conf.get_settings import get_settings +from hathor.daa import DifficultyAdjustmentAlgorithm from hathor.p2p.utils import connection_string_to_host, discover_dns, generate_certificate +from hathor.util import not_none if TYPE_CHECKING: from hathor.p2p.protocol import HathorProtocol # noqa: F401 @@ -347,7 +348,8 @@ def validate_entrypoint(self, protocol: 'HathorProtocol') -> Generator[Any, Any, break host = connection_string_to_host(entrypoint) # TODO: don't use `daa.TEST_MODE` for this - result = yield discover_dns(host, daa.TEST_MODE) + test_mode = not_none(DifficultyAdjustmentAlgorithm.singleton).TEST_MODE + result = yield discover_dns(host, test_mode) if protocol.connection_string in result: # Found the entrypoint found_entrypoint = True @@ -366,7 +368,8 @@ def validate_entrypoint(self, protocol: 'HathorProtocol') -> Generator[Any, Any, if connection_host == host: found_entrypoint = True break - result = yield discover_dns(host, daa.TEST_MODE) + test_mode = not_none(DifficultyAdjustmentAlgorithm.singleton).TEST_MODE + result = yield discover_dns(host, test_mode) if connection_host in [connection_string_to_host(x) for x in result]: # Found the entrypoint found_entrypoint = True diff --git a/hathor/simulator/simulator.py b/hathor/simulator/simulator.py index bd5c182d1..a4f3fb40b 100644 --- a/hathor/simulator/simulator.py +++ b/hathor/simulator/simulator.py @@ -23,7 +23,7 @@ from hathor.builder import BuildArtifacts, Builder from hathor.conf.get_settings import get_settings from hathor.conf.settings import HathorSettings -from hathor.daa import DifficultyAdjustmentAlgorithm, TestMode, _set_test_mode +from hathor.daa import DifficultyAdjustmentAlgorithm from hathor.feature_activation.feature_service import FeatureService from hathor.manager import HathorManager from hathor.p2p.peer_id import PeerId @@ -63,7 +63,6 @@ def _apply_patches(cls): Patches: - disable Transaction.resolve method - - set DAA test-mode to DISABLED (will actually run the pow function, that won't actually verify the pow) """ from hathor.transaction import BaseTransaction @@ -75,8 +74,6 @@ def resolve(self: BaseTransaction, update_time: bool = True) -> bool: cls._original_resolve = BaseTransaction.resolve BaseTransaction.resolve = resolve - _set_test_mode(TestMode.DISABLED) - @classmethod def _remove_patches(cls): """ Remove the patches previously applied. diff --git a/tests/p2p/test_split_brain.py b/tests/p2p/test_split_brain.py index 804377f99..e649fafa3 100644 --- a/tests/p2p/test_split_brain.py +++ b/tests/p2p/test_split_brain.py @@ -1,7 +1,7 @@ import pytest from mnemonic import Mnemonic -from hathor.daa import TestMode, _set_test_mode +from hathor.daa import TestMode from hathor.graphviz import GraphvizVisualizer from hathor.simulator import FakeConnection from hathor.wallet import HDWallet @@ -24,8 +24,8 @@ def create_peer(self, network, unlock_wallet=True): wallet = HDWallet(gap_limit=2) wallet._manually_initialize() - _set_test_mode(TestMode.TEST_ALL_WEIGHT) manager = super().create_peer(network, wallet=wallet) + manager.daa.TEST_MODE = TestMode.TEST_ALL_WEIGHT manager.avg_time_between_blocks = 64 # Don't use it anywhere else. It is unsafe to generate mnemonic words like this. diff --git a/tests/resources/base_resource.py b/tests/resources/base_resource.py index b7aebc16b..ce9a84c07 100644 --- a/tests/resources/base_resource.py +++ b/tests/resources/base_resource.py @@ -2,7 +2,7 @@ from twisted.web import server from twisted.web.test.requesthelper import DummyRequest -from hathor.daa import TestMode, _set_test_mode +from hathor.daa import TestMode from hathor.util import json_dumpb, json_loadb from tests import unittest @@ -19,7 +19,7 @@ def setUp(self, *, utxo_index: bool = False, unlock_wallet: bool = True) -> None unlock_wallet=unlock_wallet ) self.manager.allow_mining_without_peers() - _set_test_mode(TestMode.TEST_ALL_WEIGHT) + self.manager.daa.TEST_MODE = TestMode.TEST_ALL_WEIGHT def tearDown(self): return self.manager.stop() diff --git a/tests/resources/transaction/test_create_tx.py b/tests/resources/transaction/test_create_tx.py index 2217ec42b..b42e83c73 100644 --- a/tests/resources/transaction/test_create_tx.py +++ b/tests/resources/transaction/test_create_tx.py @@ -2,7 +2,7 @@ from twisted.internet.defer import inlineCallbacks -from hathor.daa import TestMode, _set_test_mode +from hathor.daa import TestMode from hathor.transaction import Transaction from hathor.transaction.resources import CreateTxResource from hathor.transaction.scripts import P2PKH, create_base_script @@ -195,7 +195,7 @@ def test_spend_tx_by_script(self): @inlineCallbacks def test_tx_propagate(self): - _set_test_mode(TestMode.DISABLED) # disable test_mode so the weight is not 1 + self.manager.daa.TEST_MODE = TestMode.DISABLED # disable test_mode so the weight is not 1 src_tx = self.unspent_tx output_address = 'HNXsVtRUmwDCtpcCJUrH4QiHo9kUKx199A' resp = (yield self.web.post('create_tx', { @@ -233,7 +233,7 @@ def test_tx_propagate(self): @inlineCallbacks def test_tx_propagate_multiple_inputs(self): - _set_test_mode(TestMode.DISABLED) # disable test_mode so the weight is not 1 + self.manager.daa.TEST_MODE = TestMode.DISABLED # disable test_mode so the weight is not 1 output_address = 'HNXsVtRUmwDCtpcCJUrH4QiHo9kUKx199A' resp = (yield self.web.post('create_tx', { 'inputs': [ diff --git a/tests/resources/wallet/test_send_tokens.py b/tests/resources/wallet/test_send_tokens.py index 0e5cbc533..7136fc85d 100644 --- a/tests/resources/wallet/test_send_tokens.py +++ b/tests/resources/wallet/test_send_tokens.py @@ -2,7 +2,7 @@ from twisted.internet.defer import inlineCallbacks -from hathor.daa import TestMode, _set_test_mode +from hathor.daa import TestMode from hathor.p2p.resources import MiningResource from hathor.wallet.resources import BalanceResource, HistoryResource, SendTokensResource from tests import unittest @@ -168,7 +168,7 @@ def test_post(self): @inlineCallbacks def test_tx_weight(self): - _set_test_mode(TestMode.DISABLED) + self.manager.daa.TEST_MODE = TestMode.DISABLED add_new_blocks(self.manager, 3, advance_clock=1) add_blocks_unlock_reward(self.manager) self.reactor.advance(3) diff --git a/tests/tx/test_blockchain.py b/tests/tx/test_blockchain.py index f52228c60..f758706d3 100644 --- a/tests/tx/test_blockchain.py +++ b/tests/tx/test_blockchain.py @@ -1,7 +1,7 @@ from itertools import chain from hathor.conf import HathorSettings -from hathor.daa import DifficultyAdjustmentAlgorithm, TestMode, _set_test_mode +from hathor.daa import DifficultyAdjustmentAlgorithm, TestMode from hathor.transaction import sum_weights from hathor.transaction.storage import TransactionMemoryStorage from tests import unittest @@ -390,8 +390,8 @@ def test_block_rewards(self): def test_daa_sanity(self): # sanity test the DAA - _set_test_mode(TestMode.DISABLED) manager = self.create_peer('testnet', tx_storage=self.tx_storage) + manager.daa.TEST_MODE = TestMode.DISABLED N = settings.BLOCK_DIFFICULTY_N_BLOCKS T = settings.AVG_TIME_BETWEEN_BLOCKS manager.avg_time_between_blocks = T @@ -417,7 +417,7 @@ def test_daa_sanity(self): self.assertLess(new_weight, base_weight) def test_daa_weight_decay_amount(self): - _set_test_mode(TestMode.DISABLED) + self.daa.TEST_MODE = TestMode.DISABLED amount = settings.WEIGHT_DECAY_AMOUNT for distance in range(0, settings.WEIGHT_DECAY_ACTIVATE_DISTANCE, 10): @@ -434,8 +434,8 @@ def test_daa_weight_decay_amount(self): self.assertAlmostEqual(self.daa.get_weight_decay_amount(distance), 11 * amount) def test_daa_weight_decay_blocks(self): - _set_test_mode(TestMode.DISABLED) manager = self.create_peer('testnet', tx_storage=self.tx_storage) + manager.daa.TEST_MODE = TestMode.DISABLED amount = settings.WEIGHT_DECAY_AMOUNT manager.daa.AVG_TIME_BETWEEN_BLOCKS = settings.AVG_TIME_BETWEEN_BLOCKS diff --git a/tests/tx/test_cache_storage.py b/tests/tx/test_cache_storage.py index a7832bd1c..c91f69db9 100644 --- a/tests/tx/test_cache_storage.py +++ b/tests/tx/test_cache_storage.py @@ -1,4 +1,4 @@ -from hathor.daa import TestMode, _set_test_mode +from hathor.daa import TestMode from hathor.transaction import Transaction, TransactionMetadata from hathor.transaction.storage import TransactionCacheStorage from tests import unittest @@ -144,7 +144,7 @@ def test_flush_thread(self): self.cache_storage._flush_to_storage(self.cache_storage.dirty_txs.copy()) def test_topological_sort_dfs(self): - _set_test_mode(TestMode.TEST_ALL_WEIGHT) + self.manager.daa.TEST_MODE = TestMode.TEST_ALL_WEIGHT add_new_blocks(self.manager, 11, advance_clock=1) tx = add_new_transactions(self.manager, 1, advance_clock=1)[0] diff --git a/tests/tx/test_genesis.py b/tests/tx/test_genesis.py index 2bf5000f5..eecabd7fa 100644 --- a/tests/tx/test_genesis.py +++ b/tests/tx/test_genesis.py @@ -1,5 +1,5 @@ from hathor.conf import HathorSettings -from hathor.daa import DifficultyAdjustmentAlgorithm, TestMode, _set_test_mode +from hathor.daa import DifficultyAdjustmentAlgorithm, TestMode from hathor.transaction.storage import TransactionMemoryStorage from hathor.verification.verification_service import VerificationService, VertexVerifiers from hathor.verification.vertex_verifier import VertexVerifier @@ -70,10 +70,10 @@ def test_genesis_weight(self): # Validate the block and tx weight # in test mode weight is always 1 - _set_test_mode(TestMode.TEST_ALL_WEIGHT) + self._daa.TEST_MODE = TestMode.TEST_ALL_WEIGHT self.assertEqual(self._daa.calculate_block_difficulty(genesis_block), 1) self.assertEqual(self._daa.minimum_tx_weight(genesis_tx), 1) - _set_test_mode(TestMode.DISABLED) + self._daa.TEST_MODE = TestMode.DISABLED self.assertEqual(self._daa.calculate_block_difficulty(genesis_block), genesis_block.weight) self.assertEqual(self._daa.minimum_tx_weight(genesis_tx), genesis_tx.weight) diff --git a/tests/tx/test_tx.py b/tests/tx/test_tx.py index b68b301c2..46d63f474 100644 --- a/tests/tx/test_tx.py +++ b/tests/tx/test_tx.py @@ -3,7 +3,7 @@ from math import isinf, isnan from hathor.crypto.util import decode_address, get_address_from_public_key, get_private_key_from_bytes -from hathor.daa import TestMode, _set_test_mode +from hathor.daa import TestMode from hathor.transaction import MAX_OUTPUT_VALUE, Block, Transaction, TxInput, TxOutput from hathor.transaction.exceptions import ( BlockWithInputs, @@ -629,8 +629,8 @@ def test_update_timestamp(self): self.assertEquals(tx.timestamp, ts) def test_propagation_error(self): - _set_test_mode(TestMode.DISABLED) manager = self.create_peer('testnet', unlock_wallet=True) + manager.daa.TEST_MODE = TestMode.DISABLED # 1. propagate genesis genesis_block = self.genesis_blocks[0] diff --git a/tests/tx/test_tx_storage.py b/tests/tx/test_tx_storage.py index 909164169..d8a6aa848 100644 --- a/tests/tx/test_tx_storage.py +++ b/tests/tx/test_tx_storage.py @@ -9,7 +9,7 @@ from twisted.trial import unittest from hathor.conf import HathorSettings -from hathor.daa import TestMode, _set_test_mode +from hathor.daa import TestMode from hathor.transaction import Block, Transaction, TxInput, TxOutput from hathor.transaction.scripts import P2PKH from hathor.transaction.storage.exceptions import TransactionDoesNotExist @@ -145,7 +145,7 @@ def test_storage_basic_v2(self): self.assertEqual(set(tx_parents_hash), {self.genesis_txs[0].hash, self.genesis_txs[1].hash}) def test_vertices_count(self): - _set_test_mode(TestMode.TEST_ALL_WEIGHT) + self.manager.daa.TEST_MODE = TestMode.TEST_ALL_WEIGHT blocks_count = 1 txs_count = 2 @@ -522,7 +522,7 @@ def _add_new_block(self, parents=None): return block def test_best_block_tips_cache(self): - _set_test_mode(TestMode.TEST_ALL_WEIGHT) + self.manager.daa.TEST_MODE = TestMode.TEST_ALL_WEIGHT self.manager.wallet.unlock(b'MYPASS') spent_blocks = add_new_blocks(self.manager, 10) self.assertEqual(self.tx_storage._best_block_tips_cache, [spent_blocks[-1].hash]) @@ -534,7 +534,7 @@ def test_best_block_tips_cache(self): self.assertEqual(self.tx_storage._best_block_tips_cache, [latest_blocks[-1].hash]) def test_topological_sort(self): - _set_test_mode(TestMode.TEST_ALL_WEIGHT) + self.manager.daa.TEST_MODE = TestMode.TEST_ALL_WEIGHT _total = 0 blocks = add_new_blocks(self.manager, 1, advance_clock=1) _total += len(blocks) diff --git a/tests/unittest.py b/tests/unittest.py index 930bb23e6..5b3b3cb7f 100644 --- a/tests/unittest.py +++ b/tests/unittest.py @@ -12,7 +12,7 @@ from hathor.builder import BuildArtifacts, Builder from hathor.conf import HathorSettings from hathor.conf.get_settings import get_settings -from hathor.daa import TestMode, _set_test_mode +from hathor.daa import DifficultyAdjustmentAlgorithm, TestMode from hathor.p2p.peer_id import PeerId from hathor.p2p.sync_version import SyncVersion from hathor.simulator.clock import MemoryReactorHeapClock @@ -104,7 +104,6 @@ class TestCase(unittest.TestCase): seed_config: Optional[int] = None def setUp(self): - _set_test_mode(TestMode.TEST_ALL_WEIGHT) self.tmpdirs = [] self.clock = TestMemoryReactorClock() self.clock.advance(time.time()) @@ -183,7 +182,7 @@ def create_peer_from_builder(self, builder, start_manager=True): def create_peer(self, network, peer_id=None, wallet=None, tx_storage=None, unlock_wallet=True, wallet_index=False, capabilities=None, full_verification=True, enable_sync_v1=None, enable_sync_v2=None, checkpoints=None, utxo_index=False, event_manager=None, use_memory_index=None, start_manager=True, - pubsub=None, event_storage=None, enable_event_queue=None, use_memory_storage=None, daa=None): + pubsub=None, event_storage=None, enable_event_queue=None, use_memory_storage=None): enable_sync_v1, enable_sync_v2 = self._syncVersionFlags(enable_sync_v1, enable_sync_v2) @@ -246,9 +245,8 @@ def create_peer(self, network, peer_id=None, wallet=None, tx_storage=None, unloc if utxo_index: builder.enable_utxo_index() - if daa: - builder.set_daa(daa) - + daa = DifficultyAdjustmentAlgorithm(settings=self._settings, test_mode=TestMode.TEST_ALL_WEIGHT) + 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