From 3b3bd3959780309ee53127d66bb50e6c22bd6c44 Mon Sep 17 00:00:00 2001 From: Adam Gibson Date: Sat, 9 Apr 2022 14:37:07 +0100 Subject: [PATCH] Replaces test_full_coinjoin with test_e2e_coinjoin The former was a stale test that we never got to a properly working state, so we replace it with test/e2e-coinjoin-test.py which does the same job more effectively, using the RPC-API. Also removed the old file from parameters of run_tests script. --- docs/TESTING.md | 2 +- test/run_tests.sh | 3 +- ...-coinjoin-test.py => test_e2e_coinjoin.py} | 21 +-- test/test_full_coinjoin.py | 147 ------------------ test/ygrunner.py | 3 +- 5 files changed, 11 insertions(+), 165 deletions(-) rename test/{e2e-coinjoin-test.py => test_e2e_coinjoin.py} (96%) delete mode 100644 test/test_full_coinjoin.py diff --git a/docs/TESTING.md b/docs/TESTING.md index 5596c40..cb424c4 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -25,7 +25,7 @@ Then copy the `regtest_joinmarket.cfg` file from the `test/` directory to the `j Run the test suite via pytest: - (jmvenv)$ pytest --btcconf=/path/to/bitcoin.conf --btcroot=/path/to/bitcoin/bin/ --btcpwd=123456abcdef --nirc=2 --ignore test/test_full_coinjoin.py -p no:warnings + (jmvenv)$ pytest --btcconf=/path/to/bitcoin.conf --btcroot=/path/to/bitcoin/bin/ --btcpwd=123456abcdef --nirc=2 -p no:warnings #### Running tests of sendpayment and tumbler (including with malicious makers) diff --git a/test/run_tests.sh b/test/run_tests.sh index 4ab8f72..ee28955 100755 --- a/test/run_tests.sh +++ b/test/run_tests.sh @@ -222,8 +222,7 @@ run_jm_tests () --btcroot=$btcroot \ --btcuser=$btcuser \ --nirc=$nirc \ - -p no:warnings \ - --ignore test/test_full_coinjoin.py + -p no:warnings local success="$?" [[ -f ./joinmarket.cfg ]] && unlink ./joinmarket.cfg if [ -f "${jm_test_datadir}/bitcoind.pid" ] && read bitcoind_pid <"${jm_test_datadir}/bitcoind.pid"; then diff --git a/test/e2e-coinjoin-test.py b/test/test_e2e_coinjoin.py similarity index 96% rename from test/e2e-coinjoin-test.py rename to test/test_e2e_coinjoin.py index 9f56e3c..df0d609 100644 --- a/test/e2e-coinjoin-test.py +++ b/test/test_e2e_coinjoin.py @@ -24,19 +24,11 @@ from jmbase import (get_nontor_agent, BytesProducer, jmprint, from jmclient import (YieldGeneratorBasic, load_test_config, jm_single, JMClientProtocolFactory, start_reactor, SegwitWallet, get_mchannels, SegwitLegacyWallet, JMWalletDaemon) +import jmclient from jmclient.wallet_rpc import api_version_string log = get_log() -# For quicker testing, restrict the range of timelock -# addresses to avoid slow load of multiple bots. -# Note: no need to revert this change as test runs -# in isolation. -from jmclient import FidelityBondMixin -FidelityBondMixin.TIMELOCK_ERA_YEARS = 2 -FidelityBondMixin.TIMELOCK_EPOCH_YEAR = datetime.now().year -FidelityBondMixin.TIMENUMBERS_PER_PUBKEY = 12 - wallet_name = "test-onion-yg-runner.jmdat" mean_amt = 2.0 @@ -196,8 +188,7 @@ def test_start_yg_and_taker_setup(setup_onion_ygrunner): wallet_service = wallet_services[end_bot_num - 1]['wallet'] jmprint("\n\nTaker wallet seed : " + wallet_services[end_bot_num - 1]['seed']) # for manual audit if necessary, show the maker's wallet seeds - # also (note this audit should be automated in future, see - # test_full_coinjoin.py in this directory) + # also (note this audit should be automated in future) jmprint("\n\nMaker wallet seeds: ") for i in range(start_bot_num, end_bot_num): jmprint("Maker seed: " + wallet_services[i - 1]['seed']) @@ -331,8 +322,12 @@ def process_coinjoin_response(response): json_body = json.loads(response.decode("utf-8")) print("coinjoin response: {}".format(json_body)) -@pytest.fixture(scope="module") -def setup_onion_ygrunner(): +@pytest.fixture +def setup_onion_ygrunner(monkeypatch): + # For quicker testing, restrict the range of timelock + # addresses to avoid slow load of multiple bots. + monkeypatch.setattr(jmclient.FidelityBondMixin, 'TIMELOCK_ERA_YEARS', 2) + monkeypatch.setattr(jmclient.FidelityBondMixin, 'TIMELOCK_EPOCH_YEAR', datetime.now().year) load_test_config() jm_single().bc_interface.tick_forward_chain_interval = 10 jm_single().bc_interface.simulate_blocks() diff --git a/test/test_full_coinjoin.py b/test/test_full_coinjoin.py deleted file mode 100644 index 9ac7353..0000000 --- a/test/test_full_coinjoin.py +++ /dev/null @@ -1,147 +0,0 @@ -#! /usr/bin/env python -from __future__ import (absolute_import, division, - print_function, unicode_literals) -from builtins import * # noqa: F401 -'''Runs a full joinmarket pit (using `nirc` miniircd servers, -with `nirc` options specified as an option to pytest),in -bitcoin regtest mode with 3 maker bots and 1 taker bot, -and does 1 coinjoin. This is intended as an E2E sanity check -but certainly could be extended further. -''' - -from common import make_wallets -import pytest -import sys -from jmclient import YieldGeneratorBasic, load_test_config, jm_single,\ - sync_wallet, JMClientProtocolFactory, start_reactor, Taker, \ - random_under_max_order_choose -from jmbase.support import get_log -from twisted.internet import reactor -from twisted.python.log import startLogging - -log = get_log() - -# Note that this parametrization is inherited (i.e. copied) from -# the previous 'ygrunner.py' script which is intended to be run -# manually to test out complex scenarios. Here, we only run one -# simple test with honest makers (and for simplicity malicious -# makers are not included in the code). Vars are left in in case -# we want to do more complex stuff in the automated tests later. -@pytest.mark.parametrize( - "num_ygs, wallet_structures, mean_amt, malicious, deterministic", - [ - # 1sp 3yg, honest makers - (3, [[1, 3, 0, 0, 0]] * 4, 2, 0, False), - ]) -def test_cj(setup_full_coinjoin, num_ygs, wallet_structures, mean_amt, - malicious, deterministic): - """Starts by setting up wallets for maker and taker bots; then, - instantiates a single taker with the final wallet. - The remaining wallets are used to set up YieldGenerators (basic form). - All the wallets are given coins according to the rules of make_wallets, - using the parameters for the values. - The final start_reactor call is the only one that actually starts the - reactor; the others only set up protocol instances. - Inline are custom callbacks for the Taker, and these are basically - copies of those in the `sendpayment.py` script for now, but they could - be customized later for testing. - The Taker's schedule is a single coinjoin, using basically random values, - again this could be easily edited or parametrized if we feel like it. - """ - - # Set up some wallets, for the ygs and 1 sp. - wallets = make_wallets(num_ygs + 1, - wallet_structures=wallet_structures, - mean_amt=mean_amt) - #the sendpayment bot uses the last wallet in the list - wallet = wallets[num_ygs]['wallet'] - sync_wallet(wallet, fast=True) - # grab a dest addr from the wallet - destaddr = wallet.get_external_addr(4) - coinjoin_amt = 20000000 - schedule = [[1, coinjoin_amt, 2, destaddr, - 0.0, False]] - - """ The following two callback functions are as simple as possible - modifications of the same in scripts/sendpayment.py - """ - def filter_orders_callback(orders_fees, cjamount): - return True - - def taker_finished(res, fromtx=False, waittime=0.0, txdetails=None): - def final_checks(): - sync_wallet(wallet, fast=True) - newbal = wallet.get_balance_by_mixdepth()[4] - oldbal = wallet.get_balance_by_mixdepth()[1] - # These are our check that the coinjoin succeeded - assert newbal == coinjoin_amt - # TODO: parametrize these; cj fees = 38K (.001 x 20M x 2 makers) - # minus 1K tx fee contribution each; 600M is original balance - # in mixdepth 1 - assert oldbal + newbal + (40000 - 2000) + taker.total_txfee == 600000000 - - if fromtx == "unconfirmed": - #If final entry, stop *here*, don't wait for confirmation - if taker.schedule_index + 1 == len(taker.schedule): - reactor.stop() - final_checks() - return - if fromtx: - # currently this test uses a schedule with only one entry - assert False, "taker_finished was called with fromtx=True" - reactor.stop() - return - else: - if not res: - assert False, "Did not complete successfully, shutting down" - # Note that this is required in both conditional branches, - # especially in testing, because it's possible to receive the - # confirmed callback before the unconfirmed. - reactor.stop() - final_checks() - - # twisted logging is required for debugging: - startLogging(sys.stdout) - - taker = Taker(wallet, - schedule, - order_chooser=random_under_max_order_choose, - max_cj_fee=(0.1, 200), - callbacks=(filter_orders_callback, None, taker_finished)) - clientfactory = JMClientProtocolFactory(taker) - nodaemon = jm_single().config.getint("DAEMON", "no_daemon") - daemon = True if nodaemon == 1 else False - start_reactor(jm_single().config.get("DAEMON", "daemon_host"), - jm_single().config.getint("DAEMON", "daemon_port"), - clientfactory, daemon=daemon, rs=False) - - txfee = 1000 - cjfee_a = 4200 - cjfee_r = '0.001' - ordertype = 'swreloffer' - minsize = 100000 - ygclass = YieldGeneratorBasic - # As noted above, this is not currently used but can be in future: - if malicious or deterministic: - raise NotImplementedError - for i in range(num_ygs): - cfg = [txfee, cjfee_a, cjfee_r, ordertype, minsize] - sync_wallet(wallets[i]["wallet"], fast=True) - yg = ygclass(wallets[i]["wallet"], cfg) - if malicious: - yg.set_maliciousness(malicious, mtype="tx") - clientfactory = JMClientProtocolFactory(yg, proto_type="MAKER") - nodaemon = jm_single().config.getint("DAEMON", "no_daemon") - daemon = True if nodaemon == 1 else False - # As noted above, only the final start_reactor() call will - # actually start it! - rs = True if i == num_ygs - 1 else False - start_reactor(jm_single().config.get("DAEMON", "daemon_host"), - jm_single().config.getint("DAEMON", "daemon_port"), - clientfactory, daemon=daemon, rs=rs) - -@pytest.fixture(scope="module") -def setup_full_coinjoin(): - load_test_config() - jm_single().bc_interface.tick_forward_chain_interval = 10 - jm_single().bc_interface.simulate_blocks() diff --git a/test/ygrunner.py b/test/ygrunner.py index d657179..751aec4 100644 --- a/test/ygrunner.py +++ b/test/ygrunner.py @@ -123,8 +123,7 @@ def test_start_ygs(setup_ygrunner, num_ygs, wallet_structures, fb_indices, wallet_service = wallet_services[num_ygs]['wallet'] jmprint("\n\nTaker wallet seed : " + wallet_services[num_ygs]['seed']) # for manual audit if necessary, show the maker's wallet seeds - # also (note this audit should be automated in future, see - # test_full_coinjoin.py in this directory) + # also (note this audit should be automated in future) jmprint("\n\nMaker wallet seeds: ") for i in range(num_ygs): jmprint("Maker seed: " + wallet_services[i]['seed'])