From 7b03ce476997ceee5f6b227c8a1b028175ed5b74 Mon Sep 17 00:00:00 2001 From: tecnovert Date: Fri, 15 Nov 2024 17:21:20 +0200 Subject: [PATCH] Reformat tests with black. --- .cirrus.yml | 2 +- .github/workflows/lint.yml | 2 +- pyproject.toml | 5 + tests/basicswap/common.py | 269 ++- tests/basicswap/common_xmr.py | 577 +++-- tests/basicswap/extended/test_dash.py | 754 ++++-- tests/basicswap/extended/test_dcr.py | 1108 ++++++--- .../extended/test_encrypted_xmr_reload.py | 122 +- tests/basicswap/extended/test_firo.py | 503 ++-- tests/basicswap/extended/test_http_ui.py | 68 - tests/basicswap/extended/test_nav.py | 1401 ++++++++--- tests/basicswap/extended/test_network.py | 310 ++- tests/basicswap/extended/test_nmc.py | 496 ++-- tests/basicswap/extended/test_pivx.py | 763 ++++-- tests/basicswap/extended/test_prepare.py | 215 +- tests/basicswap/extended/test_scripts.py | 806 ++++--- tests/basicswap/extended/test_wallet_init.py | 42 +- .../basicswap/extended/test_wallet_restore.py | 136 +- tests/basicswap/extended/test_wow.py | 148 +- .../basicswap/extended/test_xmr_persistent.py | 303 ++- tests/basicswap/mnemonics.py | 7 +- tests/basicswap/selenium/test_offer.py | 134 +- .../selenium/test_recover_chain_b_lock_tx.py | 259 +- tests/basicswap/selenium/test_settings.py | 100 +- .../basicswap/selenium/test_swap_direction.py | 58 +- tests/basicswap/selenium/test_wallets.py | 127 +- tests/basicswap/selenium/util.py | 21 +- tests/basicswap/test_bch_xmr.py | 650 +++-- tests/basicswap/test_btc_xmr.py | 1487 ++++++++---- tests/basicswap/test_ltc_xmr.py | 309 ++- tests/basicswap/test_other.py | 370 +-- tests/basicswap/test_partblind_xmr.py | 486 ++-- tests/basicswap/test_reload.py | 112 +- tests/basicswap/test_run.py | 1040 +++++--- tests/basicswap/test_xmr.py | 2091 ++++++++++++----- tests/basicswap/test_xmr_bids_offline.py | 152 +- tests/basicswap/test_xmr_reload.py | 100 +- tests/basicswap/util.py | 38 +- 38 files changed, 10345 insertions(+), 5226 deletions(-) delete mode 100644 tests/basicswap/extended/test_http_ui.py diff --git a/.cirrus.yml b/.cirrus.yml index 1c3fa8b..e4a42e4 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -6,7 +6,7 @@ lint_task: - pip install flake8 codespell script: - flake8 --version - - PYTHONWARNINGS="ignore" flake8 --ignore=E501,F841,W503,E702,E131 --exclude=basicswap/contrib,basicswap/interface/contrib,messages_pb2.py,.eggs,.tox,bin/install_certifi.py + - PYTHONWARNINGS="ignore" flake8 --ignore=E203,E501,F841,W503,E702,E131 --exclude=basicswap/contrib,basicswap/interface/contrib,messages_pb2.py,.eggs,.tox,bin/install_certifi.py - codespell --check-filenames --disable-colors --quiet-level=7 --ignore-words=tests/lint/spelling.ignore-words.txt -S .git,.eggs,.tox,pgp,*.pyc,*basicswap/contrib,*basicswap/interface/contrib,*mnemonics.py,bin/install_certifi.py,*basicswap/static test_task: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4f29fcc..eef2bc5 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -20,7 +20,7 @@ jobs: pip install flake8 codespell - name: Running flake8 run: | - flake8 --ignore=E501,F841,W503 --per-file-ignores="basicswap/interface/bch.py:E131,E702" --exclude=basicswap/contrib,basicswap/interface/contrib,messages_pb2.py,.eggs,.tox,bin/install_certifi.py + flake8 --ignore=E203,E501,F841,W503 --per-file-ignores="basicswap/interface/bch.py:E131,E702" --exclude=basicswap/contrib,basicswap/interface/contrib,messages_pb2.py,.eggs,.tox,bin/install_certifi.py - name: Running codespell run: | codespell --check-filenames --disable-colors --quiet-level=7 --ignore-words=tests/lint/spelling.ignore-words.txt -S .git,.eggs,.tox,pgp,*.pyc,*basicswap/contrib,*basicswap/interface/contrib,*mnemonics.py,bin/install_certifi.py,*basicswap/static diff --git a/pyproject.toml b/pyproject.toml index 4fdb42d..d21c9e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,6 +34,8 @@ dev = [ "flake8", "pip-tools", "pytest", + "ruff", + "black", "selenium", ] @@ -42,3 +44,6 @@ path = "basicswap/__init__.py" [tool.hatch.metadata] allow-direct-references = true + +[tool.ruff] +exclude = ["basicswap/contrib","basicswap/interface/contrib"] diff --git a/tests/basicswap/common.py b/tests/basicswap/common.py index 9004333..3068f6e 100644 --- a/tests/basicswap/common.py +++ b/tests/basicswap/common.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020-2024 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE.txt or http://www.opensource.org/licenses/mit-license.php. @@ -17,7 +18,9 @@ from basicswap.contrib.rpcauth import generate_salt, password_to_hmac from basicswap.bin.prepare import downloadPIVXParams -TEST_HTTP_HOST = os.getenv('TEST_HTTP_HOST', '127.0.0.1') # Set to 0.0.0.0 when used in docker +TEST_HTTP_HOST = os.getenv( + "TEST_HTTP_HOST", "127.0.0.1" +) # Set to 0.0.0.0 when used in docker TEST_HTTP_PORT = 1800 BASE_P2P_PORT = 12792 @@ -39,84 +42,99 @@ PIVX_BASE_PORT = 34892 PIVX_BASE_RPC_PORT = 35892 PIVX_BASE_ZMQ_PORT = 36892 -PREFIX_SECRET_KEY_REGTEST = 0x2e +PREFIX_SECRET_KEY_REGTEST = 0x2E -def prepareDataDir(datadir, node_id, conf_file, dir_prefix, base_p2p_port=BASE_PORT, base_rpc_port=BASE_RPC_PORT, num_nodes=3, extra_opts=[]): +def prepareDataDir( + datadir, + node_id, + conf_file, + dir_prefix, + base_p2p_port=BASE_PORT, + base_rpc_port=BASE_RPC_PORT, + num_nodes=3, + extra_opts=[], +): node_dir = os.path.join(datadir, dir_prefix + str(node_id)) if not os.path.exists(node_dir): os.makedirs(node_dir) cfg_file_path = os.path.join(node_dir, conf_file) if os.path.exists(cfg_file_path): return - with open(cfg_file_path, 'w+') as fp: - fp.write('regtest=1\n') - fp.write('[regtest]\n') - fp.write('port=' + str(base_p2p_port + node_id) + '\n') - fp.write('rpcport=' + str(base_rpc_port + node_id) + '\n') + with open(cfg_file_path, "w+") as fp: + fp.write("regtest=1\n") + fp.write("[regtest]\n") + fp.write("port=" + str(base_p2p_port + node_id) + "\n") + fp.write("rpcport=" + str(base_rpc_port + node_id) + "\n") salt = generate_salt(16) - fp.write('rpcauth={}:{}${}\n'.format('test' + str(node_id), salt, password_to_hmac(salt, 'test_pass' + str(node_id)))) + fp.write( + "rpcauth={}:{}${}\n".format( + "test" + str(node_id), + salt, + password_to_hmac(salt, "test_pass" + str(node_id)), + ) + ) - fp.write('daemon=0\n') - fp.write('printtoconsole=0\n') - fp.write('server=1\n') - fp.write('discover=0\n') - fp.write('listenonion=0\n') - fp.write('bind=127.0.0.1\n') - fp.write('debug=1\n') - fp.write('debugexclude=libevent\n') + fp.write("daemon=0\n") + fp.write("printtoconsole=0\n") + fp.write("server=1\n") + fp.write("discover=0\n") + fp.write("listenonion=0\n") + fp.write("bind=127.0.0.1\n") + fp.write("debug=1\n") + fp.write("debugexclude=libevent\n") - fp.write('fallbackfee=0.01\n') - fp.write('acceptnonstdtxn=0\n') - fp.write('txindex=1\n') - fp.write('wallet=wallet.dat\n') + fp.write("fallbackfee=0.01\n") + fp.write("acceptnonstdtxn=0\n") + fp.write("txindex=1\n") + fp.write("wallet=wallet.dat\n") - fp.write('findpeers=0\n') + fp.write("findpeers=0\n") for opt in extra_opts: - fp.write(opt + '\n') + fp.write(opt + "\n") if base_p2p_port == BTC_BASE_PORT: - fp.write('deprecatedrpc=create_bdb\n') + fp.write("deprecatedrpc=create_bdb\n") elif base_p2p_port == BASE_PORT: # Particl - fp.write('zmqpubsmsg=tcp://127.0.0.1:{}\n'.format(BASE_ZMQ_PORT + node_id)) + fp.write("zmqpubsmsg=tcp://127.0.0.1:{}\n".format(BASE_ZMQ_PORT + node_id)) # minstakeinterval=5 # Using walletsettings stakelimit instead - fp.write('stakethreadconddelayms=1000\n') - fp.write('smsgsregtestadjust=0\n') + fp.write("stakethreadconddelayms=1000\n") + fp.write("smsgsregtestadjust=0\n") - if conf_file == 'pivx.conf': - params_dir = os.path.join(datadir, 'pivx-params') + if conf_file == "pivx.conf": + params_dir = os.path.join(datadir, "pivx-params") downloadPIVXParams(params_dir) - fp.write(f'paramsdir={params_dir}\n') + fp.write(f"paramsdir={params_dir}\n") for i in range(0, num_nodes): if node_id == i: continue - fp.write('addnode=127.0.0.1:{}\n'.format(base_p2p_port + i)) + fp.write("addnode=127.0.0.1:{}\n".format(base_p2p_port + i)) return node_dir def checkForks(ro): try: - if 'bip9_softforks' in ro: - assert (ro['bip9_softforks']['csv']['status'] == 'active') - assert (ro['bip9_softforks']['segwit']['status'] == 'active') + if "bip9_softforks" in ro: + assert ro["bip9_softforks"]["csv"]["status"] == "active" + assert ro["bip9_softforks"]["segwit"]["status"] == "active" else: - assert (ro['softforks']['csv']['active']) - assert (ro['softforks']['segwit']['active']) + assert ro["softforks"]["csv"]["active"] + assert ro["softforks"]["segwit"]["active"] except Exception as e: - logging.warning('Could not parse deployment info') + logging.warning("Could not parse deployment info") def stopDaemons(daemons): for d in daemons: - logging.info('Interrupting %d', d.handle.pid) + logging.info("Interrupting %d", d.handle.pid) try: d.handle.send_signal(signal.SIGINT) except Exception as e: - logging.info('Interrupting %d, error %s', d.handle.pid, str(e)) + logging.info("Interrupting %d, error %s", d.handle.pid, str(e)) for d in daemons: try: d.handle.wait(timeout=20) @@ -124,21 +142,23 @@ def stopDaemons(daemons): if fp: fp.close() except Exception as e: - logging.info('Closing %d, error %s', d.handle.pid, str(e)) + logging.info("Closing %d, error %s", d.handle.pid, str(e)) -def wait_for_bid(delay_event, swap_client, bid_id, state=None, sent: bool = False, wait_for: int = 20) -> None: - logging.info('wait_for_bid %s', bid_id.hex()) +def wait_for_bid( + delay_event, swap_client, bid_id, state=None, sent: bool = False, wait_for: int = 20 +) -> None: + logging.info("wait_for_bid %s", bid_id.hex()) for i in range(wait_for): if delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") delay_event.wait(1) filters = { - 'bid_id': bid_id, + "bid_id": bid_id, } bids = swap_client.listBids(sent=sent, filters=filters) - assert (len(bids) < 2) + assert len(bids) < 2 for bid in bids: if bid[2] == bid_id: if isinstance(state, (list, tuple)): @@ -149,55 +169,65 @@ def wait_for_bid(delay_event, swap_client, bid_id, state=None, sent: bool = Fals elif state is not None and state != bid[5]: continue return - raise ValueError('wait_for_bid timed out.') + raise ValueError("wait_for_bid timed out.") -def wait_for_bid_tx_state(delay_event, swap_client, bid_id, initiate_state, participate_state, wait_for=30): - logging.info('wait_for_bid_tx_state %s %s %s', bid_id.hex(), str(initiate_state), str(participate_state)) +def wait_for_bid_tx_state( + delay_event, swap_client, bid_id, initiate_state, participate_state, wait_for=30 +): + logging.info( + "wait_for_bid_tx_state %s %s %s", + bid_id.hex(), + str(initiate_state), + str(participate_state), + ) for i in range(wait_for): if delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") delay_event.wait(1) bid = swap_client.getBid(bid_id) - if (initiate_state is None or bid.getITxState() == initiate_state) \ - and (participate_state is None or bid.getPTxState() == participate_state): + if (initiate_state is None or bid.getITxState() == initiate_state) and ( + participate_state is None or bid.getPTxState() == participate_state + ): return - raise ValueError('wait_for_bid_tx_state timed out.') + raise ValueError("wait_for_bid_tx_state timed out.") -def wait_for_event(delay_event, swap_client, linked_type, linked_id, event_type=None, wait_for=20): - logging.info('wait_for_event') +def wait_for_event( + delay_event, swap_client, linked_type, linked_id, event_type=None, wait_for=20 +): + logging.info("wait_for_event") for i in range(wait_for): if delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") delay_event.wait(1) rv = swap_client.getEvents(linked_type, linked_id) for event in rv: if event_type is None or event.event_type == event_type: return event - raise ValueError('wait_for_event timed out.') + raise ValueError("wait_for_event timed out.") def wait_for_offer(delay_event, swap_client, offer_id, wait_for=20): - logging.info('wait_for_offer %s', offer_id.hex()) + logging.info("wait_for_offer %s", offer_id.hex()) for i in range(wait_for): if delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") delay_event.wait(1) offers = swap_client.listOffers() for offer in offers: if offer.offer_id == offer_id: return - raise ValueError('wait_for_offer timed out.') + raise ValueError("wait_for_offer timed out.") def wait_for_no_offer(delay_event, swap_client, offer_id, wait_for=20): - logging.info('wait_for_no_offer %s', offer_id.hex()) + logging.info("wait_for_no_offer %s", offer_id.hex()) for i in range(wait_for): if delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") delay_event.wait(1) offers = swap_client.listOffers() found_offer = False @@ -207,35 +237,35 @@ def wait_for_no_offer(delay_event, swap_client, offer_id, wait_for=20): break if not found_offer: return True - raise ValueError('wait_for_offer timed out.') + raise ValueError("wait_for_offer timed out.") def wait_for_in_progress(delay_event, swap_client, bid_id, sent=False): - logging.info('wait_for_in_progress %s', bid_id.hex()) + logging.info("wait_for_in_progress %s", bid_id.hex()) for i in range(20): if delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") delay_event.wait(1) swaps = swap_client.listSwapsInProgress() for b in swaps: if b[0] == bid_id: return - raise ValueError('wait_for_in_progress timed out.') + raise ValueError("wait_for_in_progress timed out.") def wait_for_none_active(delay_event, port, wait_for=30): for i in range(wait_for): if delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") delay_event.wait(1) js = read_json_api(port) - if js['num_swapping'] == 0 and js['num_watched_outputs'] == 0: + if js["num_swapping"] == 0 and js["num_watched_outputs"] == 0: return - raise ValueError('wait_for_none_active timed out.') + raise ValueError("wait_for_none_active timed out.") def abandon_all_swaps(delay_event, swap_client) -> None: - logging.info('abandon_all_swaps') + logging.info("abandon_all_swaps") for bid in swap_client.listBids(sent=True): swap_client.abandonBid(bid[2]) for bid in swap_client.listBids(sent=False): @@ -245,37 +275,39 @@ def abandon_all_swaps(delay_event, swap_client) -> None: def waitForNumOffers(delay_event, port, offers, wait_for=20): for i in range(wait_for): if delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") summary = read_json_api(port) - if summary['num_network_offers'] >= offers: + if summary["num_network_offers"] >= offers: return delay_event.wait(1) - raise ValueError('waitForNumOffers failed') + raise ValueError("waitForNumOffers failed") def waitForNumBids(delay_event, port, bids, wait_for=20): for i in range(wait_for): if delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") summary = read_json_api(port) - if summary['num_recv_bids'] >= bids: + if summary["num_recv_bids"] >= bids: return delay_event.wait(1) - raise ValueError('waitForNumBids failed') + raise ValueError("waitForNumBids failed") def waitForNumSwapping(delay_event, port, bids, wait_for=60): for i in range(wait_for): if delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") summary = read_json_api(port) - if summary['num_swapping'] >= bids: + if summary["num_swapping"] >= bids: return delay_event.wait(1) - raise ValueError('waitForNumSwapping failed') + raise ValueError("waitForNumSwapping failed") -def wait_for_balance(delay_event, url, balance_key, expect_amount, iterations=20, delay_time=3) -> None: +def wait_for_balance( + delay_event, url, balance_key, expect_amount, iterations=20, delay_time=3 +) -> None: i = 0 while not delay_event.is_set(): rv_js = json.loads(urlopen(url).read()) @@ -284,11 +316,13 @@ def wait_for_balance(delay_event, url, balance_key, expect_amount, iterations=20 delay_event.wait(delay_time) i += 1 if i > iterations: - raise ValueError('Expect {} {}'.format(balance_key, expect_amount)) + raise ValueError("Expect {} {}".format(balance_key, expect_amount)) -def wait_for_unspent(delay_event, ci, expect_amount, iterations=20, delay_time=1) -> None: - logging.info(f'Waiting for unspent balance: {expect_amount}') +def wait_for_unspent( + delay_event, ci, expect_amount, iterations=20, delay_time=1 +) -> None: + logging.info(f"Waiting for unspent balance: {expect_amount}") i = 0 while not delay_event.is_set(): unspent_addr = ci.getUnspentsByAddr() @@ -298,36 +332,41 @@ def wait_for_unspent(delay_event, ci, expect_amount, iterations=20, delay_time=1 delay_event.wait(delay_time) i += 1 if i > iterations: - raise ValueError('wait_for_unspent {}'.format(expect_amount)) + raise ValueError("wait_for_unspent {}".format(expect_amount)) def delay_for(delay_event, delay_for=60): - logging.info('Delaying for {} seconds.'.format(delay_for)) + logging.info("Delaying for {} seconds.".format(delay_for)) delay_event.wait(delay_for) def make_rpc_func(node_id, base_rpc_port=BASE_RPC_PORT): node_id = node_id - auth = 'test{0}:test_pass{0}'.format(node_id) + auth = "test{0}:test_pass{0}".format(node_id) def rpc_func(method, params=None, wallet=None): nonlocal node_id, auth return callrpc(base_rpc_port + node_id, auth, method, params, wallet) + return rpc_func -def waitForRPC(rpc_func, delay_event, rpc_command='getwalletinfo', max_tries=7): +def waitForRPC(rpc_func, delay_event, rpc_command="getwalletinfo", max_tries=7): for i in range(max_tries + 1): if delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") try: rpc_func(rpc_command) return except Exception as ex: if i < max_tries: - logging.warning('Can\'t connect to RPC: %s. Retrying in %d second/s.', str(ex), (i + 1)) + logging.warning( + "Can't connect to RPC: %s. Retrying in %d second/s.", + str(ex), + (i + 1), + ) delay_event.wait(i + 1) - raise ValueError('waitForRPC failed') + raise ValueError("waitForRPC failed") def extract_states_from_xu_file(file_path, prefix): @@ -336,39 +375,41 @@ def extract_states_from_xu_file(file_path, prefix): alt_counter = 0 active_path = 0 states[active_path] = [] - path_stack = [active_path, ] + path_stack = [ + active_path, + ] with open(file_path) as fp: for line in fp: line = line.strip() - if line.startswith('#'): + if line.startswith("#"): continue - if line == '};': + if line == "};": if len(path_stack) > 1: path_stack.pop() active_path = path_stack[-1] continue - split_line = line.split('[') + split_line = line.split("[") if len(split_line) < 2: continue - definitions = split_line[0].split(' ') + definitions = split_line[0].split(" ") if len(definitions) < 2: continue - if definitions[1] == 'alt': + if definitions[1] == "alt": alt_counter += 1 path_stack.append(alt_counter) states[alt_counter] = [s for s in states[active_path]] continue - if definitions[0] == '---': + if definitions[0] == "---": active_path = path_stack[-1] continue - if definitions[1] != 'abox': + if definitions[1] != "abox": continue if definitions[0] != prefix: continue @@ -384,7 +425,7 @@ def extract_states_from_xu_file(file_path, prefix): continue label = split_line[1][pos_start:pos_end] - if line.find('textbgcolor') > 0: + if line.find("textbgcolor") > 0: # transaction status pass @@ -396,35 +437,39 @@ def extract_states_from_xu_file(file_path, prefix): def compare_bid_states(states, expect_states, exact_match: bool = True) -> bool: for i in range(len(states) - 1, -1, -1): - if states[i][1] == 'Bid Delaying': + if states[i][1] == "Bid Delaying": del states[i] try: if exact_match: - assert (len(states) == len(expect_states)) + assert len(states) == len(expect_states) else: - assert (len(states) >= len(expect_states)) + assert len(states) >= len(expect_states) for i in range(len(expect_states)): s = states[i] if s[1] != expect_states[i]: - if 'Bid ' + expect_states[i] == s[1]: - logging.warning(f'Expected state {expect_states[i]} not an exact match to {s[1]}.') + if "Bid " + expect_states[i] == s[1]: + logging.warning( + f"Expected state {expect_states[i]} not an exact match to {s[1]}." + ) continue if [s[0], expect_states[i]] in states: - logging.warning(f'Expected state {expect_states[i]} found out of order at the same time as {s[1]}.') + logging.warning( + f"Expected state {expect_states[i]} found out of order at the same time as {s[1]}." + ) continue - raise ValueError(f'Expected state {expect_states[i]}, found {s[1]}') - assert (s[1] == expect_states[i]) + raise ValueError(f"Expected state {expect_states[i]}, found {s[1]}") + assert s[1] == expect_states[i] except Exception as e: - logging.info('Expecting states: {}'.format(json.dumps(expect_states, indent=4))) - logging.info('Have states: {}'.format(json.dumps(states, indent=4))) + logging.info("Expecting states: {}".format(json.dumps(expect_states, indent=4))) + logging.info("Have states: {}".format(json.dumps(states, indent=4))) raise e return True def compare_bid_states_unordered(states, expect_states, ignore_states=[]) -> bool: - ignore_states.append('Bid Delaying') + ignore_states.append("Bid Delaying") for i in range(len(states) - 1, -1, -1): if states[i][1] in ignore_states: del states[i] @@ -432,9 +477,9 @@ def compare_bid_states_unordered(states, expect_states, ignore_states=[]) -> boo try: assert len(states) == len(expect_states) for state in expect_states: - assert (any(state in s[1] for s in states)) + assert any(state in s[1] for s in states) except Exception as e: - logging.info('Expecting states: {}'.format(json.dumps(expect_states, indent=4))) - logging.info('Have states: {}'.format(json.dumps(states, indent=4))) + logging.info("Expecting states: {}".format(json.dumps(expect_states, indent=4))) + logging.info("Have states: {}".format(json.dumps(states, indent=4))) raise e return True diff --git a/tests/basicswap/common_xmr.py b/tests/basicswap/common_xmr.py index b4b6a56..8414074 100644 --- a/tests/basicswap/common_xmr.py +++ b/tests/basicswap/common_xmr.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020-2024 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -26,16 +27,22 @@ from tests.basicswap.util import ( waitForServer, ) from tests.basicswap.common import ( - BASE_PORT, BASE_RPC_PORT, - BTC_BASE_PORT, BTC_BASE_RPC_PORT, BTC_BASE_TOR_PORT, - LTC_BASE_PORT, LTC_BASE_RPC_PORT, + BASE_PORT, + BASE_RPC_PORT, + BTC_BASE_PORT, + BTC_BASE_RPC_PORT, + BTC_BASE_TOR_PORT, + LTC_BASE_PORT, + LTC_BASE_RPC_PORT, PIVX_BASE_PORT, ) from tests.basicswap.extended.test_dcr import ( - DCR_BASE_PORT, DCR_BASE_RPC_PORT, + DCR_BASE_PORT, + DCR_BASE_RPC_PORT, ) from tests.basicswap.test_bch_xmr import ( - BCH_BASE_PORT, BCH_BASE_RPC_PORT, + BCH_BASE_PORT, + BCH_BASE_RPC_PORT, ) from basicswap.contrib.rpcauth import generate_salt, password_to_hmac @@ -43,49 +50,58 @@ from basicswap.contrib.rpcauth import generate_salt, password_to_hmac import basicswap.config as cfg import basicswap.bin.run as runSystem -TEST_PATH = os.path.expanduser(os.getenv('TEST_PATH', '~/test_basicswap1')) +TEST_PATH = os.path.expanduser(os.getenv("TEST_PATH", "~/test_basicswap1")) -PARTICL_PORT_BASE = int(os.getenv('PARTICL_PORT_BASE', BASE_PORT)) -PARTICL_RPC_PORT_BASE = int(os.getenv('PARTICL_RPC_PORT_BASE', BASE_RPC_PORT)) +PARTICL_PORT_BASE = int(os.getenv("PARTICL_PORT_BASE", BASE_PORT)) +PARTICL_RPC_PORT_BASE = int(os.getenv("PARTICL_RPC_PORT_BASE", BASE_RPC_PORT)) -BITCOIN_PORT_BASE = int(os.getenv('BITCOIN_PORT_BASE', BTC_BASE_PORT)) -BITCOIN_RPC_PORT_BASE = int(os.getenv('BITCOIN_RPC_PORT_BASE', BTC_BASE_RPC_PORT)) -BITCOIN_TOR_PORT_BASE = int(os.getenv('BITCOIN_TOR_PORT_BASE', BTC_BASE_TOR_PORT)) +BITCOIN_PORT_BASE = int(os.getenv("BITCOIN_PORT_BASE", BTC_BASE_PORT)) +BITCOIN_RPC_PORT_BASE = int(os.getenv("BITCOIN_RPC_PORT_BASE", BTC_BASE_RPC_PORT)) +BITCOIN_TOR_PORT_BASE = int(os.getenv("BITCOIN_TOR_PORT_BASE", BTC_BASE_TOR_PORT)) -LITECOIN_RPC_PORT_BASE = int(os.getenv('LITECOIN_RPC_PORT_BASE', LTC_BASE_RPC_PORT)) -DECRED_RPC_PORT_BASE = int(os.getenv('DECRED_RPC_PORT_BASE', DCR_BASE_RPC_PORT)) -BITCOINCASH_RPC_PORT_BASE = int(os.getenv('BITCOINCASH_RPC_PORT_BASE', BCH_BASE_RPC_PORT)) +LITECOIN_RPC_PORT_BASE = int(os.getenv("LITECOIN_RPC_PORT_BASE", LTC_BASE_RPC_PORT)) +DECRED_RPC_PORT_BASE = int(os.getenv("DECRED_RPC_PORT_BASE", DCR_BASE_RPC_PORT)) +BITCOINCASH_RPC_PORT_BASE = int( + os.getenv("BITCOINCASH_RPC_PORT_BASE", BCH_BASE_RPC_PORT) +) FIRO_BASE_PORT = 34832 FIRO_BASE_RPC_PORT = 35832 -FIRO_RPC_PORT_BASE = int(os.getenv('FIRO_RPC_PORT_BASE', FIRO_BASE_RPC_PORT)) +FIRO_RPC_PORT_BASE = int(os.getenv("FIRO_RPC_PORT_BASE", FIRO_BASE_RPC_PORT)) XMR_BASE_P2P_PORT = 17792 XMR_BASE_RPC_PORT = 29798 XMR_BASE_WALLET_RPC_PORT = 29998 -EXTRA_CONFIG_JSON = json.loads(os.getenv('EXTRA_CONFIG_JSON', '{}')) +EXTRA_CONFIG_JSON = json.loads(os.getenv("EXTRA_CONFIG_JSON", "{}")) def waitForBidState(delay_event, port, bid_id, state_str, wait_for=60): for i in range(wait_for): if delay_event.is_set(): - raise ValueError('Test stopped.') - bid = json.loads(urlopen('http://127.0.0.1:12700/json/bids/{}'.format(bid_id)).read()) - if bid['bid_state'] == state_str: + raise ValueError("Test stopped.") + bid = json.loads( + urlopen("http://127.0.0.1:12700/json/bids/{}".format(bid_id)).read() + ) + if bid["bid_state"] == state_str: return delay_event.wait(1) - raise ValueError('waitForBidState failed') + raise ValueError("waitForBidState failed") def updateThread(xmr_addr, delay_event, xmr_auth): while not delay_event.is_set(): try: - callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'generateblocks', {'wallet_address': xmr_addr, 'amount_of_blocks': 1}, auth=xmr_auth) + callrpc_xmr( + XMR_BASE_RPC_PORT + 1, + "generateblocks", + {"wallet_address": xmr_addr, "amount_of_blocks": 1}, + auth=xmr_auth, + ) except Exception as e: - print('updateThread error', str(e)) + print("updateThread error", str(e)) delay_event.wait(2) @@ -97,47 +113,63 @@ def recursive_update_dict(base, new_vals): base[key] = value -def run_prepare(node_id, datadir_path, bins_path, with_coins, mnemonic_in=None, num_nodes=3, use_rpcauth=False, extra_settings={}, port_ofs=0): +def run_prepare( + node_id, + datadir_path, + bins_path, + with_coins, + mnemonic_in=None, + num_nodes=3, + use_rpcauth=False, + extra_settings={}, + port_ofs=0, +): config_path = os.path.join(datadir_path, cfg.CONFIG_FILENAME) - os.environ['BSX_TEST_MODE'] = 'true' - os.environ['PART_RPC_PORT'] = str(PARTICL_RPC_PORT_BASE) - os.environ['BTC_RPC_PORT'] = str(BITCOIN_RPC_PORT_BASE) - os.environ['LTC_RPC_PORT'] = str(LITECOIN_RPC_PORT_BASE) - os.environ['DCR_RPC_PORT'] = str(DECRED_RPC_PORT_BASE) - os.environ['BCH_PORT'] = str(BCH_BASE_PORT) - os.environ['BCH_RPC_PORT'] = str(BITCOINCASH_RPC_PORT_BASE) - os.environ['FIRO_RPC_PORT'] = str(FIRO_RPC_PORT_BASE) + os.environ["BSX_TEST_MODE"] = "true" + os.environ["PART_RPC_PORT"] = str(PARTICL_RPC_PORT_BASE) + os.environ["BTC_RPC_PORT"] = str(BITCOIN_RPC_PORT_BASE) + os.environ["LTC_RPC_PORT"] = str(LITECOIN_RPC_PORT_BASE) + os.environ["DCR_RPC_PORT"] = str(DECRED_RPC_PORT_BASE) + os.environ["BCH_PORT"] = str(BCH_BASE_PORT) + os.environ["BCH_RPC_PORT"] = str(BITCOINCASH_RPC_PORT_BASE) + os.environ["FIRO_RPC_PORT"] = str(FIRO_RPC_PORT_BASE) - os.environ['XMR_RPC_USER'] = 'xmr_user' - os.environ['XMR_RPC_PWD'] = 'xmr_pwd' + os.environ["XMR_RPC_USER"] = "xmr_user" + os.environ["XMR_RPC_PWD"] = "xmr_pwd" - os.environ['DCR_RPC_PWD'] = 'dcr_pwd' + os.environ["DCR_RPC_PWD"] = "dcr_pwd" import basicswap.bin.prepare as prepareSystem + # Hack: Reload module to set env vars as the basicswap_prepare module is initialised if imported from elsewhere earlier from importlib import reload + prepareSystem = reload(prepareSystem) testargs = [ - 'basicswap-prepare', + "basicswap-prepare", f'-datadir="{datadir_path}"', f'-bindir="{bins_path}"', - f'-portoffset={(node_id + port_ofs)}', - '-regtest', - f'-withcoins={with_coins}', - '-noextractover', - '-noreleasesizecheck', - '-xmrrestoreheight=0'] + f"-portoffset={(node_id + port_ofs)}", + "-regtest", + f"-withcoins={with_coins}", + "-noextractover", + "-noreleasesizecheck", + "-xmrrestoreheight=0", + ] if mnemonic_in: testargs.append(f'-particl_mnemonic="{mnemonic_in}"') - keysdirpath = os.getenv('PGP_KEYS_DIR_PATH', None) + keysdirpath = os.getenv("PGP_KEYS_DIR_PATH", None) if keysdirpath is not None: testargs.append('-keysdirpath="' + os.path.expanduser(keysdirpath) + '"') - with patch.object(sys, 'argv', testargs), patch('sys.stdout', new=StringIO()) as mocked_stdout: + with ( + patch.object(sys, "argv", testargs), + patch("sys.stdout", new=StringIO()) as mocked_stdout, + ): prepareSystem.main() - lines = mocked_stdout.getvalue().split('\n') + lines = mocked_stdout.getvalue().split("\n") if mnemonic_in is None: mnemonic_out = lines[-4] else: @@ -146,248 +178,311 @@ def run_prepare(node_id, datadir_path, bins_path, with_coins, mnemonic_in=None, with open(config_path) as fs: settings = json.load(fs) - config_filename = os.path.join(datadir_path, 'particl', 'particl.conf') - with open(config_filename, 'r') as fp: + config_filename = os.path.join(datadir_path, "particl", "particl.conf") + with open(config_filename, "r") as fp: lines = fp.readlines() - with open(config_filename, 'w') as fp: + with open(config_filename, "w") as fp: for line in lines: - if not line.startswith('staking'): + if not line.startswith("staking"): fp.write(line) - fp.write('port={}\n'.format(PARTICL_PORT_BASE + node_id + port_ofs)) - fp.write('bind=127.0.0.1\n') - fp.write('dnsseed=0\n') - fp.write('discover=0\n') - fp.write('listenonion=0\n') - fp.write('upnp=0\n') - fp.write('minstakeinterval=5\n') - fp.write('stakethreadconddelayms=2000\n') - fp.write('smsgsregtestadjust=0\n') + fp.write("port={}\n".format(PARTICL_PORT_BASE + node_id + port_ofs)) + fp.write("bind=127.0.0.1\n") + fp.write("dnsseed=0\n") + fp.write("discover=0\n") + fp.write("listenonion=0\n") + fp.write("upnp=0\n") + fp.write("minstakeinterval=5\n") + fp.write("stakethreadconddelayms=2000\n") + fp.write("smsgsregtestadjust=0\n") if use_rpcauth: salt = generate_salt(16) - rpc_user = 'test_part_' + str(node_id) - rpc_pass = 'test_part_pwd_' + str(node_id) - fp.write('rpcauth={}:{}${}\n'.format(rpc_user, salt, password_to_hmac(salt, rpc_pass))) - settings['chainclients']['particl']['rpcuser'] = rpc_user - settings['chainclients']['particl']['rpcpassword'] = rpc_pass + rpc_user = "test_part_" + str(node_id) + rpc_pass = "test_part_pwd_" + str(node_id) + fp.write( + "rpcauth={}:{}${}\n".format( + rpc_user, salt, password_to_hmac(salt, rpc_pass) + ) + ) + settings["chainclients"]["particl"]["rpcuser"] = rpc_user + settings["chainclients"]["particl"]["rpcpassword"] = rpc_pass for ip in range(num_nodes): if ip != node_id: - fp.write('connect=127.0.0.1:{}\n'.format(PARTICL_PORT_BASE + ip + port_ofs)) - for opt in EXTRA_CONFIG_JSON.get('part{}'.format(node_id), []): - fp.write(opt + '\n') + fp.write( + "connect=127.0.0.1:{}\n".format(PARTICL_PORT_BASE + ip + port_ofs) + ) + for opt in EXTRA_CONFIG_JSON.get("part{}".format(node_id), []): + fp.write(opt + "\n") - coins_array = with_coins.split(',') + coins_array = with_coins.split(",") - if 'bitcoin' in coins_array: + if "bitcoin" in coins_array: # Pruned nodes don't provide blocks - config_filename = os.path.join(datadir_path, 'bitcoin', 'bitcoin.conf') - with open(config_filename, 'r') as fp: + config_filename = os.path.join(datadir_path, "bitcoin", "bitcoin.conf") + with open(config_filename, "r") as fp: lines = fp.readlines() - with open(config_filename, 'w') as fp: + with open(config_filename, "w") as fp: for line in lines: - if not line.startswith('prune'): + if not line.startswith("prune"): fp.write(line) - fp.write('port={}\n'.format(BITCOIN_PORT_BASE + node_id + port_ofs)) - fp.write('bind=127.0.0.1\n') + fp.write("port={}\n".format(BITCOIN_PORT_BASE + node_id + port_ofs)) + fp.write("bind=127.0.0.1\n") # listenonion=0 does not stop the node from trying to bind to the tor port # https://github.com/bitcoin/bitcoin/issues/22726 - fp.write('bind=127.0.0.1:{}=onion\n'.format(BITCOIN_TOR_PORT_BASE + node_id + port_ofs)) - fp.write('dnsseed=0\n') - fp.write('discover=0\n') - fp.write('listenonion=0\n') - fp.write('upnp=0\n') + fp.write( + "bind=127.0.0.1:{}=onion\n".format( + BITCOIN_TOR_PORT_BASE + node_id + port_ofs + ) + ) + fp.write("dnsseed=0\n") + fp.write("discover=0\n") + fp.write("listenonion=0\n") + fp.write("upnp=0\n") if use_rpcauth: salt = generate_salt(16) - rpc_user = 'test_btc_' + str(node_id) - rpc_pass = 'test_btc_pwd_' + str(node_id) - fp.write('rpcauth={}:{}${}\n'.format(rpc_user, salt, password_to_hmac(salt, rpc_pass))) - settings['chainclients']['bitcoin']['rpcuser'] = rpc_user - settings['chainclients']['bitcoin']['rpcpassword'] = rpc_pass + rpc_user = "test_btc_" + str(node_id) + rpc_pass = "test_btc_pwd_" + str(node_id) + fp.write( + "rpcauth={}:{}${}\n".format( + rpc_user, salt, password_to_hmac(salt, rpc_pass) + ) + ) + settings["chainclients"]["bitcoin"]["rpcuser"] = rpc_user + settings["chainclients"]["bitcoin"]["rpcpassword"] = rpc_pass for ip in range(num_nodes): if ip != node_id: - fp.write('connect=127.0.0.1:{}\n'.format(BITCOIN_PORT_BASE + ip + port_ofs)) - for opt in EXTRA_CONFIG_JSON.get('btc{}'.format(node_id), []): - fp.write(opt + '\n') + fp.write( + "connect=127.0.0.1:{}\n".format( + BITCOIN_PORT_BASE + ip + port_ofs + ) + ) + for opt in EXTRA_CONFIG_JSON.get("btc{}".format(node_id), []): + fp.write(opt + "\n") - if 'litecoin' in coins_array: + if "litecoin" in coins_array: # Pruned nodes don't provide blocks - config_filename = os.path.join(datadir_path, 'litecoin', 'litecoin.conf') - with open(config_filename, 'r') as fp: + config_filename = os.path.join(datadir_path, "litecoin", "litecoin.conf") + with open(config_filename, "r") as fp: lines = fp.readlines() - with open(config_filename, 'w') as fp: + with open(config_filename, "w") as fp: for line in lines: - if not line.startswith('prune'): + if not line.startswith("prune"): fp.write(line) - fp.write('port={}\n'.format(LTC_BASE_PORT + node_id + port_ofs)) - fp.write('bind=127.0.0.1\n') - fp.write('dnsseed=0\n') - fp.write('discover=0\n') - fp.write('listenonion=0\n') - fp.write('upnp=0\n') + fp.write("port={}\n".format(LTC_BASE_PORT + node_id + port_ofs)) + fp.write("bind=127.0.0.1\n") + fp.write("dnsseed=0\n") + fp.write("discover=0\n") + fp.write("listenonion=0\n") + fp.write("upnp=0\n") if use_rpcauth: salt = generate_salt(16) - rpc_user = 'test_ltc_' + str(node_id) - rpc_pass = 'test_ltc_pwd_' + str(node_id) - fp.write('rpcauth={}:{}${}\n'.format(rpc_user, salt, password_to_hmac(salt, rpc_pass))) - settings['chainclients']['litecoin']['rpcuser'] = rpc_user - settings['chainclients']['litecoin']['rpcpassword'] = rpc_pass + rpc_user = "test_ltc_" + str(node_id) + rpc_pass = "test_ltc_pwd_" + str(node_id) + fp.write( + "rpcauth={}:{}${}\n".format( + rpc_user, salt, password_to_hmac(salt, rpc_pass) + ) + ) + settings["chainclients"]["litecoin"]["rpcuser"] = rpc_user + settings["chainclients"]["litecoin"]["rpcpassword"] = rpc_pass for ip in range(num_nodes): if ip != node_id: - fp.write('connect=127.0.0.1:{}\n'.format(LTC_BASE_PORT + ip + port_ofs)) - for opt in EXTRA_CONFIG_JSON.get('ltc{}'.format(node_id), []): - fp.write(opt + '\n') + fp.write( + "connect=127.0.0.1:{}\n".format(LTC_BASE_PORT + ip + port_ofs) + ) + for opt in EXTRA_CONFIG_JSON.get("ltc{}".format(node_id), []): + fp.write(opt + "\n") - if 'decred' in coins_array: + if "decred" in coins_array: # Pruned nodes don't provide blocks - config_filename = os.path.join(datadir_path, 'decred', 'dcrd.conf') - with open(config_filename, 'r') as fp: + config_filename = os.path.join(datadir_path, "decred", "dcrd.conf") + with open(config_filename, "r") as fp: lines = fp.readlines() - with open(config_filename, 'w') as fp: + with open(config_filename, "w") as fp: for line in lines: - if not line.startswith('prune'): + if not line.startswith("prune"): fp.write(line) - fp.write('listen=127.0.0.1:{}\n'.format(DCR_BASE_PORT + node_id + port_ofs)) - fp.write('noseeders=1\n') - fp.write('nodnsseed=1\n') - fp.write('nodiscoverip=1\n') + fp.write("listen=127.0.0.1:{}\n".format(DCR_BASE_PORT + node_id + port_ofs)) + fp.write("noseeders=1\n") + fp.write("nodnsseed=1\n") + fp.write("nodiscoverip=1\n") if node_id == 0: - fp.write('miningaddr=SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH\n') + fp.write("miningaddr=SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH\n") for ip in range(num_nodes): if ip != node_id: - fp.write('addpeer=127.0.0.1:{}\n'.format(DCR_BASE_PORT + ip + port_ofs)) - config_filename = os.path.join(datadir_path, 'decred', 'dcrwallet.conf') - with open(config_filename, 'a') as fp: - fp.write('enablevoting=1\n') + fp.write( + "addpeer=127.0.0.1:{}\n".format( + DCR_BASE_PORT + ip + port_ofs + ) + ) + config_filename = os.path.join(datadir_path, "decred", "dcrwallet.conf") + with open(config_filename, "a") as fp: + fp.write("enablevoting=1\n") - if 'pivx' in coins_array: + if "pivx" in coins_array: # Pruned nodes don't provide blocks - config_filename = os.path.join(datadir_path, 'pivx', 'pivx.conf') - with open(config_filename, 'r') as fp: + config_filename = os.path.join(datadir_path, "pivx", "pivx.conf") + with open(config_filename, "r") as fp: lines = fp.readlines() - with open(config_filename, 'w') as fp: + with open(config_filename, "w") as fp: for line in lines: - if not line.startswith('prune'): + if not line.startswith("prune"): fp.write(line) - fp.write('port={}\n'.format(PIVX_BASE_PORT + node_id + port_ofs)) - fp.write('bind=127.0.0.1\n') - fp.write('dnsseed=0\n') - fp.write('discover=0\n') - fp.write('listenonion=0\n') - fp.write('upnp=0\n') + fp.write("port={}\n".format(PIVX_BASE_PORT + node_id + port_ofs)) + fp.write("bind=127.0.0.1\n") + fp.write("dnsseed=0\n") + fp.write("discover=0\n") + fp.write("listenonion=0\n") + fp.write("upnp=0\n") if use_rpcauth: salt = generate_salt(16) - rpc_user = 'test_pivx_' + str(node_id) - rpc_pass = 'test_pivx_pwd_' + str(node_id) - fp.write('rpcauth={}:{}${}\n'.format(rpc_user, salt, password_to_hmac(salt, rpc_pass))) - settings['chainclients']['pivx']['rpcuser'] = rpc_user - settings['chainclients']['pivx']['rpcpassword'] = rpc_pass + rpc_user = "test_pivx_" + str(node_id) + rpc_pass = "test_pivx_pwd_" + str(node_id) + fp.write( + "rpcauth={}:{}${}\n".format( + rpc_user, salt, password_to_hmac(salt, rpc_pass) + ) + ) + settings["chainclients"]["pivx"]["rpcuser"] = rpc_user + settings["chainclients"]["pivx"]["rpcpassword"] = rpc_pass for ip in range(num_nodes): if ip != node_id: - fp.write('connect=127.0.0.1:{}\n'.format(PIVX_BASE_PORT + ip + port_ofs)) - for opt in EXTRA_CONFIG_JSON.get('pivx{}'.format(node_id), []): - fp.write(opt + '\n') + fp.write( + "connect=127.0.0.1:{}\n".format(PIVX_BASE_PORT + ip + port_ofs) + ) + for opt in EXTRA_CONFIG_JSON.get("pivx{}".format(node_id), []): + fp.write(opt + "\n") - if 'firo' in coins_array: + if "firo" in coins_array: # Pruned nodes don't provide blocks - config_filename = os.path.join(datadir_path, 'firo', 'firo.conf') - with open(config_filename, 'r') as fp: + config_filename = os.path.join(datadir_path, "firo", "firo.conf") + with open(config_filename, "r") as fp: lines = fp.readlines() - with open(config_filename, 'w') as fp: + with open(config_filename, "w") as fp: for line in lines: - if not line.startswith('prune'): + if not line.startswith("prune"): fp.write(line) - fp.write('port={}\n'.format(FIRO_BASE_PORT + node_id + port_ofs)) - fp.write('bind=127.0.0.1\n') - fp.write('dnsseed=0\n') - fp.write('discover=0\n') - fp.write('listenonion=0\n') - fp.write('upnp=0\n') + fp.write("port={}\n".format(FIRO_BASE_PORT + node_id + port_ofs)) + fp.write("bind=127.0.0.1\n") + fp.write("dnsseed=0\n") + fp.write("discover=0\n") + fp.write("listenonion=0\n") + fp.write("upnp=0\n") if use_rpcauth: salt = generate_salt(16) - rpc_user = 'test_firo_' + str(node_id) - rpc_pass = 'test_firo_pwd_' + str(node_id) - fp.write('rpcauth={}:{}${}\n'.format(rpc_user, salt, password_to_hmac(salt, rpc_pass))) - settings['chainclients']['firo']['rpcuser'] = rpc_user - settings['chainclients']['firo']['rpcpassword'] = rpc_pass + rpc_user = "test_firo_" + str(node_id) + rpc_pass = "test_firo_pwd_" + str(node_id) + fp.write( + "rpcauth={}:{}${}\n".format( + rpc_user, salt, password_to_hmac(salt, rpc_pass) + ) + ) + settings["chainclients"]["firo"]["rpcuser"] = rpc_user + settings["chainclients"]["firo"]["rpcpassword"] = rpc_pass for ip in range(num_nodes): if ip != node_id: - fp.write('connect=127.0.0.1:{}\n'.format(FIRO_BASE_PORT + ip + port_ofs)) - for opt in EXTRA_CONFIG_JSON.get('firo{}'.format(node_id), []): - fp.write(opt + '\n') + fp.write( + "connect=127.0.0.1:{}\n".format(FIRO_BASE_PORT + ip + port_ofs) + ) + for opt in EXTRA_CONFIG_JSON.get("firo{}".format(node_id), []): + fp.write(opt + "\n") - if 'monero' in coins_array: - with open(os.path.join(datadir_path, 'monero', 'monerod.conf'), 'a') as fp: - fp.write('p2p-bind-ip=127.0.0.1\n') - fp.write('p2p-bind-port={}\n'.format(XMR_BASE_P2P_PORT + node_id + port_ofs)) + if "monero" in coins_array: + with open(os.path.join(datadir_path, "monero", "monerod.conf"), "a") as fp: + fp.write("p2p-bind-ip=127.0.0.1\n") + fp.write( + "p2p-bind-port={}\n".format(XMR_BASE_P2P_PORT + node_id + port_ofs) + ) for ip in range(num_nodes): if ip != node_id: - fp.write('add-exclusive-node=127.0.0.1:{}\n'.format(XMR_BASE_P2P_PORT + ip + port_ofs)) + fp.write( + "add-exclusive-node=127.0.0.1:{}\n".format( + XMR_BASE_P2P_PORT + ip + port_ofs + ) + ) - if 'bitcoincash' in coins_array: - config_filename = os.path.join(datadir_path, 'bitcoincash', 'bitcoin.conf') - with open(config_filename, 'r') as fp: + if "bitcoincash" in coins_array: + config_filename = os.path.join(datadir_path, "bitcoincash", "bitcoin.conf") + with open(config_filename, "r") as fp: lines = fp.readlines() - with open(config_filename, 'w') as fp: + with open(config_filename, "w") as fp: for line in lines: - if not line.startswith('prune'): + if not line.startswith("prune"): fp.write(line) # NOTE: port is set (when starting daemon) from basicswap.json - fp.write('bind=127.0.0.1\n') - fp.write('dnsseed=0\n') - fp.write('discover=0\n') - fp.write('listenonion=0\n') - fp.write('upnp=0\n') + fp.write("bind=127.0.0.1\n") + fp.write("dnsseed=0\n") + fp.write("discover=0\n") + fp.write("listenonion=0\n") + fp.write("upnp=0\n") if use_rpcauth: salt = generate_salt(16) - rpc_user = 'test_bch_' + str(node_id) - rpc_pass = 'test_bch_pwd_' + str(node_id) - fp.write('rpcauth={}:{}${}\n'.format(rpc_user, salt, password_to_hmac(salt, rpc_pass))) - settings['chainclients']['bitcoincash']['rpcuser'] = rpc_user - settings['chainclients']['bitcoincash']['rpcpassword'] = rpc_pass + rpc_user = "test_bch_" + str(node_id) + rpc_pass = "test_bch_pwd_" + str(node_id) + fp.write( + "rpcauth={}:{}${}\n".format( + rpc_user, salt, password_to_hmac(salt, rpc_pass) + ) + ) + settings["chainclients"]["bitcoincash"]["rpcuser"] = rpc_user + settings["chainclients"]["bitcoincash"]["rpcpassword"] = rpc_pass for ip in range(num_nodes): if ip != node_id: - fp.write('connect=127.0.0.1:{}\n'.format(BCH_BASE_PORT + ip + port_ofs)) - for opt in EXTRA_CONFIG_JSON.get('bch{}'.format(node_id), []): - fp.write(opt + '\n') + fp.write( + "connect=127.0.0.1:{}\n".format(BCH_BASE_PORT + ip + port_ofs) + ) + for opt in EXTRA_CONFIG_JSON.get("bch{}".format(node_id), []): + fp.write(opt + "\n") with open(config_path) as fs: settings = json.load(fs) - settings['min_delay_event'] = 1 - settings['max_delay_event'] = 4 - settings['min_delay_event_short'] = 1 - settings['max_delay_event_short'] = 4 - settings['min_delay_retry'] = 10 - settings['max_delay_retry'] = 20 + settings["min_delay_event"] = 1 + settings["max_delay_event"] = 4 + settings["min_delay_event_short"] = 1 + settings["max_delay_event_short"] = 4 + settings["min_delay_retry"] = 10 + settings["max_delay_retry"] = 20 - settings['check_progress_seconds'] = 5 - settings['check_watched_seconds'] = 5 - settings['check_expired_seconds'] = 60 - settings['check_events_seconds'] = 5 - settings['check_xmr_swaps_seconds'] = 5 + settings["check_progress_seconds"] = 5 + settings["check_watched_seconds"] = 5 + settings["check_expired_seconds"] = 60 + settings["check_events_seconds"] = 5 + settings["check_xmr_swaps_seconds"] = 5 recursive_update_dict(settings, extra_settings) - extra_config = EXTRA_CONFIG_JSON.get('sc{}'.format(node_id), {}) + extra_config = EXTRA_CONFIG_JSON.get("sc{}".format(node_id), {}) recursive_update_dict(settings, extra_config) - with open(config_path, 'w') as fp: + with open(config_path, "w") as fp: json.dump(settings, fp, indent=4) return mnemonic_out -def prepare_nodes(num_nodes, extra_coins, use_rpcauth=False, extra_settings={}, port_ofs=0): - bins_path = os.path.join(TEST_PATH, 'bin') +def prepare_nodes( + num_nodes, extra_coins, use_rpcauth=False, extra_settings={}, port_ofs=0 +): + bins_path = os.path.join(TEST_PATH, "bin") for i in range(num_nodes): - logging.info('Preparing node: %d.', i) - client_path = os.path.join(TEST_PATH, 'client{}'.format(i)) + logging.info("Preparing node: %d.", i) + client_path = os.path.join(TEST_PATH, "client{}".format(i)) try: shutil.rmtree(client_path) except Exception as ex: - logging.warning('setUpClass %s', str(ex)) + logging.warning("setUpClass %s", str(ex)) - run_prepare(i, client_path, bins_path, extra_coins, mnemonics[i] if i < len(mnemonics) else None, - num_nodes=num_nodes, use_rpcauth=use_rpcauth, extra_settings=extra_settings, port_ofs=port_ofs) + run_prepare( + i, + client_path, + bins_path, + extra_coins, + mnemonics[i] if i < len(mnemonics) else None, + num_nodes=num_nodes, + use_rpcauth=use_rpcauth, + extra_settings=extra_settings, + port_ofs=port_ofs, + ) class TestBase(unittest.TestCase): @@ -395,34 +490,38 @@ class TestBase(unittest.TestCase): super(TestBase, cls).setUpClass() cls.delay_event = threading.Event() - signal.signal(signal.SIGINT, lambda signal, frame: cls.signal_handler(cls, signal, frame)) + signal.signal( + signal.SIGINT, lambda signal, frame: cls.signal_handler(cls, signal, frame) + ) def signal_handler(self, sig, frame): - logging.info('signal {} detected.'.format(sig)) + logging.info("signal {} detected.".format(sig)) self.delay_event.set() def wait_seconds(self, seconds): self.delay_event.wait(seconds) if self.delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") def wait_for_particl_height(self, http_port, num_blocks=3): # Wait for height, or sequencelock is thrown off by genesis blocktime - logging.info('Waiting for Particl chain height %d', num_blocks) + logging.info("Waiting for Particl chain height %d", num_blocks) for i in range(60): if self.delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") try: - wallets = json.loads(urlopen(f'http://127.0.0.1:{http_port}/json/wallets').read()) - particl_blocks = wallets['PART']['blocks'] - print('particl_blocks', particl_blocks) + wallets = json.loads( + urlopen(f"http://127.0.0.1:{http_port}/json/wallets").read() + ) + particl_blocks = wallets["PART"]["blocks"] + print("particl_blocks", particl_blocks) if particl_blocks >= num_blocks: return except Exception as e: - print('Error reading wallets', str(e)) + print("Error reading wallets", str(e)) self.delay_event.wait(1) - raise ValueError(f'wait_for_particl_height failed http_port: {http_port}') + raise ValueError(f"wait_for_particl_height failed http_port: {http_port}") class XmrTestBase(TestBase): @@ -433,19 +532,21 @@ class XmrTestBase(TestBase): cls.update_thread = None cls.processes = [] - prepare_nodes(3, 'monero') + prepare_nodes(3, "monero") def run_thread(self, client_id): - client_path = os.path.join(TEST_PATH, 'client{}'.format(client_id)) - testargs = ['basicswap-run', '-datadir=' + client_path, '-regtest'] - with patch.object(sys, 'argv', testargs): + client_path = os.path.join(TEST_PATH, "client{}".format(client_id)) + testargs = ["basicswap-run", "-datadir=" + client_path, "-regtest"] + with patch.object(sys, "argv", testargs): runSystem.main() def start_processes(self): self.delay_event.clear() for i in range(3): - self.processes.append(multiprocessing.Process(target=self.run_thread, args=(i,))) + self.processes.append( + multiprocessing.Process(target=self.run_thread, args=(i,)) + ) self.processes[-1].start() waitForServer(self.delay_event, 12701) @@ -453,35 +554,55 @@ class XmrTestBase(TestBase): def waitForMainAddress(): for i in range(20): if self.delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") try: - wallets = json.loads(urlopen('http://127.0.0.1:12701/json/wallets').read()) - return wallets['XMR']['main_address'] + wallets = json.loads( + urlopen("http://127.0.0.1:12701/json/wallets").read() + ) + return wallets["XMR"]["main_address"] except Exception as e: - print('Waiting for main address {}'.format(str(e))) + print("Waiting for main address {}".format(str(e))) self.delay_event.wait(1) - raise ValueError('waitForMainAddress timedout') + raise ValueError("waitForMainAddress timedout") + xmr_addr1 = waitForMainAddress() num_blocks = 100 xmr_auth = None - if os.getenv('XMR_RPC_USER', '') != '': - xmr_auth = (os.getenv('XMR_RPC_USER', ''), os.getenv('XMR_RPC_PWD', '')) + if os.getenv("XMR_RPC_USER", "") != "": + xmr_auth = (os.getenv("XMR_RPC_USER", ""), os.getenv("XMR_RPC_PWD", "")) - if callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'get_block_count', auth=xmr_auth)['count'] < num_blocks: - logging.info('Mining {} Monero blocks to {}.'.format(num_blocks, xmr_addr1)) - callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'generateblocks', {'wallet_address': xmr_addr1, 'amount_of_blocks': num_blocks}, auth=xmr_auth) - logging.info('XMR blocks: %d', callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'get_block_count', auth=xmr_auth)['count']) + if ( + callrpc_xmr(XMR_BASE_RPC_PORT + 1, "get_block_count", auth=xmr_auth)[ + "count" + ] + < num_blocks + ): + logging.info("Mining {} Monero blocks to {}.".format(num_blocks, xmr_addr1)) + callrpc_xmr( + XMR_BASE_RPC_PORT + 1, + "generateblocks", + {"wallet_address": xmr_addr1, "amount_of_blocks": num_blocks}, + auth=xmr_auth, + ) + logging.info( + "XMR blocks: %d", + callrpc_xmr(XMR_BASE_RPC_PORT + 1, "get_block_count", auth=xmr_auth)[ + "count" + ], + ) - self.update_thread = threading.Thread(target=updateThread, args=(xmr_addr1, self.delay_event, xmr_auth)) + self.update_thread = threading.Thread( + target=updateThread, args=(xmr_addr1, self.delay_event, xmr_auth) + ) self.update_thread.start() self.wait_for_particl_height(12701, num_blocks=3) @classmethod def tearDownClass(cls): - logging.info('Stopping test') + logging.info("Stopping test") cls.delay_event.set() if cls.update_thread: cls.update_thread.join() diff --git a/tests/basicswap/extended/test_dash.py b/tests/basicswap/extended/test_dash.py index 8f7e95b..60079a4 100644 --- a/tests/basicswap/extended/test_dash.py +++ b/tests/basicswap/extended/test_dash.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2022-2023 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -83,80 +84,82 @@ BTC_NODE = 4 delay_event = threading.Event() stop_test = False -DASH_BINDIR = os.path.expanduser(os.getenv('DASH_BINDIR', os.path.join(cfg.DEFAULT_TEST_BINDIR, 'dash'))) -DASHD = os.getenv('DASHD', 'dashd' + cfg.bin_suffix) -DASH_CLI = os.getenv('DASH_CLI', 'dash-cli' + cfg.bin_suffix) -DASH_TX = os.getenv('DASH_TX', 'dash-tx' + cfg.bin_suffix) +DASH_BINDIR = os.path.expanduser( + os.getenv("DASH_BINDIR", os.path.join(cfg.DEFAULT_TEST_BINDIR, "dash")) +) +DASHD = os.getenv("DASHD", "dashd" + cfg.bin_suffix) +DASH_CLI = os.getenv("DASH_CLI", "dash-cli" + cfg.bin_suffix) +DASH_TX = os.getenv("DASH_TX", "dash-tx" + cfg.bin_suffix) -def prepareOtherDir(datadir, nodeId, conf_file='dash.conf'): +def prepareOtherDir(datadir, nodeId, conf_file="dash.conf"): node_dir = os.path.join(datadir, str(nodeId)) if not os.path.exists(node_dir): os.makedirs(node_dir) filePath = os.path.join(node_dir, conf_file) - with open(filePath, 'w+') as fp: - fp.write('regtest=1\n') - fp.write('[regtest]\n') - fp.write('port=' + str(BASE_PORT + nodeId) + '\n') - fp.write('rpcport=' + str(BASE_RPC_PORT + nodeId) + '\n') + with open(filePath, "w+") as fp: + fp.write("regtest=1\n") + fp.write("[regtest]\n") + fp.write("port=" + str(BASE_PORT + nodeId) + "\n") + fp.write("rpcport=" + str(BASE_RPC_PORT + nodeId) + "\n") - fp.write('daemon=0\n') - fp.write('printtoconsole=0\n') - fp.write('server=1\n') - fp.write('discover=0\n') - fp.write('listenonion=0\n') - fp.write('bind=127.0.0.1\n') - fp.write('findpeers=0\n') - fp.write('debug=1\n') - fp.write('debugexclude=libevent\n') + fp.write("daemon=0\n") + fp.write("printtoconsole=0\n") + fp.write("server=1\n") + fp.write("discover=0\n") + fp.write("listenonion=0\n") + fp.write("bind=127.0.0.1\n") + fp.write("findpeers=0\n") + fp.write("debug=1\n") + fp.write("debugexclude=libevent\n") - fp.write('fallbackfee=0.01\n') - fp.write('acceptnonstdtxn=0\n') + fp.write("fallbackfee=0.01\n") + fp.write("acceptnonstdtxn=0\n") - if conf_file == 'bitcoin.conf': - fp.write('wallet=wallet.dat\n') + if conf_file == "bitcoin.conf": + fp.write("wallet=wallet.dat\n") def prepareDir(datadir, nodeId, network_key, network_pubkey): node_dir = os.path.join(datadir, str(nodeId)) if not os.path.exists(node_dir): os.makedirs(node_dir) - filePath = os.path.join(node_dir, 'particl.conf') + filePath = os.path.join(node_dir, "particl.conf") - with open(filePath, 'w+') as fp: - fp.write('regtest=1\n') - fp.write('[regtest]\n') - fp.write('port=' + str(BASE_PORT + nodeId) + '\n') - fp.write('rpcport=' + str(BASE_RPC_PORT + nodeId) + '\n') + with open(filePath, "w+") as fp: + fp.write("regtest=1\n") + fp.write("[regtest]\n") + fp.write("port=" + str(BASE_PORT + nodeId) + "\n") + fp.write("rpcport=" + str(BASE_RPC_PORT + nodeId) + "\n") - fp.write('daemon=0\n') - fp.write('printtoconsole=0\n') - fp.write('server=1\n') - fp.write('discover=0\n') - fp.write('listenonion=0\n') - fp.write('bind=127.0.0.1\n') - fp.write('findpeers=0\n') - fp.write('debug=1\n') - fp.write('debugexclude=libevent\n') - fp.write('zmqpubsmsg=tcp://127.0.0.1:' + str(BASE_ZMQ_PORT + nodeId) + '\n') - fp.write('wallet=wallet.dat\n') - fp.write('fallbackfee=0.01\n') + fp.write("daemon=0\n") + fp.write("printtoconsole=0\n") + fp.write("server=1\n") + fp.write("discover=0\n") + fp.write("listenonion=0\n") + fp.write("bind=127.0.0.1\n") + fp.write("findpeers=0\n") + fp.write("debug=1\n") + fp.write("debugexclude=libevent\n") + fp.write("zmqpubsmsg=tcp://127.0.0.1:" + str(BASE_ZMQ_PORT + nodeId) + "\n") + fp.write("wallet=wallet.dat\n") + fp.write("fallbackfee=0.01\n") - fp.write('acceptnonstdtxn=0\n') - fp.write('minstakeinterval=5\n') - fp.write('smsgsregtestadjust=0\n') + fp.write("acceptnonstdtxn=0\n") + fp.write("minstakeinterval=5\n") + fp.write("smsgsregtestadjust=0\n") for i in range(0, NUM_NODES): if nodeId == i: continue - fp.write('addnode=127.0.0.1:%d\n' % (BASE_PORT + i)) + fp.write("addnode=127.0.0.1:%d\n" % (BASE_PORT + i)) if nodeId < 2: - fp.write('spentindex=1\n') - fp.write('txindex=1\n') + fp.write("spentindex=1\n") + fp.write("txindex=1\n") - basicswap_dir = os.path.join(datadir, str(nodeId), 'basicswap') + basicswap_dir = os.path.join(datadir, str(nodeId), "basicswap") if not os.path.exists(basicswap_dir): os.makedirs(basicswap_dir) @@ -164,72 +167,91 @@ def prepareDir(datadir, nodeId, network_key, network_pubkey): btcdatadir = os.path.join(datadir, str(BTC_NODE)) settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME) settings = { - 'debug': True, - 'zmqhost': 'tcp://127.0.0.1', - 'zmqport': BASE_ZMQ_PORT + nodeId, - 'htmlhost': '127.0.0.1', - 'htmlport': 12700 + nodeId, - 'network_key': network_key, - 'network_pubkey': network_pubkey, - 'chainclients': { - 'particl': { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': BASE_RPC_PORT + nodeId, - 'datadir': node_dir, - 'bindir': cfg.PARTICL_BINDIR, - 'blocks_confirmed': 2, # Faster testing + "debug": True, + "zmqhost": "tcp://127.0.0.1", + "zmqport": BASE_ZMQ_PORT + nodeId, + "htmlhost": "127.0.0.1", + "htmlport": 12700 + nodeId, + "network_key": network_key, + "network_pubkey": network_pubkey, + "chainclients": { + "particl": { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": BASE_RPC_PORT + nodeId, + "datadir": node_dir, + "bindir": cfg.PARTICL_BINDIR, + "blocks_confirmed": 2, # Faster testing }, - 'dash': { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': BASE_RPC_PORT + DASH_NODE, - 'datadir': dashdatadir, - 'bindir': DASH_BINDIR, - 'use_csv': True, - 'use_segwit': False, + "dash": { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": BASE_RPC_PORT + DASH_NODE, + "datadir": dashdatadir, + "bindir": DASH_BINDIR, + "use_csv": True, + "use_segwit": False, + }, + "bitcoin": { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": BASE_RPC_PORT + BTC_NODE, + "datadir": btcdatadir, + "bindir": cfg.BITCOIN_BINDIR, + "use_segwit": True, }, - 'bitcoin': { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': BASE_RPC_PORT + BTC_NODE, - 'datadir': btcdatadir, - 'bindir': cfg.BITCOIN_BINDIR, - 'use_segwit': True, - } }, - 'check_progress_seconds': 2, - 'check_watched_seconds': 4, - 'check_expired_seconds': 60, - 'check_events_seconds': 1, - 'check_xmr_swaps_seconds': 1, - 'min_delay_event': 1, - 'max_delay_event': 3, - 'min_delay_event_short': 1, - 'max_delay_event_short': 3, - 'min_delay_retry': 2, - 'max_delay_retry': 10, - 'restrict_unknown_seed_wallets': False + "check_progress_seconds": 2, + "check_watched_seconds": 4, + "check_expired_seconds": 60, + "check_events_seconds": 1, + "check_xmr_swaps_seconds": 1, + "min_delay_event": 1, + "max_delay_event": 3, + "min_delay_event_short": 1, + "max_delay_event_short": 3, + "min_delay_retry": 2, + "max_delay_retry": 10, + "restrict_unknown_seed_wallets": False, } - with open(settings_path, 'w') as fp: + with open(settings_path, "w") as fp: json.dump(settings, fp, indent=4) def partRpc(cmd, node_id=0): - return callrpc_cli(cfg.PARTICL_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(node_id)), 'regtest', cmd, cfg.PARTICL_CLI) + return callrpc_cli( + cfg.PARTICL_BINDIR, + os.path.join(cfg.TEST_DATADIRS, str(node_id)), + "regtest", + cmd, + cfg.PARTICL_CLI, + ) def btcRpc(cmd): - return callrpc_cli(cfg.BITCOIN_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)), 'regtest', cmd, cfg.BITCOIN_CLI) + return callrpc_cli( + cfg.BITCOIN_BINDIR, + os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)), + "regtest", + cmd, + cfg.BITCOIN_CLI, + ) def dashRpc(cmd, wallet=None): - return callrpc_cli(DASH_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(DASH_NODE)), 'regtest', cmd, DASH_CLI, wallet=wallet) + return callrpc_cli( + DASH_BINDIR, + os.path.join(cfg.TEST_DATADIRS, str(DASH_NODE)), + "regtest", + cmd, + DASH_CLI, + wallet=wallet, + ) def signal_handler(sig, frame): global stop_test - print('signal {} detected.'.format(sig)) + print("signal {} detected.".format(sig)) stop_test = True delay_event.set() @@ -237,10 +259,10 @@ def signal_handler(sig, frame): def run_coins_loop(cls): while not stop_test: try: - dashRpc('generatetoaddress 1 {}'.format(cls.dash_addr)) - btcRpc('generatetoaddress 1 {}'.format(cls.btc_addr)) + dashRpc("generatetoaddress 1 {}".format(cls.dash_addr)) + btcRpc("generatetoaddress 1 {}".format(cls.btc_addr)) except Exception as e: - logging.warning('run_coins_loop ' + str(e)) + logging.warning("run_coins_loop " + str(e)) time.sleep(1.0) @@ -261,6 +283,7 @@ def make_part_cli_rpc_func(node_id): for p in params: cmd += ' "' + p + '"' return partRpc(cmd, node_id) + return rpc_func @@ -277,78 +300,126 @@ class Test(unittest.TestCase): cls.network_pubkey = eckey.get_pubkey().get_bytes().hex() if os.path.isdir(cfg.TEST_DATADIRS): - logging.info('Removing ' + cfg.TEST_DATADIRS) + logging.info("Removing " + cfg.TEST_DATADIRS) shutil.rmtree(cfg.TEST_DATADIRS) for i in range(NUM_NODES): prepareDir(cfg.TEST_DATADIRS, i, cls.network_key, cls.network_pubkey) prepareOtherDir(cfg.TEST_DATADIRS, DASH_NODE) - prepareOtherDir(cfg.TEST_DATADIRS, BTC_NODE, 'bitcoin.conf') + prepareOtherDir(cfg.TEST_DATADIRS, BTC_NODE, "bitcoin.conf") cls.daemons = [] cls.swap_clients = [] cls.http_threads = [] btc_data_dir = os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)) - if os.path.exists(os.path.join(cfg.BITCOIN_BINDIR, 'bitcoin-wallet')): - logging.info('Creating BTC wallet.') + if os.path.exists(os.path.join(cfg.BITCOIN_BINDIR, "bitcoin-wallet")): + logging.info("Creating BTC wallet.") try: - callrpc_cli(cfg.BITCOIN_BINDIR, btc_data_dir, 'regtest', '-wallet=wallet.dat -legacy create', 'bitcoin-wallet') + callrpc_cli( + cfg.BITCOIN_BINDIR, + btc_data_dir, + "regtest", + "-wallet=wallet.dat -legacy create", + "bitcoin-wallet", + ) except Exception: - callrpc_cli(cfg.BITCOIN_BINDIR, btc_data_dir, 'regtest', '-wallet=wallet.dat create', 'bitcoin-wallet') + callrpc_cli( + cfg.BITCOIN_BINDIR, + btc_data_dir, + "regtest", + "-wallet=wallet.dat create", + "bitcoin-wallet", + ) cls.daemons.append(startDaemon(btc_data_dir, cfg.BITCOIN_BINDIR, cfg.BITCOIND)) - logging.info('Started %s %d', cfg.BITCOIND, cls.daemons[-1].handle.pid) + logging.info("Started %s %d", cfg.BITCOIND, cls.daemons[-1].handle.pid) dash_data_dir = os.path.join(cfg.TEST_DATADIRS, str(DASH_NODE)) - ''' + """ dash-wallet does not seem to create valid wallet files. if os.path.exists(os.path.join(DASH_BINDIR, 'dash-wallet')): logging.info('Creating DASH wallet.') callrpc_cli(DASH_BINDIR, dash_data_dir, 'regtest', '-wallet=wallet.dat create', 'dash-wallet') - ''' + """ cls.daemons.append(startDaemon(dash_data_dir, DASH_BINDIR, DASHD)) - logging.info('Started %s %d', DASHD, cls.daemons[-1].handle.pid) + logging.info("Started %s %d", DASHD, cls.daemons[-1].handle.pid) for i in range(NUM_NODES): data_dir = os.path.join(cfg.TEST_DATADIRS, str(i)) - if os.path.exists(os.path.join(cfg.PARTICL_BINDIR, 'particl-wallet')): + if os.path.exists(os.path.join(cfg.PARTICL_BINDIR, "particl-wallet")): try: - callrpc_cli(cfg.PARTICL_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat -legacy create', 'particl-wallet') + callrpc_cli( + cfg.PARTICL_BINDIR, + data_dir, + "regtest", + "-wallet=wallet.dat -legacy create", + "particl-wallet", + ) except Exception: - callrpc_cli(cfg.PARTICL_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat create', 'particl-wallet') + callrpc_cli( + cfg.PARTICL_BINDIR, + data_dir, + "regtest", + "-wallet=wallet.dat create", + "particl-wallet", + ) cls.daemons.append(startDaemon(data_dir, cfg.PARTICL_BINDIR, cfg.PARTICLD)) - logging.info('Started %s %d', cfg.PARTICLD, cls.daemons[-1].handle.pid) + logging.info("Started %s %d", cfg.PARTICLD, cls.daemons[-1].handle.pid) for i in range(NUM_NODES): rpc = make_part_cli_rpc_func(i) waitForRPC(rpc, delay_event) if i == 0: - rpc('extkeyimportmaster', ['abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb']) + rpc( + "extkeyimportmaster", + [ + "abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb" + ], + ) elif i == 1: - rpc('extkeyimportmaster', ['pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic', '', 'true']) - rpc('getnewextaddress', ['lblExtTest']) - rpc('rescanblockchain') + rpc( + "extkeyimportmaster", + [ + "pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic", + "", + "true", + ], + ) + rpc("getnewextaddress", ["lblExtTest"]) + rpc("rescanblockchain") else: - rpc('extkeyimportmaster', [rpc('mnemonic', ['new'])['master']]) - rpc('walletsettings', ['stakingoptions', json.dumps({'stakecombinethreshold': 100, 'stakesplitthreshold': 200}).replace('"', '\\"')]) - rpc('reservebalance', ['false']) + rpc("extkeyimportmaster", [rpc("mnemonic", ["new"])["master"]]) + rpc( + "walletsettings", + [ + "stakingoptions", + json.dumps( + {"stakecombinethreshold": 100, "stakesplitthreshold": 200} + ).replace('"', '\\"'), + ], + ) + rpc("reservebalance", ["false"]) - basicswap_dir = os.path.join(os.path.join(cfg.TEST_DATADIRS, str(i)), 'basicswap') + basicswap_dir = os.path.join( + os.path.join(cfg.TEST_DATADIRS, str(i)), "basicswap" + ) settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME) with open(settings_path) as fs: settings = json.load(fs) - fp = open(os.path.join(basicswap_dir, 'basicswap.log'), 'w') - sc = BasicSwap(fp, basicswap_dir, settings, 'regtest', log_name='BasicSwap{}'.format(i)) + fp = open(os.path.join(basicswap_dir, "basicswap.log"), "w") + sc = BasicSwap( + fp, basicswap_dir, settings, "regtest", log_name="BasicSwap{}".format(i) + ) cls.swap_clients.append(sc) sc.setDaemonPID(Coins.BTC, cls.daemons[0].handle.pid) sc.setDaemonPID(Coins.DASH, cls.daemons[1].handle.pid) sc.setDaemonPID(Coins.PART, cls.daemons[2 + i].handle.pid) - waitForRPC(dashRpc, delay_event, rpc_command='getblockchaininfo') - if len(dashRpc('listwallets')) < 1: - dashRpc('createwallet wallet.dat') + waitForRPC(dashRpc, delay_event, rpc_command="getblockchaininfo") + if len(dashRpc("listwallets")) < 1: + dashRpc("createwallet wallet.dat") sc.start() @@ -358,30 +429,30 @@ class Test(unittest.TestCase): waitForRPC(dashRpc, delay_event) num_blocks = 500 - logging.info('Mining %d dash blocks', num_blocks) - cls.dash_addr = dashRpc('getnewaddress mining_addr') - dashRpc('generatetoaddress {} {}'.format(num_blocks, cls.dash_addr)) + logging.info("Mining %d dash blocks", num_blocks) + cls.dash_addr = dashRpc("getnewaddress mining_addr") + dashRpc("generatetoaddress {} {}".format(num_blocks, cls.dash_addr)) - ro = dashRpc('getblockchaininfo') + ro = dashRpc("getblockchaininfo") try: - assert (ro['bip9_softforks']['csv']['status'] == 'active') + assert ro["bip9_softforks"]["csv"]["status"] == "active" except Exception: - logging.info('dash: csv is not active') + logging.info("dash: csv is not active") try: - assert (ro['bip9_softforks']['segwit']['status'] == 'active') + assert ro["bip9_softforks"]["segwit"]["status"] == "active" except Exception: - logging.info('dash: segwit is not active') + logging.info("dash: segwit is not active") waitForRPC(btcRpc, delay_event) - cls.btc_addr = btcRpc('getnewaddress mining_addr bech32') - logging.info('Mining %d Bitcoin blocks to %s', num_blocks, cls.btc_addr) - btcRpc('generatetoaddress {} {}'.format(num_blocks, cls.btc_addr)) + cls.btc_addr = btcRpc("getnewaddress mining_addr bech32") + logging.info("Mining %d Bitcoin blocks to %s", num_blocks, cls.btc_addr) + btcRpc("generatetoaddress {} {}".format(num_blocks, cls.btc_addr)) - ro = btcRpc('getblockchaininfo') + ro = btcRpc("getblockchaininfo") checkForks(ro) - ro = dashRpc('getwalletinfo') - print('dashRpc', ro) + ro = dashRpc("getwalletinfo") + print("dashRpc", ro) signal.signal(signal.SIGINT, signal_handler) cls.update_thread = threading.Thread(target=run_loop, args=(cls,)) @@ -392,19 +463,19 @@ class Test(unittest.TestCase): # Wait for height, or sequencelock is thrown off by genesis blocktime num_blocks = 3 - logging.info('Waiting for Particl chain height %d', num_blocks) + logging.info("Waiting for Particl chain height %d", num_blocks) for i in range(60): - particl_blocks = cls.swap_clients[0].callrpc('getblockcount') - print('particl_blocks', particl_blocks) + particl_blocks = cls.swap_clients[0].callrpc("getblockcount") + print("particl_blocks", particl_blocks) if particl_blocks >= num_blocks: break delay_event.wait(1) - assert (particl_blocks >= num_blocks) + assert particl_blocks >= num_blocks @classmethod def tearDownClass(cls): global stop_test - logging.info('Finalising') + logging.info("Finalising") stop_test = True cls.update_thread.join() cls.coins_update_thread.join() @@ -424,10 +495,17 @@ class Test(unittest.TestCase): super(Test, cls).tearDownClass() def test_02_part_dash(self): - logging.info('---------- Test PART to DASH') + logging.info("---------- Test PART to DASH") swap_clients = self.swap_clients - offer_id = swap_clients[0].postOffer(Coins.PART, Coins.DASH, 100 * COIN, 0.1 * COIN, 100 * COIN, SwapTypes.SELLER_FIRST) + offer_id = swap_clients[0].postOffer( + Coins.PART, + Coins.DASH, + 100 * COIN, + 0.1 * COIN, + 100 * COIN, + SwapTypes.SELLER_FIRST, + ) wait_for_offer(delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -439,19 +517,35 @@ class Test(unittest.TestCase): wait_for_in_progress(delay_event, swap_clients[1], bid_id, sent=True) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) - wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60) + wait_for_bid( + delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60 + ) + wait_for_bid( + delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=60, + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 def test_03_dash_part(self): - logging.info('---------- Test DASH to PART') + logging.info("---------- Test DASH to PART") swap_clients = self.swap_clients - offer_id = swap_clients[1].postOffer(Coins.DASH, Coins.PART, 10 * COIN, 9.0 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST) + offer_id = swap_clients[1].postOffer( + Coins.DASH, + Coins.PART, + 10 * COIN, + 9.0 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + ) wait_for_offer(delay_event, swap_clients[0], offer_id) offer = swap_clients[0].getOffer(offer_id) @@ -462,19 +556,35 @@ class Test(unittest.TestCase): wait_for_in_progress(delay_event, swap_clients[0], bid_id, sent=True) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60) - wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) + wait_for_bid( + delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=60, + ) + wait_for_bid( + delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=60 + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 def test_04_dash_btc(self): - logging.info('---------- Test DASH to BTC') + logging.info("---------- Test DASH to BTC") swap_clients = self.swap_clients - offer_id = swap_clients[0].postOffer(Coins.DASH, Coins.BTC, 10 * COIN, 0.1 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST) + offer_id = swap_clients[0].postOffer( + Coins.DASH, + Coins.BTC, + 10 * COIN, + 0.1 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + ) wait_for_offer(delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -485,24 +595,39 @@ class Test(unittest.TestCase): wait_for_in_progress(delay_event, swap_clients[1], bid_id, sent=True) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) - wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60) - - js_0bid = read_json_api(1800, 'bids/{}'.format(bid_id.hex())) + wait_for_bid( + delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60 + ) + wait_for_bid( + delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=60, + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 def test_05_refund(self): # Seller submits initiate txn, buyer doesn't respond - logging.info('---------- Test refund, DASH to BTC') + logging.info("---------- Test refund, DASH to BTC") swap_clients = self.swap_clients - offer_id = swap_clients[0].postOffer(Coins.DASH, Coins.BTC, 10 * COIN, 0.1 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST, - TxLockTypes.SEQUENCE_LOCK_BLOCKS, 10) + offer_id = swap_clients[0].postOffer( + Coins.DASH, + Coins.BTC, + 10 * COIN, + 0.1 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + TxLockTypes.SEQUENCE_LOCK_BLOCKS, + 10, + ) wait_for_offer(delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -512,21 +637,37 @@ class Test(unittest.TestCase): swap_clients[1].abandonBid(bid_id) swap_clients[0].acceptBid(bid_id) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) - wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.BID_ABANDONED, sent=True, wait_for=60) + wait_for_bid( + delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60 + ) + wait_for_bid( + delay_event, + swap_clients[1], + bid_id, + BidStates.BID_ABANDONED, + sent=True, + wait_for=60, + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 def test_06_self_bid(self): - logging.info('---------- Test same client, BTC to DASH') + logging.info("---------- Test same client, BTC to DASH") swap_clients = self.swap_clients js_0_before = read_json_api(1800) - offer_id = swap_clients[0].postOffer(Coins.DASH, Coins.BTC, 10 * COIN, 10 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST) + offer_id = swap_clients[0].postOffer( + Coins.DASH, + Coins.BTC, + 10 * COIN, + 10 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + ) wait_for_offer(delay_event, swap_clients[0], offer_id) offer = swap_clients[0].getOffer(offer_id) @@ -535,20 +676,37 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id) swap_clients[0].acceptBid(bid_id) - wait_for_bid_tx_state(delay_event, swap_clients[0], bid_id, TxStates.TX_REDEEMED, TxStates.TX_REDEEMED, wait_for=60) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) + wait_for_bid_tx_state( + delay_event, + swap_clients[0], + bid_id, + TxStates.TX_REDEEMED, + TxStates.TX_REDEEMED, + wait_for=60, + ) + wait_for_bid( + delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60 + ) js_0 = read_json_api(1800) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_0['num_recv_bids'] == js_0_before['num_recv_bids'] + 1 and js_0['num_sent_bids'] == js_0_before['num_sent_bids'] + 1) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert ( + js_0["num_recv_bids"] == js_0_before["num_recv_bids"] + 1 + and js_0["num_sent_bids"] == js_0_before["num_sent_bids"] + 1 + ) def test_07_error(self): - logging.info('---------- Test error, BTC to DASH, set fee above bid value') + logging.info("---------- Test error, BTC to DASH, set fee above bid value") swap_clients = self.swap_clients - js_0_before = read_json_api(1800) - - offer_id = swap_clients[0].postOffer(Coins.DASH, Coins.BTC, 0.001 * COIN, 1.0 * COIN, 0.001 * COIN, SwapTypes.SELLER_FIRST) + offer_id = swap_clients[0].postOffer( + Coins.DASH, + Coins.BTC, + 0.001 * COIN, + 1.0 * COIN, + 0.001 * COIN, + SwapTypes.SELLER_FIRST, + ) wait_for_offer(delay_event, swap_clients[0], offer_id) offer = swap_clients[0].getOffer(offer_id) @@ -557,57 +715,69 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id) swap_clients[0].acceptBid(bid_id) try: - swap_clients[0].getChainClientSettings(Coins.BTC)['override_feerate'] = 10.0 - swap_clients[0].getChainClientSettings(Coins.DASH)['override_feerate'] = 10.0 - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.BID_ERROR, wait_for=60) + swap_clients[0].getChainClientSettings(Coins.BTC)["override_feerate"] = 10.0 + swap_clients[0].getChainClientSettings(Coins.DASH)[ + "override_feerate" + ] = 10.0 + wait_for_bid( + delay_event, swap_clients[0], bid_id, BidStates.BID_ERROR, wait_for=60 + ) swap_clients[0].abandonBid(bid_id) finally: - del swap_clients[0].getChainClientSettings(Coins.BTC)['override_feerate'] - del swap_clients[0].getChainClientSettings(Coins.DASH)['override_feerate'] + del swap_clients[0].getChainClientSettings(Coins.BTC)["override_feerate"] + del swap_clients[0].getChainClientSettings(Coins.DASH)["override_feerate"] def test_08_wallet(self): - logging.info('---------- Test {} wallet'.format(self.test_coin_from.name)) + logging.info("---------- Test {} wallet".format(self.test_coin_from.name)) - logging.info('Test withdrawal') - addr = dashRpc('getnewaddress \"Withdrawal test\"') - wallets = read_json_api(TEST_HTTP_PORT + 0, 'wallets') - assert (float(wallets[self.test_coin_from.name]['balance']) > 100) + logging.info("Test withdrawal") + addr = dashRpc('getnewaddress "Withdrawal test"') + wallets = read_json_api(TEST_HTTP_PORT + 0, "wallets") + assert float(wallets[self.test_coin_from.name]["balance"]) > 100 post_json = { - 'value': 100, - 'address': addr, - 'subfee': False, + "value": 100, + "address": addr, + "subfee": False, } - json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/{}/withdraw'.format(self.test_coin_from.name.lower()), post_json) - assert (len(json_rv['txid']) == 64) + json_rv = read_json_api( + TEST_HTTP_PORT + 0, + "wallets/{}/withdraw".format(self.test_coin_from.name.lower()), + post_json, + ) + assert len(json_rv["txid"]) == 64 - logging.info('Test createutxo') + logging.info("Test createutxo") post_json = { - 'value': 10, + "value": 10, } - json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/{}/createutxo'.format(self.test_coin_from.name.lower()), post_json) - assert (len(json_rv['txid']) == 64) + json_rv = read_json_api( + TEST_HTTP_PORT + 0, + "wallets/{}/createutxo".format(self.test_coin_from.name.lower()), + post_json, + ) + assert len(json_rv["txid"]) == 64 def test_09_initialise_wallet(self): - logging.info('---------- Test DASH initialiseWallet') + logging.info("---------- Test DASH initialiseWallet") self.swap_clients[0].initialiseWallet(Coins.DASH, raise_errors=True) assert self.swap_clients[0].checkWalletSeed(Coins.DASH) is True - addr = dashRpc('getnewaddress \"hd wallet test\"') - assert addr == 'ybzWYJbZEhZai8kiKkTtPFKTuDNwhpiwac' + addr = dashRpc('getnewaddress "hd wallet test"') + assert addr == "ybzWYJbZEhZai8kiKkTtPFKTuDNwhpiwac" - logging.info('Test that getcoinseed returns a mnemonic for Dash') - mnemonic = read_json_api(1800, 'getcoinseed', {'coin': 'DASH'})['mnemonic'] + logging.info("Test that getcoinseed returns a mnemonic for Dash") + mnemonic = read_json_api(1800, "getcoinseed", {"coin": "DASH"})["mnemonic"] new_wallet_name = random.randbytes(10).hex() - dashRpc(f'createwallet \"{new_wallet_name}\"') - dashRpc(f'upgradetohd \"{mnemonic}\"', wallet=new_wallet_name) - addr_test = dashRpc('getnewaddress', wallet=new_wallet_name) - dashRpc('unloadwallet', wallet=new_wallet_name) - assert (addr_test == addr) + dashRpc(f'createwallet "{new_wallet_name}"') + dashRpc(f'upgradetohd "{mnemonic}"', wallet=new_wallet_name) + addr_test = dashRpc("getnewaddress", wallet=new_wallet_name) + dashRpc("unloadwallet", wallet=new_wallet_name) + assert addr_test == addr def test_10_prefunded_itx(self): - logging.info('---------- Test prefunded itx offer') + logging.info("---------- Test prefunded itx offer") swap_clients = self.swap_clients coin_from = Coins.DASH @@ -618,50 +788,74 @@ class Test(unittest.TestCase): tla_from = coin_from.name # Prepare balance - js_w2 = read_json_api(1802, 'wallets') - if float(js_w2[tla_from]['balance']) < 100.0: + js_w2 = read_json_api(1802, "wallets") + if float(js_w2[tla_from]["balance"]) < 100.0: post_json = { - 'value': 100, - 'address': js_w2[tla_from]['deposit_address'], - 'subfee': False, + "value": 100, + "address": js_w2[tla_from]["deposit_address"], + "subfee": False, } - json_rv = read_json_api(1800, 'wallets/{}/withdraw'.format(tla_from.lower()), post_json) - assert (len(json_rv['txid']) == 64) - wait_for_balance(delay_event, 'http://127.0.0.1:1802/json/wallets/{}'.format(tla_from.lower()), 'balance', 100.0) + json_rv = read_json_api( + 1800, "wallets/{}/withdraw".format(tla_from.lower()), post_json + ) + assert len(json_rv["txid"]) == 64 + wait_for_balance( + delay_event, + "http://127.0.0.1:1802/json/wallets/{}".format(tla_from.lower()), + "balance", + 100.0, + ) - js_w2 = read_json_api(1802, 'wallets') - assert (float(js_w2[tla_from]['balance']) >= 100.0) + js_w2 = read_json_api(1802, "wallets") + assert float(js_w2[tla_from]["balance"]) >= 100.0 - js_w2 = read_json_api(1802, 'wallets') + js_w2 = read_json_api(1802, "wallets") post_json = { - 'value': 100.0, - 'address': read_json_api(1802, 'wallets/{}/nextdepositaddr'.format(tla_from.lower())), - 'subfee': True, + "value": 100.0, + "address": read_json_api( + 1802, "wallets/{}/nextdepositaddr".format(tla_from.lower()) + ), + "subfee": True, } - json_rv = read_json_api(1802, 'wallets/{}/withdraw'.format(tla_from.lower()), post_json) - wait_for_balance(delay_event, 'http://127.0.0.1:1802/json/wallets/{}'.format(tla_from.lower()), 'balance', 10.0) - assert (len(json_rv['txid']) == 64) + json_rv = read_json_api( + 1802, "wallets/{}/withdraw".format(tla_from.lower()), post_json + ) + wait_for_balance( + delay_event, + "http://127.0.0.1:1802/json/wallets/{}".format(tla_from.lower()), + "balance", + 10.0, + ) + assert len(json_rv["txid"]) == 64 # Create prefunded ITX pi = swap_clients[2].pi(SwapTypes.XMR_SWAP) - js_w2 = read_json_api(1802, 'wallets') + js_w2 = read_json_api(1802, "wallets") swap_value = 100.0 - if float(js_w2[tla_from]['balance']) < swap_value: - swap_value = js_w2[tla_from]['balance'] + if float(js_w2[tla_from]["balance"]) < swap_value: + swap_value = js_w2[tla_from]["balance"] swap_value = ci_from.make_int(swap_value) - assert (swap_value > ci_from.make_int(95)) + assert swap_value > ci_from.make_int(95) itx = pi.getFundedInitiateTxTemplate(ci_from, swap_value, True) itx_decoded = ci_from.describeTx(itx.hex()) n = pi.findMockVout(ci_from, itx_decoded) - value_after_subfee = ci_from.make_int(itx_decoded['vout'][n]['value']) - assert (value_after_subfee < swap_value) + value_after_subfee = ci_from.make_int(itx_decoded["vout"][n]["value"]) + assert value_after_subfee < swap_value swap_value = value_after_subfee wait_for_unspent(delay_event, ci_from, swap_value) - extra_options = {'prefunded_itx': itx} + extra_options = {"prefunded_itx": itx} rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) - offer_id = swap_clients[2].postOffer(coin_from, coin_to, swap_value, rate_swap, swap_value, swap_type, extra_options=extra_options) + offer_id = swap_clients[2].postOffer( + coin_from, + coin_to, + swap_value, + rate_swap, + swap_value, + swap_type, + extra_options=extra_options, + ) wait_for_offer(delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -670,21 +864,35 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[2], bid_id, BidStates.BID_RECEIVED) swap_clients[2].acceptBid(bid_id) - wait_for_bid(delay_event, swap_clients[2], bid_id, BidStates.SWAP_COMPLETED, wait_for=120) - wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=120) + wait_for_bid( + delay_event, swap_clients[2], bid_id, BidStates.SWAP_COMPLETED, wait_for=120 + ) + wait_for_bid( + delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=120, + ) # Verify expected inputs were used bid, offer = swap_clients[2].getBidAndOffer(bid_id) - assert (bid.initiate_tx) - wtx = ci_from.rpc_wallet('gettransaction', [bid.initiate_tx.txid.hex(),]) - itx_after = ci_from.describeTx(wtx['hex']) - assert (len(itx_after['vin']) == len(itx_decoded['vin'])) - for i, txin in enumerate(itx_decoded['vin']): - assert (txin['txid'] == itx_after['vin'][i]['txid']) - assert (txin['vout'] == itx_after['vin'][i]['vout']) + assert bid.initiate_tx + wtx = ci_from.rpc_wallet( + "gettransaction", + [ + bid.initiate_tx.txid.hex(), + ], + ) + itx_after = ci_from.describeTx(wtx["hex"]) + assert len(itx_after["vin"]) == len(itx_decoded["vin"]) + for i, txin in enumerate(itx_decoded["vin"]): + assert txin["txid"] == itx_after["vin"][i]["txid"] + assert txin["vout"] == itx_after["vin"][i]["vout"] def test_11_xmrswap_to(self): - logging.info('---------- Test xmr swap protocol to') + logging.info("---------- Test xmr swap protocol to") swap_clients = self.swap_clients coin_from = Coins.BTC @@ -695,7 +903,9 @@ class Test(unittest.TestCase): swap_value = ci_from.make_int(random.uniform(0.2, 20.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) - offer_id = swap_clients[0].postOffer(coin_from, coin_to, swap_value, rate_swap, swap_value, swap_type) + offer_id = swap_clients[0].postOffer( + coin_from, coin_to, swap_value, rate_swap, swap_value, swap_type + ) wait_for_offer(delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -704,13 +914,26 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) swap_clients[0].acceptBid(bid_id) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=120) - wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=120) + wait_for_bid( + delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=120 + ) + wait_for_bid( + delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=120, + ) def test_12_xmrswap_to_recover_b_lock_tx(self): coin_from = Coins.BTC coin_to = Coins.DASH - logging.info('---------- Test {} to {} follower recovers coin b lock tx'.format(coin_from.name, coin_to.name)) + logging.info( + "---------- Test {} to {} follower recovers coin b lock tx".format( + coin_from.name, coin_to.name + ) + ) swap_clients = self.swap_clients ci_from = swap_clients[0].ci(coin_from) @@ -719,8 +942,15 @@ class Test(unittest.TestCase): amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) offer_id = swap_clients[0].postOffer( - coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, - lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=32) + coin_from, + coin_to, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, + lock_value=32, + ) wait_for_offer(delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -731,9 +961,21 @@ class Test(unittest.TestCase): swap_clients[1].setBidDebugInd(bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK) swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=180) - wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=True) + wait_for_bid( + delay_event, + swap_clients[0], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + wait_for=180, + ) + wait_for_bid( + delay_event, + swap_clients[1], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + sent=True, + ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/extended/test_dcr.py b/tests/basicswap/extended/test_dcr.py index 4e37a9c..6fbef2d 100644 --- a/tests/basicswap/extended/test_dcr.py +++ b/tests/basicswap/extended/test_dcr.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2024 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -21,18 +22,12 @@ from basicswap.basicswap import ( SwapTypes, TxStates, ) -from basicswap.basicswap_util import ( - TxLockTypes, - TxTypes -) -from basicswap.util.crypto import ( - hash160 -) +from basicswap.basicswap_util import TxLockTypes, TxTypes +from basicswap.util.crypto import hash160 from basicswap.interface.dcr.rpc import ( callrpc, ) from basicswap.interface.dcr.messages import ( - SigHashType, TxSerializeType, ) from basicswap.interface.dcr.util import ( @@ -59,9 +54,11 @@ from basicswap.bin.run import startDaemon logger = logging.getLogger() -DCR_BINDIR = os.path.expanduser(os.getenv('DCR_BINDIR', os.path.join(cfg.DEFAULT_TEST_BINDIR, 'decred'))) -DCRD = os.getenv('DCRD', 'dcrd' + cfg.bin_suffix) -DCR_WALLET = os.getenv('DCR_WALLET', 'dcrwallet' + cfg.bin_suffix) +DCR_BINDIR = os.path.expanduser( + os.getenv("DCR_BINDIR", os.path.join(cfg.DEFAULT_TEST_BINDIR, "decred")) +) +DCRD = os.getenv("DCRD", "dcrd" + cfg.bin_suffix) +DCR_WALLET = os.getenv("DCR_WALLET", "dcrwallet" + cfg.bin_suffix) DCR_BASE_PORT = 44932 DCR_BASE_RPC_PORT = 45932 @@ -70,34 +67,35 @@ DCR_BASE_WALLET_RPC_PORT = 45952 def make_rpc_func(node_id, base_rpc_port): node_id = node_id - auth = 'test{0}:test_pass{0}'.format(node_id) + auth = "test{0}:test_pass{0}".format(node_id) def rpc_func(method, params=None): nonlocal node_id, auth return callrpc(base_rpc_port + node_id, auth, method, params) + return rpc_func def wait_for_dcr_height(http_port, num_blocks=3): - logging.info('Waiting for DCR chain height %d', num_blocks) + logging.info("Waiting for DCR chain height %d", num_blocks) for i in range(60): if test_delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") try: - wallet = read_json_api(http_port, 'wallets/dcr') - decred_blocks = wallet['blocks'] - print('decred_blocks', decred_blocks) + wallet = read_json_api(http_port, "wallets/dcr") + decred_blocks = wallet["blocks"] + print("decred_blocks", decred_blocks) if decred_blocks >= num_blocks: return except Exception as e: - print('Error reading wallets', str(e)) + print("Error reading wallets", str(e)) test_delay_event.wait(1) - raise ValueError(f'wait_for_decred_blocks failed http_port: {http_port}') + raise ValueError(f"wait_for_decred_blocks failed http_port: {http_port}") def run_test_success_path(self, coin_from: Coins, coin_to: Coins): - logging.info(f'---------- Test {coin_from.name} to {coin_to.name}') + logging.info(f"---------- Test {coin_from.name} to {coin_to.name}") node_from = 0 node_to = 1 @@ -111,7 +109,9 @@ def run_test_success_path(self, coin_from: Coins, coin_to: Coins): amt_swap = ci_from.make_int(random.uniform(0.1, 5.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 10.0), r=1) - offer_id = swap_clients[node_from].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.SELLER_FIRST) + offer_id = swap_clients[node_from].postOffer( + coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.SELLER_FIRST + ) wait_for_offer(test_delay_event, swap_clients[node_to], offer_id) @@ -121,43 +121,68 @@ def run_test_success_path(self, coin_from: Coins, coin_to: Coins): wait_for_bid(test_delay_event, swap_clients[node_from], bid_id) swap_clients[node_from].acceptBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[node_from], bid_id, BidStates.SWAP_COMPLETED, wait_for=120) - wait_for_bid(test_delay_event, swap_clients[node_to], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=30) + wait_for_bid( + test_delay_event, + swap_clients[node_from], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=120, + ) + wait_for_bid( + test_delay_event, + swap_clients[node_to], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=30, + ) # Verify lock tx spends are found in the expected wallets bid, offer = swap_clients[node_from].getBidAndOffer(bid_id) max_fee: int = 10000 itx_spend = bid.initiate_tx.spend_txid.hex() node_to_ci_from = swap_clients[node_to].ci(coin_from) - wtx = node_to_ci_from.rpc_wallet('gettransaction', [itx_spend,]) - assert (amt_swap - node_to_ci_from.make_int(wtx['details'][0]['amount']) < max_fee) + wtx = node_to_ci_from.rpc_wallet( + "gettransaction", + [ + itx_spend, + ], + ) + assert amt_swap - node_to_ci_from.make_int(wtx["details"][0]["amount"]) < max_fee node_from_ci_to = swap_clients[node_from].ci(coin_to) ptx_spend = bid.participate_tx.spend_txid.hex() - wtx = node_from_ci_to.rpc_wallet('gettransaction', [ptx_spend,]) - assert (bid.amount_to - node_from_ci_to.make_int(wtx['details'][0]['amount']) < max_fee) + wtx = node_from_ci_to.rpc_wallet( + "gettransaction", + [ + ptx_spend, + ], + ) + assert ( + bid.amount_to - node_from_ci_to.make_int(wtx["details"][0]["amount"]) < max_fee + ) js_0 = read_json_api(1800 + node_from) js_1 = read_json_api(1800 + node_to) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 bid_id_hex = bid_id.hex() - path = f'bids/{bid_id_hex}/states' + path = f"bids/{bid_id_hex}/states" offerer_states = read_json_api(1800 + node_from, path) bidder_states = read_json_api(1800 + node_to, path) expect_states = copy.deepcopy(self.states_offerer_sh[0]) # Will miss PTX Sent event as PTX is found by searching the chain. if coin_to == Coins.DCR: - expect_states[5] = 'PTX In Chain' - assert (compare_bid_states(offerer_states, expect_states) is True) - assert (compare_bid_states(bidder_states, self.states_bidder_sh[0]) is True) + expect_states[5] = "PTX In Chain" + assert compare_bid_states(offerer_states, expect_states) is True + assert compare_bid_states(bidder_states, self.states_bidder_sh[0]) is True def run_test_bad_ptx(self, coin_from: Coins, coin_to: Coins): # Invalid PTX sent, swap should stall and ITx and PTx should be reclaimed by senders - logging.info(f'---------- Test bad ptx {coin_from.name} to {coin_to.name}') + logging.info(f"---------- Test bad ptx {coin_from.name} to {coin_to.name}") node_from = 0 node_to = 1 @@ -171,57 +196,91 @@ def run_test_bad_ptx(self, coin_from: Coins, coin_to: Coins): amt_swap = ci_from.make_int(random.uniform(1.1, 10.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.1, 2.0), r=1) - offer_id = swap_clients[node_from].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.SELLER_FIRST, - TxLockTypes.SEQUENCE_LOCK_BLOCKS, 10, auto_accept_bids=True) + offer_id = swap_clients[node_from].postOffer( + coin_from, + coin_to, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.SELLER_FIRST, + TxLockTypes.SEQUENCE_LOCK_BLOCKS, + 10, + auto_accept_bids=True, + ) wait_for_offer(test_delay_event, swap_clients[node_to], offer_id) offer = swap_clients[node_to].getOffer(offer_id) bid_id = swap_clients[node_to].postBid(offer_id, offer.amount_from) swap_clients[node_to].setBidDebugInd(bid_id, DebugTypes.MAKE_INVALID_PTX) - wait_for_bid(test_delay_event, swap_clients[node_from], bid_id, BidStates.SWAP_COMPLETED, wait_for=120) - wait_for_bid(test_delay_event, swap_clients[node_to], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=30) + wait_for_bid( + test_delay_event, + swap_clients[node_from], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=120, + ) + wait_for_bid( + test_delay_event, + swap_clients[node_to], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=30, + ) - js_0_bid = read_json_api(1800 + node_from, 'bids/{}'.format(bid_id.hex())) - js_1_bid = read_json_api(1800 + node_to, 'bids/{}'.format(bid_id.hex())) - assert (js_0_bid['itx_state'] == 'Refunded') - assert (js_1_bid['ptx_state'] == 'Refunded') + js_0_bid = read_json_api(1800 + node_from, "bids/{}".format(bid_id.hex())) + js_1_bid = read_json_api(1800 + node_to, "bids/{}".format(bid_id.hex())) + assert js_0_bid["itx_state"] == "Refunded" + assert js_1_bid["ptx_state"] == "Refunded" # Verify lock tx spends are found in the expected wallets bid, offer = swap_clients[node_from].getBidAndOffer(bid_id) max_fee: int = 10000 itx_spend = bid.initiate_tx.spend_txid.hex() node_from_ci_from = swap_clients[node_from].ci(coin_from) - wtx = node_from_ci_from.rpc_wallet('gettransaction', [itx_spend,]) - assert (amt_swap - node_from_ci_from.make_int(wtx['details'][0]['amount']) < max_fee) + wtx = node_from_ci_from.rpc_wallet( + "gettransaction", + [ + itx_spend, + ], + ) + assert amt_swap - node_from_ci_from.make_int(wtx["details"][0]["amount"]) < max_fee node_to_ci_to = swap_clients[node_to].ci(coin_to) bid, offer = swap_clients[node_to].getBidAndOffer(bid_id) ptx_spend = bid.participate_tx.spend_txid.hex() - wtx = node_to_ci_to.rpc_wallet('gettransaction', [ptx_spend,]) - assert (bid.amount_to - node_to_ci_to.make_int(wtx['details'][0]['amount']) < max_fee) + wtx = node_to_ci_to.rpc_wallet( + "gettransaction", + [ + ptx_spend, + ], + ) + assert bid.amount_to - node_to_ci_to.make_int(wtx["details"][0]["amount"]) < max_fee bid_id_hex = bid_id.hex() - path = f'bids/{bid_id_hex}/states' + path = f"bids/{bid_id_hex}/states" offerer_states = read_json_api(1800 + node_from, path) bidder_states = read_json_api(1800 + node_to, path) if coin_to not in (Coins.XMR, Coins.WOW): return # Hard to get the timing right - assert (compare_bid_states_unordered(offerer_states, self.states_offerer_sh[1]) is True) - assert (compare_bid_states_unordered(bidder_states, self.states_bidder_sh[1]) is True) + assert ( + compare_bid_states_unordered(offerer_states, self.states_offerer_sh[1]) is True + ) + assert compare_bid_states_unordered(bidder_states, self.states_bidder_sh[1]) is True js_0 = read_json_api(1800 + node_from) js_1 = read_json_api(1800 + node_to) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 def run_test_itx_refund(self, coin_from: Coins, coin_to: Coins): # Offerer claims PTX and refunds ITX after lock expires # Bidder loses PTX value without gaining ITX value - logging.info(f'---------- Test itx refund {coin_from.name} to {coin_to.name}') + logging.info(f"---------- Test itx refund {coin_from.name} to {coin_to.name}") node_from = 0 node_to = 1 @@ -234,8 +293,16 @@ def run_test_itx_refund(self, coin_from: Coins, coin_to: Coins): swap_value = ci_from.make_int(random.uniform(2.0, 20.0), r=1) rate_swap = ci_to.make_int(0.5, r=1) - offer_id = swap_clients[node_from].postOffer(coin_from, coin_to, swap_value, rate_swap, swap_value, SwapTypes.SELLER_FIRST, - TxLockTypes.SEQUENCE_LOCK_BLOCKS, 12) + offer_id = swap_clients[node_from].postOffer( + coin_from, + coin_to, + swap_value, + rate_swap, + swap_value, + SwapTypes.SELLER_FIRST, + TxLockTypes.SEQUENCE_LOCK_BLOCKS, + 12, + ) wait_for_offer(test_delay_event, swap_clients[node_to], offer_id) offer = swap_clients[node_to].getOffer(offer_id) @@ -247,29 +314,59 @@ def run_test_itx_refund(self, coin_from: Coins, coin_to: Coins): # For testing: Block refunding the ITX until PTX has been redeemed, else ITX refund can become spendable before PTX confirms swap_clients[node_from].setBidDebugInd(bid_id, DebugTypes.SKIP_LOCK_TX_REFUND) swap_clients[node_from].acceptBid(bid_id) - wait_for_bid_tx_state(test_delay_event, swap_clients[node_from], bid_id, TxStates.TX_CONFIRMED, TxStates.TX_REDEEMED, wait_for=120) + wait_for_bid_tx_state( + test_delay_event, + swap_clients[node_from], + bid_id, + TxStates.TX_CONFIRMED, + TxStates.TX_REDEEMED, + wait_for=120, + ) swap_clients[node_from].setBidDebugInd(bid_id, DebugTypes.NONE) - wait_for_bid_tx_state(test_delay_event, swap_clients[node_from], bid_id, TxStates.TX_REFUNDED, TxStates.TX_REDEEMED, wait_for=90) + wait_for_bid_tx_state( + test_delay_event, + swap_clients[node_from], + bid_id, + TxStates.TX_REFUNDED, + TxStates.TX_REDEEMED, + wait_for=90, + ) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) + wait_for_bid( + test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60 + ) # Verify lock tx spends are found in the expected wallets bid, offer = swap_clients[node_from].getBidAndOffer(bid_id) max_fee: int = 10000 itx_spend = bid.initiate_tx.spend_txid.hex() node_from_ci_from = swap_clients[node_from].ci(coin_from) - wtx = node_from_ci_from.rpc_wallet('gettransaction', [itx_spend,]) - assert (swap_value - node_from_ci_from.make_int(wtx['details'][0]['amount']) < max_fee) + wtx = node_from_ci_from.rpc_wallet( + "gettransaction", + [ + itx_spend, + ], + ) + assert ( + swap_value - node_from_ci_from.make_int(wtx["details"][0]["amount"]) < max_fee + ) node_from_ci_to = swap_clients[node_from].ci(coin_to) ptx_spend = bid.participate_tx.spend_txid.hex() - wtx = node_from_ci_to.rpc_wallet('gettransaction', [ptx_spend,]) - assert (bid.amount_to - node_from_ci_to.make_int(wtx['details'][0]['amount']) < max_fee) + wtx = node_from_ci_to.rpc_wallet( + "gettransaction", + [ + ptx_spend, + ], + ) + assert ( + bid.amount_to - node_from_ci_to.make_int(wtx["details"][0]["amount"]) < max_fee + ) def run_test_ads_success_path(self, coin_from: Coins, coin_to: Coins): - logging.info(f'---------- Test ADS swap {coin_from.name} to {coin_to.name}') + logging.info(f"---------- Test ADS swap {coin_from.name} to {coin_to.name}") # Offerer sends the offer # Bidder sends the bid @@ -288,20 +385,39 @@ def run_test_ads_success_path(self, coin_from: Coins, coin_to: Coins): # Follower sends the participate (chain b) lock tx. id_leader: int = id_bidder if reverse_bid else id_offerer id_follower: int = id_offerer if reverse_bid else id_bidder - logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}') + logging.info( + f"Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}" + ) amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) - offer_id = swap_clients[id_offerer].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP) + offer_id = swap_clients[id_offerer].postOffer( + coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP + ) wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id) bid_id = swap_clients[id_bidder].postXmrBid(offer_id, amt_swap) - wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED) + wait_for_bid( + test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED + ) swap_clients[id_offerer].acceptBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.SWAP_COMPLETED, wait_for=(180)) - wait_for_bid(test_delay_event, swap_clients[id_bidder], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=(30)) + wait_for_bid( + test_delay_event, + swap_clients[id_offerer], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=(180), + ) + wait_for_bid( + test_delay_event, + swap_clients[id_bidder], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=(30), + ) if reverse_bid: return # TODO @@ -314,27 +430,48 @@ def run_test_ads_success_path(self, coin_from: Coins, coin_to: Coins): if node_from_ci_to.coin_type() in (Coins.XMR, Coins.WOW): pass else: - wtx = node_from_ci_to.rpc_wallet('gettransaction', [bid.xmr_b_lock_tx.spend_txid.hex(),]) - assert (bid.amount_to - node_from_ci_to.make_int(wtx['details'][0]['amount']) < max_fee) + wtx = node_from_ci_to.rpc_wallet( + "gettransaction", + [ + bid.xmr_b_lock_tx.spend_txid.hex(), + ], + ) + assert ( + bid.amount_to - node_from_ci_to.make_int(wtx["details"][0]["amount"]) + < max_fee + ) node_to_ci_from = swap_clients[1].ci(coin_from) if node_to_ci_from.coin_type() in (Coins.XMR, Coins.WOW): pass else: - wtx = node_to_ci_from.rpc_wallet('gettransaction', [xmr_swap.a_lock_spend_tx_id.hex(),]) - assert (bid.amount - node_to_ci_from.make_int(wtx['details'][0]['amount']) < max_fee) + wtx = node_to_ci_from.rpc_wallet( + "gettransaction", + [ + xmr_swap.a_lock_spend_tx_id.hex(), + ], + ) + assert ( + bid.amount - node_to_ci_from.make_int(wtx["details"][0]["amount"]) < max_fee + ) bid_id_hex = bid_id.hex() - path = f'bids/{bid_id_hex}/states' + path = f"bids/{bid_id_hex}/states" offerer_states = read_json_api(1800 + id_offerer, path) bidder_states = read_json_api(1800 + id_bidder, path) - assert (compare_bid_states(offerer_states, self.states_offerer[0]) is True) - assert (compare_bid_states(bidder_states, self.states_bidder[0]) is True) + assert compare_bid_states(offerer_states, self.states_offerer[0]) is True + assert compare_bid_states(bidder_states, self.states_bidder[0]) is True -def run_test_ads_both_refund(self, coin_from: Coins, coin_to: Coins, lock_value: int = 32) -> None: - logging.info('---------- Test {} to {} both lock txns refunded'.format(coin_from.name, coin_to.name)) +def run_test_ads_both_refund( + self, coin_from: Coins, coin_to: Coins, lock_value: int = 32 +) -> None: + logging.info( + "---------- Test {} to {} both lock txns refunded".format( + coin_from.name, coin_to.name + ) + ) id_offerer: int = 0 id_bidder: int = 1 @@ -349,7 +486,9 @@ def run_test_ads_both_refund(self, coin_from: Coins, coin_to: Coins, lock_value: id_leader: int = id_bidder if reverse_bid else id_offerer id_follower: int = id_offerer if reverse_bid else id_bidder - logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}') + logging.info( + f"Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}" + ) amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) @@ -359,8 +498,15 @@ def run_test_ads_both_refund(self, coin_from: Coins, coin_to: Coins, lock_value: swap_clients[0]._debug_cases.append(debug_case) swap_clients[1]._debug_cases.append(debug_case) offer_id = swap_clients[id_offerer].postOffer( - coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, - lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=lock_value) + coin_from, + coin_to, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, + lock_value=lock_value, + ) wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id) offer = swap_clients[id_bidder].getOffer(offer_id) finally: @@ -368,14 +514,32 @@ def run_test_ads_both_refund(self, coin_from: Coins, coin_to: Coins, lock_value: swap_clients[1]._debug_cases.remove(debug_case) bid_id = swap_clients[id_bidder].postXmrBid(offer_id, offer.amount_from) - wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED) + wait_for_bid( + test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED + ) - swap_clients[id_follower].setBidDebugInd(bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK) + swap_clients[id_follower].setBidDebugInd( + bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK + ) swap_clients[id_offerer].acceptBid(bid_id) leader_sent_bid: bool = True if reverse_bid else False - wait_for_bid(test_delay_event, swap_clients[id_leader], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=leader_sent_bid, wait_for=(self.extra_wait_time + 180)) - wait_for_bid(test_delay_event, swap_clients[id_follower], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=(not leader_sent_bid), wait_for=(self.extra_wait_time + 40)) + wait_for_bid( + test_delay_event, + swap_clients[id_leader], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + sent=leader_sent_bid, + wait_for=(self.extra_wait_time + 180), + ) + wait_for_bid( + test_delay_event, + swap_clients[id_follower], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + sent=(not leader_sent_bid), + wait_for=(self.extra_wait_time + 40), + ) if reverse_bid: return # TODO @@ -391,27 +555,49 @@ def run_test_ads_both_refund(self, coin_from: Coins, coin_to: Coins, lock_value: if node_from_ci_from.coin_type() in (Coins.XMR, Coins.WOW): pass else: - wtx = node_from_ci_from.rpc_wallet('gettransaction', [lock_refund_spend_txid.hex(),]) - assert (bid.amount - node_from_ci_from.make_int(wtx['details'][0]['amount']) < max_fee) + wtx = node_from_ci_from.rpc_wallet( + "gettransaction", + [ + lock_refund_spend_txid.hex(), + ], + ) + assert ( + bid.amount - node_from_ci_from.make_int(wtx["details"][0]["amount"]) + < max_fee + ) node_to_ci_to = swap_clients[1].ci(coin_to) if node_to_ci_to.coin_type() in (Coins.XMR, Coins.WOW): pass else: - wtx = node_to_ci_to.rpc_wallet('gettransaction', [bid.xmr_b_lock_tx.spend_txid.hex(),]) - assert (bid.amount_to - node_to_ci_to.make_int(wtx['details'][0]['amount']) < max_fee) + wtx = node_to_ci_to.rpc_wallet( + "gettransaction", + [ + bid.xmr_b_lock_tx.spend_txid.hex(), + ], + ) + assert ( + bid.amount_to - node_to_ci_to.make_int(wtx["details"][0]["amount"]) + < max_fee + ) bid_id_hex = bid_id.hex() - path = f'bids/{bid_id_hex}/states' + path = f"bids/{bid_id_hex}/states" offerer_states = read_json_api(1800 + id_offerer, path) bidder_states = read_json_api(1800 + id_bidder, path) - assert (compare_bid_states(offerer_states, self.states_offerer[1]) is True) - assert (compare_bid_states(bidder_states, self.states_bidder[1]) is True) + assert compare_bid_states(offerer_states, self.states_offerer[1]) is True + assert compare_bid_states(bidder_states, self.states_bidder[1]) is True -def run_test_ads_swipe_refund(self, coin_from: Coins, coin_to: Coins, lock_value: int = 32) -> None: - logging.info('---------- Test {} to {} coin a lock refund tx swiped'.format(coin_from.name, coin_to.name)) +def run_test_ads_swipe_refund( + self, coin_from: Coins, coin_to: Coins, lock_value: int = 32 +) -> None: + logging.info( + "---------- Test {} to {} coin a lock refund tx swiped".format( + coin_from.name, coin_to.name + ) + ) id_offerer: int = 0 id_bidder: int = 1 @@ -423,7 +609,9 @@ def run_test_ads_swipe_refund(self, coin_from: Coins, coin_to: Coins, lock_value id_leader: int = id_bidder if reverse_bid else id_offerer id_follower: int = id_offerer if reverse_bid else id_bidder - logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}') + logging.info( + f"Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}" + ) if reverse_bid: self.prepare_balance(coin_to, 100.0, 1801, 1800) @@ -432,22 +620,49 @@ def run_test_ads_swipe_refund(self, coin_from: Coins, coin_to: Coins, lock_value amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) offer_id = swap_clients[id_offerer].postOffer( - coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, - lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=lock_value) + coin_from, + coin_to, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, + lock_value=lock_value, + ) wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id) offer = swap_clients[id_bidder].getOffer(offer_id) bid_id = swap_clients[id_bidder].postXmrBid(offer_id, offer.amount_from) - wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED) + wait_for_bid( + test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED + ) - swap_clients[id_follower].setBidDebugInd(bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK) - swap_clients[id_leader].setBidDebugInd(bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND) + swap_clients[id_follower].setBidDebugInd( + bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK + ) + swap_clients[id_leader].setBidDebugInd( + bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND + ) swap_clients[id_offerer].acceptBid(bid_id) leader_sent_bid: bool = True if reverse_bid else False - wait_for_bid(test_delay_event, swap_clients[id_leader], bid_id, BidStates.BID_STALLED_FOR_TEST, wait_for=(self.extra_wait_time + 180), sent=leader_sent_bid) - wait_for_bid(test_delay_event, swap_clients[id_follower], bid_id, BidStates.XMR_SWAP_FAILED_SWIPED, wait_for=(self.extra_wait_time + 80), sent=(not leader_sent_bid)) + wait_for_bid( + test_delay_event, + swap_clients[id_leader], + bid_id, + BidStates.BID_STALLED_FOR_TEST, + wait_for=(self.extra_wait_time + 180), + sent=leader_sent_bid, + ) + wait_for_bid( + test_delay_event, + swap_clients[id_follower], + bid_id, + BidStates.XMR_SWAP_FAILED_SWIPED, + wait_for=(self.extra_wait_time + 80), + sent=(not leader_sent_bid), + ) def prepareDCDDataDir(datadir, node_id, conf_file, dir_prefix, num_nodes=3): @@ -458,40 +673,42 @@ def prepareDCDDataDir(datadir, node_id, conf_file, dir_prefix, num_nodes=3): if os.path.exists(cfg_file_path): return config = [ - 'simnet=1\n', - 'debuglevel=debug\n', - f'listen=127.0.0.1:{DCR_BASE_PORT + node_id}\n', - f'rpclisten=127.0.0.1:{DCR_BASE_RPC_PORT + node_id}\n', - f'rpcuser=test{node_id}\n', - f'rpcpass=test_pass{node_id}\n', - 'notls=1\n', - 'noseeders=1\n', - 'nodnsseed=1\n', - 'nodiscoverip=1\n', - 'miningaddr=SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH\n',] + "simnet=1\n", + "debuglevel=debug\n", + f"listen=127.0.0.1:{DCR_BASE_PORT + node_id}\n", + f"rpclisten=127.0.0.1:{DCR_BASE_RPC_PORT + node_id}\n", + f"rpcuser=test{node_id}\n", + f"rpcpass=test_pass{node_id}\n", + "notls=1\n", + "noseeders=1\n", + "nodnsseed=1\n", + "nodiscoverip=1\n", + "miningaddr=SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH\n", + ] for i in range(0, num_nodes): if node_id == i: continue - config.append('addpeer=127.0.0.1:{}\n'.format(DCR_BASE_PORT + i)) + config.append("addpeer=127.0.0.1:{}\n".format(DCR_BASE_PORT + i)) - with open(cfg_file_path, 'w+') as fp: + with open(cfg_file_path, "w+") as fp: for line in config: fp.write(line) config = [ - 'simnet=1\n', - 'debuglevel=debug\n', - f'rpclisten=127.0.0.1:{DCR_BASE_WALLET_RPC_PORT + node_id}\n', - f'rpcconnect=127.0.0.1:{DCR_BASE_RPC_PORT + node_id}\n', - f'username=test{node_id}\n', - f'password=test_pass{node_id}\n', - 'noservertls=1\n', - 'noclienttls=1\n', - 'enablevoting=1\n',] + "simnet=1\n", + "debuglevel=debug\n", + f"rpclisten=127.0.0.1:{DCR_BASE_WALLET_RPC_PORT + node_id}\n", + f"rpcconnect=127.0.0.1:{DCR_BASE_RPC_PORT + node_id}\n", + f"username=test{node_id}\n", + f"password=test_pass{node_id}\n", + "noservertls=1\n", + "noclienttls=1\n", + "enablevoting=1\n", + ] - wallet_cfg_file_path = os.path.join(node_dir, 'dcrwallet.conf') - with open(wallet_cfg_file_path, 'w+') as fp: + wallet_cfg_file_path = os.path.join(node_dir, "dcrwallet.conf") + with open(wallet_cfg_file_path, "w+") as fp: for line in config: fp.write(line) @@ -502,28 +719,43 @@ class Test(BaseTest): dcr_daemons = [] start_ltc_nodes = False start_xmr_nodes = True - dcr_mining_addr = 'SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH' + dcr_mining_addr = "SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH" extra_wait_time = 0 hex_seeds = [ - 'e8574b2a94404ee62d8acc0258cab4c0defcfab8a5dfc2f4954c1f9d7e09d72a', - '10689fc6378e5f318b663560012673441dcdd8d796134e6021a4248cc6342cc6', - 'efc96ffe4fee469407826841d9700ef0a0735b0aa5ec5e7a4aa9bc1afd9a9a30', # Won't match main seed, as it's set randomly + "e8574b2a94404ee62d8acc0258cab4c0defcfab8a5dfc2f4954c1f9d7e09d72a", + "10689fc6378e5f318b663560012673441dcdd8d796134e6021a4248cc6342cc6", + "efc96ffe4fee469407826841d9700ef0a0735b0aa5ec5e7a4aa9bc1afd9a9a30", # Won't match main seed, as it's set randomly ] @classmethod def prepareExtraCoins(cls): ci0 = cls.swap_clients[0].ci(cls.test_coin) if not cls.restore_instance: - assert (ci0.rpc_wallet('getnewaddress') == cls.dcr_mining_addr) - cls.dcr_ticket_account = ci0.rpc_wallet('getaccount', [cls.dcr_mining_addr, ]) - ci0.rpc('generate', [110,]) + assert ci0.rpc_wallet("getnewaddress") == cls.dcr_mining_addr + cls.dcr_ticket_account = ci0.rpc_wallet( + "getaccount", + [ + cls.dcr_mining_addr, + ], + ) + ci0.rpc( + "generate", + [ + 110, + ], + ) else: - cls.dcr_ticket_account = ci0.rpc_wallet('getaccount', [cls.dcr_mining_addr, ]) + cls.dcr_ticket_account = ci0.rpc_wallet( + "getaccount", + [ + cls.dcr_mining_addr, + ], + ) @classmethod def tearDownClass(cls): - logging.info('Finalising Decred Test') + logging.info("Finalising Decred Test") super(Test, cls).tearDownClass() stopDaemons(cls.dcr_daemons) @@ -537,48 +769,86 @@ class Test(BaseTest): num_passed: int = 0 for i in range(30): try: - ci0.rpc_wallet('purchaseticket', [cls.dcr_ticket_account, 0.1, 0]) + ci0.rpc_wallet("purchaseticket", [cls.dcr_ticket_account, 0.1, 0]) num_passed += 1 if num_passed >= 5: break test_delay_event.wait(0.1) except Exception as e: - if 'double spend' in str(e): + if "double spend" in str(e): pass else: - logging.warning('coins_loop purchaseticket {}'.format(e)) + logging.warning("coins_loop purchaseticket {}".format(e)) test_delay_event.wait(0.5) try: if num_passed >= 5: - ci0.rpc('generate', [1,]) + ci0.rpc( + "generate", + [ + 1, + ], + ) except Exception as e: - logging.warning('coins_loop generate {}'.format(e)) + logging.warning("coins_loop generate {}".format(e)) @classmethod def prepareExtraDataDir(cls, i): extra_opts = [] if not cls.restore_instance: - data_dir = prepareDCDDataDir(cfg.TEST_DATADIRS, i, 'dcrd.conf', 'dcr_') + prepareDCDDataDir(cfg.TEST_DATADIRS, i, "dcrd.conf", "dcr_") - appdata = os.path.join(cfg.TEST_DATADIRS, 'dcr_' + str(i)) - datadir = os.path.join(appdata, 'data') + appdata = os.path.join(cfg.TEST_DATADIRS, "dcr_" + str(i)) extra_opts.append(f'--appdata="{appdata}"') - cls.dcr_daemons.append(startDaemon(appdata, DCR_BINDIR, DCRD, opts=extra_opts, extra_config={'add_datadir': False, 'stdout_to_file': True, 'stdout_filename': 'dcrd_stdout.log'})) - logging.info('Started %s %d', DCRD, cls.dcr_daemons[-1].handle.pid) + cls.dcr_daemons.append( + startDaemon( + appdata, + DCR_BINDIR, + DCRD, + opts=extra_opts, + extra_config={ + "add_datadir": False, + "stdout_to_file": True, + "stdout_filename": "dcrd_stdout.log", + }, + ) + ) + logging.info("Started %s %d", DCRD, cls.dcr_daemons[-1].handle.pid) - waitForRPC(make_rpc_func(i, base_rpc_port=DCR_BASE_RPC_PORT), test_delay_event, rpc_command='getnetworkinfo', max_tries=12) + waitForRPC( + make_rpc_func(i, base_rpc_port=DCR_BASE_RPC_PORT), + test_delay_event, + rpc_command="getnetworkinfo", + max_tries=12, + ) - extra_opts.append('--pass=test_pass') - args = [os.path.join(DCR_BINDIR, DCR_WALLET), '--create'] + extra_opts + extra_opts.append("--pass=test_pass") + args = [os.path.join(DCR_BINDIR, DCR_WALLET), "--create"] + extra_opts createDCRWallet(args, cls.hex_seeds[i], logging, test_delay_event) test_delay_event.wait(1.0) - cls.dcr_daemons.append(startDaemon(appdata, DCR_BINDIR, DCR_WALLET, opts=extra_opts, extra_config={'add_datadir': False, 'stdout_to_file': True, 'stdout_filename': 'dcrwallet_stdout.log'})) - logging.info('Started %s %d', DCR_WALLET, cls.dcr_daemons[-1].handle.pid) + cls.dcr_daemons.append( + startDaemon( + appdata, + DCR_BINDIR, + DCR_WALLET, + opts=extra_opts, + extra_config={ + "add_datadir": False, + "stdout_to_file": True, + "stdout_filename": "dcrwallet_stdout.log", + }, + ) + ) + logging.info("Started %s %d", DCR_WALLET, cls.dcr_daemons[-1].handle.pid) - waitForRPC(make_rpc_func(i, base_rpc_port=DCR_BASE_WALLET_RPC_PORT), test_delay_event, rpc_command='getinfo', max_tries=12) + waitForRPC( + make_rpc_func(i, base_rpc_port=DCR_BASE_WALLET_RPC_PORT), + test_delay_event, + rpc_command="getinfo", + max_tries=12, + ) @classmethod def addPIDInfo(cls, sc, i): @@ -586,134 +856,189 @@ class Test(BaseTest): @classmethod def addCoinSettings(cls, settings, datadir, node_id): - settings['chainclients']['decred'] = { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': DCR_BASE_RPC_PORT + node_id, - 'walletrpcport': DCR_BASE_WALLET_RPC_PORT + node_id, - 'rpcuser': 'test' + str(node_id), - 'rpcpassword': 'test_pass' + str(node_id), - 'datadir': os.path.join(datadir, 'dcr_' + str(node_id)), - 'bindir': DCR_BINDIR, - 'wallet_pwd': 'test_pass', - 'use_csv': True, - 'use_segwit': True, - 'blocks_confirmed': 1, + settings["chainclients"]["decred"] = { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": DCR_BASE_RPC_PORT + node_id, + "walletrpcport": DCR_BASE_WALLET_RPC_PORT + node_id, + "rpcuser": "test" + str(node_id), + "rpcpassword": "test_pass" + str(node_id), + "datadir": os.path.join(datadir, "dcr_" + str(node_id)), + "bindir": DCR_BINDIR, + "wallet_pwd": "test_pass", + "use_csv": True, + "use_segwit": True, + "blocks_confirmed": 1, } def test_0001_decred_address(self): - logging.info('---------- Test {}'.format(self.test_coin.name)) + logging.info("---------- Test {}".format(self.test_coin.name)) - coin_settings = {'rpcport': 0, 'rpcauth': 'none'} + coin_settings = {"rpcport": 0, "rpcauth": "none"} coin_settings.update(REQUIRED_SETTINGS) - ci = DCRInterface(coin_settings, 'mainnet') + ci = DCRInterface(coin_settings, "mainnet") k = ci.getNewSecretKey() K = ci.getPubkey(k) pkh = ci.pkh(K) address = ci.pkh_to_address(pkh) - assert (address.startswith('Ds')) + assert address.startswith("Ds") data = ci.decode_address(address) - assert (data[2:] == pkh) + assert data[2:] == pkh for i, sc in enumerate(self.swap_clients): loop_ci = sc.ci(self.test_coin) root_key = sc.getWalletKey(Coins.DCR, 1) - masterpubkey = loop_ci.rpc_wallet('getmasterpubkey') + masterpubkey = loop_ci.rpc_wallet("getmasterpubkey") masterpubkey_data = loop_ci.decode_address(masterpubkey)[4:] seed_hash = loop_ci.getSeedHash(root_key) if i == 0: - assert (masterpubkey == 'spubVV1z2AFYjVZvzM45FSaWMPRqyUoUwyW78wfANdjdNG6JGCXrr8AbRvUgYb3Lm1iun9CgHew1KswdePryNLKEnBSQ82AjNpYdQgzXPUme9c6') + assert ( + masterpubkey + == "spubVV1z2AFYjVZvzM45FSaWMPRqyUoUwyW78wfANdjdNG6JGCXrr8AbRvUgYb3Lm1iun9CgHew1KswdePryNLKEnBSQ82AjNpYdQgzXPUme9c6" + ) if i < 2: - assert (seed_hash == hash160(masterpubkey_data)) + assert seed_hash == hash160(masterpubkey_data) def test_001_segwit(self): - logging.info('---------- Test {} segwit'.format(self.test_coin.name)) + logging.info("---------- Test {} segwit".format(self.test_coin.name)) swap_clients = self.swap_clients ci0 = swap_clients[0].ci(self.test_coin) - assert (ci0.using_segwit() is True) + assert ci0.using_segwit() is True addr_out = ci0.getNewAddress() - addr_info = ci0.rpc_wallet('validateaddress', [addr_out,]) - assert (addr_info['isvalid'] is True) - assert (addr_info['ismine'] is True) + addr_info = ci0.rpc_wallet( + "validateaddress", + [ + addr_out, + ], + ) + assert addr_info["isvalid"] is True + assert addr_info["ismine"] is True - rtx = ci0.rpc_wallet('createrawtransaction', [[], {addr_out: 2.0}]) + rtx = ci0.rpc_wallet("createrawtransaction", [[], {addr_out: 2.0}]) - account_from = ci0.rpc_wallet('getaccount', [self.dcr_mining_addr, ]) - frtx = ci0.rpc_wallet('fundrawtransaction', [rtx, account_from]) + account_from = ci0.rpc_wallet( + "getaccount", + [ + self.dcr_mining_addr, + ], + ) + frtx = ci0.rpc_wallet("fundrawtransaction", [rtx, account_from]) - f_decoded = ci0.rpc_wallet('decoderawtransaction', [frtx['hex'], ]) - assert (f_decoded['version'] == 1) + f_decoded = ci0.rpc_wallet( + "decoderawtransaction", + [ + frtx["hex"], + ], + ) + assert f_decoded["version"] == 1 - sfrtx = ci0.rpc_wallet('signrawtransaction', [frtx['hex']]) - s_decoded = ci0.rpc_wallet('decoderawtransaction', [sfrtx['hex'], ]) - sent_txid = ci0.rpc_wallet('sendrawtransaction', [sfrtx['hex'], ]) + sfrtx = ci0.rpc_wallet("signrawtransaction", [frtx["hex"]]) + s_decoded = ci0.rpc_wallet( + "decoderawtransaction", + [ + sfrtx["hex"], + ], + ) + sent_txid = ci0.rpc_wallet( + "sendrawtransaction", + [ + sfrtx["hex"], + ], + ) - assert (f_decoded['txid'] == sent_txid) - assert (f_decoded['txid'] == s_decoded['txid']) - assert (f_decoded['txid'] == s_decoded['txid']) + assert f_decoded["txid"] == sent_txid + assert f_decoded["txid"] == s_decoded["txid"] + assert f_decoded["txid"] == s_decoded["txid"] - ctx = ci0.loadTx(bytes.fromhex(sfrtx['hex'])) + ctx = ci0.loadTx(bytes.fromhex(sfrtx["hex"])) ser_out = ctx.serialize() - assert (ser_out.hex() == sfrtx['hex']) - assert (f_decoded['txid'] == ctx.TxHash().hex()) + assert ser_out.hex() == sfrtx["hex"] + assert f_decoded["txid"] == ctx.TxHash().hex() def test_003_signature_hash(self): - logging.info('---------- Test {} signature_hash'.format(self.test_coin.name)) + logging.info("---------- Test {} signature_hash".format(self.test_coin.name)) # Test that signing a transaction manually produces the same result when signed with the wallet swap_clients = self.swap_clients ci0 = swap_clients[0].ci(self.test_coin) - utxos = ci0.rpc_wallet('listunspent') - addr_out = ci0.rpc_wallet('getnewaddress') - rtx = ci0.rpc_wallet('createrawtransaction', [[], {addr_out: 2.0}]) + utxos = ci0.rpc_wallet("listunspent") + addr_out = ci0.rpc_wallet("getnewaddress") + rtx = ci0.rpc_wallet("createrawtransaction", [[], {addr_out: 2.0}]) - account_from = ci0.rpc_wallet('getaccount', [self.dcr_mining_addr, ]) - frtx = ci0.rpc_wallet('fundrawtransaction', [rtx, account_from]) - sfrtx = ci0.rpc_wallet('signrawtransaction', [frtx['hex']]) + account_from = ci0.rpc_wallet( + "getaccount", + [ + self.dcr_mining_addr, + ], + ) + frtx = ci0.rpc_wallet("fundrawtransaction", [rtx, account_from]) + sfrtx = ci0.rpc_wallet("signrawtransaction", [frtx["hex"]]) - ctx = ci0.loadTx(bytes.fromhex(frtx['hex'])) + ctx = ci0.loadTx(bytes.fromhex(frtx["hex"])) prevout = None prevout_txid = ctx.vin[0].prevout.get_hash().hex() prevout_n = ctx.vin[0].prevout.n for utxo in utxos: - if prevout_txid == utxo['txid'] and prevout_n == utxo['vout']: + if prevout_txid == utxo["txid"] and prevout_n == utxo["vout"]: prevout = utxo break - assert (prevout is not None) + assert prevout is not None tx_bytes_no_witness: bytes = ctx.serialize(TxSerializeType.NoWitness) - sig0 = ci0.rpc_wallet('createsignature', [prevout['address'], 0, SigHashType.SigHashAll, prevout['scriptPubKey'], tx_bytes_no_witness.hex()]) - priv_key_wif = ci0.rpc_wallet('dumpprivkey', [prevout['address'], ]) + priv_key_wif = ci0.rpc_wallet( + "dumpprivkey", + [ + prevout["address"], + ], + ) sig_type, key_bytes = ci0.decodeKey(priv_key_wif) - addr_info = ci0.rpc_wallet('validateaddress', [prevout['address'],]) - pk_hex: str = addr_info['pubkey'] + addr_info = ci0.rpc_wallet( + "validateaddress", + [ + prevout["address"], + ], + ) + pk_hex: str = addr_info["pubkey"] - sig0_py = ci0.signTx(key_bytes, tx_bytes_no_witness, 0, bytes.fromhex(prevout['scriptPubKey']), ci0.make_int(prevout['amount'])) - tx_bytes_signed = ci0.setTxSignature(tx_bytes_no_witness, [sig0_py, bytes.fromhex(pk_hex)]) + sig0_py = ci0.signTx( + key_bytes, + tx_bytes_no_witness, + 0, + bytes.fromhex(prevout["scriptPubKey"]), + ci0.make_int(prevout["amount"]), + ) + tx_bytes_signed = ci0.setTxSignature( + tx_bytes_no_witness, [sig0_py, bytes.fromhex(pk_hex)] + ) # Set prevout value ctx = ci0.loadTx(tx_bytes_signed) - assert (ctx.vout[0].version == 0) - ctx.vin[0].value_in = ci0.make_int(prevout['amount']) + assert ctx.vout[0].version == 0 + ctx.vin[0].value_in = ci0.make_int(prevout["amount"]) tx_bytes_signed = ctx.serialize() - assert (tx_bytes_signed.hex() == sfrtx['hex']) + assert tx_bytes_signed.hex() == sfrtx["hex"] - sent_txid = ci0.rpc_wallet('sendrawtransaction', [tx_bytes_signed.hex(), ]) - assert (len(sent_txid) == 64) + sent_txid = ci0.rpc_wallet( + "sendrawtransaction", + [ + tx_bytes_signed.hex(), + ], + ) + assert len(sent_txid) == 64 def test_004_csv(self): - logging.info('---------- Test {} csv'.format(self.test_coin.name)) + logging.info("---------- Test {} csv".format(self.test_coin.name)) swap_clients = self.swap_clients ci0 = swap_clients[0].ci(self.test_coin) @@ -722,36 +1047,56 @@ class Test(BaseTest): script += bytes((OP_CHECKSEQUENCEVERIFY,)) script_dest = ci0.getScriptDest(script) - script_info = ci0.rpc_wallet('decodescript', [script_dest.hex(),]) + script_info = ci0.rpc_wallet( + "decodescript", + [ + script_dest.hex(), + ], + ) script_addr = ci0.encodeScriptDest(script_dest) - assert (script_info['addresses'][0] == script_addr) + assert script_info["addresses"][0] == script_addr prevout_amount: int = ci0.make_int(1.1) tx = CTransaction() tx.version = ci0.txVersion() tx.vout.append(ci0.txoType()(prevout_amount, script_dest)) tx_hex = tx.serialize().hex() - tx_decoded = ci0.rpc_wallet('decoderawtransaction', [tx_hex, ]) + tx_decoded = ci0.rpc_wallet( + "decoderawtransaction", + [ + tx_hex, + ], + ) utxo_pos = None script_address = None - for i, txo in enumerate(tx_decoded['vout']): - script_address = tx_decoded['vout'][0]['scriptPubKey']['addresses'][0] - addr_info = ci0.rpc_wallet('validateaddress', [script_address,]) - if addr_info['isscript'] is True: + for i, txo in enumerate(tx_decoded["vout"]): + script_address = tx_decoded["vout"][0]["scriptPubKey"]["addresses"][0] + addr_info = ci0.rpc_wallet( + "validateaddress", + [ + script_address, + ], + ) + if addr_info["isscript"] is True: utxo_pos = i break - assert (utxo_pos is not None) + assert utxo_pos is not None - accounts = ci0.rpc_wallet('listaccounts') + accounts = ci0.rpc_wallet("listaccounts") for account_from in accounts: try: - frtx = ci0.rpc_wallet('fundrawtransaction', [tx_hex, account_from]) + frtx = ci0.rpc_wallet("fundrawtransaction", [tx_hex, account_from]) break except Exception as e: - logging.warning('fundrawtransaction failed {}'.format(e)) - sfrtx = ci0.rpc_wallet('signrawtransaction', [frtx['hex']]) - sent_txid = ci0.rpc_wallet('sendrawtransaction', [sfrtx['hex'], ]) + logging.warning("fundrawtransaction failed {}".format(e)) + sfrtx = ci0.rpc_wallet("signrawtransaction", [frtx["hex"]]) + sent_txid = ci0.rpc_wallet( + "sendrawtransaction", + [ + sfrtx["hex"], + ], + ) tx_spend = CTransaction() tx_spend.version = ci0.txVersion() @@ -772,26 +1117,42 @@ class Test(BaseTest): tx_spend_hex = tx_spend.serialize().hex() try: - sent_spend_txid = ci0.rpc_wallet('sendrawtransaction', [tx_spend_hex, ]) - logging.info('Sent tx spending csv output, txid: {}'.format(sent_spend_txid)) + sent_spend_txid = ci0.rpc_wallet( + "sendrawtransaction", + [ + tx_spend_hex, + ], + ) + logging.info( + "Sent tx spending csv output, txid: {}".format(sent_spend_txid) + ) except Exception as e: - assert ('transaction sequence locks on inputs not met' in str(e)) + assert "transaction sequence locks on inputs not met" in str(e) else: - assert False, 'Should fail' + assert False, "Should fail" sent_spend_txid = None for i in range(20): try: - sent_spend_txid = ci0.rpc_wallet('sendrawtransaction', [tx_spend_hex, ]) + sent_spend_txid = ci0.rpc_wallet( + "sendrawtransaction", + [ + tx_spend_hex, + ], + ) break except Exception as e: - logging.info('sendrawtransaction failed {}, height {}'.format(e, ci0.getChainHeight())) + logging.info( + "sendrawtransaction failed {}, height {}".format( + e, ci0.getChainHeight() + ) + ) test_delay_event.wait(1) - assert (sent_spend_txid is not None) + assert sent_spend_txid is not None def test_005_watchonly(self): - logging.info('---------- Test {} watchonly'.format(self.test_coin.name)) + logging.info("---------- Test {} watchonly".format(self.test_coin.name)) swap_clients = self.swap_clients ci0 = swap_clients[0].ci(self.test_coin) @@ -799,27 +1160,52 @@ class Test(BaseTest): addr = ci0.getNewAddress() pkh = ci0.decode_address(addr)[2:] - addr_info = ci0.rpc_wallet('validateaddress', [addr,]) + addr_info = ci0.rpc_wallet( + "validateaddress", + [ + addr, + ], + ) addr_script = ci0.getPubkeyHashDest(pkh).hex() - script_info = ci0.rpc_wallet('decodescript', [addr_script,]) - assert (addr in script_info['addresses']) + script_info = ci0.rpc_wallet( + "decodescript", + [ + addr_script, + ], + ) + assert addr in script_info["addresses"] # Importscript doesn't import an address - ci1.rpc_wallet('importscript', [addr_script,]) - addr_info1 = ci1.rpc_wallet('validateaddress', [addr,]) - assert (addr_info1.get('ismine', False) is False) + ci1.rpc_wallet( + "importscript", + [ + addr_script, + ], + ) + addr_info1 = ci1.rpc_wallet( + "validateaddress", + [ + addr, + ], + ) + assert addr_info1.get("ismine", False) is False # Would need to run a second wallet daemon? try: - ro = ci1.rpc_wallet('importpubkey', [addr_info['pubkey'],]) + ci1.rpc_wallet( + "importpubkey", + [ + addr_info["pubkey"], + ], + ) except Exception as e: - assert ('public keys may only be imported by watching-only wallets' in str(e)) + assert "public keys may only be imported by watching-only wallets" in str(e) else: - logging.info('Expected importpubkey to fail on non watching-only wallet') + logging.info("Expected importpubkey to fail on non watching-only wallet") chain_height_last = ci1.getChainHeight() - txid = ci0.rpc_wallet('sendtoaddress', [addr, 1]) + ci0.rpc_wallet("sendtoaddress", [addr, 1]) found_txid = None for i in range(20): @@ -831,30 +1217,42 @@ class Test(BaseTest): if found_txid is not None: break try: - check_hash = ci1.rpc('getblockhash', [chain_height_last + 1, ]) + check_hash = ci1.rpc( + "getblockhash", + [ + chain_height_last + 1, + ], + ) except Exception as e: - logging.warning('getblockhash {} failed {}'.format(chain_height_last + 1, e)) + logging.warning( + "getblockhash {} failed {}".format(chain_height_last + 1, e) + ) test_delay_event.wait(1) break chain_height_last += 1 - check_hash = ci1.rpc('getblockhash', [chain_height_last, ]) - block_tx = ci1.rpc('getblock', [check_hash, True, True]) - for tx in block_tx['rawtx']: + check_hash = ci1.rpc( + "getblockhash", + [ + chain_height_last, + ], + ) + block_tx = ci1.rpc("getblock", [check_hash, True, True]) + for tx in block_tx["rawtx"]: if found_txid is not None: break - for txo in tx['vout']: - if addr_script == txo['scriptPubKey']['hex']: - found_txid = tx['txid'] - logging.info('found_txid {}'.format(found_txid)) + for txo in tx["vout"]: + if addr_script == txo["scriptPubKey"]["hex"]: + found_txid = tx["txid"] + logging.info("found_txid {}".format(found_txid)) break test_delay_event.wait(1) - assert (found_txid is not None) + assert found_txid is not None def test_008_gettxout(self): - logging.info('---------- Test {} gettxout'.format(self.test_coin.name)) + logging.info("---------- Test {} gettxout".format(self.test_coin.name)) ci0 = self.swap_clients[0].ci(self.test_coin) @@ -866,95 +1264,146 @@ class Test(BaseTest): unspents = None for i in range(30): - unspents = ci0.rpc_wallet('listunspent', [0, 999999999, [addr,]]) + unspents = ci0.rpc_wallet( + "listunspent", + [ + 0, + 999999999, + [ + addr, + ], + ], + ) if unspents is None: unspents = [] if len(unspents) > 0: break test_delay_event.wait(1) - assert (len(unspents) == 1) + assert len(unspents) == 1 utxo = unspents[0] include_mempool: bool = False - txout = ci0.rpc('gettxout', [utxo['txid'], utxo['vout'], utxo['tree'], include_mempool]) + txout = ci0.rpc( + "gettxout", [utxo["txid"], utxo["vout"], utxo["tree"], include_mempool] + ) # Lock utxo so it's not spent for tickets, while waiting for depth - rv = ci0.rpc_wallet('lockunspent', [False, [utxo, ]]) + ci0.rpc_wallet( + "lockunspent", + [ + False, + [ + utxo, + ], + ], + ) def wait_for_depth(): for i in range(20): - logging.info('Waiting for txout depth, iter {}'.format(i)) - txout = ci0.rpc('gettxout', [utxo['txid'], utxo['vout'], utxo['tree'], True]) - if txout['confirmations'] > 0: + logging.info("Waiting for txout depth, iter {}".format(i)) + txout = ci0.rpc( + "gettxout", [utxo["txid"], utxo["vout"], utxo["tree"], True] + ) + if txout["confirmations"] > 0: return txout test_delay_event.wait(1) - raise ValueError('prevout not confirmed') + raise ValueError("prevout not confirmed") + txout = wait_for_depth() - assert (txout['confirmations'] > 0) - assert (addr in txout['scriptPubKey']['addresses']) + assert txout["confirmations"] > 0 + assert addr in txout["scriptPubKey"]["addresses"] addr_out = ci0.getNewAddress() - rtx = ci0.rpc_wallet('createrawtransaction', [[utxo, ], {addr_out: test_amount - 0.0001}]) - stx = ci0.rpc_wallet('signrawtransaction', [rtx]) + rtx = ci0.rpc_wallet( + "createrawtransaction", + [ + [ + utxo, + ], + {addr_out: test_amount - 0.0001}, + ], + ) + stx = ci0.rpc_wallet("signrawtransaction", [rtx]) chain_height_before_send = ci0.getChainHeight() - sent_txid = ci0.rpc_wallet('sendrawtransaction', [stx['hex'], ]) + ci0.rpc_wallet( + "sendrawtransaction", + [ + stx["hex"], + ], + ) # NOTE: UTXO is still found when spent in the mempool (tested in loop, not delay from wallet to core) - txout = ci0.rpc('gettxout', [utxo['txid'], utxo['vout'], utxo['tree'], include_mempool]) - assert (addr in txout['scriptPubKey']['addresses']) + txout = ci0.rpc( + "gettxout", [utxo["txid"], utxo["vout"], utxo["tree"], include_mempool] + ) + assert addr in txout["scriptPubKey"]["addresses"] for i in range(20): - txout = ci0.rpc('gettxout', [utxo['txid'], utxo['vout'], utxo['tree'], include_mempool]) + txout = ci0.rpc( + "gettxout", [utxo["txid"], utxo["vout"], utxo["tree"], include_mempool] + ) if txout is None: - logging.info('txout spent, height before spent {}, height spent {}'.format(chain_height_before_send, ci0.getChainHeight())) + logging.info( + "txout spent, height before spent {}, height spent {}".format( + chain_height_before_send, ci0.getChainHeight() + ) + ) break test_delay_event.wait(1) - assert (txout is None) + assert txout is None - logging.info('Testing getProofOfFunds') + logging.info("Testing getProofOfFunds") require_amount: int = ci0.make_int(1) - funds_proof = ci0.getProofOfFunds(require_amount, 'test'.encode('utf-8')) + funds_proof = ci0.getProofOfFunds(require_amount, "test".encode("utf-8")) - logging.info('Testing verifyProofOfFunds') - amount_proved = ci0.verifyProofOfFunds(funds_proof[0], funds_proof[1], funds_proof[2], 'test'.encode('utf-8')) - assert (amount_proved >= require_amount) + logging.info("Testing verifyProofOfFunds") + amount_proved = ci0.verifyProofOfFunds( + funds_proof[0], funds_proof[1], funds_proof[2], "test".encode("utf-8") + ) + assert amount_proved >= require_amount def test_009_wallet_encryption(self): - logging.info('---------- Test {} wallet encryption'.format(self.test_coin.name)) + logging.info("---------- Test {} wallet encryption".format(self.test_coin.name)) - for coin in ('part', 'dcr', 'xmr'): - jsw = read_json_api(1800, f'wallets/{coin}') - assert (jsw['encrypted'] is (True if coin == 'dcr' else False)) - assert (jsw['locked'] is False) + for coin in ("part", "dcr", "xmr"): + jsw = read_json_api(1800, f"wallets/{coin}") + assert jsw["encrypted"] is (True if coin == "dcr" else False) + assert jsw["locked"] is False - read_json_api(1800, 'setpassword', {'oldpassword': '', 'newpassword': 'notapassword123'}) + read_json_api( + 1800, "setpassword", {"oldpassword": "", "newpassword": "notapassword123"} + ) # Entire system is locked with Particl wallet - jsw = read_json_api(1800, 'wallets/dcr') - assert ('Coin must be unlocked' in jsw['error']) + jsw = read_json_api(1800, "wallets/dcr") + assert "Coin must be unlocked" in jsw["error"] - read_json_api(1800, 'unlock', {'coin': 'part', 'password': 'notapassword123'}) + read_json_api(1800, "unlock", {"coin": "part", "password": "notapassword123"}) - for coin in ('dcr', 'xmr'): - jsw = read_json_api(1800, f'wallets/{coin}') - assert (jsw['encrypted'] is True) - assert (jsw['locked'] is True) + for coin in ("dcr", "xmr"): + jsw = read_json_api(1800, f"wallets/{coin}") + assert jsw["encrypted"] is True + assert jsw["locked"] is True - read_json_api(1800, 'lock', {'coin': 'part'}) - jsw = read_json_api(1800, 'wallets/part') - assert ('Coin must be unlocked' in jsw['error']) + read_json_api(1800, "lock", {"coin": "part"}) + jsw = read_json_api(1800, "wallets/part") + assert "Coin must be unlocked" in jsw["error"] - read_json_api(1800, 'setpassword', {'oldpassword': 'notapassword123', 'newpassword': 'notapassword456'}) - read_json_api(1800, 'unlock', {'password': 'notapassword456'}) + read_json_api( + 1800, + "setpassword", + {"oldpassword": "notapassword123", "newpassword": "notapassword456"}, + ) + read_json_api(1800, "unlock", {"password": "notapassword456"}) - for coin in ('part', 'dcr', 'xmr'): - jsw = read_json_api(1800, f'wallets/{coin}') - assert (jsw['encrypted'] is True) - assert (jsw['locked'] is False) + for coin in ("part", "dcr", "xmr"): + jsw = read_json_api(1800, f"wallets/{coin}") + assert jsw["encrypted"] is True + assert jsw["locked"] is False def test_010_txn_size(self): - logging.info('---------- Test {} txn size'.format(self.test_coin.name)) + logging.info("---------- Test {} txn size".format(self.test_coin.name)) swap_clients = self.swap_clients ci = swap_clients[0].ci(self.test_coin) @@ -963,7 +1412,7 @@ class Test(BaseTest): amount: int = ci.make_int(random.uniform(0.1, 2.0), r=1) # Record unspents before createSCLockTx as the used ones will be locked - unspents = ci.rpc_wallet('listunspent') + unspents = ci.rpc_wallet("listunspent") # fee_rate is in sats/kvB fee_rate: int = 10000 @@ -979,40 +1428,37 @@ class Test(BaseTest): lock_tx = ci.fundSCLockTx(lock_tx, fee_rate) lock_tx = ci.signTxWithWallet(lock_tx) - unspents_after = ci.rpc_wallet('listunspent') - assert (len(unspents) > len(unspents_after)) + unspents_after = ci.rpc_wallet("listunspent") + assert len(unspents) > len(unspents_after) - tx_decoded = ci.rpc('decoderawtransaction', [lock_tx.hex()]) - txid = tx_decoded['txid'] - - size = len(lock_tx) - expect_fee_int = round(fee_rate * size / 1000) - expect_fee = ci.format_amount(expect_fee_int) + tx_decoded = ci.rpc("decoderawtransaction", [lock_tx.hex()]) + txid = tx_decoded["txid"] out_value: int = 0 - for txo in tx_decoded['vout']: - if 'value' in txo: - out_value += ci.make_int(txo['value']) + for txo in tx_decoded["vout"]: + if "value" in txo: + out_value += ci.make_int(txo["value"]) in_value: int = 0 - for txi in tx_decoded['vin']: + for txi in tx_decoded["vin"]: for utxo in unspents: - if 'vout' not in utxo: + if "vout" not in utxo: continue - if utxo['txid'] == txi['txid'] and utxo['vout'] == txi['vout']: - in_value += ci.make_int(utxo['amount']) + if utxo["txid"] == txi["txid"] and utxo["vout"] == txi["vout"]: + in_value += ci.make_int(utxo["amount"]) break - fee_value = in_value - out_value - ci.rpc('sendrawtransaction', [lock_tx.hex()]) + ci.rpc("sendrawtransaction", [lock_tx.hex()]) addr_out = ci.getNewAddress(True) pkh_out = ci.decodeAddress(addr_out) fee_info = {} - lock_spend_tx = ci.createSCLockSpendTx(lock_tx, lock_tx_script, pkh_out, fee_rate, fee_info=fee_info) - size_estimated: int = fee_info['size'] + lock_spend_tx = ci.createSCLockSpendTx( + lock_tx, lock_tx_script, pkh_out, fee_rate, fee_info=fee_info + ) + size_estimated: int = fee_info["size"] - tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()]) - txid = tx_decoded['txid'] + tx_decoded = ci.rpc("decoderawtransaction", [lock_spend_tx.hex()]) + txid = tx_decoded["txid"] witness_stack = [ ci.signTx(a, lock_spend_tx, 0, lock_tx_script, amount), @@ -1023,12 +1469,12 @@ class Test(BaseTest): size_actual: int = len(lock_spend_tx) - assert (size_actual <= size_estimated and size_estimated - size_actual < 4) - assert (ci.rpc('sendrawtransaction', [lock_spend_tx.hex()]) == txid) + assert size_actual <= size_estimated and size_estimated - size_actual < 4 + assert ci.rpc("sendrawtransaction", [lock_spend_tx.hex()]) == txid expect_size: int = ci.xmr_swap_a_lock_spend_tx_vsize() - assert (expect_size >= size_actual) - assert (expect_size - size_actual < 10) + assert expect_size >= size_actual + assert expect_size - size_actual < 10 # Test chain b (no-script) lock tx size v = ci.getNewSecretKey() @@ -1038,7 +1484,9 @@ class Test(BaseTest): test_delay_event.wait(1) addr_out = ci.getNewAddress(True) - lock_tx_b_spend_txid = ci.spendBLockTx(lock_tx_b_txid, addr_out, v, s, amount, fee_rate, 0) + lock_tx_b_spend_txid = ci.spendBLockTx( + lock_tx_b_txid, addr_out, v, s, amount, fee_rate, 0 + ) test_delay_event.wait(1) lock_tx_b_spend = ci.getWalletTransaction(lock_tx_b_spend_txid) if lock_tx_b_spend is None: @@ -1051,9 +1499,9 @@ class Test(BaseTest): actual_size = len(lock_tx_b_spend) expect_size: int = ci.xmr_swap_b_lock_spend_tx_vsize() fee_expect = round(fee_rate * expect_size / 1000) - assert (fee_expect == fee_paid) - assert (expect_size >= actual_size) - assert (expect_size - actual_size < 10) + assert fee_expect == fee_paid + assert expect_size >= actual_size + assert expect_size - actual_size < 10 def test_02_part_coin(self): run_test_success_path(self, Coins.PART, self.test_coin) @@ -1101,5 +1549,5 @@ class Test(BaseTest): run_test_ads_swipe_refund(self, Coins.XMR, self.test_coin, lock_value=20) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/extended/test_encrypted_xmr_reload.py b/tests/basicswap/extended/test_encrypted_xmr_reload.py index 8224a39..8e3e79d 100644 --- a/tests/basicswap/extended/test_encrypted_xmr_reload.py +++ b/tests/basicswap/extended/test_encrypted_xmr_reload.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020-2023 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -47,77 +48,76 @@ class Test(XmrTestBase): waitForServer(self.delay_event, 12700) waitForServer(self.delay_event, 12701) - wallets1 = read_json_api(12701, 'wallets') - assert (float(wallets1['XMR']['balance']) > 0.0) + wallets1 = read_json_api(12701, "wallets") + assert float(wallets1["XMR"]["balance"]) > 0.0 - node1_password: str = 'notapassword123' - logger.info('Encrypting node 1 wallets') - rv = read_json_api(12701, 'setpassword', {'oldpassword': '', 'newpassword': node1_password}) - assert ('success' in rv) - rv = read_json_api(12701, 'unlock', {'password': node1_password}) - assert ('success' in rv) + node1_password: str = "notapassword123" + logger.info("Encrypting node 1 wallets") + rv = read_json_api( + 12701, "setpassword", {"oldpassword": "", "newpassword": node1_password} + ) + assert "success" in rv + rv = read_json_api(12701, "unlock", {"password": node1_password}) + assert "success" in rv data = { - 'addr_from': '-1', - 'coin_from': 'part', - 'coin_to': 'xmr', - 'amt_from': '1', - 'amt_to': '1', - 'lockhrs': '24'} + "addr_from": "-1", + "coin_from": "part", + "coin_to": "xmr", + "amt_from": "1", + "amt_to": "1", + "lockhrs": "24", + } - offer_id = post_json_api(12700, 'offers/new', data)['offer_id'] + offer_id = post_json_api(12700, "offers/new", data)["offer_id"] summary = read_json_api(12700) - assert (summary['num_sent_offers'] == 1) + assert summary["num_sent_offers"] == 1 - logger.info('Waiting for offer') + logger.info("Waiting for offer") waitForNumOffers(self.delay_event, 12701, 1) - offers = read_json_api(12701, 'offers') + offers = read_json_api(12701, "offers") offer = offers[0] - data = { - 'offer_id': offer['offer_id'], - 'amount_from': offer['amount_from']} + data = {"offer_id": offer["offer_id"], "amount_from": offer["amount_from"]} - data['valid_for_seconds'] = 24 * 60 * 60 + 1 - bid = post_json_api(12701, 'bids/new', data) - assert (bid['error'] == 'Bid TTL too high') - del data['valid_for_seconds'] - data['validmins'] = 24 * 60 + 1 - bid = post_json_api(12701, 'bids/new', data) - assert (bid['error'] == 'Bid TTL too high') + data["valid_for_seconds"] = 24 * 60 * 60 + 1 + bid = post_json_api(12701, "bids/new", data) + assert bid["error"] == "Bid TTL too high" + del data["valid_for_seconds"] + data["validmins"] = 24 * 60 + 1 + bid = post_json_api(12701, "bids/new", data) + assert bid["error"] == "Bid TTL too high" - del data['validmins'] - data['valid_for_seconds'] = 10 - bid = post_json_api(12701, 'bids/new', data) - assert (bid['error'] == 'Bid TTL too low') - del data['valid_for_seconds'] - data['validmins'] = 1 - bid = post_json_api(12701, 'bids/new', data) - assert (bid['error'] == 'Bid TTL too low') + del data["validmins"] + data["valid_for_seconds"] = 10 + bid = post_json_api(12701, "bids/new", data) + assert bid["error"] == "Bid TTL too low" + del data["valid_for_seconds"] + data["validmins"] = 1 + bid = post_json_api(12701, "bids/new", data) + assert bid["error"] == "Bid TTL too low" - data['validmins'] = 60 - bid_id = post_json_api(12701, 'bids/new', data) + data["validmins"] = 60 + post_json_api(12701, "bids/new", data) waitForNumBids(self.delay_event, 12700, 1) for i in range(10): - bids = read_json_api(12700, 'bids') + bids = read_json_api(12700, "bids") bid = bids[0] - if bid['bid_state'] == 'Received': + if bid["bid_state"] == "Received": break self.delay_event.wait(1) - assert (bid['expire_at'] == bid['created_at'] + data['validmins'] * 60) + assert bid["expire_at"] == bid["created_at"] + data["validmins"] * 60 - data = { - 'accept': True - } - rv = post_json_api(12700, 'bids/{}'.format(bid['bid_id']), data) - assert (rv['bid_state'] == 'Accepted') + data = {"accept": True} + rv = post_json_api(12700, "bids/{}".format(bid["bid_id"]), data) + assert rv["bid_state"] == "Accepted" waitForNumSwapping(self.delay_event, 12701, 1) - logger.info('Restarting node 1') + logger.info("Restarting node 1") c1 = self.processes[1] c1.terminate() c1.join() @@ -126,35 +126,35 @@ class Test(XmrTestBase): waitForServer(self.delay_event, 12701) rv = read_json_api(12701) - assert ('error' in rv) + assert "error" in rv - logger.info('Unlocking node 1') - rv = read_json_api(12701, 'unlock', {'password': node1_password}) - assert ('success' in rv) + logger.info("Unlocking node 1") + rv = read_json_api(12701, "unlock", {"password": node1_password}) + assert "success" in rv rv = read_json_api(12701) - assert (rv['num_swapping'] == 1) + assert rv["num_swapping"] == 1 - rv = read_json_api(12700, 'revokeoffer/{}'.format(offer_id)) - assert (rv['revoked_offer'] == offer_id) + rv = read_json_api(12700, "revokeoffer/{}".format(offer_id)) + assert rv["revoked_offer"] == offer_id - logger.info('Completing swap') + logger.info("Completing swap") for i in range(240): if self.delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") self.delay_event.wait(4) - rv = read_json_api(12700, 'bids/{}'.format(bid['bid_id'])) - if rv['bid_state'] == 'Completed': + rv = read_json_api(12700, "bids/{}".format(bid["bid_id"])) + if rv["bid_state"] == "Completed": break - assert (rv['bid_state'] == 'Completed') + assert rv["bid_state"] == "Completed" # Ensure offer was revoked summary = read_json_api(12700) - assert (summary['num_network_offers'] == 0) + assert summary["num_network_offers"] == 0 # Wait for bid to be removed from in-progress waitForNumBids(self.delay_event, 12700, 0) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/extended/test_firo.py b/tests/basicswap/extended/test_firo.py index a01eb71..b402d5a 100644 --- a/tests/basicswap/extended/test_firo.py +++ b/tests/basicswap/extended/test_firo.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2022-2023 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -49,10 +50,12 @@ from tests.basicswap.test_xmr import BaseTest, test_delay_event, callnoderpc logger = logging.getLogger() -FIRO_BINDIR = os.path.expanduser(os.getenv('FIRO_BINDIR', os.path.join(cfg.DEFAULT_TEST_BINDIR, 'firo'))) -FIROD = os.getenv('FIROD', 'firod' + cfg.bin_suffix) -FIRO_CLI = os.getenv('FIRO_CLI', 'firo-cli' + cfg.bin_suffix) -FIRO_TX = os.getenv('FIRO_TX', 'firo-tx' + cfg.bin_suffix) +FIRO_BINDIR = os.path.expanduser( + os.getenv("FIRO_BINDIR", os.path.join(cfg.DEFAULT_TEST_BINDIR, "firo")) +) +FIROD = os.getenv("FIROD", "firod" + cfg.bin_suffix) +FIRO_CLI = os.getenv("FIRO_CLI", "firo-cli" + cfg.bin_suffix) +FIRO_TX = os.getenv("FIRO_TX", "firo-tx" + cfg.bin_suffix) FIRO_BASE_PORT = 34832 FIRO_BASE_RPC_PORT = 35832 @@ -60,50 +63,64 @@ FIRO_BASE_ZMQ_PORT = 36832 def firoCli(cmd, node_id=0): - return callrpc_cli(FIRO_BINDIR, os.path.join(cfg.TEST_DATADIRS, 'firo_' + str(node_id)), 'regtest', cmd, FIRO_CLI) + return callrpc_cli( + FIRO_BINDIR, + os.path.join(cfg.TEST_DATADIRS, "firo_" + str(node_id)), + "regtest", + cmd, + FIRO_CLI, + ) -def prepareDataDir(datadir, node_id, conf_file, dir_prefix, base_p2p_port, base_rpc_port, num_nodes=3): +def prepareDataDir( + datadir, node_id, conf_file, dir_prefix, base_p2p_port, base_rpc_port, num_nodes=3 +): node_dir = os.path.join(datadir, dir_prefix + str(node_id)) if not os.path.exists(node_dir): os.makedirs(node_dir) cfg_file_path = os.path.join(node_dir, conf_file) if os.path.exists(cfg_file_path): return - with open(cfg_file_path, 'w+') as fp: - fp.write('regtest=1\n') - fp.write('port=' + str(base_p2p_port + node_id) + '\n') - fp.write('rpcport=' + str(base_rpc_port + node_id) + '\n') + with open(cfg_file_path, "w+") as fp: + fp.write("regtest=1\n") + fp.write("port=" + str(base_p2p_port + node_id) + "\n") + fp.write("rpcport=" + str(base_rpc_port + node_id) + "\n") salt = generate_salt(16) - fp.write('rpcauth={}:{}${}\n'.format('test' + str(node_id), salt, password_to_hmac(salt, 'test_pass' + str(node_id)))) + fp.write( + "rpcauth={}:{}${}\n".format( + "test" + str(node_id), + salt, + password_to_hmac(salt, "test_pass" + str(node_id)), + ) + ) - fp.write('daemon=0\n') - fp.write('dandelion=0\n') - fp.write('printtoconsole=0\n') - fp.write('server=1\n') - fp.write('discover=0\n') - fp.write('listenonion=0\n') - fp.write('bind=127.0.0.1\n') - fp.write('findpeers=0\n') - fp.write('debug=1\n') - fp.write('debugexclude=libevent\n') + fp.write("daemon=0\n") + fp.write("dandelion=0\n") + fp.write("printtoconsole=0\n") + fp.write("server=1\n") + fp.write("discover=0\n") + fp.write("listenonion=0\n") + fp.write("bind=127.0.0.1\n") + fp.write("findpeers=0\n") + fp.write("debug=1\n") + fp.write("debugexclude=libevent\n") - fp.write('fallbackfee=0.01\n') - fp.write('acceptnonstdtxn=0\n') + fp.write("fallbackfee=0.01\n") + fp.write("acceptnonstdtxn=0\n") - ''' + """ # qa/rpc-tests/segwit.py fp.write('prematurewitness=1\n') fp.write('walletprematurewitness=1\n') fp.write('blockversion=4\n') fp.write('promiscuousmempoolflags=517\n') - ''' + """ for i in range(0, num_nodes): if node_id == i: continue - fp.write('addnode=127.0.0.1:{}\n'.format(base_p2p_port + i)) + fp.write("addnode=127.0.0.1:{}\n".format(base_p2p_port + i)) return node_dir @@ -121,9 +138,9 @@ class Test(BaseTest): # Particl node mnemonics are test_xmr.py, node 2 is set randomly firo_seeds = [ - 'd90b7ed1be614e1c172653aee1f3b6230f43b7fa99cf07fa984a17966ad81de7', - '6c81d6d74ba33a0db9e41518c2b6789fbe938e98018a4597dac661cfc5f2dfc1', - 'c5de2be44834e7e47ad7dc8e35c6b77c79f17c6bb40d5509a00fc3dff384a865', + "d90b7ed1be614e1c172653aee1f3b6230f43b7fa99cf07fa984a17966ad81de7", + "6c81d6d74ba33a0db9e41518c2b6789fbe938e98018a4597dac661cfc5f2dfc1", + "c5de2be44834e7e47ad7dc8e35c6b77c79f17c6bb40d5509a00fc3dff384a865", ] @classmethod @@ -131,13 +148,33 @@ class Test(BaseTest): extra_opts = [] if not cls.restore_instance: seed_hex = cls.firo_seeds[i] - extra_opts.append(f'-hdseed={seed_hex}') - data_dir = prepareDataDir(cfg.TEST_DATADIRS, i, 'firo.conf', 'firo_', base_p2p_port=FIRO_BASE_PORT, base_rpc_port=FIRO_BASE_RPC_PORT) - if os.path.exists(os.path.join(FIRO_BINDIR, 'firo-wallet')): - callrpc_cli(FIRO_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat create', 'firo-wallet') + extra_opts.append(f"-hdseed={seed_hex}") + data_dir = prepareDataDir( + cfg.TEST_DATADIRS, + i, + "firo.conf", + "firo_", + base_p2p_port=FIRO_BASE_PORT, + base_rpc_port=FIRO_BASE_RPC_PORT, + ) + if os.path.exists(os.path.join(FIRO_BINDIR, "firo-wallet")): + callrpc_cli( + FIRO_BINDIR, + data_dir, + "regtest", + "-wallet=wallet.dat create", + "firo-wallet", + ) - cls.firo_daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, 'firo_' + str(i)), FIRO_BINDIR, FIROD, opts=extra_opts)) - logging.info('Started %s %d', FIROD, cls.firo_daemons[-1].handle.pid) + cls.firo_daemons.append( + startDaemon( + os.path.join(cfg.TEST_DATADIRS, "firo_" + str(i)), + FIRO_BINDIR, + FIROD, + opts=extra_opts, + ) + ) + logging.info("Started %s %d", FIROD, cls.firo_daemons[-1].handle.pid) waitForRPC(make_rpc_func(i, base_rpc_port=FIRO_BASE_RPC_PORT), test_delay_event) @@ -153,30 +190,59 @@ class Test(BaseTest): if cls.restore_instance: void_block_rewards_pubkey = cls.getRandomPubkey() - cls.firo_addr = cls.swap_clients[0].ci(Coins.FIRO).pubkey_to_address(void_block_rewards_pubkey) + cls.firo_addr = ( + cls.swap_clients[0] + .ci(Coins.FIRO) + .pubkey_to_address(void_block_rewards_pubkey) + ) else: num_blocks = 400 - cls.firo_addr = callnoderpc(0, 'getnewaddress', ['mining_addr'], base_rpc_port=FIRO_BASE_RPC_PORT) + cls.firo_addr = callnoderpc( + 0, "getnewaddress", ["mining_addr"], base_rpc_port=FIRO_BASE_RPC_PORT + ) # cls.firo_addr = callnoderpc(0, 'addwitnessaddress', [cls.firo_addr], base_rpc_port=FIRO_BASE_RPC_PORT) - logging.info('Mining %d Firo blocks to %s', num_blocks, cls.firo_addr) - callnoderpc(0, 'generatetoaddress', [num_blocks, cls.firo_addr], base_rpc_port=FIRO_BASE_RPC_PORT) + logging.info("Mining %d Firo blocks to %s", num_blocks, cls.firo_addr) + callnoderpc( + 0, + "generatetoaddress", + [num_blocks, cls.firo_addr], + base_rpc_port=FIRO_BASE_RPC_PORT, + ) - firo_addr1 = callnoderpc(1, 'getnewaddress', ['initial addr'], base_rpc_port=FIRO_BASE_RPC_PORT) + firo_addr1 = callnoderpc( + 1, "getnewaddress", ["initial addr"], base_rpc_port=FIRO_BASE_RPC_PORT + ) # firo_addr1 = callnoderpc(1, 'addwitnessaddress', [firo_addr1], base_rpc_port=FIRO_BASE_RPC_PORT) for i in range(5): - callnoderpc(0, 'sendtoaddress', [firo_addr1, 1000], base_rpc_port=FIRO_BASE_RPC_PORT) + callnoderpc( + 0, + "sendtoaddress", + [firo_addr1, 1000], + base_rpc_port=FIRO_BASE_RPC_PORT, + ) # Set future block rewards to nowhere (a random address), so wallet amounts stay constant void_block_rewards_pubkey = cls.getRandomPubkey() - cls.firo_addr = cls.swap_clients[0].ci(Coins.FIRO).pubkey_to_address(void_block_rewards_pubkey) - chain_height = callnoderpc(0, 'getblockcount', base_rpc_port=FIRO_BASE_RPC_PORT) + cls.firo_addr = ( + cls.swap_clients[0] + .ci(Coins.FIRO) + .pubkey_to_address(void_block_rewards_pubkey) + ) + chain_height = callnoderpc( + 0, "getblockcount", base_rpc_port=FIRO_BASE_RPC_PORT + ) num_blocks = 1352 - chain_height # Activate CTLV (bip65) - logging.info('Mining %d Firo blocks to %s', num_blocks, cls.firo_addr) - callnoderpc(0, 'generatetoaddress', [num_blocks, cls.firo_addr], base_rpc_port=FIRO_BASE_RPC_PORT) + logging.info("Mining %d Firo blocks to %s", num_blocks, cls.firo_addr) + callnoderpc( + 0, + "generatetoaddress", + [num_blocks, cls.firo_addr], + base_rpc_port=FIRO_BASE_RPC_PORT, + ) @classmethod def tearDownClass(cls): - logging.info('Finalising FIRO Test') + logging.info("Finalising FIRO Test") super(Test, cls).tearDownClass() stopDaemons(cls.firo_daemons) @@ -184,163 +250,223 @@ class Test(BaseTest): @classmethod def addCoinSettings(cls, settings, datadir, node_id): - settings['chainclients']['firo'] = { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': FIRO_BASE_RPC_PORT + node_id, - 'rpcuser': 'test' + str(node_id), - 'rpcpassword': 'test_pass' + str(node_id), - 'datadir': os.path.join(datadir, 'firo_' + str(node_id)), - 'bindir': FIRO_BINDIR, - 'use_csv': False, - 'use_segwit': False, + settings["chainclients"]["firo"] = { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": FIRO_BASE_RPC_PORT + node_id, + "rpcuser": "test" + str(node_id), + "rpcpassword": "test_pass" + str(node_id), + "datadir": os.path.join(datadir, "firo_" + str(node_id)), + "bindir": FIRO_BINDIR, + "use_csv": False, + "use_segwit": False, } @classmethod def coins_loop(cls): super(Test, cls).coins_loop() - callnoderpc(0, 'generatetoaddress', [1, cls.firo_addr], base_rpc_port=FIRO_BASE_RPC_PORT) + callnoderpc( + 0, "generatetoaddress", [1, cls.firo_addr], base_rpc_port=FIRO_BASE_RPC_PORT + ) def getBalance(self, js_wallets): - return float(js_wallets[self.test_coin_from.name]['balance']) + float(js_wallets[self.test_coin_from.name]['unconfirmed']) + return float(js_wallets[self.test_coin_from.name]["balance"]) + float( + js_wallets[self.test_coin_from.name]["unconfirmed"] + ) def getXmrBalance(self, js_wallets): - return float(js_wallets[Coins.XMR.name]['unconfirmed']) + float(js_wallets[Coins.XMR.name]['balance']) + return float(js_wallets[Coins.XMR.name]["unconfirmed"]) + float( + js_wallets[Coins.XMR.name]["balance"] + ) def callnoderpc(self, method, params=[], wallet=None, node_id=0): - return callnoderpc(node_id, method, params, wallet, base_rpc_port=FIRO_BASE_RPC_PORT) + return callnoderpc( + node_id, method, params, wallet, base_rpc_port=FIRO_BASE_RPC_PORT + ) def mineBlock(self, num_blocks: int = 1): - self.callnoderpc('generatetoaddress', [num_blocks, self.firo_addr]) + self.callnoderpc("generatetoaddress", [num_blocks, self.firo_addr]) def test_001_firo(self): - logging.info('---------- Test {} segwit'.format(self.test_coin_from.name)) + logging.info("---------- Test {} segwit".format(self.test_coin_from.name)) - ''' + """ Segwit is not currently enabled: https://github.com/firoorg/firo/blob/master/src/validation.cpp#L4425 Txns spending segwit utxos don't get mined. - ''' + """ return - swap_clients = self.swap_clients - - addr_plain = firoCli('getnewaddress \"segwit test\"') - addr_witness = firoCli(f'addwitnessaddress {addr_plain}') - addr_witness_info = firoCli(f'validateaddress {addr_witness}') - txid = firoCli(f'sendtoaddress {addr_witness} 1.0') + addr_plain = firoCli('getnewaddress "segwit test"') + addr_witness = firoCli(f"addwitnessaddress {addr_plain}") + addr_witness_info = firoCli(f"validateaddress {addr_witness}") + txid = firoCli(f"sendtoaddress {addr_witness} 1.0") assert len(txid) == 64 - self.callnoderpc('generatetoaddress', [1, self.firo_addr]) - ''' + self.callnoderpc("generatetoaddress", [1, self.firo_addr]) + """ TODO: Add back when segwit is active ro = self.callnoderpc('scantxoutset', ['start', ['addr({})'.format(addr_witness)]]) assert (len(ro['unspents']) == 1) assert (ro['unspents'][0]['txid'] == txid) - ''' + """ - tx_wallet = firoCli(f'gettransaction {txid}') - tx_hex = tx_wallet['hex'] - tx = firoCli(f'decoderawtransaction {tx_hex}') + tx_wallet = firoCli(f"gettransaction {txid}") + tx_hex = tx_wallet["hex"] + tx = firoCli(f"decoderawtransaction {tx_hex}") prevout_n = -1 - for txo in tx['vout']: - if addr_witness in txo['scriptPubKey']['addresses']: - prevout_n = txo['n'] + for txo in tx["vout"]: + if addr_witness in txo["scriptPubKey"]["addresses"]: + prevout_n = txo["n"] break assert prevout_n > -1 - tx_funded = firoCli(f'createrawtransaction [{{\\"txid\\":\\"{txid}\\",\\"vout\\":{prevout_n}}}] {{\\"{addr_plain}\\":0.99}}') - tx_signed = firoCli(f'signrawtransaction {tx_funded}')['hex'] + tx_funded = firoCli( + f'createrawtransaction [{{\\"txid\\":\\"{txid}\\",\\"vout\\":{prevout_n}}}] {{\\"{addr_plain}\\":0.99}}' + ) + tx_signed = firoCli(f"signrawtransaction {tx_funded}")["hex"] # Add scriptsig for txids to match decoded_tx = CTransaction() decoded_tx = FromHex(decoded_tx, tx_funded) - decoded_tx.vin[0].scriptSig = bytes.fromhex('16' + addr_witness_info['hex']) + decoded_tx.vin[0].scriptSig = bytes.fromhex("16" + addr_witness_info["hex"]) decoded_tx.rehash() txid_with_scriptsig = decoded_tx.hash - tx_funded_decoded = firoCli(f'decoderawtransaction {tx_funded}') - tx_signed_decoded = firoCli(f'decoderawtransaction {tx_signed}') - assert tx_funded_decoded['txid'] != tx_signed_decoded['txid'] - assert txid_with_scriptsig == tx_signed_decoded['txid'] + tx_funded_decoded = firoCli(f"decoderawtransaction {tx_funded}") + tx_signed_decoded = firoCli(f"decoderawtransaction {tx_signed}") + assert tx_funded_decoded["txid"] != tx_signed_decoded["txid"] + assert txid_with_scriptsig == tx_signed_decoded["txid"] def test_007_hdwallet(self): - logging.info('---------- Test {} hdwallet'.format(self.test_coin_from.name)) + logging.info("---------- Test {} hdwallet".format(self.test_coin_from.name)) swap_client = self.swap_clients[0] # Run initialiseWallet to set 'main_wallet_seedid_' swap_client.initialiseWallet(self.test_coin_from) ci = swap_client.ci(self.test_coin_from) - assert ('490ba1e2c3894d5534c467141ee3cdf77292c362' == ci.getWalletSeedID()) + assert "490ba1e2c3894d5534c467141ee3cdf77292c362" == ci.getWalletSeedID() assert swap_client.checkWalletSeed(self.test_coin_from) is True def test_008_gettxout(self): - logging.info('---------- Test {} gettxout'.format(self.test_coin_from.name)) + logging.info("---------- Test {} gettxout".format(self.test_coin_from.name)) swap_client = self.swap_clients[0] # First address sometimes has a balance already - addr_plain = self.callnoderpc('getnewaddress', ['gettxout test',]) + _ = self.callnoderpc( + "getnewaddress", + [ + "gettxout test", + ], + ) - addr_plain1 = self.callnoderpc('getnewaddress', ['gettxout test 1',]) + addr_plain = self.callnoderpc( + "getnewaddress", + [ + "gettxout test 1", + ], + ) - txid = self.callnoderpc('sendtoaddress', [addr_plain1, 1.0]) + txid = self.callnoderpc("sendtoaddress", [addr_plain, 1.0]) assert len(txid) == 64 self.mineBlock() - unspents = self.callnoderpc('listunspent', [0, 999999999, [addr_plain1,]]) - assert (len(unspents) == 1) + unspents = self.callnoderpc( + "listunspent", + [ + 0, + 999999999, + [ + addr_plain, + ], + ], + ) + assert len(unspents) == 1 utxo = unspents[0] - txout = self.callnoderpc('gettxout', [utxo['txid'], utxo['vout']]) - assert (addr_plain1 in txout['scriptPubKey']['addresses']) + txout = self.callnoderpc("gettxout", [utxo["txid"], utxo["vout"]]) + assert addr_plain in txout["scriptPubKey"]["addresses"] # Spend - addr_plain2 = self.callnoderpc('getnewaddress', ['gettxout test 2',]) - tx_funded = self.callnoderpc('createrawtransaction', [[{'txid': utxo['txid'], 'vout': utxo['vout']}], {addr_plain2: 0.99}]) - tx_signed = self.callnoderpc('signrawtransaction', [tx_funded,])['hex'] - self.callnoderpc('sendrawtransaction', [tx_signed,]) + addr_plain2 = self.callnoderpc( + "getnewaddress", + [ + "gettxout test 2", + ], + ) + tx_funded = self.callnoderpc( + "createrawtransaction", + [[{"txid": utxo["txid"], "vout": utxo["vout"]}], {addr_plain2: 0.99}], + ) + tx_signed = self.callnoderpc( + "signrawtransaction", + [ + tx_funded, + ], + )["hex"] + self.callnoderpc( + "sendrawtransaction", + [ + tx_signed, + ], + ) # utxo should be unavailable when spent in the mempool - txout = self.callnoderpc('gettxout', [utxo['txid'], utxo['vout']]) - assert (txout is None) + txout = self.callnoderpc("gettxout", [utxo["txid"], utxo["vout"]]) + assert txout is None self.mineBlock() ci = swap_client.ci(Coins.FIRO) require_amount: int = ci.make_int(1) - funds_proof = ci.getProofOfFunds(require_amount, 'test'.encode('utf-8')) + funds_proof = ci.getProofOfFunds(require_amount, "test".encode("utf-8")) - amount_proved = ci.verifyProofOfFunds(funds_proof[0], funds_proof[1], funds_proof[2], 'test'.encode('utf-8')) - assert (amount_proved >= require_amount) + amount_proved = ci.verifyProofOfFunds( + funds_proof[0], funds_proof[1], funds_proof[2], "test".encode("utf-8") + ) + assert amount_proved >= require_amount def test_08_wallet(self): - logging.info('---------- Test {} wallet'.format(self.test_coin_from.name)) + logging.info("---------- Test {} wallet".format(self.test_coin_from.name)) - logging.info('Test withdrawal') - addr = self.callnoderpc('getnewaddress', ['Withdrawal test', ]) - wallets = read_json_api(TEST_HTTP_PORT + 0, 'wallets') - assert (float(wallets[self.test_coin_from.name]['balance']) > 100) + logging.info("Test withdrawal") + addr = self.callnoderpc( + "getnewaddress", + [ + "Withdrawal test", + ], + ) + wallets = read_json_api(TEST_HTTP_PORT + 0, "wallets") + assert float(wallets[self.test_coin_from.name]["balance"]) > 100 post_json = { - 'value': 100, - 'address': addr, - 'subfee': False, + "value": 100, + "address": addr, + "subfee": False, } - json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/{}/withdraw'.format(self.test_coin_from.name.lower()), post_json) - assert (len(json_rv['txid']) == 64) + json_rv = read_json_api( + TEST_HTTP_PORT + 0, + "wallets/{}/withdraw".format(self.test_coin_from.name.lower()), + post_json, + ) + assert len(json_rv["txid"]) == 64 - logging.info('Test createutxo') + logging.info("Test createutxo") post_json = { - 'value': 10, + "value": 10, } - json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/{}/createutxo'.format(self.test_coin_from.name.lower()), post_json) - assert (len(json_rv['txid']) == 64) + json_rv = read_json_api( + TEST_HTTP_PORT + 0, + "wallets/{}/createutxo".format(self.test_coin_from.name.lower()), + post_json, + ) + assert len(json_rv["txid"]) == 64 def test_11_xmrswap_to(self): - logging.info('---------- Test xmr swap protocol to') + logging.info("---------- Test xmr swap protocol to") swap_clients = self.swap_clients coin_from = Coins.BTC @@ -351,7 +477,9 @@ class Test(BaseTest): swap_value = ci_from.make_int(random.uniform(0.2, 20.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) - offer_id = swap_clients[0].postOffer(coin_from, coin_to, swap_value, rate_swap, swap_value, swap_type) + offer_id = swap_clients[0].postOffer( + coin_from, coin_to, swap_value, rate_swap, swap_value, swap_type + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -360,13 +488,30 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) swap_clients[0].acceptBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=120) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=120) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=120, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=120, + ) def test_12_xmrswap_to_recover_b_lock_tx(self): coin_from = Coins.BTC coin_to = Coins.FIRO - logging.info('---------- Test {} to {} follower recovers coin b lock tx'.format(coin_from.name, coin_to.name)) + logging.info( + "---------- Test {} to {} follower recovers coin b lock tx".format( + coin_from.name, coin_to.name + ) + ) swap_clients = self.swap_clients ci_from = swap_clients[0].ci(coin_from) @@ -375,8 +520,15 @@ class Test(BaseTest): amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) offer_id = swap_clients[0].postOffer( - coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, - lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=32) + coin_from, + coin_to, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, + lock_value=32, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -387,11 +539,23 @@ class Test(BaseTest): swap_clients[1].setBidDebugInd(bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK) swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=180) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + wait_for=180, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + sent=True, + ) def test_13_adsswap_reverse(self): - logging.info('---------- Test ads swap protocol reverse') + logging.info("---------- Test ads swap protocol reverse") swap_clients = self.swap_clients coin_from = Coins.FIRO @@ -402,7 +566,9 @@ class Test(BaseTest): swap_value = ci_from.make_int(random.uniform(0.2, 20.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 10.0), r=1) - offer_id = swap_clients[0].postOffer(coin_from, coin_to, swap_value, rate_swap, swap_value, swap_type) + offer_id = swap_clients[0].postOffer( + coin_from, coin_to, swap_value, rate_swap, swap_value, swap_type + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -411,28 +577,44 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) swap_clients[0].acceptBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=120) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=120) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=120, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=120, + ) def test_101_full_swap(self): - logging.info('---------- Test {} to XMR'.format(self.test_coin_from.name)) + logging.info("---------- Test {} to XMR".format(self.test_coin_from.name)) if not self.test_xmr: - logging.warning('Skipping test') + logging.warning("Skipping test") return swap_clients = self.swap_clients - js_0 = read_json_api(1800, 'wallets') - node0_from_before = self.getBalance(js_0) - - js_1 = read_json_api(1801, 'wallets') + js_1 = read_json_api(1801, "wallets") node1_from_before = self.getBalance(js_1) - js_0_xmr = read_json_api(1800, 'wallets/xmr') - js_1_xmr = read_json_api(1801, 'wallets/xmr') + js_1_xmr = read_json_api(1801, "wallets/xmr") amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1) rate_swap = make_int(random.uniform(0.2, 20.0), scale=12, r=1) - offer_id = swap_clients[0].postOffer(self.test_coin_from, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP) + offer_id = swap_clients[0].postOffer( + self.test_coin_from, + Coins.XMR, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[0].getOffer(offer_id) @@ -440,29 +622,42 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=180, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + ) amount_from = float(format_amount(amt_swap, 8)) - js_1 = read_json_api(1801, 'wallets') + js_1 = read_json_api(1801, "wallets") node1_from_after = self.getBalance(js_1) - assert (node1_from_after > node1_from_before + (amount_from - 0.05)) + assert node1_from_after > node1_from_before + (amount_from - 0.05) - js_0 = read_json_api(1800, 'wallets') - node0_from_after = self.getBalance(js_0) # TODO: Discard block rewards + # js_0 = read_json_api(1800, 'wallets') + # node0_from_after = self.getBalance(js_0) # assert (node0_from_after < node0_from_before - amount_from) - js_0_xmr_after = read_json_api(1800, 'wallets/xmr') - js_1_xmr_after = read_json_api(1801, 'wallets/xmr') + js_1_xmr_after = read_json_api(1801, "wallets/xmr") scale_from = 8 - amount_to = int((amt_swap * rate_swap) // (10 ** scale_from)) + amount_to = int((amt_swap * rate_swap) // (10**scale_from)) amount_to_float = float(format_amount(amount_to, 12)) - node1_xmr_after = float(js_1_xmr_after['unconfirmed']) + float(js_1_xmr_after['balance']) - node1_xmr_before = float(js_1_xmr['unconfirmed']) + float(js_1_xmr['balance']) - assert (node1_xmr_after > node1_xmr_before + (amount_to_float - 0.02)) + node1_xmr_after = float(js_1_xmr_after["unconfirmed"]) + float( + js_1_xmr_after["balance"] + ) + node1_xmr_before = float(js_1_xmr["unconfirmed"]) + float(js_1_xmr["balance"]) + assert node1_xmr_after > node1_xmr_before + (amount_to_float - 0.02) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/extended/test_http_ui.py b/tests/basicswap/extended/test_http_ui.py deleted file mode 100644 index 6afb0eb..0000000 --- a/tests/basicswap/extended/test_http_ui.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -# https://chromedriver.chromium.org/downloads -# 7z x chromedriver_linux64.zip -# sudo mv chromedriver /opt/chromedriver88 - -# Run test_xmr_persistent.py -# python tests/basicswap/extended/test_http_ui.py - -import time -import logging -from urllib.parse import urljoin - -from selenium import webdriver -from selenium.webdriver.support.ui import Select, WebDriverWait - -logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') - - -def run_test(): - base_url = 'http://localhost:12701' - driver = webdriver.Chrome('/opt/chromedriver88') - - driver.get(base_url) - link = driver.find_element_by_xpath('//a[@href="/offers"]') - num_offers_start = int(link.text.split(':')[1].strip()) - logging.info('Offers: %d', num_offers_start) - - logging.info('Creating offer') - driver.get(urljoin(base_url, 'newoffer')) - select_coin_from = Select(driver.find_element_by_name('coin_from')) - select_coin_from.select_by_visible_text('Particl') - - select_coin_to = Select(driver.find_element_by_name('coin_to')) - select_coin_to.select_by_visible_text('Monero') - - from_value = driver.find_element_by_name('amt_from') - from_value.send_keys('1') - to_value = driver.find_element_by_name('amt_to') - to_value.send_keys('2') - - submit_button = driver.find_element_by_name('continue') - submit_button.click() - time.sleep(0.1) - - submit_button = driver.find_element_by_name('check_offer') - submit_button.click() - time.sleep(0.1) - - submit_button = driver.find_element_by_name('submit_offer') - submit_button.click() - time.sleep(0.1) - - link = WebDriverWait(driver, 5).until(lambda d: d.find_element_by_xpath("//a[contains(@href, '/offer')]")) - offer_id = link.text.rsplit(' ', 1)[1] - logging.info('Offer ID: %s', offer_id) - - driver.get(base_url) - link = driver.find_element_by_xpath('//a[@href="/offers"]') - num_offers_end = int(link.text.split(':')[1].strip()) - assert num_offers_end == num_offers_start + 1 - - driver.quit() - - -if __name__ == '__main__': - run_test() diff --git a/tests/basicswap/extended/test_nav.py b/tests/basicswap/extended/test_nav.py index 7364f94..7027f6a 100644 --- a/tests/basicswap/extended/test_nav.py +++ b/tests/basicswap/extended/test_nav.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2023 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -55,7 +56,7 @@ from basicswap.interface.contrib.nav_test_framework.mininode import ( from basicswap.interface.contrib.nav_test_framework.script import ( CScript, OP_EQUAL, - OP_CHECKSEQUENCEVERIFY + OP_CHECKSEQUENCEVERIFY, ) from basicswap.bin.run import startDaemon @@ -67,60 +68,70 @@ from tests.basicswap.test_btc_xmr import TestFunctions logger = logging.getLogger() -NAV_BINDIR = os.path.expanduser(os.getenv('NAV_BINDIR', os.path.join(cfg.DEFAULT_TEST_BINDIR, 'navcoin'))) -NAVD = os.getenv('NAVD', 'navcoind' + cfg.bin_suffix) -NAV_CLI = os.getenv('NAV_CLI', 'navcoin-cli' + cfg.bin_suffix) -NAV_TX = os.getenv('NAV_TX', 'navcoin-tx' + cfg.bin_suffix) +NAV_BINDIR = os.path.expanduser( + os.getenv("NAV_BINDIR", os.path.join(cfg.DEFAULT_TEST_BINDIR, "navcoin")) +) +NAVD = os.getenv("NAVD", "navcoind" + cfg.bin_suffix) +NAV_CLI = os.getenv("NAV_CLI", "navcoin-cli" + cfg.bin_suffix) +NAV_TX = os.getenv("NAV_TX", "navcoin-tx" + cfg.bin_suffix) NAV_BASE_PORT = 44832 NAV_BASE_RPC_PORT = 45832 NAV_BASE_ZMQ_PORT = 46832 -def prepareDataDir(datadir, node_id, conf_file, dir_prefix, base_p2p_port, base_rpc_port, num_nodes=3): +def prepareDataDir( + datadir, node_id, conf_file, dir_prefix, base_p2p_port, base_rpc_port, num_nodes=3 +): node_dir = os.path.join(datadir, dir_prefix + str(node_id)) if not os.path.exists(node_dir): os.makedirs(node_dir) cfg_file_path = os.path.join(node_dir, conf_file) if os.path.exists(cfg_file_path): return - with open(cfg_file_path, 'w+') as fp: - fp.write('devnet=1\n') # regtest=1 ? - fp.write('port=' + str(base_p2p_port + node_id) + '\n') - fp.write('rpcport=' + str(base_rpc_port + node_id) + '\n') + with open(cfg_file_path, "w+") as fp: + fp.write("devnet=1\n") # regtest=1 ? + fp.write("port=" + str(base_p2p_port + node_id) + "\n") + fp.write("rpcport=" + str(base_rpc_port + node_id) + "\n") salt = generate_salt(16) - fp.write('rpcauth={}:{}${}\n'.format('test' + str(node_id), salt, password_to_hmac(salt, 'test_pass' + str(node_id)))) + fp.write( + "rpcauth={}:{}${}\n".format( + "test" + str(node_id), + salt, + password_to_hmac(salt, "test_pass" + str(node_id)), + ) + ) - fp.write('daemon=0\n') - fp.write('printtoconsole=0\n') - fp.write('server=1\n') - fp.write('discover=0\n') - fp.write('listenonion=0\n') - fp.write('bind=127.0.0.1\n') - fp.write('findpeers=0\n') - fp.write('debug=1\n') - fp.write('debugexclude=libevent\n') + fp.write("daemon=0\n") + fp.write("printtoconsole=0\n") + fp.write("server=1\n") + fp.write("discover=0\n") + fp.write("listenonion=0\n") + fp.write("bind=127.0.0.1\n") + fp.write("findpeers=0\n") + fp.write("debug=1\n") + fp.write("debugexclude=libevent\n") - fp.write('fallbackfee=0.01\n') - fp.write('acceptnonstdtxn=0\n') + fp.write("fallbackfee=0.01\n") + fp.write("acceptnonstdtxn=0\n") # test/rpc-tests/segwit.py - fp.write('prematurewitness=1\n') - fp.write('walletprematurewitness=1\n') - fp.write('blockversion=4\n') - fp.write('promiscuousmempoolflags=517\n') + fp.write("prematurewitness=1\n") + fp.write("walletprematurewitness=1\n") + fp.write("blockversion=4\n") + fp.write("promiscuousmempoolflags=517\n") - fp.write('listenonion=0\n') - fp.write('dandelion=0\n') - fp.write('ntpminmeasures=-1\n') - fp.write('torserver=0\n') - fp.write('suppressblsctwarning=1\n') + fp.write("listenonion=0\n") + fp.write("dandelion=0\n") + fp.write("ntpminmeasures=-1\n") + fp.write("torserver=0\n") + fp.write("suppressblsctwarning=1\n") for i in range(0, num_nodes): if node_id == i: continue - fp.write('addnode=127.0.0.1:{}\n'.format(base_p2p_port + i)) + fp.write("addnode=127.0.0.1:{}\n".format(base_p2p_port + i)) return node_dir @@ -141,9 +152,9 @@ class Test(TestFunctions): # Particl node mnemonics are test_xmr.py, node 2 is set randomly # Get the expected seeds from BasicSwap::initialiseWallet nav_seeds = [ - '516b471da2a67bcfd42a1da7f7ae8f9a1b02c34f6a2d6a943ceec5dca68e7fa1', - 'a8c0911fba070d5cc2784703afeb0f7c3b9b524b8a53466c04e01933d9fede78', - '7b3b533ac3a27114ae17c8cca0d2cd9f736e7519ae52b8ec8f1f452e8223d082', + "516b471da2a67bcfd42a1da7f7ae8f9a1b02c34f6a2d6a943ceec5dca68e7fa1", + "a8c0911fba070d5cc2784703afeb0f7c3b9b524b8a53466c04e01933d9fede78", + "7b3b533ac3a27114ae17c8cca0d2cd9f736e7519ae52b8ec8f1f452e8223d082", ] @classmethod @@ -151,14 +162,32 @@ class Test(TestFunctions): extra_opts = [] if not cls.restore_instance: seed_hex = cls.nav_seeds[i] - mnemonic = Mnemonic('english').to_mnemonic(bytes.fromhex(seed_hex)) - extra_opts.append(f'-importmnemonic={mnemonic}') - data_dir = prepareDataDir(cfg.TEST_DATADIRS, i, 'navcoin.conf', 'nav_', base_p2p_port=NAV_BASE_PORT, base_rpc_port=NAV_BASE_RPC_PORT) + mnemonic = Mnemonic("english").to_mnemonic(bytes.fromhex(seed_hex)) + extra_opts.append(f"-importmnemonic={mnemonic}") + prepareDataDir( + cfg.TEST_DATADIRS, + i, + "navcoin.conf", + "nav_", + base_p2p_port=NAV_BASE_PORT, + base_rpc_port=NAV_BASE_RPC_PORT, + ) - cls.nav_daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, 'nav_' + str(i)), NAV_BINDIR, NAVD, opts=extra_opts)) - logging.info('Started %s %d', NAVD, cls.nav_daemons[-1].handle.pid) + cls.nav_daemons.append( + startDaemon( + os.path.join(cfg.TEST_DATADIRS, "nav_" + str(i)), + NAV_BINDIR, + NAVD, + opts=extra_opts, + ) + ) + logging.info("Started %s %d", NAVD, cls.nav_daemons[-1].handle.pid) - waitForRPC(make_rpc_func(i, base_rpc_port=NAV_BASE_RPC_PORT), test_delay_event, max_tries=12) + waitForRPC( + make_rpc_func(i, base_rpc_port=NAV_BASE_RPC_PORT), + test_delay_event, + max_tries=12, + ) @classmethod def addPIDInfo(cls, sc, i): @@ -166,51 +195,84 @@ class Test(TestFunctions): @classmethod def sync_blocks(cls, wait_for: int = 20, num_nodes: int = 3) -> None: - logging.info('Syncing blocks') + logging.info("Syncing blocks") for i in range(wait_for): if test_delay_event.is_set(): - raise ValueError('Test stopped.') - block_hash0 = callnoderpc(0, 'getbestblockhash', base_rpc_port=NAV_BASE_RPC_PORT) + raise ValueError("Test stopped.") + block_hash0 = callnoderpc( + 0, "getbestblockhash", base_rpc_port=NAV_BASE_RPC_PORT + ) matches: int = 0 for i in range(1, num_nodes): - block_hash = callnoderpc(i, 'getbestblockhash', base_rpc_port=NAV_BASE_RPC_PORT) + block_hash = callnoderpc( + i, "getbestblockhash", base_rpc_port=NAV_BASE_RPC_PORT + ) if block_hash == block_hash0: matches += 1 if matches == num_nodes - 1: return test_delay_event.wait(1) - raise ValueError('sync_blocks timed out.') + raise ValueError("sync_blocks timed out.") @classmethod def prepareExtraCoins(cls): if cls.restore_instance: void_block_rewards_pubkey = cls.getRandomPubkey() - cls.nav_addr = cls.swap_clients[0].ci(Coins.NAV).pubkey_to_address(void_block_rewards_pubkey) + cls.nav_addr = ( + cls.swap_clients[0] + .ci(Coins.NAV) + .pubkey_to_address(void_block_rewards_pubkey) + ) else: num_blocks = 400 - cls.nav_addr = callnoderpc(0, 'getnewaddress', ['mining_addr'], base_rpc_port=NAV_BASE_RPC_PORT) + cls.nav_addr = callnoderpc( + 0, "getnewaddress", ["mining_addr"], base_rpc_port=NAV_BASE_RPC_PORT + ) # cls.nav_addr = addwitnessaddress doesn't work with generatetoaddress - logging.info('Mining %d NAV blocks to %s', num_blocks, cls.nav_addr) - callnoderpc(0, 'generatetoaddress', [num_blocks, cls.nav_addr], base_rpc_port=NAV_BASE_RPC_PORT) + logging.info("Mining %d NAV blocks to %s", num_blocks, cls.nav_addr) + callnoderpc( + 0, + "generatetoaddress", + [num_blocks, cls.nav_addr], + base_rpc_port=NAV_BASE_RPC_PORT, + ) - nav_addr1 = callnoderpc(1, 'getnewaddress', ['initial addr'], base_rpc_port=NAV_BASE_RPC_PORT) - nav_addr1 = callnoderpc(1, 'addwitnessaddress', [nav_addr1], base_rpc_port=NAV_BASE_RPC_PORT) + nav_addr1 = callnoderpc( + 1, "getnewaddress", ["initial addr"], base_rpc_port=NAV_BASE_RPC_PORT + ) + nav_addr1 = callnoderpc( + 1, "addwitnessaddress", [nav_addr1], base_rpc_port=NAV_BASE_RPC_PORT + ) for i in range(5): - callnoderpc(0, 'sendtoaddress', [nav_addr1, 1000], base_rpc_port=NAV_BASE_RPC_PORT) + callnoderpc( + 0, + "sendtoaddress", + [nav_addr1, 1000], + base_rpc_port=NAV_BASE_RPC_PORT, + ) # Set future block rewards to nowhere (a random address), so wallet amounts stay constant void_block_rewards_pubkey = cls.getRandomPubkey() - cls.nav_addr = cls.swap_clients[0].ci(Coins.NAV).pubkey_to_address(void_block_rewards_pubkey) + cls.nav_addr = ( + cls.swap_clients[0] + .ci(Coins.NAV) + .pubkey_to_address(void_block_rewards_pubkey) + ) num_blocks = 100 - logging.info('Mining %d NAV blocks to %s', num_blocks, cls.nav_addr) - callnoderpc(0, 'generatetoaddress', [num_blocks, cls.nav_addr], base_rpc_port=NAV_BASE_RPC_PORT) + logging.info("Mining %d NAV blocks to %s", num_blocks, cls.nav_addr) + callnoderpc( + 0, + "generatetoaddress", + [num_blocks, cls.nav_addr], + base_rpc_port=NAV_BASE_RPC_PORT, + ) cls.sync_blocks() @classmethod def tearDownClass(cls): - logging.info('Finalising NAV Test') + logging.info("Finalising NAV Test") super(Test, cls).tearDownClass() stopDaemons(cls.nav_daemons) @@ -218,188 +280,319 @@ class Test(TestFunctions): @classmethod def addCoinSettings(cls, settings, datadir, node_id): - settings['chainclients']['navcoin'] = { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': NAV_BASE_RPC_PORT + node_id, - 'rpcuser': 'test' + str(node_id), - 'rpcpassword': 'test_pass' + str(node_id), - 'datadir': os.path.join(datadir, 'nav_' + str(node_id)), - 'bindir': NAV_BINDIR, - 'use_csv': True, - 'use_segwit': True, - 'blocks_confirmed': 1, + settings["chainclients"]["navcoin"] = { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": NAV_BASE_RPC_PORT + node_id, + "rpcuser": "test" + str(node_id), + "rpcpassword": "test_pass" + str(node_id), + "datadir": os.path.join(datadir, "nav_" + str(node_id)), + "bindir": NAV_BINDIR, + "use_csv": True, + "use_segwit": True, + "blocks_confirmed": 1, } @classmethod def coins_loop(cls): super(Test, cls).coins_loop() - chain_height: int = callnoderpc(0, 'getblockcount', [], base_rpc_port=NAV_BASE_RPC_PORT) - staking_info = callnoderpc(0, 'getstakinginfo', [], base_rpc_port=NAV_BASE_RPC_PORT) - print('Staking loop: NAV node 0 chain_height {}, staking {}, currentblocktx {}'.format(chain_height, staking_info['staking'], staking_info['currentblocktx'])) + chain_height: int = callnoderpc( + 0, "getblockcount", [], base_rpc_port=NAV_BASE_RPC_PORT + ) + staking_info = callnoderpc( + 0, "getstakinginfo", [], base_rpc_port=NAV_BASE_RPC_PORT + ) + print( + "Staking loop: NAV node 0 chain_height {}, staking {}, currentblocktx {}".format( + chain_height, staking_info["staking"], staking_info["currentblocktx"] + ) + ) def getXmrBalance(self, js_wallets): - return float(js_wallets[Coins.XMR.name]['unconfirmed']) + float(js_wallets[Coins.XMR.name]['balance']) + return float(js_wallets[Coins.XMR.name]["unconfirmed"]) + float( + js_wallets[Coins.XMR.name]["balance"] + ) def callnoderpc(self, method, params=[], wallet=None, node_id=0): - return callnoderpc(node_id, method, params, wallet, base_rpc_port=NAV_BASE_RPC_PORT) + return callnoderpc( + node_id, method, params, wallet, base_rpc_port=NAV_BASE_RPC_PORT + ) def mineBlock(self, num_blocks: int = 1): - self.callnoderpc('generatetoaddress', [num_blocks, self.nav_addr]) + self.callnoderpc("generatetoaddress", [num_blocks, self.nav_addr]) def stake_block(self, num_blocks: int = 1, node_id: int = 0, wait_for: int = 360): - print(f'Trying to stake {num_blocks} blocks') - blockcount = self.callnoderpc('getblockcount', node_id=node_id) + print(f"Trying to stake {num_blocks} blocks") + blockcount = self.callnoderpc("getblockcount", node_id=node_id) try: # Turn staking on - self.callnoderpc('staking', [True,], node_id=node_id) + self.callnoderpc( + "staking", + [ + True, + ], + node_id=node_id, + ) # Wait for a new block to be mined for i in range(wait_for): if test_delay_event.is_set(): - raise ValueError('Test stopped.') - if self.callnoderpc('getblockcount', node_id=node_id) >= blockcount + num_blocks: + raise ValueError("Test stopped.") + if ( + self.callnoderpc("getblockcount", node_id=node_id) + >= blockcount + num_blocks + ): return test_delay_event.wait(1) - raise ValueError('stake_block timed out.') + raise ValueError("stake_block timed out.") finally: # Turn staking off - self.callnoderpc('staking', [False,], node_id=node_id) + self.callnoderpc( + "staking", + [ + False, + ], + node_id=node_id, + ) def test_001_segwit(self): - logging.info('---------- Test {} segwit'.format(self.test_coin_from.name)) + logging.info("---------- Test {} segwit".format(self.test_coin_from.name)) swap_clients = self.swap_clients ci = swap_clients[0].ci(self.test_coin_from) - assert (ci.using_segwit() is True) + assert ci.using_segwit() is True - addr_plain = self.callnoderpc('getnewaddress', ['segwit test', ]) - addr_witness = self.callnoderpc('addwitnessaddress', [addr_plain, ]) - addr_witness_info = self.callnoderpc('validateaddress', [addr_witness, ]) - txid = self.callnoderpc('sendtoaddress', [addr_witness, 1.0]) + addr_plain = self.callnoderpc( + "getnewaddress", + [ + "segwit test", + ], + ) + addr_witness = self.callnoderpc( + "addwitnessaddress", + [ + addr_plain, + ], + ) + addr_witness_info = self.callnoderpc( + "validateaddress", + [ + addr_witness, + ], + ) + txid = self.callnoderpc("sendtoaddress", [addr_witness, 1.0]) assert len(txid) == 64 self.mineBlock() - tx_wallet = self.callnoderpc('gettransaction', [txid, ]) - tx_hex = tx_wallet['hex'] - tx = self.callnoderpc('decoderawtransaction', [tx_hex, ]) + tx_wallet = self.callnoderpc( + "gettransaction", + [ + txid, + ], + ) + tx_hex = tx_wallet["hex"] + tx = self.callnoderpc( + "decoderawtransaction", + [ + tx_hex, + ], + ) prevout_n = -1 - for txo in tx['vout']: - if addr_witness in txo['scriptPubKey']['addresses']: - prevout_n = txo['n'] + for txo in tx["vout"]: + if addr_witness in txo["scriptPubKey"]["addresses"]: + prevout_n = txo["n"] break assert prevout_n > -1 - inputs = [{'txid': txid, 'vout': prevout_n}, ] + inputs = [ + {"txid": txid, "vout": prevout_n}, + ] outputs = {addr_plain: 0.99} - tx_funded = self.callnoderpc('createrawtransaction', [inputs, outputs]) - tx_signed = self.callnoderpc('signrawtransaction', [tx_funded, ])['hex'] + tx_funded = self.callnoderpc("createrawtransaction", [inputs, outputs]) + tx_signed = self.callnoderpc( + "signrawtransaction", + [ + tx_funded, + ], + )["hex"] # Add scriptsig for txids to match decoded_tx = CTransaction() decoded_tx = FromHex(decoded_tx, tx_funded) - tx_funded_with_scriptsig = ToHex(decoded_tx) - decoded_tx.vin[0].scriptSig = bytes.fromhex('16' + addr_witness_info['hex']) + decoded_tx.vin[0].scriptSig = bytes.fromhex("16" + addr_witness_info["hex"]) decoded_tx.rehash() txid_with_scriptsig = decoded_tx.hash - tx_funded_decoded = self.callnoderpc('decoderawtransaction', [tx_funded, ]) - tx_signed_decoded = self.callnoderpc('decoderawtransaction', [tx_signed, ]) - assert tx_funded_decoded['txid'] != tx_signed_decoded['txid'] - assert txid_with_scriptsig == tx_signed_decoded['txid'] + tx_funded_decoded = self.callnoderpc( + "decoderawtransaction", + [ + tx_funded, + ], + ) + tx_signed_decoded = self.callnoderpc( + "decoderawtransaction", + [ + tx_signed, + ], + ) + assert tx_funded_decoded["txid"] != tx_signed_decoded["txid"] + assert txid_with_scriptsig == tx_signed_decoded["txid"] ci = swap_clients[0].ci(self.test_coin_from) - assert tx_signed_decoded['version'] == ci.txVersion() + assert tx_signed_decoded["version"] == ci.txVersion() # Ensure txn can get into the chain - txid = self.callnoderpc('sendrawtransaction', [tx_signed, ]) + txid = self.callnoderpc( + "sendrawtransaction", + [ + tx_signed, + ], + ) # Block must be staked, witness merkle root mismatch if mined self.stake_block(1) - tx_wallet = self.callnoderpc('gettransaction', [txid, ]) - assert (len(tx_wallet['blockhash']) == 64) + tx_wallet = self.callnoderpc( + "gettransaction", + [ + txid, + ], + ) + assert len(tx_wallet["blockhash"]) == 64 def test_002_scantxoutset(self): - logging.info('---------- Test {} scantxoutset'.format(self.test_coin_from.name)) - logging.warning('Skipping test') + logging.info("---------- Test {} scantxoutset".format(self.test_coin_from.name)) + logging.warning("Skipping test") return # TODO - addr_plain = self.callnoderpc('getnewaddress', ['scantxoutset test', ]) - addr_witness = self.callnoderpc('addwitnessaddress', [addr_plain, ]) - addr_witness_info = self.callnoderpc('validateaddress', [addr_witness, ]) - txid = self.callnoderpc('sendtoaddress', [addr_witness, 1.0]) + addr_plain = self.callnoderpc( + "getnewaddress", + [ + "scantxoutset test", + ], + ) + addr_witness = self.callnoderpc( + "addwitnessaddress", + [ + addr_plain, + ], + ) + txid = self.callnoderpc("sendtoaddress", [addr_witness, 1.0]) assert len(txid) == 64 self.mineBlock() - ro = self.callnoderpc('scantxoutset', ['start', ['addr({})'.format(addr_witness)]]) - assert (len(ro['unspents']) == 1) - assert (ro['unspents'][0]['txid'] == txid) + ro = self.callnoderpc( + "scantxoutset", ["start", ["addr({})".format(addr_witness)]] + ) + assert len(ro["unspents"]) == 1 + assert ro["unspents"][0]["txid"] == txid def test_003_signature_hash(self): - logging.info('---------- Test {} signature_hash'.format(self.test_coin_from.name)) + logging.info( + "---------- Test {} signature_hash".format(self.test_coin_from.name) + ) # Test that signing a transaction manually produces the same result when signed with the wallet swap_clients = self.swap_clients - addr_plain = self.callnoderpc('getnewaddress', ['address test',]) - addr_witness = self.callnoderpc('addwitnessaddress', [addr_plain,]) - validate_plain = self.callnoderpc('validateaddress', [addr_plain]) - validate_witness = self.callnoderpc('validateaddress', [addr_witness]) - assert (validate_plain['ismine'] is True) - assert (validate_witness['script'] == 'witness_v0_keyhash') - assert (validate_witness['ismine'] is True) + addr_plain = self.callnoderpc( + "getnewaddress", + [ + "address test", + ], + ) + addr_witness = self.callnoderpc( + "addwitnessaddress", + [ + addr_plain, + ], + ) + validate_plain = self.callnoderpc("validateaddress", [addr_plain]) + validate_witness = self.callnoderpc("validateaddress", [addr_witness]) + assert validate_plain["ismine"] is True + assert validate_witness["script"] == "witness_v0_keyhash" + assert validate_witness["ismine"] is True ci = swap_clients[0].ci(self.test_coin_from) pkh = ci.decodeAddress(addr_plain) script_out = ci.getScriptForPubkeyHash(pkh) addr_out = ci.encodeSegwitAddressScript(script_out) - assert (addr_out == addr_witness) + assert addr_out == addr_witness # Test address from pkh test_addr = ci.encodeSegwitAddress(pkh) - assert (addr_out == test_addr) + assert addr_out == test_addr - txid = self.callnoderpc('sendtoaddress', [addr_out, 1.0]) + txid = self.callnoderpc("sendtoaddress", [addr_out, 1.0]) assert len(txid) == 64 self.mineBlock() - tx_wallet = self.callnoderpc('gettransaction', [txid, ]) - tx_hex = tx_wallet['hex'] - tx = self.callnoderpc('decoderawtransaction', [tx_hex, ]) + tx_wallet = self.callnoderpc( + "gettransaction", + [ + txid, + ], + ) + tx_hex = tx_wallet["hex"] + tx = self.callnoderpc( + "decoderawtransaction", + [ + tx_hex, + ], + ) prevout_n = -1 - for txo in tx['vout']: - if addr_witness in txo['scriptPubKey']['addresses']: - prevout_n = txo['n'] + for txo in tx["vout"]: + if addr_witness in txo["scriptPubKey"]["addresses"]: + prevout_n = txo["n"] break assert prevout_n > -1 - inputs = [{'txid': txid, 'vout': prevout_n}, ] + inputs = [ + {"txid": txid, "vout": prevout_n}, + ] outputs = {addr_witness: 0.99} - tx_wallet_funded = self.callnoderpc('createrawtransaction', [inputs, outputs]) - tx_wallet_signed = self.callnoderpc('signrawtransaction', [tx_wallet_funded, ])['hex'] - tx_wallet_decoded = self.callnoderpc('decoderawtransaction', [tx_wallet_signed, ]) + tx_wallet_funded = self.callnoderpc("createrawtransaction", [inputs, outputs]) + tx_wallet_signed = self.callnoderpc( + "signrawtransaction", + [ + tx_wallet_funded, + ], + )["hex"] + tx_wallet_decoded = self.callnoderpc( + "decoderawtransaction", + [ + tx_wallet_signed, + ], + ) script_in = ci.getInputScriptForPubkeyHash(pkh) # TODO: Are there more restrictions on tx.nTime? # - tx.nTime can't be greater than the blocktime tx_spend = CTransaction() tx_spend.nVersion = ci.txVersion() - tx_spend.nTime = tx_wallet_decoded['time'] - tx_spend.vin.append(CTxIn(COutPoint(int(txid, 16), prevout_n), - scriptSig=script_in, - nSequence=tx_wallet_decoded['vin'][0]['sequence'])) + tx_spend.nTime = tx_wallet_decoded["time"] + tx_spend.vin.append( + CTxIn( + COutPoint(int(txid, 16), prevout_n), + scriptSig=script_in, + nSequence=tx_wallet_decoded["vin"][0]["sequence"], + ) + ) tx_spend.vout.append(ci.txoType()(ci.make_int(0.99), script_out)) tx_spend_bytes = tx_spend.serialize_with_witness() - tx_spend_hex = tx_spend_bytes.hex() script = ci.getScriptForP2PKH(pkh) - key_wif = self.callnoderpc('dumpprivkey', [addr_plain, ]) + key_wif = self.callnoderpc( + "dumpprivkey", + [ + addr_plain, + ], + ) key = decodeWif(key_wif) sig = ci.signTx(key, tx_spend_bytes, 0, script, ci.make_int(1.0)) @@ -409,122 +602,190 @@ class Test(TestFunctions): ci.getPubkey(key), ] tx_spend_signed = ci.setTxSignature(tx_spend_bytes, stack) - assert (tx_spend_signed.hex() == tx_wallet_signed) + assert tx_spend_signed.hex() == tx_wallet_signed def test_004_csv(self): - logging.info('---------- Test {} csv'.format(self.test_coin_from.name)) + logging.info("---------- Test {} csv".format(self.test_coin_from.name)) swap_clients = self.swap_clients ci = swap_clients[0].ci(self.test_coin_from) - script = CScript([3, OP_CHECKSEQUENCEVERIFY, ]) + script = CScript( + [ + 3, + OP_CHECKSEQUENCEVERIFY, + ] + ) script_dest = ci.getScriptDest(script) tx = CTransaction() tx.nVersion = ci.txVersion() tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest)) tx_hex = ToHex(tx) - tx_funded = self.callnoderpc('fundrawtransaction', [tx_hex]) - utxo_pos: int = 0 if tx_funded['changepos'] == 1 else 1 - tx_signed = self.callnoderpc('signrawtransaction', [tx_funded['hex'], ])['hex'] + tx_funded = self.callnoderpc("fundrawtransaction", [tx_hex]) + utxo_pos: int = 0 if tx_funded["changepos"] == 1 else 1 + tx_signed = self.callnoderpc( + "signrawtransaction", + [ + tx_funded["hex"], + ], + )["hex"] self.sync_blocks() - txid = self.callnoderpc('sendrawtransaction', [tx_signed, ]) + txid = self.callnoderpc( + "sendrawtransaction", + [ + tx_signed, + ], + ) - self.callnoderpc('getnewaddress', ['used?',]) # First generated address has a positive balance - addr_out = self.callnoderpc('getnewaddress', ['csv test',]) - addr_witness = self.callnoderpc('addwitnessaddress', [addr_out,]) + self.callnoderpc( + "getnewaddress", + [ + "used?", + ], + ) # First generated address has a positive balance + addr_out = self.callnoderpc( + "getnewaddress", + [ + "csv test", + ], + ) + addr_witness = self.callnoderpc( + "addwitnessaddress", + [ + addr_out, + ], + ) # Test switching address from p2pkh to p2sh-p2wsh pkh = ci.decodeAddress(addr_out) script_out = ci.getScriptForPubkeyHash(pkh) # Convert to p2sh-p2wsh addr_out = ci.encodeSegwitAddressScript(script_out) - assert (addr_out == addr_witness) + assert addr_out == addr_witness p2wsh = ci.getP2SHP2WSHDest(script) - assert (p2wsh == script_dest) + assert p2wsh == script_dest addr_out_test = ci.encodeScriptDest(p2wsh) - tx_decoded = self.callnoderpc('decoderawtransaction', [tx_signed, ]) - assert (addr_out_test in tx_decoded['vout'][utxo_pos]['scriptPubKey']['addresses']) + tx_decoded = self.callnoderpc( + "decoderawtransaction", + [ + tx_signed, + ], + ) + assert ( + addr_out_test in tx_decoded["vout"][utxo_pos]["scriptPubKey"]["addresses"] + ) tx_spend = CTransaction() tx_spend.nVersion = ci.txVersion() - tx_spend.vin.append(CTxIn(COutPoint(int(txid, 16), utxo_pos), - nSequence=3, - scriptSig=ci.getScriptScriptSig(script))) + tx_spend.vin.append( + CTxIn( + COutPoint(int(txid, 16), utxo_pos), + nSequence=3, + scriptSig=ci.getScriptScriptSig(script), + ) + ) tx_spend.vout.append(ci.txoType()(ci.make_int(1.0999), script_out)) tx_spend.wit.vtxinwit.append(CTxInWitness()) - tx_spend.wit.vtxinwit[0].scriptWitness.stack = [script, ] + tx_spend.wit.vtxinwit[0].scriptWitness.stack = [ + script, + ] tx_spend_hex = tx_spend.serialize_with_witness().hex() - txid_spent = txid try: - txid = self.callnoderpc('sendrawtransaction', [tx_spend_hex, ]) + txid = self.callnoderpc( + "sendrawtransaction", + [ + tx_spend_hex, + ], + ) except Exception as e: - assert ('non-BIP68-final' in str(e)) + assert "non-BIP68-final" in str(e) else: - assert False, 'Should fail' + assert False, "Should fail" self.stake_block(3) - tx_spend_decoded = self.callnoderpc('decoderawtransaction', [tx_spend_hex, ]) - txid = self.callnoderpc('sendrawtransaction', [tx_spend_hex, ]) + txid = self.callnoderpc( + "sendrawtransaction", + [ + tx_spend_hex, + ], + ) self.stake_block(1) - ro = self.callnoderpc('listtransactions') + ro = self.callnoderpc("listtransactions") sum_addr = 0 for entry in ro: - if 'address' in entry and entry['address'] == addr_out: - if 'category' in entry and entry['category'] == 'receive': - sum_addr += entry['amount'] - assert (sum_addr == 1.0999) + if "address" in entry and entry["address"] == addr_out: + if "category" in entry and entry["category"] == "receive": + sum_addr += entry["amount"] + assert sum_addr == 1.0999 # listreceivedbyaddress doesn't seem to find witness utxos - ''' + """ ro = self.callnoderpc('listreceivedbyaddress', [0, ]) sum_addr = 0 for entry in ro: if entry['address'] == addr_out: sum_addr += entry['amount'] assert (sum_addr == 1.0999) - ''' + """ def test_005_watchonly(self): - logging.info('---------- Test {} watchonly'.format(self.test_coin_from.name)) + logging.info("---------- Test {} watchonly".format(self.test_coin_from.name)) - addr = self.callnoderpc('getnewaddress', ['watchonly test']) - ro = self.callnoderpc('importaddress', [addr, '', False], node_id=1) + addr = self.callnoderpc("getnewaddress", ["watchonly test"]) + ro = self.callnoderpc("importaddress", [addr, "", False], node_id=1) - ro = self.callnoderpc('validateaddress', [addr,], node_id=1) - assert (ro['iswatchonly'] is True) + ro = self.callnoderpc( + "validateaddress", + [ + addr, + ], + node_id=1, + ) + assert ro["iswatchonly"] is True - txid = self.callnoderpc('sendtoaddress', [addr, 1.0]) - tx_hex = self.callnoderpc('getrawtransaction', [txid, ]) + txid = self.callnoderpc("sendtoaddress", [addr, 1.0]) + tx_hex = self.callnoderpc( + "getrawtransaction", + [ + txid, + ], + ) self.sync_blocks() try: - self.callnoderpc('sendrawtransaction', [tx_hex, ], node_id=1) + self.callnoderpc( + "sendrawtransaction", + [ + tx_hex, + ], + node_id=1, + ) except Exception as e: - if 'transaction already in block chain' not in str(e): + if "transaction already in block chain" not in str(e): raise (e) - ro = self.callnoderpc('gettransaction', [txid, True], node_id=1) - assert (ro['txid'] == txid) - assert (ro['details'][0]['involvesWatchonly'] is True) - assert (ro['details'][0]['amount'] == 1.0) + ro = self.callnoderpc("gettransaction", [txid, True], node_id=1) + assert ro["txid"] == txid + assert ro["details"][0]["involvesWatchonly"] is True + assert ro["details"][0]["amount"] == 1.0 # No watchonly balance in getwalletinfo - ro = self.callnoderpc('listreceivedbyaddress', [0, False, True], node_id=1) + ro = self.callnoderpc("listreceivedbyaddress", [0, False, True], node_id=1) sum_addr = 0 for entry in ro: - if entry['address'] == addr: - sum_addr += entry['amount'] - assert (sum_addr == 1.0) + if entry["address"] == addr: + sum_addr += entry["amount"] + assert sum_addr == 1.0 def test_007_hdwallet(self): - logging.info('---------- Test {} hdwallet'.format(self.test_coin_from.name)) + logging.info("---------- Test {} hdwallet".format(self.test_coin_from.name)) # Run initialiseWallet to set 'main_wallet_seedid_' for i, sc in enumerate(self.swap_clients): @@ -534,73 +795,133 @@ class Test(TestFunctions): sc.initialiseWallet(self.test_coin_from) ci = sc.ci(self.test_coin_from) if i == 0: - assert ('19ac5fdb423421b7f9a33cf319715742be5f4caa' == ci.getWalletSeedID()) + assert ( + "19ac5fdb423421b7f9a33cf319715742be5f4caa" == ci.getWalletSeedID() + ) assert sc.checkWalletSeed(self.test_coin_from) is True def test_012_p2sh_p2wsh(self): - logging.info('---------- Test {} p2sh-p2wsh'.format(self.test_coin_from.name)) + logging.info("---------- Test {} p2sh-p2wsh".format(self.test_coin_from.name)) - swap_clients = self.swap_clients ci = self.swap_clients[0].ci(self.test_coin_from) - script = CScript([2, 2, OP_EQUAL, ]) + script = CScript( + [ + 2, + 2, + OP_EQUAL, + ] + ) script_dest = ci.getP2SHP2WSHDest(script) tx = CTransaction() tx.nVersion = ci.txVersion() tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest)) tx_hex = ToHex(tx) - tx_funded = self.callnoderpc('fundrawtransaction', [tx_hex]) - utxo_pos = 0 if tx_funded['changepos'] == 1 else 1 - tx_signed = self.callnoderpc('signrawtransaction', [tx_funded['hex'], ])['hex'] - txid = self.callnoderpc('sendrawtransaction', [tx_signed, ]) + tx_funded = self.callnoderpc("fundrawtransaction", [tx_hex]) + utxo_pos = 0 if tx_funded["changepos"] == 1 else 1 + tx_signed = self.callnoderpc( + "signrawtransaction", + [ + tx_funded["hex"], + ], + )["hex"] + txid = self.callnoderpc( + "sendrawtransaction", + [ + tx_signed, + ], + ) self.stake_block(1) - addr_out = self.callnoderpc('getnewaddress', ['used?',]) - addr_out = self.callnoderpc('getnewaddress', ['csv test']) - addr_witness = self.callnoderpc('addwitnessaddress', [addr_out,]) + addr_out = self.callnoderpc( + "getnewaddress", + [ + "used?", + ], + ) + addr_out = self.callnoderpc("getnewaddress", ["csv test"]) + _ = self.callnoderpc( + "addwitnessaddress", + [ + addr_out, + ], + ) pkh = ci.decodeAddress(addr_out) script_out = ci.getScriptForPubkeyHash(pkh) addr_out = ci.encodeSegwitAddressScript(script_out) # Double check output type - prev_tx = self.callnoderpc('decoderawtransaction', [tx_signed, ]) - assert (prev_tx['vout'][utxo_pos]['scriptPubKey']['type'] == 'scripthash') + prev_tx = self.callnoderpc( + "decoderawtransaction", + [ + tx_signed, + ], + ) + assert prev_tx["vout"][utxo_pos]["scriptPubKey"]["type"] == "scripthash" tx_spend = CTransaction() tx_spend.nVersion = ci.txVersion() - tx_spend.vin.append(CTxIn(COutPoint(int(txid, 16), utxo_pos), - scriptSig=ci.getP2SHP2WSHScriptSig(script))) + tx_spend.vin.append( + CTxIn( + COutPoint(int(txid, 16), utxo_pos), + scriptSig=ci.getP2SHP2WSHScriptSig(script), + ) + ) tx_spend.vout.append(ci.txoType()(ci.make_int(1.0999), script_out)) tx_spend.wit.vtxinwit.append(CTxInWitness()) - tx_spend.wit.vtxinwit[0].scriptWitness.stack = [script, ] + tx_spend.wit.vtxinwit[0].scriptWitness.stack = [ + script, + ] tx_spend_hex = tx_spend.serialize_with_witness().hex() - txid = self.callnoderpc('sendrawtransaction', [tx_spend_hex, ]) + txid = self.callnoderpc( + "sendrawtransaction", + [ + tx_spend_hex, + ], + ) self.stake_block(1) - ro = self.callnoderpc('listtransactions') + ro = self.callnoderpc("listtransactions") sum_addr = 0 for entry in ro: - if 'address' in entry and entry['address'] == addr_out: - if 'category' in entry and entry['category'] == 'receive': - sum_addr += entry['amount'] - assert (sum_addr == 1.0999) + if "address" in entry and entry["address"] == addr_out: + if "category" in entry and entry["category"] == "receive": + sum_addr += entry["amount"] + assert sum_addr == 1.0999 # Ensure tx was mined - tx_wallet = self.callnoderpc('gettransaction', [txid, ]) - assert (len(tx_wallet['blockhash']) == 64) + tx_wallet = self.callnoderpc( + "gettransaction", + [ + txid, + ], + ) + assert len(tx_wallet["blockhash"]) == 64 def test_02_part_coin(self): - logging.info('---------- Test PART to {}'.format(self.test_coin_from.name)) + logging.info("---------- Test PART to {}".format(self.test_coin_from.name)) if not self.test_atomic: - logging.warning('Skipping test') + logging.warning("Skipping test") return swap_clients = self.swap_clients - self.callnoderpc('staking', [True,]) + self.callnoderpc( + "staking", + [ + True, + ], + ) - offer_id = swap_clients[0].postOffer(Coins.PART, self.test_coin_from, 100 * COIN, 0.1 * COIN, 100 * COIN, SwapTypes.SELLER_FIRST) + offer_id = swap_clients[0].postOffer( + Coins.PART, + self.test_coin_from, + 100 * COIN, + 0.1 * COIN, + 100 * COIN, + SwapTypes.SELLER_FIRST, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -610,23 +931,53 @@ class Test(TestFunctions): swap_clients[0].acceptBid(bid_id) wait_for_in_progress(test_delay_event, swap_clients[1], bid_id, sent=True) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=260) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=260) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=260, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=260, + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 - self.callnoderpc('staking', [False,]) + self.callnoderpc( + "staking", + [ + False, + ], + ) def test_03_coin_part(self): - logging.info('---------- Test {} to PART'.format(self.test_coin_from.name)) + logging.info("---------- Test {} to PART".format(self.test_coin_from.name)) swap_clients = self.swap_clients - self.callnoderpc('staking', [True,]) + self.callnoderpc( + "staking", + [ + True, + ], + ) - offer_id = swap_clients[1].postOffer(self.test_coin_from, Coins.PART, 10 * COIN, 9.0 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST) + offer_id = swap_clients[1].postOffer( + self.test_coin_from, + Coins.PART, + 10 * COIN, + 9.0 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + ) wait_for_offer(test_delay_event, swap_clients[0], offer_id) offer = swap_clients[0].getOffer(offer_id) @@ -637,24 +988,54 @@ class Test(TestFunctions): wait_for_in_progress(test_delay_event, swap_clients[0], bid_id, sent=True) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=260) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=260) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=260, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=260, + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 - self.callnoderpc('staking', [False,]) + self.callnoderpc( + "staking", + [ + False, + ], + ) def test_04_coin_btc(self): - logging.info('---------- Test {} to BTC'.format(self.test_coin_from.name)) + logging.info("---------- Test {} to BTC".format(self.test_coin_from.name)) - self.callnoderpc('staking', [True,]) + self.callnoderpc( + "staking", + [ + True, + ], + ) swap_clients = self.swap_clients - offer_id = swap_clients[0].postOffer(self.test_coin_from, Coins.BTC, 10 * COIN, 0.1 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST) + offer_id = swap_clients[0].postOffer( + self.test_coin_from, + Coins.BTC, + 10 * COIN, + 0.1 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -665,28 +1046,59 @@ class Test(TestFunctions): wait_for_in_progress(test_delay_event, swap_clients[1], bid_id, sent=True) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=260) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=260) - - js_0bid = read_json_api(1800, 'bids/{}'.format(bid_id.hex())) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=260, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=260, + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 - self.callnoderpc('staking', [False,]) + self.callnoderpc( + "staking", + [ + False, + ], + ) def test_05_refund(self): # Seller submits initiate txn, buyer doesn't respond - logging.info('---------- Test refund, {} to BTC'.format(self.test_coin_from.name)) + logging.info( + "---------- Test refund, {} to BTC".format(self.test_coin_from.name) + ) swap_clients = self.swap_clients - self.callnoderpc('staking', [True,]) + self.callnoderpc( + "staking", + [ + True, + ], + ) - offer_id = swap_clients[0].postOffer(self.test_coin_from, Coins.BTC, 10 * COIN, 0.1 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST, - TxLockTypes.SEQUENCE_LOCK_BLOCKS, 5) + offer_id = swap_clients[0].postOffer( + self.test_coin_from, + Coins.BTC, + 10 * COIN, + 0.1 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + TxLockTypes.SEQUENCE_LOCK_BLOCKS, + 5, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -696,28 +1108,61 @@ class Test(TestFunctions): swap_clients[1].abandonBid(bid_id) swap_clients[0].acceptBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=260) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.BID_ABANDONED, sent=True, wait_for=260) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=260, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.BID_ABANDONED, + sent=True, + wait_for=260, + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 - self.callnoderpc('staking', [False,]) + self.callnoderpc( + "staking", + [ + False, + ], + ) def test_05_bad_ptx(self): # Invalid PTX sent, swap should stall and ITx and PTx should be reclaimed by senders - logging.info('---------- Test bad PTx, BTC to {}'.format(self.test_coin_from.name)) + logging.info( + "---------- Test bad PTx, BTC to {}".format(self.test_coin_from.name) + ) - self.callnoderpc('staking', [True,]) + self.callnoderpc( + "staking", + [ + True, + ], + ) swap_clients = self.swap_clients swap_value = make_int(random.uniform(0.001, 10.0), scale=8, r=1) - logging.info('swap_value {}'.format(format_amount(swap_value, 8))) - offer_id = swap_clients[0].postOffer(Coins.BTC, self.test_coin_from, swap_value, 0.1 * COIN, swap_value, SwapTypes.SELLER_FIRST, - TxLockTypes.SEQUENCE_LOCK_BLOCKS, 5) + logging.info("swap_value {}".format(format_amount(swap_value, 8))) + offer_id = swap_clients[0].postOffer( + Coins.BTC, + self.test_coin_from, + swap_value, + 0.1 * COIN, + swap_value, + SwapTypes.SELLER_FIRST, + TxLockTypes.SEQUENCE_LOCK_BLOCKS, + 5, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -727,31 +1172,63 @@ class Test(TestFunctions): wait_for_bid(test_delay_event, swap_clients[0], bid_id) swap_clients[0].acceptBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=320) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=320) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=320, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=320, + ) - js_0_bid = read_json_api(1800, 'bids/{}'.format(bid_id.hex())) - js_1_bid = read_json_api(1801, 'bids/{}'.format(bid_id.hex())) - assert (js_0_bid['itx_state'] == 'Refunded') - assert (js_1_bid['ptx_state'] == 'Refunded') + js_0_bid = read_json_api(1800, "bids/{}".format(bid_id.hex())) + js_1_bid = read_json_api(1801, "bids/{}".format(bid_id.hex())) + assert js_0_bid["itx_state"] == "Refunded" + assert js_1_bid["ptx_state"] == "Refunded" js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 - self.callnoderpc('staking', [False,]) + self.callnoderpc( + "staking", + [ + False, + ], + ) def test_06_self_bid(self): - logging.info('---------- Test same client, BTC to {}'.format(self.test_coin_from.name)) + logging.info( + "---------- Test same client, BTC to {}".format(self.test_coin_from.name) + ) - self.callnoderpc('staking', [True,]) + self.callnoderpc( + "staking", + [ + True, + ], + ) swap_clients = self.swap_clients js_0_before = read_json_api(1800) - offer_id = swap_clients[0].postOffer(self.test_coin_from, Coins.BTC, 10 * COIN, 10 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST) + offer_id = swap_clients[0].postOffer( + self.test_coin_from, + Coins.BTC, + 10 * COIN, + 10 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + ) wait_for_offer(test_delay_event, swap_clients[0], offer_id) offer = swap_clients[0].getOffer(offer_id) @@ -760,24 +1237,59 @@ class Test(TestFunctions): wait_for_bid(test_delay_event, swap_clients[0], bid_id) swap_clients[0].acceptBid(bid_id) - wait_for_bid_tx_state(test_delay_event, swap_clients[0], bid_id, TxStates.TX_REDEEMED, TxStates.TX_REDEEMED, wait_for=260) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=260) + wait_for_bid_tx_state( + test_delay_event, + swap_clients[0], + bid_id, + TxStates.TX_REDEEMED, + TxStates.TX_REDEEMED, + wait_for=260, + ) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=260, + ) js_0 = read_json_api(1800) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_0['num_recv_bids'] == js_0_before['num_recv_bids'] + 1 and js_0['num_sent_bids'] == js_0_before['num_sent_bids'] + 1) - self.callnoderpc('staking', [False,]) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert ( + js_0["num_recv_bids"] == js_0_before["num_recv_bids"] + 1 + and js_0["num_sent_bids"] == js_0_before["num_sent_bids"] + 1 + ) + self.callnoderpc( + "staking", + [ + False, + ], + ) def test_07_error(self): - logging.info('---------- Test error, BTC to {}, set fee above bid value'.format(self.test_coin_from.name)) + logging.info( + "---------- Test error, BTC to {}, set fee above bid value".format( + self.test_coin_from.name + ) + ) - self.callnoderpc('staking', [True,]) + self.callnoderpc( + "staking", + [ + True, + ], + ) swap_clients = self.swap_clients - js_0_before = read_json_api(1800) - - offer_id = swap_clients[0].postOffer(self.test_coin_from, Coins.BTC, 0.001 * COIN, 1.0 * COIN, 0.001 * COIN, SwapTypes.SELLER_FIRST) + offer_id = swap_clients[0].postOffer( + self.test_coin_from, + Coins.BTC, + 0.001 * COIN, + 1.0 * COIN, + 0.001 * COIN, + SwapTypes.SELLER_FIRST, + ) wait_for_offer(test_delay_event, swap_clients[0], offer_id) offer = swap_clients[0].getOffer(offer_id) @@ -786,55 +1298,95 @@ class Test(TestFunctions): wait_for_bid(test_delay_event, swap_clients[0], bid_id) swap_clients[0].acceptBid(bid_id) try: - swap_clients[0].getChainClientSettings(Coins.BTC)['override_feerate'] = 10.0 - swap_clients[0].getChainClientSettings(Coins.NAV)['override_feerate'] = 10.0 - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_ERROR, wait_for=260) + swap_clients[0].getChainClientSettings(Coins.BTC)["override_feerate"] = 10.0 + swap_clients[0].getChainClientSettings(Coins.NAV)["override_feerate"] = 10.0 + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.BID_ERROR, + wait_for=260, + ) swap_clients[0].abandonBid(bid_id) finally: - del swap_clients[0].getChainClientSettings(Coins.BTC)['override_feerate'] - del swap_clients[0].getChainClientSettings(Coins.NAV)['override_feerate'] - self.callnoderpc('staking', [False,]) + del swap_clients[0].getChainClientSettings(Coins.BTC)["override_feerate"] + del swap_clients[0].getChainClientSettings(Coins.NAV)["override_feerate"] + self.callnoderpc( + "staking", + [ + False, + ], + ) def test_08_wallet(self): - logging.info('---------- Test {} wallet'.format(self.test_coin_from.name)) + logging.info("---------- Test {} wallet".format(self.test_coin_from.name)) - logging.info('Test withdrawal') - addr = self.callnoderpc('getnewaddress', ['Withdrawal test', ]) - wallets = read_json_api(TEST_HTTP_PORT + 0, 'wallets') - assert (float(wallets[self.test_coin_from.name]['balance']) > 100) + logging.info("Test withdrawal") + addr = self.callnoderpc( + "getnewaddress", + [ + "Withdrawal test", + ], + ) + wallets = read_json_api(TEST_HTTP_PORT + 0, "wallets") + assert float(wallets[self.test_coin_from.name]["balance"]) > 100 post_json = { - 'value': 100, - 'address': addr, - 'subfee': False, + "value": 100, + "address": addr, + "subfee": False, } - json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/{}/withdraw'.format(self.test_coin_from.name.lower()), post_json) - assert (len(json_rv['txid']) == 64) + json_rv = read_json_api( + TEST_HTTP_PORT + 0, + "wallets/{}/withdraw".format(self.test_coin_from.name.lower()), + post_json, + ) + assert len(json_rv["txid"]) == 64 - logging.info('Test createutxo') + logging.info("Test createutxo") post_json = { - 'value': 10, + "value": 10, } - json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/{}/createutxo'.format(self.test_coin_from.name.lower()), post_json) - assert (len(json_rv['txid']) == 64) + json_rv = read_json_api( + TEST_HTTP_PORT + 0, + "wallets/{}/createutxo".format(self.test_coin_from.name.lower()), + post_json, + ) + assert len(json_rv["txid"]) == 64 def ensure_balance(self, coin_type, node_id, amount): tla = coin_type.name - js_w = read_json_api(1800 + node_id, 'wallets') - if float(js_w[tla]['balance']) < amount: + js_w = read_json_api(1800 + node_id, "wallets") + if float(js_w[tla]["balance"]) < amount: post_json = { - 'value': amount, - 'address': js_w[tla]['deposit_address'], - 'subfee': False, + "value": amount, + "address": js_w[tla]["deposit_address"], + "subfee": False, } - json_rv = read_json_api(1800, 'wallets/{}/withdraw'.format(tla.lower()), post_json) - assert (len(json_rv['txid']) == 64) - wait_for_balance(test_delay_event, 'http://127.0.0.1:{}/json/wallets/{}'.format(1800 + node_id, tla.lower()), 'balance', amount, iterations=120, delay_time=5) + json_rv = read_json_api( + 1800, "wallets/{}/withdraw".format(tla.lower()), post_json + ) + assert len(json_rv["txid"]) == 64 + wait_for_balance( + test_delay_event, + "http://127.0.0.1:{}/json/wallets/{}".format( + 1800 + node_id, tla.lower() + ), + "balance", + amount, + iterations=120, + delay_time=5, + ) def test_10_prefunded_itx(self): - logging.info('---------- Test prefunded itx offer') + logging.info("---------- Test prefunded itx offer") - self.callnoderpc('staking', [True,]) + self.callnoderpc( + "staking", + [ + True, + ], + ) swap_clients = self.swap_clients coin_from = Coins.NAV @@ -848,44 +1400,61 @@ class Test(TestFunctions): self.ensure_balance(coin_from, 2, 10.0) self.ensure_balance(coin_to, 1, 100.0) - js_w2 = read_json_api(1802, 'wallets') + js_w2 = read_json_api(1802, "wallets") post_json = { - 'value': 10.0, - 'address': read_json_api(1802, 'wallets/{}/nextdepositaddr'.format(tla_from.lower())), - 'subfee': True, + "value": 10.0, + "address": read_json_api( + 1802, "wallets/{}/nextdepositaddr".format(tla_from.lower()) + ), + "subfee": True, } - json_rv = read_json_api(1802, 'wallets/{}/withdraw'.format(tla_from.lower()), post_json) - wait_for_balance(test_delay_event, 'http://127.0.0.1:1802/json/wallets/{}'.format(tla_from.lower()), 'balance', 9.0) - assert (len(json_rv['txid']) == 64) + json_rv = read_json_api( + 1802, "wallets/{}/withdraw".format(tla_from.lower()), post_json + ) + wait_for_balance( + test_delay_event, + "http://127.0.0.1:1802/json/wallets/{}".format(tla_from.lower()), + "balance", + 9.0, + ) + assert len(json_rv["txid"]) == 64 # Create prefunded ITX pi = swap_clients[2].pi(SwapTypes.XMR_SWAP) - js_w2 = read_json_api(1802, 'wallets') + js_w2 = read_json_api(1802, "wallets") swap_value = 9.5 - if float(js_w2[tla_from]['balance']) < swap_value: - swap_value = js_w2[tla_from]['balance'] + if float(js_w2[tla_from]["balance"]) < swap_value: + swap_value = js_w2[tla_from]["balance"] swap_value = ci_from.make_int(swap_value) - assert (swap_value > ci_from.make_int(9)) + assert swap_value > ci_from.make_int(9) # Missing fundrawtransaction subtractFeeFromOutputs parameter try: itx = pi.getFundedInitiateTxTemplate(ci_from, swap_value, True) except Exception as e: - assert ('subtractFeeFromOutputs' in str(e)) + assert "subtractFeeFromOutputs" in str(e) else: - assert False, 'Should fail' + assert False, "Should fail" itx = pi.getFundedInitiateTxTemplate(ci_from, swap_value, False) itx_decoded = ci_from.describeTx(itx.hex()) n = pi.findMockVout(ci_from, itx_decoded) - value_after = ci_from.make_int(itx_decoded['vout'][n]['value']) - assert (value_after == swap_value) + value_after = ci_from.make_int(itx_decoded["vout"][n]["value"]) + assert value_after == swap_value swap_value = value_after wait_for_unspent(test_delay_event, ci_from, swap_value) - extra_options = {'prefunded_itx': itx} + extra_options = {"prefunded_itx": itx} rate_swap = ci_to.make_int(random.uniform(0.2, 10.0), r=1) - offer_id = swap_clients[2].postOffer(coin_from, coin_to, swap_value, rate_swap, swap_value, swap_type, extra_options=extra_options) + offer_id = swap_clients[2].postOffer( + coin_from, + coin_to, + swap_value, + rate_swap, + swap_value, + swap_type, + extra_options=extra_options, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -894,24 +1463,52 @@ class Test(TestFunctions): wait_for_bid(test_delay_event, swap_clients[2], bid_id, BidStates.BID_RECEIVED) swap_clients[2].acceptBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[2], bid_id, BidStates.SWAP_COMPLETED, wait_for=320) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=320) + wait_for_bid( + test_delay_event, + swap_clients[2], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=320, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=320, + ) # Verify expected inputs were used bid, offer = swap_clients[2].getBidAndOffer(bid_id) - assert (bid.initiate_tx) - wtx = ci_from.rpc('gettransaction', [bid.initiate_tx.txid.hex(),]) - itx_after = ci_from.describeTx(wtx['hex']) - assert (len(itx_after['vin']) == len(itx_decoded['vin'])) - for i, txin in enumerate(itx_decoded['vin']): - assert (txin['txid'] == itx_after['vin'][i]['txid']) - assert (txin['vout'] == itx_after['vin'][i]['vout']) - self.callnoderpc('staking', [False,]) + assert bid.initiate_tx + wtx = ci_from.rpc( + "gettransaction", + [ + bid.initiate_tx.txid.hex(), + ], + ) + itx_after = ci_from.describeTx(wtx["hex"]) + assert len(itx_after["vin"]) == len(itx_decoded["vin"]) + for i, txin in enumerate(itx_decoded["vin"]): + assert txin["txid"] == itx_after["vin"][i]["txid"] + assert txin["vout"] == itx_after["vin"][i]["vout"] + self.callnoderpc( + "staking", + [ + False, + ], + ) def test_11_xmrswap_to(self): - logging.info('---------- Test xmr swap protocol to') + logging.info("---------- Test xmr swap protocol to") - self.callnoderpc('staking', [True,]) + self.callnoderpc( + "staking", + [ + True, + ], + ) swap_clients = self.swap_clients coin_from = Coins.BTC @@ -922,7 +1519,9 @@ class Test(TestFunctions): swap_value = ci_from.make_int(random.uniform(0.2, 20.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) - offer_id = swap_clients[0].postOffer(coin_from, coin_to, swap_value, rate_swap, swap_value, swap_type) + offer_id = swap_clients[0].postOffer( + coin_from, coin_to, swap_value, rate_swap, swap_value, swap_type + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -931,17 +1530,44 @@ class Test(TestFunctions): wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) swap_clients[0].acceptBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=320) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=320) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=320, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=320, + ) - self.callnoderpc('staking', [False,]) + self.callnoderpc( + "staking", + [ + False, + ], + ) def test_12_xmrswap_to_recover_b_lock_tx(self): coin_from = Coins.BTC coin_to = Coins.NAV - logging.info('---------- Test {} to {} follower recovers coin b lock tx'.format(coin_from.name, coin_to.name)) + logging.info( + "---------- Test {} to {} follower recovers coin b lock tx".format( + coin_from.name, coin_to.name + ) + ) - self.callnoderpc('staking', [True,]) + self.callnoderpc( + "staking", + [ + True, + ], + ) swap_clients = self.swap_clients ci_from = swap_clients[0].ci(coin_from) @@ -950,8 +1576,15 @@ class Test(TestFunctions): amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) offer_id = swap_clients[0].postOffer( - coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, - lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=12) + coin_from, + coin_to, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, + lock_value=12, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -962,67 +1595,117 @@ class Test(TestFunctions): swap_clients[1].setBidDebugInd(bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK) swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=380) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=True, wait_for=180) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + wait_for=380, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + sent=True, + wait_for=180, + ) - self.callnoderpc('staking', [False,]) + self.callnoderpc( + "staking", + [ + False, + ], + ) # Adaptor sig swap tests def test_01_a_full_swap(self): self.node_a_id = 2 self.sync_blocks() - self.callnoderpc('staking', [True,]) + self.callnoderpc( + "staking", + [ + True, + ], + ) self.do_test_01_full_swap(self.test_coin_from, Coins.XMR) - self.callnoderpc('staking', [False,]) + self.callnoderpc( + "staking", + [ + False, + ], + ) def test_01_b_full_swap_reverse(self): self.node_a_id = 0 self.sync_blocks() - self.callnoderpc('staking', [True,]) + self.callnoderpc( + "staking", + [ + True, + ], + ) self.prepare_balance(Coins.XMR, 100.0, 1800, 1801) self.do_test_01_full_swap(Coins.XMR, self.test_coin_from) - self.callnoderpc('staking', [False,]) + self.callnoderpc( + "staking", + [ + False, + ], + ) def test_02_a_leader_recover_a_lock_tx(self): self.node_a_id = 2 self.sync_blocks() self.prepare_balance(Coins.NAV, 1000.0, 1802, 1800) - self.do_test_02_leader_recover_a_lock_tx(self.test_coin_from, Coins.XMR, lock_value=5) + self.do_test_02_leader_recover_a_lock_tx( + self.test_coin_from, Coins.XMR, lock_value=5 + ) def test_02_b_leader_recover_a_lock_tx_reverse(self): self.sync_blocks() self.prepare_balance(Coins.XMR, 100.0, 1800, 1801) - self.do_test_02_leader_recover_a_lock_tx(Coins.XMR, self.test_coin_from, lock_value=5) + self.do_test_02_leader_recover_a_lock_tx( + Coins.XMR, self.test_coin_from, lock_value=5 + ) def test_03_a_follower_recover_a_lock_tx(self): self.node_a_id = 2 self.sync_blocks() self.prepare_balance(Coins.NAV, 1000.0, 1802, 1800) - self.do_test_03_follower_recover_a_lock_tx(self.test_coin_from, Coins.XMR, lock_value=5) + self.do_test_03_follower_recover_a_lock_tx( + self.test_coin_from, Coins.XMR, lock_value=5 + ) def test_03_b_follower_recover_a_lock_tx_reverse(self): self.sync_blocks() self.prepare_balance(Coins.XMR, 100.0, 1800, 1801) - self.do_test_03_follower_recover_a_lock_tx(Coins.XMR, self.test_coin_from, lock_value=5) + self.do_test_03_follower_recover_a_lock_tx( + Coins.XMR, self.test_coin_from, lock_value=5 + ) def test_04_a_follower_recover_b_lock_tx(self): self.node_a_id = 2 self.sync_blocks() self.prepare_balance(Coins.NAV, 1000.0, 1802, 1800) - self.do_test_04_follower_recover_b_lock_tx(self.test_coin_from, Coins.XMR, lock_value=5) + self.do_test_04_follower_recover_b_lock_tx( + self.test_coin_from, Coins.XMR, lock_value=5 + ) def test_04_b_follower_recover_b_lock_tx_reverse(self): self.sync_blocks() self.prepare_balance(Coins.XMR, 100.0, 1800, 1801) - self.do_test_04_follower_recover_b_lock_tx(Coins.XMR, self.test_coin_from, lock_value=5) + self.do_test_04_follower_recover_b_lock_tx( + Coins.XMR, self.test_coin_from, lock_value=5 + ) def test_05_self_bid(self): self.sync_blocks() self.do_test_05_self_bid(self.test_coin_from, Coins.XMR) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/extended/test_network.py b/tests/basicswap/extended/test_network.py index 5465dec..0c79f9b 100644 --- a/tests/basicswap/extended/test_network.py +++ b/tests/basicswap/extended/test_network.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020-2021 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -72,79 +73,90 @@ stop_test = False def prepare_swapclient_dir(datadir, node_id, network_key, network_pubkey): - basicswap_dir = os.path.join(datadir, 'basicswap_' + str(node_id)) + basicswap_dir = os.path.join(datadir, "basicswap_" + str(node_id)) if not os.path.exists(basicswap_dir): os.makedirs(basicswap_dir) settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME) settings = { - 'debug': True, - 'p2p_host': '127.0.0.1', - 'p2p_port': BASE_P2P_PORT + node_id, - 'zmqhost': 'tcp://127.0.0.1', - 'zmqport': BASE_ZMQ_PORT + node_id, - 'htmlhost': '127.0.0.1', - 'htmlport': TEST_HTTP_PORT + node_id, - 'network_key': network_key, - 'network_pubkey': network_pubkey, - 'chainclients': { - 'particl': { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': BASE_RPC_PORT + node_id, - 'rpcuser': 'test' + str(node_id), - 'rpcpassword': 'test_pass' + str(node_id), - 'datadir': os.path.join(datadir, 'part_' + str(node_id)), - 'bindir': cfg.PARTICL_BINDIR, - 'blocks_confirmed': 2, # Faster testing + "debug": True, + "p2p_host": "127.0.0.1", + "p2p_port": BASE_P2P_PORT + node_id, + "zmqhost": "tcp://127.0.0.1", + "zmqport": BASE_ZMQ_PORT + node_id, + "htmlhost": "127.0.0.1", + "htmlport": TEST_HTTP_PORT + node_id, + "network_key": network_key, + "network_pubkey": network_pubkey, + "chainclients": { + "particl": { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": BASE_RPC_PORT + node_id, + "rpcuser": "test" + str(node_id), + "rpcpassword": "test_pass" + str(node_id), + "datadir": os.path.join(datadir, "part_" + str(node_id)), + "bindir": cfg.PARTICL_BINDIR, + "blocks_confirmed": 2, # Faster testing + }, + "bitcoin": { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": BTC_BASE_RPC_PORT + node_id, + "rpcuser": "test" + str(node_id), + "rpcpassword": "test_pass" + str(node_id), + "datadir": os.path.join(datadir, "btc_" + str(node_id)), + "bindir": cfg.BITCOIN_BINDIR, + "use_segwit": True, }, - 'bitcoin': { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': BTC_BASE_RPC_PORT + node_id, - 'rpcuser': 'test' + str(node_id), - 'rpcpassword': 'test_pass' + str(node_id), - 'datadir': os.path.join(datadir, 'btc_' + str(node_id)), - 'bindir': cfg.BITCOIN_BINDIR, - 'use_segwit': True, - } - }, - 'check_progress_seconds': 2, - 'check_watched_seconds': 4, - 'check_expired_seconds': 60, - 'check_events_seconds': 1, - 'check_xmr_swaps_seconds': 1, - 'min_delay_event': 1, - 'max_delay_event': 5, - 'min_delay_event_short': 1, - 'max_delay_event_short': 5, - 'min_delay_retry': 2, - 'max_delay_retry': 10, - 'restrict_unknown_seed_wallets': False + "check_progress_seconds": 2, + "check_watched_seconds": 4, + "check_expired_seconds": 60, + "check_events_seconds": 1, + "check_xmr_swaps_seconds": 1, + "min_delay_event": 1, + "max_delay_event": 5, + "min_delay_event_short": 1, + "max_delay_event_short": 5, + "min_delay_retry": 2, + "max_delay_retry": 10, + "restrict_unknown_seed_wallets": False, } - with open(settings_path, 'w') as fp: + with open(settings_path, "w") as fp: json.dump(settings, fp, indent=4) def partRpc(cmd, node_id=0): - return callrpc_cli(cfg.PARTICL_BINDIR, os.path.join(TEST_DIR, 'part_' + str(node_id)), 'regtest', cmd, cfg.PARTICL_CLI) + return callrpc_cli( + cfg.PARTICL_BINDIR, + os.path.join(TEST_DIR, "part_" + str(node_id)), + "regtest", + cmd, + cfg.PARTICL_CLI, + ) def btcRpc(cmd, node_id=0): - return callrpc_cli(cfg.BITCOIN_BINDIR, os.path.join(TEST_DIR, 'btc_' + str(node_id)), 'regtest', cmd, cfg.BITCOIN_CLI) + return callrpc_cli( + cfg.BITCOIN_BINDIR, + os.path.join(TEST_DIR, "btc_" + str(node_id)), + "regtest", + cmd, + cfg.BITCOIN_CLI, + ) def signal_handler(sig, frame): global stop_test - logging.info('signal {} detected.'.format(sig)) + logging.info("signal {} detected.".format(sig)) stop_test = True delay_event.set() def callnoderpc(node_id, method, params=[], wallet=None, base_rpc_port=BASE_RPC_PORT): - auth = 'test{0}:test_pass{0}'.format(node_id) + auth = "test{0}:test_pass{0}".format(node_id) return callrpc(base_rpc_port + node_id, auth, method, params, wallet) @@ -152,9 +164,9 @@ def run_coins_loop(cls): while not stop_test: try: if cls.btc_addr is not None: - btcRpc('generatetoaddress 1 {}'.format(cls.btc_addr)) + btcRpc("generatetoaddress 1 {}".format(cls.btc_addr)) except Exception as e: - logging.warning('run_coins_loop ' + str(e)) + logging.warning("run_coins_loop " + str(e)) time.sleep(1.0) @@ -183,58 +195,122 @@ class Test(unittest.TestCase): logger.propagate = False logger.handlers = [] logger.setLevel(logging.INFO) # DEBUG shows many messages from requests.post - formatter = logging.Formatter('%(asctime)s %(levelname)s : %(message)s') + formatter = logging.Formatter("%(asctime)s %(levelname)s : %(message)s") stream_stdout = logging.StreamHandler() stream_stdout.setFormatter(formatter) logger.addHandler(stream_stdout) if os.path.isdir(TEST_DIR): - logging.info('Removing ' + TEST_DIR) + logging.info("Removing " + TEST_DIR) shutil.rmtree(TEST_DIR) if not os.path.exists(TEST_DIR): os.makedirs(TEST_DIR) - cls.stream_fp = logging.FileHandler(os.path.join(TEST_DIR, 'test.log')) + cls.stream_fp = logging.FileHandler(os.path.join(TEST_DIR, "test.log")) cls.stream_fp.setFormatter(formatter) logger.addHandler(cls.stream_fp) try: - logging.info('Preparing coin nodes.') + logging.info("Preparing coin nodes.") for i in range(NUM_NODES): - data_dir = prepareDataDir(TEST_DIR, i, 'particl.conf', 'part_') - if os.path.exists(os.path.join(cfg.PARTICL_BINDIR, 'particl-wallet')): - callrpc_cli(cfg.PARTICL_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat -legacy create', 'particl-wallet') + data_dir = prepareDataDir(TEST_DIR, i, "particl.conf", "part_") + if os.path.exists(os.path.join(cfg.PARTICL_BINDIR, "particl-wallet")): + callrpc_cli( + cfg.PARTICL_BINDIR, + data_dir, + "regtest", + "-wallet=wallet.dat -legacy create", + "particl-wallet", + ) - cls.part_daemons.append(startDaemon(os.path.join(TEST_DIR, 'part_' + str(i)), cfg.PARTICL_BINDIR, cfg.PARTICLD)) - logging.info('Started %s %d', cfg.PARTICLD, cls.handle.part_daemons[-1].handle.pid) + cls.part_daemons.append( + startDaemon( + os.path.join(TEST_DIR, "part_" + str(i)), + cfg.PARTICL_BINDIR, + cfg.PARTICLD, + ) + ) + logging.info( + "Started %s %d", + cfg.PARTICLD, + cls.handle.part_daemons[-1].handle.pid, + ) for i in range(NUM_NODES): # Load mnemonics after all nodes have started to avoid staking getting stuck in TryToSync rpc = make_rpc_func(i) waitForRPC(rpc, delay_event) if i == 0: - rpc('extkeyimportmaster', ['abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb']) + rpc( + "extkeyimportmaster", + [ + "abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb" + ], + ) elif i == 1: - rpc('extkeyimportmaster', ['pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic', '', 'true']) - rpc('getnewextaddress', ['lblExtTest']) - rpc('rescanblockchain') + rpc( + "extkeyimportmaster", + [ + "pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic", + "", + "true", + ], + ) + rpc("getnewextaddress", ["lblExtTest"]) + rpc("rescanblockchain") else: - rpc('extkeyimportmaster', [rpc('mnemonic', ['new'])['master']]) + rpc("extkeyimportmaster", [rpc("mnemonic", ["new"])["master"]]) # Lower output split threshold for more stakeable outputs - rpc('walletsettings', ['stakingoptions', {'stakecombinethreshold': 100, 'stakesplitthreshold': 200}]) - rpc('reservebalance', [False,]) + rpc( + "walletsettings", + [ + "stakingoptions", + {"stakecombinethreshold": 100, "stakesplitthreshold": 200}, + ], + ) + rpc( + "reservebalance", + [ + False, + ], + ) for i in range(NUM_BTC_NODES): - data_dir = prepareDataDir(TEST_DIR, i, 'bitcoin.conf', 'btc_', base_p2p_port=BTC_BASE_PORT, base_rpc_port=BTC_BASE_RPC_PORT) - if os.path.exists(os.path.join(cfg.BITCOIN_BINDIR, 'bitcoin-wallet')): - callrpc_cli(cfg.BITCOIN_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat -legacy create', 'bitcoin-wallet') + data_dir = prepareDataDir( + TEST_DIR, + i, + "bitcoin.conf", + "btc_", + base_p2p_port=BTC_BASE_PORT, + base_rpc_port=BTC_BASE_RPC_PORT, + ) + if os.path.exists(os.path.join(cfg.BITCOIN_BINDIR, "bitcoin-wallet")): + callrpc_cli( + cfg.BITCOIN_BINDIR, + data_dir, + "regtest", + "-wallet=wallet.dat -legacy create", + "bitcoin-wallet", + ) - cls.btc_daemons.append(startDaemon(os.path.join(TEST_DIR, 'btc_' + str(i)), cfg.BITCOIN_BINDIR, cfg.BITCOIND)) - logging.info('Started %s %d', cfg.BITCOIND, cls.handle.part_daemons[-1].handle.pid) + cls.btc_daemons.append( + startDaemon( + os.path.join(TEST_DIR, "btc_" + str(i)), + cfg.BITCOIN_BINDIR, + cfg.BITCOIND, + ) + ) + logging.info( + "Started %s %d", + cfg.BITCOIND, + cls.handle.part_daemons[-1].handle.pid, + ) - waitForRPC(make_rpc_func(i, base_rpc_port=BTC_BASE_RPC_PORT), delay_event) + waitForRPC( + make_rpc_func(i, base_rpc_port=BTC_BASE_RPC_PORT), delay_event + ) - logging.info('Preparing swap clients.') + logging.info("Preparing swap clients.") eckey = ECKey() eckey.generate() cls.network_key = toWIF(PREFIX_SECRET_KEY_REGTEST, eckey.get_bytes()) @@ -242,12 +318,20 @@ class Test(unittest.TestCase): for i in range(NUM_NODES): prepare_swapclient_dir(TEST_DIR, i, cls.network_key, cls.network_pubkey) - basicswap_dir = os.path.join(os.path.join(TEST_DIR, 'basicswap_' + str(i))) + basicswap_dir = os.path.join( + os.path.join(TEST_DIR, "basicswap_" + str(i)) + ) settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME) with open(settings_path) as fs: settings = json.load(fs) - fp = open(os.path.join(basicswap_dir, 'basicswap.log'), 'w') - sc = BasicSwap(fp, basicswap_dir, settings, 'regtest', log_name='BasicSwap{}'.format(i)) + fp = open(os.path.join(basicswap_dir, "basicswap.log"), "w") + sc = BasicSwap( + fp, + basicswap_dir, + settings, + "regtest", + log_name="BasicSwap{}".format(i), + ) cls.swap_clients.append(sc) sc.setDaemonPID(Coins.BTC, cls.btc_daemons[i].handle.pid) sc.setDaemonPID(Coins.PART, cls.part_daemons[i].handle.pid) @@ -257,41 +341,55 @@ class Test(unittest.TestCase): cls.http_threads.append(t) t.start() - cls.btc_addr = callnoderpc(0, 'getnewaddress', ['mining_addr', 'bech32'], base_rpc_port=BTC_BASE_RPC_PORT) + cls.btc_addr = callnoderpc( + 0, + "getnewaddress", + ["mining_addr", "bech32"], + base_rpc_port=BTC_BASE_RPC_PORT, + ) num_blocks = 500 - logging.info('Mining %d Bitcoin blocks to %s', num_blocks, cls.btc_addr) - callnoderpc(0, 'generatetoaddress', [num_blocks, cls.btc_addr], base_rpc_port=BTC_BASE_RPC_PORT) + logging.info("Mining %d Bitcoin blocks to %s", num_blocks, cls.btc_addr) + callnoderpc( + 0, + "generatetoaddress", + [num_blocks, cls.btc_addr], + base_rpc_port=BTC_BASE_RPC_PORT, + ) - checkForks(callnoderpc(0, 'getblockchaininfo', base_rpc_port=BTC_BASE_RPC_PORT)) + checkForks( + callnoderpc(0, "getblockchaininfo", base_rpc_port=BTC_BASE_RPC_PORT) + ) - logging.info('Starting update thread.') + logging.info("Starting update thread.") signal.signal(signal.SIGINT, signal_handler) cls.update_thread = threading.Thread(target=run_loop, args=(cls,)) cls.update_thread.start() - cls.coins_update_thread = threading.Thread(target=run_coins_loop, args=(cls,)) + cls.coins_update_thread = threading.Thread( + target=run_coins_loop, args=(cls,) + ) cls.coins_update_thread.start() except Exception: traceback.print_exc() cls.tearDownClass() - raise ValueError('setUpClass() failed.') + raise ValueError("setUpClass() failed.") @classmethod def tearDownClass(cls): global stop_test - logging.info('Finalising') + logging.info("Finalising") stop_test = True if cls.update_thread is not None: try: cls.update_thread.join() except Exception: - logging.info('Failed to join update_thread') + logging.info("Failed to join update_thread") if cls.coins_update_thread is not None: try: cls.coins_update_thread.join() except Exception: - logging.info('Failed to join coins_update_thread') + logging.info("Failed to join coins_update_thread") for t in cls.http_threads: t.stop() @@ -313,39 +411,51 @@ class Test(unittest.TestCase): def wait_for_num_nodes(self, port, expect_nodes, wait_for=20): for i in range(wait_for): if delay_event.is_set(): - raise ValueError('Test stopped.') - js = read_json_api(port, 'network') + raise ValueError("Test stopped.") + js = read_json_api(port, "network") num_nodes = 0 - for p in js['peers']: - if p['ready'] is True: + for p in js["peers"]: + if p["ready"] is True: num_nodes += 1 if num_nodes >= expect_nodes: return True delay_event.wait(1) - raise ValueError('wait_for_num_nodes timed out.') + raise ValueError("wait_for_num_nodes timed out.") def test_01_network(self): - logging.info('---------- Test Network') + logging.info("---------- Test Network") swap_clients = self.swap_clients - js_1 = read_json_api(1801, 'wallets') + swap_clients[0].postOffer( + Coins.PART, + Coins.BTC, + 100 * COIN, + 0.1 * COIN, + 100 * COIN, + SwapTypes.SELLER_FIRST, + ) - offer_id = swap_clients[0].postOffer(Coins.PART, Coins.BTC, 100 * COIN, 0.1 * COIN, 100 * COIN, SwapTypes.SELLER_FIRST) - - swap_clients[1].add_connection('127.0.0.1', BASE_P2P_PORT + 0, swap_clients[0]._network._network_pubkey) - swap_clients[2].add_connection('127.0.0.1', BASE_P2P_PORT + 0, swap_clients[0]._network._network_pubkey) + swap_clients[1].add_connection( + "127.0.0.1", BASE_P2P_PORT + 0, swap_clients[0]._network._network_pubkey + ) + swap_clients[2].add_connection( + "127.0.0.1", BASE_P2P_PORT + 0, swap_clients[0]._network._network_pubkey + ) self.wait_for_num_nodes(1800, 2) - js_n0 = read_json_api(1800, 'network') + js_n0 = read_json_api(1800, "network") print(dumpj(js_n0)) - path = [swap_clients[0]._network._network_pubkey, swap_clients[2]._network._network_pubkey] + path = [ + swap_clients[0]._network._network_pubkey, + swap_clients[2]._network._network_pubkey, + ] swap_clients[1]._network.test_onion(path) delay_for(delay_event, 1000) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/extended/test_nmc.py b/tests/basicswap/extended/test_nmc.py index 104620e..ed21b08 100644 --- a/tests/basicswap/extended/test_nmc.py +++ b/tests/basicswap/extended/test_nmc.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019-2021 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -80,74 +81,74 @@ delay_event = threading.Event() stop_test = False -def prepareOtherDir(datadir, nodeId, conf_file='namecoin.conf'): +def prepareOtherDir(datadir, nodeId, conf_file="namecoin.conf"): node_dir = os.path.join(datadir, str(nodeId)) if not os.path.exists(node_dir): os.makedirs(node_dir) filePath = os.path.join(node_dir, conf_file) - with open(filePath, 'w+') as fp: - fp.write('regtest=1\n') - fp.write('[regtest]\n') - fp.write('port=' + str(BASE_PORT + nodeId) + '\n') - fp.write('rpcport=' + str(BASE_RPC_PORT + nodeId) + '\n') + with open(filePath, "w+") as fp: + fp.write("regtest=1\n") + fp.write("[regtest]\n") + fp.write("port=" + str(BASE_PORT + nodeId) + "\n") + fp.write("rpcport=" + str(BASE_RPC_PORT + nodeId) + "\n") - fp.write('daemon=0\n') - fp.write('printtoconsole=0\n') - fp.write('server=1\n') - fp.write('discover=0\n') - fp.write('listenonion=0\n') - fp.write('bind=127.0.0.1\n') - fp.write('findpeers=0\n') - fp.write('debug=1\n') - fp.write('debugexclude=libevent\n') + fp.write("daemon=0\n") + fp.write("printtoconsole=0\n") + fp.write("server=1\n") + fp.write("discover=0\n") + fp.write("listenonion=0\n") + fp.write("bind=127.0.0.1\n") + fp.write("findpeers=0\n") + fp.write("debug=1\n") + fp.write("debugexclude=libevent\n") - fp.write('fallbackfee=0.01\n') - fp.write('acceptnonstdtxn=0\n') + fp.write("fallbackfee=0.01\n") + fp.write("acceptnonstdtxn=0\n") - if conf_file == 'bitcoin.conf': - fp.write('wallet=wallet.dat\n') + if conf_file == "bitcoin.conf": + fp.write("wallet=wallet.dat\n") def prepareDir(datadir, nodeId, network_key, network_pubkey): node_dir = os.path.join(datadir, str(nodeId)) if not os.path.exists(node_dir): os.makedirs(node_dir) - filePath = os.path.join(node_dir, 'particl.conf') + filePath = os.path.join(node_dir, "particl.conf") - with open(filePath, 'w+') as fp: - fp.write('regtest=1\n') - fp.write('[regtest]\n') - fp.write('port=' + str(BASE_PORT + nodeId) + '\n') - fp.write('rpcport=' + str(BASE_RPC_PORT + nodeId) + '\n') + with open(filePath, "w+") as fp: + fp.write("regtest=1\n") + fp.write("[regtest]\n") + fp.write("port=" + str(BASE_PORT + nodeId) + "\n") + fp.write("rpcport=" + str(BASE_RPC_PORT + nodeId) + "\n") - fp.write('daemon=0\n') - fp.write('printtoconsole=0\n') - fp.write('server=1\n') - fp.write('discover=0\n') - fp.write('listenonion=0\n') - fp.write('bind=127.0.0.1\n') - fp.write('findpeers=0\n') - fp.write('debug=1\n') - fp.write('debugexclude=libevent\n') - fp.write('zmqpubsmsg=tcp://127.0.0.1:' + str(BASE_ZMQ_PORT + nodeId) + '\n') - fp.write('wallet=wallet.dat\n') - fp.write('fallbackfee=0.01\n') + fp.write("daemon=0\n") + fp.write("printtoconsole=0\n") + fp.write("server=1\n") + fp.write("discover=0\n") + fp.write("listenonion=0\n") + fp.write("bind=127.0.0.1\n") + fp.write("findpeers=0\n") + fp.write("debug=1\n") + fp.write("debugexclude=libevent\n") + fp.write("zmqpubsmsg=tcp://127.0.0.1:" + str(BASE_ZMQ_PORT + nodeId) + "\n") + fp.write("wallet=wallet.dat\n") + fp.write("fallbackfee=0.01\n") - fp.write('acceptnonstdtxn=0\n') - fp.write('minstakeinterval=5\n') - fp.write('smsgsregtestadjust=0\n') + fp.write("acceptnonstdtxn=0\n") + fp.write("minstakeinterval=5\n") + fp.write("smsgsregtestadjust=0\n") for i in range(0, NUM_NODES): if nodeId == i: continue - fp.write('addnode=127.0.0.1:%d\n' % (BASE_PORT + i)) + fp.write("addnode=127.0.0.1:%d\n" % (BASE_PORT + i)) if nodeId < 2: - fp.write('spentindex=1\n') - fp.write('txindex=1\n') + fp.write("spentindex=1\n") + fp.write("txindex=1\n") - basicswap_dir = os.path.join(datadir, str(nodeId), 'basicswap') + basicswap_dir = os.path.join(datadir, str(nodeId), "basicswap") if not os.path.exists(basicswap_dir): os.makedirs(basicswap_dir) @@ -155,64 +156,82 @@ def prepareDir(datadir, nodeId, network_key, network_pubkey): btcdatadir = os.path.join(datadir, str(BTC_NODE)) settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME) settings = { - 'debug': True, - 'zmqhost': 'tcp://127.0.0.1', - 'zmqport': BASE_ZMQ_PORT + nodeId, - 'htmlhost': '127.0.0.1', - 'htmlport': 12700 + nodeId, - 'network_key': network_key, - 'network_pubkey': network_pubkey, - 'chainclients': { - 'particl': { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': BASE_RPC_PORT + nodeId, - 'datadir': node_dir, - 'bindir': cfg.PARTICL_BINDIR, - 'blocks_confirmed': 2, # Faster testing + "debug": True, + "zmqhost": "tcp://127.0.0.1", + "zmqport": BASE_ZMQ_PORT + nodeId, + "htmlhost": "127.0.0.1", + "htmlport": 12700 + nodeId, + "network_key": network_key, + "network_pubkey": network_pubkey, + "chainclients": { + "particl": { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": BASE_RPC_PORT + nodeId, + "datadir": node_dir, + "bindir": cfg.PARTICL_BINDIR, + "blocks_confirmed": 2, # Faster testing }, - 'namecoin': { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': BASE_RPC_PORT + NMC_NODE, - 'datadir': nmcdatadir, - 'bindir': cfg.NAMECOIN_BINDIR, - 'use_csv': False, + "namecoin": { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": BASE_RPC_PORT + NMC_NODE, + "datadir": nmcdatadir, + "bindir": cfg.NAMECOIN_BINDIR, + "use_csv": False, # 'use_segwit': True, }, - 'bitcoin': { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': BASE_RPC_PORT + BTC_NODE, - 'datadir': btcdatadir, - 'bindir': cfg.BITCOIN_BINDIR, - 'use_segwit': True, - } + "bitcoin": { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": BASE_RPC_PORT + BTC_NODE, + "datadir": btcdatadir, + "bindir": cfg.BITCOIN_BINDIR, + "use_segwit": True, + }, }, - 'check_progress_seconds': 2, - 'check_watched_seconds': 4, - 'check_expired_seconds': 60, - 'restrict_unknown_seed_wallets': False, + "check_progress_seconds": 2, + "check_watched_seconds": 4, + "check_expired_seconds": 60, + "restrict_unknown_seed_wallets": False, } - with open(settings_path, 'w') as fp: + with open(settings_path, "w") as fp: json.dump(settings, fp, indent=4) def partRpc(cmd, node_id=0): - return callrpc_cli(cfg.PARTICL_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(node_id)), 'regtest', cmd, cfg.PARTICL_CLI) + return callrpc_cli( + cfg.PARTICL_BINDIR, + os.path.join(cfg.TEST_DATADIRS, str(node_id)), + "regtest", + cmd, + cfg.PARTICL_CLI, + ) def btcRpc(cmd): - return callrpc_cli(cfg.BITCOIN_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)), 'regtest', cmd, cfg.BITCOIN_CLI) + return callrpc_cli( + cfg.BITCOIN_BINDIR, + os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)), + "regtest", + cmd, + cfg.BITCOIN_CLI, + ) def nmcRpc(cmd): - return callrpc_cli(cfg.NAMECOIN_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(NMC_NODE)), 'regtest', cmd, cfg.NAMECOIN_CLI) + return callrpc_cli( + cfg.NAMECOIN_BINDIR, + os.path.join(cfg.TEST_DATADIRS, str(NMC_NODE)), + "regtest", + cmd, + cfg.NAMECOIN_CLI, + ) def signal_handler(sig, frame): global stop_test - print('signal {} detected.'.format(sig)) + print("signal {} detected.".format(sig)) stop_test = True delay_event.set() @@ -220,10 +239,10 @@ def signal_handler(sig, frame): def run_coins_loop(cls): while not stop_test: try: - nmcRpc('generatetoaddress 1 {}'.format(cls.nmc_addr)) - btcRpc('generatetoaddress 1 {}'.format(cls.btc_addr)) + nmcRpc("generatetoaddress 1 {}".format(cls.nmc_addr)) + btcRpc("generatetoaddress 1 {}".format(cls.btc_addr)) except Exception as e: - logging.warning('run_coins_loop ' + str(e)) + logging.warning("run_coins_loop " + str(e)) time.sleep(1.0) @@ -244,6 +263,7 @@ def make_part_cli_rpc_func(node_id): for p in params: cmd += ' "' + p + '"' return partRpc(cmd, node_id) + return rpc_func @@ -259,54 +279,96 @@ class Test(unittest.TestCase): cls.network_pubkey = eckey.get_pubkey().get_bytes().hex() if os.path.isdir(cfg.TEST_DATADIRS): - logging.info('Removing ' + cfg.TEST_DATADIRS) + logging.info("Removing " + cfg.TEST_DATADIRS) shutil.rmtree(cfg.TEST_DATADIRS) for i in range(NUM_NODES): prepareDir(cfg.TEST_DATADIRS, i, cls.network_key, cls.network_pubkey) prepareOtherDir(cfg.TEST_DATADIRS, NMC_NODE) - prepareOtherDir(cfg.TEST_DATADIRS, BTC_NODE, 'bitcoin.conf') + prepareOtherDir(cfg.TEST_DATADIRS, BTC_NODE, "bitcoin.conf") cls.daemons = [] cls.swap_clients = [] cls.http_threads = [] btc_data_dir = os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)) - if os.path.exists(os.path.join(cfg.BITCOIN_BINDIR, 'bitcoin-wallet')): - callrpc_cli(cfg.BITCOIN_BINDIR, btc_data_dir, 'regtest', '-wallet=wallet.dat -legacy create', 'bitcoin-wallet') + if os.path.exists(os.path.join(cfg.BITCOIN_BINDIR, "bitcoin-wallet")): + callrpc_cli( + cfg.BITCOIN_BINDIR, + btc_data_dir, + "regtest", + "-wallet=wallet.dat -legacy create", + "bitcoin-wallet", + ) cls.daemons.append(startDaemon(btc_data_dir, cfg.BITCOIN_BINDIR, cfg.BITCOIND)) - logging.info('Started %s %d', cfg.BITCOIND, cls.daemons[-1].handle.pid) - cls.daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, str(NMC_NODE)), cfg.NAMECOIN_BINDIR, cfg.NAMECOIND)) - logging.info('Started %s %d', cfg.NAMECOIND, cls.daemons[-1].handle.pid) + logging.info("Started %s %d", cfg.BITCOIND, cls.daemons[-1].handle.pid) + cls.daemons.append( + startDaemon( + os.path.join(cfg.TEST_DATADIRS, str(NMC_NODE)), + cfg.NAMECOIN_BINDIR, + cfg.NAMECOIND, + ) + ) + logging.info("Started %s %d", cfg.NAMECOIND, cls.daemons[-1].handle.pid) for i in range(NUM_NODES): data_dir = os.path.join(cfg.TEST_DATADIRS, str(i)) - if os.path.exists(os.path.join(cfg.PARTICL_BINDIR, 'particl-wallet')): - callrpc_cli(cfg.PARTICL_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat -legacy create', 'particl-wallet') + if os.path.exists(os.path.join(cfg.PARTICL_BINDIR, "particl-wallet")): + callrpc_cli( + cfg.PARTICL_BINDIR, + data_dir, + "regtest", + "-wallet=wallet.dat -legacy create", + "particl-wallet", + ) cls.daemons.append(startDaemon(data_dir, cfg.PARTICL_BINDIR, cfg.PARTICLD)) - logging.info('Started %s %d', cfg.PARTICLD, cls.daemons[-1].handle.pid) + logging.info("Started %s %d", cfg.PARTICLD, cls.daemons[-1].handle.pid) for i in range(NUM_NODES): rpc = make_part_cli_rpc_func(i) waitForRPC(rpc, delay_event) if i == 0: - rpc('extkeyimportmaster', ['abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb']) + rpc( + "extkeyimportmaster", + [ + "abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb" + ], + ) elif i == 1: - rpc('extkeyimportmaster', ['pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic', '', 'true']) - rpc('getnewextaddress', ['lblExtTest']) - rpc('rescanblockchain') + rpc( + "extkeyimportmaster", + [ + "pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic", + "", + "true", + ], + ) + rpc("getnewextaddress", ["lblExtTest"]) + rpc("rescanblockchain") else: - rpc('extkeyimportmaster', [rpc('mnemonic', ['new'])['master']]) - rpc('walletsettings', ['stakingoptions', json.dumps({'stakecombinethreshold': 100, 'stakesplitthreshold': 200}).replace('"', '\\"')]) - rpc('reservebalance', ['false']) + rpc("extkeyimportmaster", [rpc("mnemonic", ["new"])["master"]]) + rpc( + "walletsettings", + [ + "stakingoptions", + json.dumps( + {"stakecombinethreshold": 100, "stakesplitthreshold": 200} + ).replace('"', '\\"'), + ], + ) + rpc("reservebalance", ["false"]) - basicswap_dir = os.path.join(os.path.join(cfg.TEST_DATADIRS, str(i)), 'basicswap') + basicswap_dir = os.path.join( + os.path.join(cfg.TEST_DATADIRS, str(i)), "basicswap" + ) settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME) with open(settings_path) as fs: settings = json.load(fs) - fp = open(os.path.join(basicswap_dir, 'basicswap.log'), 'w') - sc = BasicSwap(fp, basicswap_dir, settings, 'regtest', log_name='BasicSwap{}'.format(i)) + fp = open(os.path.join(basicswap_dir, "basicswap.log"), "w") + sc = BasicSwap( + fp, basicswap_dir, settings, "regtest", log_name="BasicSwap{}".format(i) + ) cls.swap_clients.append(sc) sc.setDaemonPID(Coins.BTC, cls.daemons[0].handle.pid) @@ -320,30 +382,30 @@ class Test(unittest.TestCase): waitForRPC(nmcRpc, delay_event) num_blocks = 500 - logging.info('Mining %d namecoin blocks', num_blocks) - cls.nmc_addr = nmcRpc('getnewaddress mining_addr legacy') - nmcRpc('generatetoaddress {} {}'.format(num_blocks, cls.nmc_addr)) + logging.info("Mining %d namecoin blocks", num_blocks) + cls.nmc_addr = nmcRpc("getnewaddress mining_addr legacy") + nmcRpc("generatetoaddress {} {}".format(num_blocks, cls.nmc_addr)) - ro = nmcRpc('getblockchaininfo') + ro = nmcRpc("getblockchaininfo") try: - assert (ro['bip9_softforks']['csv']['status'] == 'active') + assert ro["bip9_softforks"]["csv"]["status"] == "active" except Exception: - logging.info('nmc: csv is not active') + logging.info("nmc: csv is not active") try: - assert (ro['bip9_softforks']['segwit']['status'] == 'active') + assert ro["bip9_softforks"]["segwit"]["status"] == "active" except Exception: - logging.info('nmc: segwit is not active') + logging.info("nmc: segwit is not active") waitForRPC(btcRpc, delay_event) - cls.btc_addr = btcRpc('getnewaddress mining_addr bech32') - logging.info('Mining %d Bitcoin blocks to %s', num_blocks, cls.btc_addr) - btcRpc('generatetoaddress {} {}'.format(num_blocks, cls.btc_addr)) + cls.btc_addr = btcRpc("getnewaddress mining_addr bech32") + logging.info("Mining %d Bitcoin blocks to %s", num_blocks, cls.btc_addr) + btcRpc("generatetoaddress {} {}".format(num_blocks, cls.btc_addr)) - ro = btcRpc('getblockchaininfo') + ro = btcRpc("getblockchaininfo") checkForks(ro) - ro = nmcRpc('getwalletinfo') - print('nmcRpc', ro) + ro = nmcRpc("getwalletinfo") + print("nmcRpc", ro) signal.signal(signal.SIGINT, signal_handler) cls.update_thread = threading.Thread(target=run_loop, args=(cls,)) @@ -354,19 +416,19 @@ class Test(unittest.TestCase): # Wait for height, or sequencelock is thrown off by genesis blocktime num_blocks = 3 - logging.info('Waiting for Particl chain height %d', num_blocks) + logging.info("Waiting for Particl chain height %d", num_blocks) for i in range(60): - particl_blocks = cls.swap_clients[0].callrpc('getblockcount') - print('particl_blocks', particl_blocks) + particl_blocks = cls.swap_clients[0].callrpc("getblockcount") + print("particl_blocks", particl_blocks) if particl_blocks >= num_blocks: break delay_event.wait(1) - assert (particl_blocks >= num_blocks) + assert particl_blocks >= num_blocks @classmethod def tearDownClass(cls): global stop_test - logging.info('Finalising') + logging.info("Finalising") stop_test = True cls.update_thread.join() cls.coins_update_thread.join() @@ -385,10 +447,18 @@ class Test(unittest.TestCase): super(Test, cls).tearDownClass() def test_02_part_nmc(self): - logging.info('---------- Test PART to NMC') + logging.info("---------- Test PART to NMC") swap_clients = self.swap_clients - offer_id = swap_clients[0].postOffer(Coins.PART, Coins.NMC, 100 * COIN, 0.1 * COIN, 100 * COIN, SwapTypes.SELLER_FIRST, TxLockTypes.ABS_LOCK_TIME) + offer_id = swap_clients[0].postOffer( + Coins.PART, + Coins.NMC, + 100 * COIN, + 0.1 * COIN, + 100 * COIN, + SwapTypes.SELLER_FIRST, + TxLockTypes.ABS_LOCK_TIME, + ) wait_for_offer(delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -400,19 +470,36 @@ class Test(unittest.TestCase): wait_for_in_progress(delay_event, swap_clients[1], bid_id, sent=True) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) - wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60) + wait_for_bid( + delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60 + ) + wait_for_bid( + delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=60, + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 def test_03_nmc_part(self): - logging.info('---------- Test NMC to PART') + logging.info("---------- Test NMC to PART") swap_clients = self.swap_clients - offer_id = swap_clients[1].postOffer(Coins.NMC, Coins.PART, 10 * COIN, 9.0 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST, TxLockTypes.ABS_LOCK_TIME) + offer_id = swap_clients[1].postOffer( + Coins.NMC, + Coins.PART, + 10 * COIN, + 9.0 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + TxLockTypes.ABS_LOCK_TIME, + ) wait_for_offer(delay_event, swap_clients[0], offer_id) offer = swap_clients[0].getOffer(offer_id) @@ -423,19 +510,36 @@ class Test(unittest.TestCase): wait_for_in_progress(delay_event, swap_clients[0], bid_id, sent=True) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60) - wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) + wait_for_bid( + delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=60, + ) + wait_for_bid( + delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=60 + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 def test_04_nmc_btc(self): - logging.info('---------- Test NMC to BTC') + logging.info("---------- Test NMC to BTC") swap_clients = self.swap_clients - offer_id = swap_clients[0].postOffer(Coins.NMC, Coins.BTC, 10 * COIN, 0.1 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST, TxLockTypes.ABS_LOCK_TIME) + offer_id = swap_clients[0].postOffer( + Coins.NMC, + Coins.BTC, + 10 * COIN, + 0.1 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + TxLockTypes.ABS_LOCK_TIME, + ) wait_for_offer(delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -446,24 +550,39 @@ class Test(unittest.TestCase): wait_for_in_progress(delay_event, swap_clients[1], bid_id, sent=True) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) - wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60) - - js_0bid = read_json_api(1800, 'bids/{}'.format(bid_id.hex())) + wait_for_bid( + delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60 + ) + wait_for_bid( + delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=60, + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 def test_05_refund(self): # Seller submits initiate txn, buyer doesn't respond - logging.info('---------- Test refund, NMC to BTC') + logging.info("---------- Test refund, NMC to BTC") swap_clients = self.swap_clients - offer_id = swap_clients[0].postOffer(Coins.NMC, Coins.BTC, 10 * COIN, 0.1 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST, - TxLockTypes.ABS_LOCK_BLOCKS, 10) + offer_id = swap_clients[0].postOffer( + Coins.NMC, + Coins.BTC, + 10 * COIN, + 0.1 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + TxLockTypes.ABS_LOCK_BLOCKS, + 10, + ) wait_for_offer(delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -473,21 +592,38 @@ class Test(unittest.TestCase): swap_clients[1].abandonBid(bid_id) swap_clients[0].acceptBid(bid_id) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) - wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.BID_ABANDONED, sent=True, wait_for=60) + wait_for_bid( + delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60 + ) + wait_for_bid( + delay_event, + swap_clients[1], + bid_id, + BidStates.BID_ABANDONED, + sent=True, + wait_for=60, + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 def test_06_self_bid(self): - logging.info('---------- Test same client, BTC to NMC') + logging.info("---------- Test same client, BTC to NMC") swap_clients = self.swap_clients js_0_before = read_json_api(1800) - offer_id = swap_clients[0].postOffer(Coins.NMC, Coins.BTC, 10 * COIN, 10 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST, TxLockTypes.ABS_LOCK_TIME) + offer_id = swap_clients[0].postOffer( + Coins.NMC, + Coins.BTC, + 10 * COIN, + 10 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + TxLockTypes.ABS_LOCK_TIME, + ) wait_for_offer(delay_event, swap_clients[0], offer_id) offer = swap_clients[0].getOffer(offer_id) @@ -496,20 +632,38 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id) swap_clients[0].acceptBid(bid_id) - wait_for_bid_tx_state(delay_event, swap_clients[0], bid_id, TxStates.TX_REDEEMED, TxStates.TX_REDEEMED, wait_for=60) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) + wait_for_bid_tx_state( + delay_event, + swap_clients[0], + bid_id, + TxStates.TX_REDEEMED, + TxStates.TX_REDEEMED, + wait_for=60, + ) + wait_for_bid( + delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60 + ) js_0 = read_json_api(1800) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_0['num_recv_bids'] == js_0_before['num_recv_bids'] + 1 and js_0['num_sent_bids'] == js_0_before['num_sent_bids'] + 1) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert ( + js_0["num_recv_bids"] == js_0_before["num_recv_bids"] + 1 + and js_0["num_sent_bids"] == js_0_before["num_sent_bids"] + 1 + ) def test_07_error(self): - logging.info('---------- Test error, BTC to NMC, set fee above bid value') + logging.info("---------- Test error, BTC to NMC, set fee above bid value") swap_clients = self.swap_clients - js_0_before = read_json_api(1800) - - offer_id = swap_clients[0].postOffer(Coins.NMC, Coins.BTC, 0.001 * COIN, 1.0 * COIN, 0.001 * COIN, SwapTypes.SELLER_FIRST, TxLockTypes.ABS_LOCK_TIME) + offer_id = swap_clients[0].postOffer( + Coins.NMC, + Coins.BTC, + 0.001 * COIN, + 1.0 * COIN, + 0.001 * COIN, + SwapTypes.SELLER_FIRST, + TxLockTypes.ABS_LOCK_TIME, + ) wait_for_offer(delay_event, swap_clients[0], offer_id) offer = swap_clients[0].getOffer(offer_id) @@ -518,24 +672,26 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id) swap_clients[0].acceptBid(bid_id) try: - swap_clients[0].getChainClientSettings(Coins.BTC)['override_feerate'] = 10.0 - swap_clients[0].getChainClientSettings(Coins.NMC)['override_feerate'] = 10.0 - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.BID_ERROR, wait_for=60) + swap_clients[0].getChainClientSettings(Coins.BTC)["override_feerate"] = 10.0 + swap_clients[0].getChainClientSettings(Coins.NMC)["override_feerate"] = 10.0 + wait_for_bid( + delay_event, swap_clients[0], bid_id, BidStates.BID_ERROR, wait_for=60 + ) swap_clients[0].abandonBid(bid_id) finally: - del swap_clients[0].getChainClientSettings(Coins.BTC)['override_feerate'] - del swap_clients[0].getChainClientSettings(Coins.NMC)['override_feerate'] + del swap_clients[0].getChainClientSettings(Coins.BTC)["override_feerate"] + del swap_clients[0].getChainClientSettings(Coins.NMC)["override_feerate"] def pass_99_delay(self): global stop_test - logging.info('Delay') + logging.info("Delay") for i in range(60 * 5): if stop_test: break time.sleep(1) - print('delay', i) + print("delay", i) stop_test = True -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/extended/test_pivx.py b/tests/basicswap/extended/test_pivx.py index 690a664..3c03dea 100644 --- a/tests/basicswap/extended/test_pivx.py +++ b/tests/basicswap/extended/test_pivx.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2022-2023 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -84,85 +85,87 @@ BTC_NODE = 4 delay_event = threading.Event() stop_test = False -PIVX_BINDIR = os.path.expanduser(os.getenv('PIVX_BINDIR', os.path.join(cfg.DEFAULT_TEST_BINDIR, 'pivx'))) -PIVXD = os.getenv('PIVXD', 'pivxd' + cfg.bin_suffix) -PIVX_CLI = os.getenv('PIVX_CLI', 'pivx-cli' + cfg.bin_suffix) -PIVX_TX = os.getenv('PIVX_TX', 'pivx-tx' + cfg.bin_suffix) +PIVX_BINDIR = os.path.expanduser( + os.getenv("PIVX_BINDIR", os.path.join(cfg.DEFAULT_TEST_BINDIR, "pivx")) +) +PIVXD = os.getenv("PIVXD", "pivxd" + cfg.bin_suffix) +PIVX_CLI = os.getenv("PIVX_CLI", "pivx-cli" + cfg.bin_suffix) +PIVX_TX = os.getenv("PIVX_TX", "pivx-tx" + cfg.bin_suffix) -def prepareOtherDir(datadir, nodeId, conf_file='pivx.conf'): +def prepareOtherDir(datadir, nodeId, conf_file="pivx.conf"): node_dir = os.path.join(datadir, str(nodeId)) if not os.path.exists(node_dir): os.makedirs(node_dir) filePath = os.path.join(node_dir, conf_file) - with open(filePath, 'w+') as fp: - fp.write('regtest=1\n') - fp.write('[regtest]\n') - fp.write('port=' + str(BASE_PORT + nodeId) + '\n') - fp.write('rpcport=' + str(BASE_RPC_PORT + nodeId) + '\n') + with open(filePath, "w+") as fp: + fp.write("regtest=1\n") + fp.write("[regtest]\n") + fp.write("port=" + str(BASE_PORT + nodeId) + "\n") + fp.write("rpcport=" + str(BASE_RPC_PORT + nodeId) + "\n") - fp.write('daemon=0\n') - fp.write('printtoconsole=0\n') - fp.write('server=1\n') - fp.write('discover=0\n') - fp.write('listenonion=0\n') - fp.write('bind=127.0.0.1\n') - fp.write('findpeers=0\n') - fp.write('debug=1\n') - fp.write('debugexclude=libevent\n') + fp.write("daemon=0\n") + fp.write("printtoconsole=0\n") + fp.write("server=1\n") + fp.write("discover=0\n") + fp.write("listenonion=0\n") + fp.write("bind=127.0.0.1\n") + fp.write("findpeers=0\n") + fp.write("debug=1\n") + fp.write("debugexclude=libevent\n") - fp.write('fallbackfee=0.01\n') - fp.write('acceptnonstdtxn=0\n') + fp.write("fallbackfee=0.01\n") + fp.write("acceptnonstdtxn=0\n") - if conf_file == 'pivx.conf': - params_dir = os.path.join(datadir, 'pivx-params') + if conf_file == "pivx.conf": + params_dir = os.path.join(datadir, "pivx-params") downloadPIVXParams(params_dir) - fp.write(f'paramsdir={params_dir}\n') + fp.write(f"paramsdir={params_dir}\n") - if conf_file == 'bitcoin.conf': - fp.write('wallet=wallet.dat\n') + if conf_file == "bitcoin.conf": + fp.write("wallet=wallet.dat\n") def prepareDir(datadir, nodeId, network_key, network_pubkey): node_dir = os.path.join(datadir, str(nodeId)) if not os.path.exists(node_dir): os.makedirs(node_dir) - filePath = os.path.join(node_dir, 'particl.conf') + filePath = os.path.join(node_dir, "particl.conf") - with open(filePath, 'w+') as fp: - fp.write('regtest=1\n') - fp.write('[regtest]\n') - fp.write('port=' + str(BASE_PORT + nodeId) + '\n') - fp.write('rpcport=' + str(BASE_RPC_PORT + nodeId) + '\n') + with open(filePath, "w+") as fp: + fp.write("regtest=1\n") + fp.write("[regtest]\n") + fp.write("port=" + str(BASE_PORT + nodeId) + "\n") + fp.write("rpcport=" + str(BASE_RPC_PORT + nodeId) + "\n") - fp.write('daemon=0\n') - fp.write('printtoconsole=0\n') - fp.write('server=1\n') - fp.write('discover=0\n') - fp.write('listenonion=0\n') - fp.write('bind=127.0.0.1\n') - fp.write('findpeers=0\n') - fp.write('debug=1\n') - fp.write('debugexclude=libevent\n') - fp.write('zmqpubsmsg=tcp://127.0.0.1:' + str(BASE_ZMQ_PORT + nodeId) + '\n') - fp.write('wallet=wallet.dat\n') - fp.write('fallbackfee=0.01\n') + fp.write("daemon=0\n") + fp.write("printtoconsole=0\n") + fp.write("server=1\n") + fp.write("discover=0\n") + fp.write("listenonion=0\n") + fp.write("bind=127.0.0.1\n") + fp.write("findpeers=0\n") + fp.write("debug=1\n") + fp.write("debugexclude=libevent\n") + fp.write("zmqpubsmsg=tcp://127.0.0.1:" + str(BASE_ZMQ_PORT + nodeId) + "\n") + fp.write("wallet=wallet.dat\n") + fp.write("fallbackfee=0.01\n") - fp.write('acceptnonstdtxn=0\n') - fp.write('minstakeinterval=5\n') - fp.write('smsgsregtestadjust=0\n') + fp.write("acceptnonstdtxn=0\n") + fp.write("minstakeinterval=5\n") + fp.write("smsgsregtestadjust=0\n") for i in range(0, NUM_NODES): if nodeId == i: continue - fp.write('addnode=127.0.0.1:%d\n' % (BASE_PORT + i)) + fp.write("addnode=127.0.0.1:%d\n" % (BASE_PORT + i)) if nodeId < 2: - fp.write('spentindex=1\n') - fp.write('txindex=1\n') + fp.write("spentindex=1\n") + fp.write("txindex=1\n") - basicswap_dir = os.path.join(datadir, str(nodeId), 'basicswap') + basicswap_dir = os.path.join(datadir, str(nodeId), "basicswap") if not os.path.exists(basicswap_dir): os.makedirs(basicswap_dir) @@ -170,72 +173,90 @@ def prepareDir(datadir, nodeId, network_key, network_pubkey): btcdatadir = os.path.join(datadir, str(BTC_NODE)) settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME) settings = { - 'debug': True, - 'zmqhost': 'tcp://127.0.0.1', - 'zmqport': BASE_ZMQ_PORT + nodeId, - 'htmlhost': '127.0.0.1', - 'htmlport': 12700 + nodeId, - 'network_key': network_key, - 'network_pubkey': network_pubkey, - 'chainclients': { - 'particl': { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': BASE_RPC_PORT + nodeId, - 'datadir': node_dir, - 'bindir': cfg.PARTICL_BINDIR, - 'blocks_confirmed': 2, # Faster testing + "debug": True, + "zmqhost": "tcp://127.0.0.1", + "zmqport": BASE_ZMQ_PORT + nodeId, + "htmlhost": "127.0.0.1", + "htmlport": 12700 + nodeId, + "network_key": network_key, + "network_pubkey": network_pubkey, + "chainclients": { + "particl": { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": BASE_RPC_PORT + nodeId, + "datadir": node_dir, + "bindir": cfg.PARTICL_BINDIR, + "blocks_confirmed": 2, # Faster testing }, - 'pivx': { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': BASE_RPC_PORT + PIVX_NODE, - 'datadir': pivxdatadir, - 'bindir': PIVX_BINDIR, - 'use_csv': False, - 'use_segwit': False, + "pivx": { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": BASE_RPC_PORT + PIVX_NODE, + "datadir": pivxdatadir, + "bindir": PIVX_BINDIR, + "use_csv": False, + "use_segwit": False, + }, + "bitcoin": { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": BASE_RPC_PORT + BTC_NODE, + "datadir": btcdatadir, + "bindir": cfg.BITCOIN_BINDIR, + "use_segwit": True, }, - 'bitcoin': { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': BASE_RPC_PORT + BTC_NODE, - 'datadir': btcdatadir, - 'bindir': cfg.BITCOIN_BINDIR, - 'use_segwit': True, - } }, - 'check_progress_seconds': 2, - 'check_watched_seconds': 4, - 'check_expired_seconds': 60, - 'check_events_seconds': 1, - 'check_xmr_swaps_seconds': 1, - 'min_delay_event': 1, - 'max_delay_event': 3, - 'min_delay_event_short': 1, - 'max_delay_event_short': 3, - 'min_delay_retry': 2, - 'max_delay_retry': 10, - 'restrict_unknown_seed_wallets': False + "check_progress_seconds": 2, + "check_watched_seconds": 4, + "check_expired_seconds": 60, + "check_events_seconds": 1, + "check_xmr_swaps_seconds": 1, + "min_delay_event": 1, + "max_delay_event": 3, + "min_delay_event_short": 1, + "max_delay_event_short": 3, + "min_delay_retry": 2, + "max_delay_retry": 10, + "restrict_unknown_seed_wallets": False, } - with open(settings_path, 'w') as fp: + with open(settings_path, "w") as fp: json.dump(settings, fp, indent=4) def partRpc(cmd, node_id=0): - return callrpc_cli(cfg.PARTICL_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(node_id)), 'regtest', cmd, cfg.PARTICL_CLI) + return callrpc_cli( + cfg.PARTICL_BINDIR, + os.path.join(cfg.TEST_DATADIRS, str(node_id)), + "regtest", + cmd, + cfg.PARTICL_CLI, + ) def btcRpc(cmd): - return callrpc_cli(cfg.BITCOIN_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)), 'regtest', cmd, cfg.BITCOIN_CLI) + return callrpc_cli( + cfg.BITCOIN_BINDIR, + os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)), + "regtest", + cmd, + cfg.BITCOIN_CLI, + ) def pivxRpc(cmd): - return callrpc_cli(PIVX_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(PIVX_NODE)), 'regtest', cmd, PIVX_CLI) + return callrpc_cli( + PIVX_BINDIR, + os.path.join(cfg.TEST_DATADIRS, str(PIVX_NODE)), + "regtest", + cmd, + PIVX_CLI, + ) def signal_handler(sig, frame): global stop_test - print('signal {} detected.'.format(sig)) + print("signal {} detected.".format(sig)) stop_test = True delay_event.set() @@ -243,10 +264,10 @@ def signal_handler(sig, frame): def run_coins_loop(cls): while not stop_test: try: - pivxRpc('generatetoaddress 1 {}'.format(cls.pivx_addr)) - btcRpc('generatetoaddress 1 {}'.format(cls.btc_addr)) + pivxRpc("generatetoaddress 1 {}".format(cls.pivx_addr)) + btcRpc("generatetoaddress 1 {}".format(cls.btc_addr)) except Exception as e: - logging.warning('run_coins_loop ' + str(e)) + logging.warning("run_coins_loop " + str(e)) time.sleep(1.0) @@ -267,6 +288,7 @@ def make_part_cli_rpc_func(node_id): for p in params: cmd += ' "' + p + '"' return partRpc(cmd, node_id) + return rpc_func @@ -283,9 +305,9 @@ class Test(unittest.TestCase): cls.network_pubkey = eckey.get_pubkey().get_bytes().hex() if os.path.isdir(cfg.TEST_DATADIRS): - logging.info('Removing ' + cfg.TEST_DATADIRS) + logging.info("Removing " + cfg.TEST_DATADIRS) for name in os.listdir(cfg.TEST_DATADIRS): - if name == 'pivx-params': + if name == "pivx-params": continue fullpath = os.path.join(cfg.TEST_DATADIRS, name) if os.path.isdir(fullpath): @@ -297,53 +319,105 @@ class Test(unittest.TestCase): prepareDir(cfg.TEST_DATADIRS, i, cls.network_key, cls.network_pubkey) prepareOtherDir(cfg.TEST_DATADIRS, PIVX_NODE) - prepareOtherDir(cfg.TEST_DATADIRS, BTC_NODE, 'bitcoin.conf') + prepareOtherDir(cfg.TEST_DATADIRS, BTC_NODE, "bitcoin.conf") cls.daemons = [] cls.swap_clients = [] cls.http_threads = [] btc_data_dir = os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)) - if os.path.exists(os.path.join(cfg.BITCOIN_BINDIR, 'bitcoin-wallet')): + if os.path.exists(os.path.join(cfg.BITCOIN_BINDIR, "bitcoin-wallet")): try: - callrpc_cli(cfg.BITCOIN_BINDIR, btc_data_dir, 'regtest', '-wallet=wallet.dat -legacy create', 'bitcoin-wallet') + callrpc_cli( + cfg.BITCOIN_BINDIR, + btc_data_dir, + "regtest", + "-wallet=wallet.dat -legacy create", + "bitcoin-wallet", + ) except Exception: - callrpc_cli(cfg.BITCOIN_BINDIR, btc_data_dir, 'regtest', '-wallet=wallet.dat create', 'bitcoin-wallet') + callrpc_cli( + cfg.BITCOIN_BINDIR, + btc_data_dir, + "regtest", + "-wallet=wallet.dat create", + "bitcoin-wallet", + ) cls.daemons.append(startDaemon(btc_data_dir, cfg.BITCOIN_BINDIR, cfg.BITCOIND)) - logging.info('Started %s %d', cfg.BITCOIND, cls.daemons[-1].handle.pid) - cls.daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, str(PIVX_NODE)), PIVX_BINDIR, PIVXD)) - logging.info('Started %s %d', PIVXD, cls.daemons[-1].handle.pid) + logging.info("Started %s %d", cfg.BITCOIND, cls.daemons[-1].handle.pid) + cls.daemons.append( + startDaemon( + os.path.join(cfg.TEST_DATADIRS, str(PIVX_NODE)), PIVX_BINDIR, PIVXD + ) + ) + logging.info("Started %s %d", PIVXD, cls.daemons[-1].handle.pid) for i in range(NUM_NODES): data_dir = os.path.join(cfg.TEST_DATADIRS, str(i)) - if os.path.exists(os.path.join(cfg.PARTICL_BINDIR, 'particl-wallet')): + if os.path.exists(os.path.join(cfg.PARTICL_BINDIR, "particl-wallet")): try: - callrpc_cli(cfg.PARTICL_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat -legacy create', 'particl-wallet') + callrpc_cli( + cfg.PARTICL_BINDIR, + data_dir, + "regtest", + "-wallet=wallet.dat -legacy create", + "particl-wallet", + ) except Exception: - callrpc_cli(cfg.PARTICL_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat create', 'particl-wallet') + callrpc_cli( + cfg.PARTICL_BINDIR, + data_dir, + "regtest", + "-wallet=wallet.dat create", + "particl-wallet", + ) cls.daemons.append(startDaemon(data_dir, cfg.PARTICL_BINDIR, cfg.PARTICLD)) - logging.info('Started %s %d', cfg.PARTICLD, cls.daemons[-1].handle.pid) + logging.info("Started %s %d", cfg.PARTICLD, cls.daemons[-1].handle.pid) for i in range(NUM_NODES): rpc = make_part_cli_rpc_func(i) waitForRPC(rpc, delay_event) if i == 0: - rpc('extkeyimportmaster', ['abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb']) + rpc( + "extkeyimportmaster", + [ + "abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb" + ], + ) elif i == 1: - rpc('extkeyimportmaster', ['pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic', '', 'true']) - rpc('getnewextaddress', ['lblExtTest']) - rpc('rescanblockchain') + rpc( + "extkeyimportmaster", + [ + "pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic", + "", + "true", + ], + ) + rpc("getnewextaddress", ["lblExtTest"]) + rpc("rescanblockchain") else: - rpc('extkeyimportmaster', [rpc('mnemonic', ['new'])['master']]) - rpc('walletsettings', ['stakingoptions', json.dumps({'stakecombinethreshold': 100, 'stakesplitthreshold': 200}).replace('"', '\\"')]) - rpc('reservebalance', ['false']) + rpc("extkeyimportmaster", [rpc("mnemonic", ["new"])["master"]]) + rpc( + "walletsettings", + [ + "stakingoptions", + json.dumps( + {"stakecombinethreshold": 100, "stakesplitthreshold": 200} + ).replace('"', '\\"'), + ], + ) + rpc("reservebalance", ["false"]) - basicswap_dir = os.path.join(os.path.join(cfg.TEST_DATADIRS, str(i)), 'basicswap') + basicswap_dir = os.path.join( + os.path.join(cfg.TEST_DATADIRS, str(i)), "basicswap" + ) settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME) with open(settings_path) as fs: settings = json.load(fs) - fp = open(os.path.join(basicswap_dir, 'basicswap.log'), 'w') - sc = BasicSwap(fp, basicswap_dir, settings, 'regtest', log_name='BasicSwap{}'.format(i)) + fp = open(os.path.join(basicswap_dir, "basicswap.log"), "w") + sc = BasicSwap( + fp, basicswap_dir, settings, "regtest", log_name="BasicSwap{}".format(i) + ) cls.swap_clients.append(sc) sc.setDaemonPID(Coins.BTC, cls.daemons[0].handle.pid) sc.setDaemonPID(Coins.PIVX, cls.daemons[1].handle.pid) @@ -356,26 +430,26 @@ class Test(unittest.TestCase): waitForRPC(pivxRpc, delay_event) num_blocks = 1352 # CHECKLOCKTIMEVERIFY soft-fork activates at (regtest) block height 1351. - logging.info('Mining %d pivx blocks', num_blocks) - cls.pivx_addr = pivxRpc('getnewaddress mining_addr') - pivxRpc('generatetoaddress {} {}'.format(num_blocks, cls.pivx_addr)) + logging.info("Mining %d pivx blocks", num_blocks) + cls.pivx_addr = pivxRpc("getnewaddress mining_addr") + pivxRpc("generatetoaddress {} {}".format(num_blocks, cls.pivx_addr)) - ro = pivxRpc('getblockchaininfo') + ro = pivxRpc("getblockchaininfo") try: - assert (ro['bip9_softforks']['csv']['status'] == 'active') + assert ro["bip9_softforks"]["csv"]["status"] == "active" except Exception: - logging.info('pivx: csv is not active') + logging.info("pivx: csv is not active") try: - assert (ro['bip9_softforks']['segwit']['status'] == 'active') + assert ro["bip9_softforks"]["segwit"]["status"] == "active" except Exception: - logging.info('pivx: segwit is not active') + logging.info("pivx: segwit is not active") waitForRPC(btcRpc, delay_event) - cls.btc_addr = btcRpc('getnewaddress mining_addr bech32') - logging.info('Mining %d Bitcoin blocks to %s', num_blocks, cls.btc_addr) - btcRpc('generatetoaddress {} {}'.format(num_blocks, cls.btc_addr)) + cls.btc_addr = btcRpc("getnewaddress mining_addr bech32") + logging.info("Mining %d Bitcoin blocks to %s", num_blocks, cls.btc_addr) + btcRpc("generatetoaddress {} {}".format(num_blocks, cls.btc_addr)) - ro = btcRpc('getblockchaininfo') + ro = btcRpc("getblockchaininfo") checkForks(ro) signal.signal(signal.SIGINT, signal_handler) @@ -387,19 +461,19 @@ class Test(unittest.TestCase): # Wait for height, or sequencelock is thrown off by genesis blocktime num_blocks = 3 - logging.info('Waiting for Particl chain height %d', num_blocks) + logging.info("Waiting for Particl chain height %d", num_blocks) for i in range(60): - particl_blocks = cls.swap_clients[0].callrpc('getblockcount') - print('particl_blocks', particl_blocks) + particl_blocks = cls.swap_clients[0].callrpc("getblockcount") + print("particl_blocks", particl_blocks) if particl_blocks >= num_blocks: break delay_event.wait(1) - assert (particl_blocks >= num_blocks) + assert particl_blocks >= num_blocks @classmethod def tearDownClass(cls): global stop_test - logging.info('Finalising') + logging.info("Finalising") stop_test = True cls.update_thread.join() cls.coins_update_thread.join() @@ -418,10 +492,18 @@ class Test(unittest.TestCase): super(Test, cls).tearDownClass() def test_02_part_pivx(self): - logging.info('---------- Test PART to PIVX') + logging.info("---------- Test PART to PIVX") swap_clients = self.swap_clients - offer_id = swap_clients[0].postOffer(Coins.PART, Coins.PIVX, 100 * COIN, 0.1 * COIN, 100 * COIN, SwapTypes.SELLER_FIRST, TxLockTypes.ABS_LOCK_TIME) + offer_id = swap_clients[0].postOffer( + Coins.PART, + Coins.PIVX, + 100 * COIN, + 0.1 * COIN, + 100 * COIN, + SwapTypes.SELLER_FIRST, + TxLockTypes.ABS_LOCK_TIME, + ) wait_for_offer(delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -433,19 +515,36 @@ class Test(unittest.TestCase): wait_for_in_progress(delay_event, swap_clients[1], bid_id, sent=True) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) - wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60) + wait_for_bid( + delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60 + ) + wait_for_bid( + delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=60, + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 def test_03_pivx_part(self): - logging.info('---------- Test PIVX to PART') + logging.info("---------- Test PIVX to PART") swap_clients = self.swap_clients - offer_id = swap_clients[1].postOffer(Coins.PIVX, Coins.PART, 10 * COIN, 9.0 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST, TxLockTypes.ABS_LOCK_TIME) + offer_id = swap_clients[1].postOffer( + Coins.PIVX, + Coins.PART, + 10 * COIN, + 9.0 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + TxLockTypes.ABS_LOCK_TIME, + ) wait_for_offer(delay_event, swap_clients[0], offer_id) offer = swap_clients[0].getOffer(offer_id) @@ -456,19 +555,36 @@ class Test(unittest.TestCase): wait_for_in_progress(delay_event, swap_clients[0], bid_id, sent=True) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60) - wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) + wait_for_bid( + delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=60, + ) + wait_for_bid( + delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=60 + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 def test_04_pivx_btc(self): - logging.info('---------- Test PIVX to BTC') + logging.info("---------- Test PIVX to BTC") swap_clients = self.swap_clients - offer_id = swap_clients[0].postOffer(Coins.PIVX, Coins.BTC, 10 * COIN, 0.1 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST, TxLockTypes.ABS_LOCK_TIME) + offer_id = swap_clients[0].postOffer( + Coins.PIVX, + Coins.BTC, + 10 * COIN, + 0.1 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + TxLockTypes.ABS_LOCK_TIME, + ) wait_for_offer(delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -479,24 +595,39 @@ class Test(unittest.TestCase): wait_for_in_progress(delay_event, swap_clients[1], bid_id, sent=True) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) - wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60) - - js_0bid = read_json_api(1800, 'bids/{}'.format(bid_id.hex())) + wait_for_bid( + delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60 + ) + wait_for_bid( + delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=60, + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 def test_05_refund(self): # Seller submits initiate txn, buyer doesn't respond - logging.info('---------- Test refund, PIVX to BTC') + logging.info("---------- Test refund, PIVX to BTC") swap_clients = self.swap_clients - offer_id = swap_clients[0].postOffer(Coins.PIVX, Coins.BTC, 10 * COIN, 0.1 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST, - TxLockTypes.ABS_LOCK_BLOCKS, 10) + offer_id = swap_clients[0].postOffer( + Coins.PIVX, + Coins.BTC, + 10 * COIN, + 0.1 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + TxLockTypes.ABS_LOCK_BLOCKS, + 10, + ) wait_for_offer(delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -506,21 +637,38 @@ class Test(unittest.TestCase): swap_clients[1].abandonBid(bid_id) swap_clients[0].acceptBid(bid_id) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) - wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.BID_ABANDONED, sent=True, wait_for=60) + wait_for_bid( + delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60 + ) + wait_for_bid( + delay_event, + swap_clients[1], + bid_id, + BidStates.BID_ABANDONED, + sent=True, + wait_for=60, + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 def test_06_self_bid(self): - logging.info('---------- Test same client, BTC to PIVX') + logging.info("---------- Test same client, BTC to PIVX") swap_clients = self.swap_clients js_0_before = read_json_api(1800) - offer_id = swap_clients[0].postOffer(Coins.PIVX, Coins.BTC, 10 * COIN, 10 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST, TxLockTypes.ABS_LOCK_TIME) + offer_id = swap_clients[0].postOffer( + Coins.PIVX, + Coins.BTC, + 10 * COIN, + 10 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + TxLockTypes.ABS_LOCK_TIME, + ) wait_for_offer(delay_event, swap_clients[0], offer_id) offer = swap_clients[0].getOffer(offer_id) @@ -529,20 +677,38 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id) swap_clients[0].acceptBid(bid_id) - wait_for_bid_tx_state(delay_event, swap_clients[0], bid_id, TxStates.TX_REDEEMED, TxStates.TX_REDEEMED, wait_for=60) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) + wait_for_bid_tx_state( + delay_event, + swap_clients[0], + bid_id, + TxStates.TX_REDEEMED, + TxStates.TX_REDEEMED, + wait_for=60, + ) + wait_for_bid( + delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60 + ) js_0 = read_json_api(1800) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_0['num_recv_bids'] == js_0_before['num_recv_bids'] + 1 and js_0['num_sent_bids'] == js_0_before['num_sent_bids'] + 1) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert ( + js_0["num_recv_bids"] == js_0_before["num_recv_bids"] + 1 + and js_0["num_sent_bids"] == js_0_before["num_sent_bids"] + 1 + ) def test_07_error(self): - logging.info('---------- Test error, BTC to PIVX, set fee above bid value') + logging.info("---------- Test error, BTC to PIVX, set fee above bid value") swap_clients = self.swap_clients - js_0_before = read_json_api(1800) - - offer_id = swap_clients[0].postOffer(Coins.PIVX, Coins.BTC, 0.001 * COIN, 1.0 * COIN, 0.001 * COIN, SwapTypes.SELLER_FIRST, TxLockTypes.ABS_LOCK_TIME) + offer_id = swap_clients[0].postOffer( + Coins.PIVX, + Coins.BTC, + 0.001 * COIN, + 1.0 * COIN, + 0.001 * COIN, + SwapTypes.SELLER_FIRST, + TxLockTypes.ABS_LOCK_TIME, + ) wait_for_offer(delay_event, swap_clients[0], offer_id) offer = swap_clients[0].getOffer(offer_id) @@ -551,78 +717,103 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id) swap_clients[0].acceptBid(bid_id) try: - swap_clients[0].getChainClientSettings(Coins.BTC)['override_feerate'] = 10.0 - swap_clients[0].getChainClientSettings(Coins.PIVX)['override_feerate'] = 10.0 - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.BID_ERROR, wait_for=60) + swap_clients[0].getChainClientSettings(Coins.BTC)["override_feerate"] = 10.0 + swap_clients[0].getChainClientSettings(Coins.PIVX)[ + "override_feerate" + ] = 10.0 + wait_for_bid( + delay_event, swap_clients[0], bid_id, BidStates.BID_ERROR, wait_for=60 + ) swap_clients[0].abandonBid(bid_id) finally: - del swap_clients[0].getChainClientSettings(Coins.BTC)['override_feerate'] - del swap_clients[0].getChainClientSettings(Coins.PIVX)['override_feerate'] + del swap_clients[0].getChainClientSettings(Coins.BTC)["override_feerate"] + del swap_clients[0].getChainClientSettings(Coins.PIVX)["override_feerate"] def test_08_wallet(self): - logging.info('---------- Test {} wallet'.format(self.test_coin_from.name)) + logging.info("---------- Test {} wallet".format(self.test_coin_from.name)) - logging.info('Test withdrawal') - addr = pivxRpc('getnewaddress \"Withdrawal test\"') - wallets = read_json_api(TEST_HTTP_PORT + 0, 'wallets') - assert (float(wallets[self.test_coin_from.name]['balance']) > 100) + logging.info("Test withdrawal") + addr = pivxRpc('getnewaddress "Withdrawal test"') + wallets = read_json_api(TEST_HTTP_PORT + 0, "wallets") + assert float(wallets[self.test_coin_from.name]["balance"]) > 100 post_json = { - 'value': 100, - 'address': addr, - 'subfee': False, + "value": 100, + "address": addr, + "subfee": False, } - json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/{}/withdraw'.format(self.test_coin_from.name.lower()), post_json) - assert (len(json_rv['txid']) == 64) + json_rv = read_json_api( + TEST_HTTP_PORT + 0, + "wallets/{}/withdraw".format(self.test_coin_from.name.lower()), + post_json, + ) + assert len(json_rv["txid"]) == 64 - logging.info('Test createutxo') + logging.info("Test createutxo") post_json = { - 'value': 10, + "value": 10, } - json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/{}/createutxo'.format(self.test_coin_from.name.lower()), post_json) - assert (len(json_rv['txid']) == 64) + json_rv = read_json_api( + TEST_HTTP_PORT + 0, + "wallets/{}/createutxo".format(self.test_coin_from.name.lower()), + post_json, + ) + assert len(json_rv["txid"]) == 64 def test_09_v3_tx(self): - logging.info('---------- Test PIVX v3 txns') + logging.info("---------- Test PIVX v3 txns") - generate_addr = pivxRpc('getnewaddress \"generate test\"') - pivx_addr = pivxRpc('getnewaddress \"Sapling test\"') - pivx_sapling_addr = pivxRpc('getnewshieldaddress \"shield addr\"') + generate_addr = pivxRpc('getnewaddress "generate test"') + pivx_addr = pivxRpc('getnewaddress "Sapling test"') + pivx_sapling_addr = pivxRpc('getnewshieldaddress "shield addr"') - pivxRpc(f'sendtoaddress \"{pivx_addr}\" 6.0') - pivxRpc(f'generatetoaddress 1 \"{generate_addr}\"') + pivxRpc(f'sendtoaddress "{pivx_addr}" 6.0') + pivxRpc(f'generatetoaddress 1 "{generate_addr}"') - txid = pivxRpc('shieldsendmany "{}" "[{{\\"address\\": \\"{}\\", \\"amount\\": 1}}]"'.format(pivx_addr, pivx_sapling_addr)) - rtx = pivxRpc(f'getrawtransaction \"{txid}\" true') - assert (rtx['version'] == 3) + txid = pivxRpc( + 'shieldsendmany "{}" "[{{\\"address\\": \\"{}\\", \\"amount\\": 1}}]"'.format( + pivx_addr, pivx_sapling_addr + ) + ) + rtx = pivxRpc(f'getrawtransaction "{txid}" true') + assert rtx["version"] == 3 - block_hash = pivxRpc(f'generatetoaddress 1 \"{generate_addr}\"')[0] + block_hash = pivxRpc(f'generatetoaddress 1 "{generate_addr}"')[0] ci = self.swap_clients[0].ci(Coins.PIVX) block = ci.getBlockWithTxns(block_hash) found = False - for tx in block['tx']: - if txid == tx['txid']: + for tx in block["tx"]: + if txid == tx["txid"]: found = True break assert found def ensure_balance(self, coin_type, node_id, amount): tla = coin_type.name - js_w = read_json_api(1800 + node_id, 'wallets') - if float(js_w[tla]['balance']) < amount: + js_w = read_json_api(1800 + node_id, "wallets") + if float(js_w[tla]["balance"]) < amount: post_json = { - 'value': amount, - 'address': js_w[tla]['deposit_address'], - 'subfee': False, + "value": amount, + "address": js_w[tla]["deposit_address"], + "subfee": False, } - json_rv = read_json_api(1800, 'wallets/{}/withdraw'.format(tla.lower()), post_json) - assert (len(json_rv['txid']) == 64) - wait_for_balance(delay_event, 'http://127.0.0.1:{}/json/wallets/{}'.format(1800 + node_id, tla.lower()), 'balance', amount) + json_rv = read_json_api( + 1800, "wallets/{}/withdraw".format(tla.lower()), post_json + ) + assert len(json_rv["txid"]) == 64 + wait_for_balance( + delay_event, + "http://127.0.0.1:{}/json/wallets/{}".format( + 1800 + node_id, tla.lower() + ), + "balance", + amount, + ) def test_10_prefunded_itx(self): - logging.info('---------- Test prefunded itx offer') + logging.info("---------- Test prefunded itx offer") swap_clients = self.swap_clients coin_from = Coins.PIVX @@ -636,37 +827,55 @@ class Test(unittest.TestCase): self.ensure_balance(coin_from, 2, 10.0) self.ensure_balance(coin_to, 1, 100.0) - js_w2 = read_json_api(1802, 'wallets') + js_w2 = read_json_api(1802, "wallets") post_json = { - 'value': 10.0, - 'address': read_json_api(1802, 'wallets/{}/nextdepositaddr'.format(tla_from.lower())), - 'subfee': True, + "value": 10.0, + "address": read_json_api( + 1802, "wallets/{}/nextdepositaddr".format(tla_from.lower()) + ), + "subfee": True, } - json_rv = read_json_api(1802, 'wallets/{}/withdraw'.format(tla_from.lower()), post_json) - wait_for_balance(delay_event, 'http://127.0.0.1:1802/json/wallets/{}'.format(tla_from.lower()), 'balance', 9.0) - assert (len(json_rv['txid']) == 64) + json_rv = read_json_api( + 1802, "wallets/{}/withdraw".format(tla_from.lower()), post_json + ) + wait_for_balance( + delay_event, + "http://127.0.0.1:1802/json/wallets/{}".format(tla_from.lower()), + "balance", + 9.0, + ) + assert len(json_rv["txid"]) == 64 # Create prefunded ITX pi = swap_clients[2].pi(SwapTypes.XMR_SWAP) - js_w2 = read_json_api(1802, 'wallets') + js_w2 = read_json_api(1802, "wallets") swap_value = 10.0 - if float(js_w2[tla_from]['balance']) < swap_value: - swap_value = js_w2[tla_from]['balance'] + if float(js_w2[tla_from]["balance"]) < swap_value: + swap_value = js_w2[tla_from]["balance"] swap_value = ci_from.make_int(swap_value) - assert (swap_value > ci_from.make_int(9)) + assert swap_value > ci_from.make_int(9) itx = pi.getFundedInitiateTxTemplate(ci_from, swap_value, True) itx_decoded = ci_from.describeTx(itx.hex()) n = pi.findMockVout(ci_from, itx_decoded) - value_after_subfee = ci_from.make_int(itx_decoded['vout'][n]['value']) - assert (value_after_subfee < swap_value) + value_after_subfee = ci_from.make_int(itx_decoded["vout"][n]["value"]) + assert value_after_subfee < swap_value swap_value = value_after_subfee wait_for_unspent(delay_event, ci_from, swap_value) - extra_options = {'prefunded_itx': itx} + extra_options = {"prefunded_itx": itx} rate_swap = ci_to.make_int(random.uniform(0.2, 10.0), r=1) - offer_id = swap_clients[2].postOffer(coin_from, coin_to, swap_value, rate_swap, swap_value, swap_type, TxLockTypes.ABS_LOCK_TIME, extra_options=extra_options) + offer_id = swap_clients[2].postOffer( + coin_from, + coin_to, + swap_value, + rate_swap, + swap_value, + swap_type, + TxLockTypes.ABS_LOCK_TIME, + extra_options=extra_options, + ) wait_for_offer(delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -675,21 +884,35 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[2], bid_id, BidStates.BID_RECEIVED) swap_clients[2].acceptBid(bid_id) - wait_for_bid(delay_event, swap_clients[2], bid_id, BidStates.SWAP_COMPLETED, wait_for=120) - wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=120) + wait_for_bid( + delay_event, swap_clients[2], bid_id, BidStates.SWAP_COMPLETED, wait_for=120 + ) + wait_for_bid( + delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=120, + ) # Verify expected inputs were used bid, offer = swap_clients[2].getBidAndOffer(bid_id) - assert (bid.initiate_tx) - wtx = ci_from.rpc('gettransaction', [bid.initiate_tx.txid.hex(),]) - itx_after = ci_from.describeTx(wtx['hex']) - assert (len(itx_after['vin']) == len(itx_decoded['vin'])) - for i, txin in enumerate(itx_decoded['vin']): - assert (txin['txid'] == itx_after['vin'][i]['txid']) - assert (txin['vout'] == itx_after['vin'][i]['vout']) + assert bid.initiate_tx + wtx = ci_from.rpc( + "gettransaction", + [ + bid.initiate_tx.txid.hex(), + ], + ) + itx_after = ci_from.describeTx(wtx["hex"]) + assert len(itx_after["vin"]) == len(itx_decoded["vin"]) + for i, txin in enumerate(itx_decoded["vin"]): + assert txin["txid"] == itx_after["vin"][i]["txid"] + assert txin["vout"] == itx_after["vin"][i]["vout"] def test_11_xmrswap_to(self): - logging.info('---------- Test xmr swap protocol to') + logging.info("---------- Test xmr swap protocol to") swap_clients = self.swap_clients coin_from = Coins.BTC @@ -700,7 +923,9 @@ class Test(unittest.TestCase): swap_value = ci_from.make_int(random.uniform(0.2, 20.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) - offer_id = swap_clients[0].postOffer(coin_from, coin_to, swap_value, rate_swap, swap_value, swap_type) + offer_id = swap_clients[0].postOffer( + coin_from, coin_to, swap_value, rate_swap, swap_value, swap_type + ) wait_for_offer(delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -709,13 +934,26 @@ class Test(unittest.TestCase): wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) swap_clients[0].acceptBid(bid_id) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=120) - wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=120) + wait_for_bid( + delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=120 + ) + wait_for_bid( + delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=120, + ) def test_12_xmrswap_to_recover_b_lock_tx(self): coin_from = Coins.BTC coin_to = Coins.PIVX - logging.info('---------- Test {} to {} follower recovers coin b lock tx'.format(coin_from.name, coin_to.name)) + logging.info( + "---------- Test {} to {} follower recovers coin b lock tx".format( + coin_from.name, coin_to.name + ) + ) swap_clients = self.swap_clients ci_from = swap_clients[0].ci(coin_from) @@ -724,8 +962,15 @@ class Test(unittest.TestCase): amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) offer_id = swap_clients[0].postOffer( - coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, - lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=32) + coin_from, + coin_to, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, + lock_value=32, + ) wait_for_offer(delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -736,9 +981,21 @@ class Test(unittest.TestCase): swap_clients[1].setBidDebugInd(bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK) swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=180) - wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=True) + wait_for_bid( + delay_event, + swap_clients[0], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + wait_for=180, + ) + wait_for_bid( + delay_event, + swap_clients[1], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + sent=True, + ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/extended/test_prepare.py b/tests/basicswap/extended/test_prepare.py index 26f3562..d4d71f8 100644 --- a/tests/basicswap/extended/test_prepare.py +++ b/tests/basicswap/extended/test_prepare.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019-2024 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -23,11 +24,11 @@ from tests.basicswap.util import ( waitForServer, ) -bin_path = os.path.expanduser(os.getenv('TEST_BIN_PATH', '')) -test_base_path = os.path.expanduser(os.getenv('TEST_PREPARE_PATH', '~/test_basicswap')) -test_path_plain = os.path.join(test_base_path, 'plain') -test_path_encrypted = os.path.join(test_base_path, 'encrypted') -test_path_encrypt = os.path.join(test_base_path, 'encrypt') +bin_path = os.path.expanduser(os.getenv("TEST_BIN_PATH", "")) +test_base_path = os.path.expanduser(os.getenv("TEST_PREPARE_PATH", "~/test_basicswap")) +test_path_plain = os.path.join(test_base_path, "plain") +test_path_encrypted = os.path.join(test_base_path, "encrypted") +test_path_encrypt = os.path.join(test_base_path, "encrypt") delay_event = threading.Event() logger = logging.getLogger() @@ -40,7 +41,8 @@ def start_prepare(args, env_pairs=[]): os.environ[pair[0]] = pair[1] print(pair[0], os.environ[pair[0]]) import basicswap.bin.prepare as prepareSystemThread - with patch.object(sys, 'argv', args): + + with patch.object(sys, "argv", args): prepareSystemThread.main() del prepareSystemThread @@ -50,7 +52,8 @@ def start_run(args, env_pairs=[]): os.environ[pair[0]] = pair[1] print(pair[0], os.environ[pair[0]]) import basicswap.bin.run as runSystemThread - with patch.object(sys, 'argv', args): + + with patch.object(sys, "argv", args): runSystemThread.main() del runSystemThread @@ -63,17 +66,21 @@ class Test(unittest.TestCase): if os.path.exists(test_dir): shutil.rmtree(test_dir) except Exception as ex: - logger.warning('tearDownClass %s', str(ex)) + logger.warning("tearDownClass %s", str(ex)) super(Test, self).tearDownClass() def test_plain(self): if os.path.exists(test_path_plain): shutil.rmtree(test_path_plain) - if bin_path != '': + if bin_path != "": os.makedirs(test_path_plain) - os.symlink(bin_path, os.path.join(test_path_plain, 'bin')) + os.symlink(bin_path, os.path.join(test_path_plain, "bin")) - testargs = ('basicswap-prepare', '-datadir=' + test_path_plain, '-withcoin=litecoin') + testargs = ( + "basicswap-prepare", + "-datadir=" + test_path_plain, + "-withcoin=litecoin", + ) process = multiprocessing.Process(target=start_prepare, args=(testargs,)) process.start() process.join() @@ -82,50 +89,81 @@ class Test(unittest.TestCase): self.assertTrue(os.path.exists(config_path)) import basicswap.bin.prepare as prepareSystem + try: - logging.info('Test no overwrite') - testargs = ['basicswap-prepare', '-datadir=' + test_path_plain, '-withcoin=litecoin'] - with patch('sys.stderr', new=StringIO()) as fake_stderr: - with patch.object(sys, 'argv', testargs): + logging.info("Test no overwrite") + testargs = [ + "basicswap-prepare", + "-datadir=" + test_path_plain, + "-withcoin=litecoin", + ] + with patch("sys.stderr", new=StringIO()) as fake_stderr: + with patch.object(sys, "argv", testargs): with self.assertRaises(SystemExit) as cm: prepareSystem.main() self.assertEqual(cm.exception.code, 1) - self.assertTrue('exists, exiting' in fake_stderr.getvalue()) + self.assertTrue("exists, exiting" in fake_stderr.getvalue()) - logger.info('Test addcoin new') - testargs = ['basicswap-prepare', '-datadir=' + test_path_plain, '-addcoin=namecoin'] - with patch.object(sys, 'argv', testargs): + logger.info("Test addcoin new") + testargs = [ + "basicswap-prepare", + "-datadir=" + test_path_plain, + "-addcoin=namecoin", + ] + with patch.object(sys, "argv", testargs): prepareSystem.main() with open(config_path) as fs: settings = json.load(fs) - self.assertTrue(settings['chainclients']['namecoin']['connection_type'] == 'rpc') + self.assertTrue( + settings["chainclients"]["namecoin"]["connection_type"] == "rpc" + ) - logger.info('Test disablecoin') - testargs = ['basicswap-prepare', '-datadir=' + test_path_plain, '-disablecoin=namecoin'] - with patch.object(sys, 'argv', testargs): + logger.info("Test disablecoin") + testargs = [ + "basicswap-prepare", + "-datadir=" + test_path_plain, + "-disablecoin=namecoin", + ] + with patch.object(sys, "argv", testargs): prepareSystem.main() with open(config_path) as fs: settings = json.load(fs) - self.assertTrue(settings['chainclients']['namecoin']['connection_type'] == 'none') + self.assertTrue( + settings["chainclients"]["namecoin"]["connection_type"] == "none" + ) - logger.info('Test addcoin existing') - testargs = ['basicswap-prepare', '-datadir=' + test_path_plain, '-addcoin=namecoin'] - with patch.object(sys, 'argv', testargs): + logger.info("Test addcoin existing") + testargs = [ + "basicswap-prepare", + "-datadir=" + test_path_plain, + "-addcoin=namecoin", + ] + with patch.object(sys, "argv", testargs): prepareSystem.main() with open(config_path) as fs: settings = json.load(fs) - self.assertTrue(settings['chainclients']['namecoin']['connection_type'] == 'rpc') + self.assertTrue( + settings["chainclients"]["namecoin"]["connection_type"] == "rpc" + ) - logging.info('notorproxy') - testargs = ['basicswap-prepare', '-datadir=' + test_path_plain, '-addcoin=firo', '--usetorproxy', '--notorproxy'] - with patch('sys.stderr', new=StringIO()) as fake_stderr: - with patch.object(sys, 'argv', testargs): + logging.info("notorproxy") + testargs = [ + "basicswap-prepare", + "-datadir=" + test_path_plain, + "-addcoin=firo", + "--usetorproxy", + "--notorproxy", + ] + with patch("sys.stderr", new=StringIO()) as fake_stderr: + with patch.object(sys, "argv", testargs): with self.assertRaises(SystemExit) as cm: prepareSystem.main() self.assertEqual(cm.exception.code, 1) - self.assertTrue('--usetorproxy and --notorproxy together' in fake_stderr.getvalue()) + self.assertTrue( + "--usetorproxy and --notorproxy together" in fake_stderr.getvalue() + ) finally: del prepareSystem @@ -133,81 +171,114 @@ class Test(unittest.TestCase): def test_encrypted(self): if os.path.exists(test_path_encrypted): shutil.rmtree(test_path_encrypted) - if bin_path != '': + if bin_path != "": os.makedirs(test_path_encrypted) - os.symlink(bin_path, os.path.join(test_path_encrypted, 'bin')) + os.symlink(bin_path, os.path.join(test_path_encrypted, "bin")) - env_vars = [('WALLET_ENCRYPTION_PWD', 'test123'), ] - testargs = ('basicswap-prepare', '-datadir=' + test_path_encrypted, '-withcoin=litecoin,monero') - process = multiprocessing.Process(target=start_prepare, args=(testargs, env_vars)) + env_vars = [ + ("WALLET_ENCRYPTION_PWD", "test123"), + ] + testargs = ( + "basicswap-prepare", + "-datadir=" + test_path_encrypted, + "-withcoin=litecoin,monero", + ) + process = multiprocessing.Process( + target=start_prepare, args=(testargs, env_vars) + ) process.start() process.join() - assert (process.exitcode == 0) + assert process.exitcode == 0 - logger.info('Should not be able to add a coin without setting WALLET_ENCRYPTION_PWD') - testargs = ('basicswap-prepare', '-datadir=' + test_path_encrypted, '-addcoin=bitcoin') + logger.info( + "Should not be able to add a coin without setting WALLET_ENCRYPTION_PWD" + ) + testargs = ( + "basicswap-prepare", + "-datadir=" + test_path_encrypted, + "-addcoin=bitcoin", + ) process = multiprocessing.Process(target=start_prepare, args=(testargs, [])) process.start() process.join() - assert (process.exitcode == 1) + assert process.exitcode == 1 - testargs = ('basicswap-prepare', '-datadir=' + test_path_encrypted, '-addcoin=bitcoin') - process = multiprocessing.Process(target=start_prepare, args=(testargs, env_vars)) + testargs = ( + "basicswap-prepare", + "-datadir=" + test_path_encrypted, + "-addcoin=bitcoin", + ) + process = multiprocessing.Process( + target=start_prepare, args=(testargs, env_vars) + ) process.start() process.join() - assert (process.exitcode == 0) + assert process.exitcode == 0 def test_encrypt(self): if os.path.exists(test_path_encrypt): shutil.rmtree(test_path_encrypt) - if bin_path != '': + if bin_path != "": os.makedirs(test_path_encrypt) - os.symlink(bin_path, os.path.join(test_path_encrypt, 'bin')) + os.symlink(bin_path, os.path.join(test_path_encrypt, "bin")) - testargs = ('basicswap-prepare', '-regtest=1', '-datadir=' + test_path_encrypt, '-withcoin=litecoin,monero') - process = multiprocessing.Process(target=start_prepare, args=(testargs, )) + testargs = ( + "basicswap-prepare", + "-regtest=1", + "-datadir=" + test_path_encrypt, + "-withcoin=litecoin,monero", + ) + process = multiprocessing.Process(target=start_prepare, args=(testargs,)) process.start() process.join() - assert (process.exitcode == 0) + assert process.exitcode == 0 - logger.info('basicswap-run should fail if WALLET_ENCRYPTION_PWD is set') - env_vars = [('WALLET_ENCRYPTION_PWD', 'test123'), ] - testargs = ('basicswap-run', '-regtest=1', '-datadir=' + test_path_encrypt) + logger.info("basicswap-run should fail if WALLET_ENCRYPTION_PWD is set") + env_vars = [ + ("WALLET_ENCRYPTION_PWD", "test123"), + ] + testargs = ("basicswap-run", "-regtest=1", "-datadir=" + test_path_encrypt) process = multiprocessing.Process(target=start_run, args=(testargs, env_vars)) process.start() process.join() - assert (process.exitcode == 1) + assert process.exitcode == 1 - testargs = ('basicswap-run', '-regtest=1', '-datadir=' + test_path_encrypt) - process = multiprocessing.Process(target=start_run, args=(testargs, )) + testargs = ("basicswap-run", "-regtest=1", "-datadir=" + test_path_encrypt) + process = multiprocessing.Process(target=start_run, args=(testargs,)) process.start() waitForServer(delay_event, 12700) - rv = read_json_api(12700, 'setpassword', {'oldpassword': 'wrongpass', 'newpassword': 'test123'}) - assert ('error' in rv) + rv = read_json_api( + 12700, "setpassword", {"oldpassword": "wrongpass", "newpassword": "test123"} + ) + assert "error" in rv - rv = read_json_api(12700, 'setpassword', {'oldpassword': '', 'newpassword': 'test123'}) - assert ('success' in rv) + rv = read_json_api( + 12700, "setpassword", {"oldpassword": "", "newpassword": "test123"} + ) + assert "success" in rv - rv = read_json_api(12700, 'setpassword', {'oldpassword': 'test123', 'newpassword': 'next123'}) - assert ('success' in rv) + rv = read_json_api( + 12700, "setpassword", {"oldpassword": "test123", "newpassword": "next123"} + ) + assert "success" in rv - rv = read_json_api(12700, 'lock') - assert ('success' in rv) + rv = read_json_api(12700, "lock") + assert "success" in rv - rv = read_json_api(12700, 'wallets') - assert ('error' in rv) + rv = read_json_api(12700, "wallets") + assert "error" in rv - rv = read_json_api(12700, 'unlock', {'password': 'next123'}) - assert ('success' in rv) + rv = read_json_api(12700, "unlock", {"password": "next123"}) + assert "success" in rv - rv = read_json_api(12700, 'wallets') - assert ('PART' in rv) + rv = read_json_api(12700, "wallets") + assert "PART" in rv process.terminate() process.join() - assert (process.exitcode == 0) + assert process.exitcode == 0 -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/extended/test_scripts.py b/tests/basicswap/extended/test_scripts.py index dc3ce70..5072753 100644 --- a/tests/basicswap/extended/test_scripts.py +++ b/tests/basicswap/extended/test_scripts.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2023-2024 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -43,52 +44,52 @@ if not len(logger.handlers): logger.addHandler(logging.StreamHandler(sys.stdout)) -PORT_OFS = int(os.getenv('PORT_OFS', 1)) +PORT_OFS = int(os.getenv("PORT_OFS", 1)) UI_PORT = 12700 + PORT_OFS class HttpHandler(BaseHTTPRequestHandler): def js_response(self, url_split, post_string, is_json): - return bytes(json.dumps(self.server.return_data[url_split[3]]), 'UTF-8') + return bytes(json.dumps(self.server.return_data[url_split[3]]), "UTF-8") def putHeaders(self, status_code, content_type): self.send_response(status_code) - self.send_header('Content-Type', content_type) + self.send_header("Content-Type", content_type) self.end_headers() - def handle_http(self, status_code, path, post_string='', is_json=False): + def handle_http(self, status_code, path, post_string="", is_json=False): parsed = parse.urlparse(self.path) - url_split = parsed.path.split('/') - if post_string == '' and len(parsed.query) > 0: + url_split = parsed.path.split("/") + if post_string == "" and len(parsed.query) > 0: post_string = parsed.query - if len(url_split) > 1 and url_split[1] == 'json': - self.putHeaders(status_code, 'text/plain') + if len(url_split) > 1 and url_split[1] == "json": + self.putHeaders(status_code, "text/plain") return self.js_response(url_split, post_string, is_json) - self.putHeaders(status_code, 'text/plain') - return bytes('No response', 'UTF-8') + self.putHeaders(status_code, "text/plain") + return bytes("No response", "UTF-8") def do_GET(self): response = self.handle_http(200, self.path) self.wfile.write(response) def do_POST(self): - post_string = self.rfile.read(int(self.headers.get('Content-Length'))) + post_string = self.rfile.read(int(self.headers.get("Content-Length"))) - is_json = True if 'json' in self.headers.get('Content-Type', '') else False + is_json = True if "json" in self.headers.get("Content-Type", "") else False response = self.handle_http(200, self.path, post_string, is_json) self.wfile.write(response) def do_HEAD(self): - self.putHeaders(200, 'text/html') + self.putHeaders(200, "text/html") class HttpThread(threading.Thread, HTTPServer): - host = '127.0.0.1' + host = "127.0.0.1" port_no = 12699 stop_event = threading.Event() - return_data = {'test': 1} + return_data = {"test": 1} def __init__(self): threading.Thread.__init__(self) @@ -101,9 +102,9 @@ class HttpThread(threading.Thread, HTTPServer): # Send fake request conn = http.client.HTTPConnection(self.host, self.port_no) conn.connect() - conn.request('GET', '/none') + conn.request("GET", "/none") response = conn.getresponse() - data = response.read() + _ = response.read() conn.close() def serve_forever(self): @@ -116,28 +117,28 @@ class HttpThread(threading.Thread, HTTPServer): def clear_offers(delay_event, node_id) -> None: - logging.info(f'clear_offers node {node_id}') - offers = read_json_api(UI_PORT + node_id, 'offers') + logging.info(f"clear_offers node {node_id}") + offers = read_json_api(UI_PORT + node_id, "offers") for offer in offers: - read_json_api(UI_PORT + node_id, 'revokeoffer/{}'.format(offer['offer_id'])) + read_json_api(UI_PORT + node_id, "revokeoffer/{}".format(offer["offer_id"])) for i in range(20): delay_event.wait(1) - offers = read_json_api(UI_PORT + node_id, 'offers') + offers = read_json_api(UI_PORT + node_id, "offers") if len(offers) == 0: return - raise ValueError('clear_offers failed') + raise ValueError("clear_offers failed") def wait_for_offers(delay_event, node_id, num_offers) -> None: - logging.info(f'Waiting for {num_offers} offers on node {node_id}') + logging.info(f"Waiting for {num_offers} offers on node {node_id}") for i in range(20): delay_event.wait(1) - offers = read_json_api(UI_PORT + node_id, 'offers') + offers = read_json_api(UI_PORT + node_id, "offers") if len(offers) >= num_offers: return - raise ValueError('wait_for_offers failed') + raise ValueError("wait_for_offers failed") def delete_file(filepath: str) -> None: @@ -148,8 +149,8 @@ def delete_file(filepath: str) -> None: def get_created_offers(rv_stdout): offers = [] for line in rv_stdout: - if line.startswith('New offer'): - offers.append(line.split(':')[1].strip()) + if line.startswith("New offer"): + offers.append(line.split(":")[1].strip()) return offers @@ -164,17 +165,17 @@ def count_lines_with(rv_stdout, str_needle): def get_created_bids(rv_stdout): bids = [] for line in rv_stdout: - if line.startswith('New bid'): - bids.append(line.split(':')[1].strip()) + if line.startswith("New bid"): + bids.append(line.split(":")[1].strip()) return bids def get_possible_bids(rv_stdout): bids = [] - tag = 'Would create bid: ' + tag = "Would create bid: " for line in rv_stdout: if line.startswith(tag): - bids.append(json.loads(line[len(tag):].replace("'", '"'))) + bids.append(json.loads(line[len(tag) :].replace("'", '"'))) return bids @@ -187,22 +188,42 @@ class Test(unittest.TestCase): super(Test, cls).setUpClass() cls.thread_http.start() - script_path = 'scripts/createoffers.py' - datadir = '/tmp/bsx_scripts' + script_path = "scripts/createoffers.py" + datadir = "/tmp/bsx_scripts" if not os.path.isdir(datadir): os.makedirs(datadir) - cls.node0_configfile = os.path.join(datadir, 'node0.json') - cls.node0_statefile = os.path.join(datadir, 'node0_state.json') - cls.node0_args = [script_path, '--port', str(UI_PORT), '--configfile', cls.node0_configfile, '--statefile', cls.node0_statefile, '--oneshot', '--debug'] + cls.node0_configfile = os.path.join(datadir, "node0.json") + cls.node0_statefile = os.path.join(datadir, "node0_state.json") + cls.node0_args = [ + script_path, + "--port", + str(UI_PORT), + "--configfile", + cls.node0_configfile, + "--statefile", + cls.node0_statefile, + "--oneshot", + "--debug", + ] - cls.node1_configfile = os.path.join(datadir, 'node1.json') - cls.node1_statefile = os.path.join(datadir, 'node1_state.json') - cls.node1_args = [script_path, '--port', str(UI_PORT + 1), '--configfile', cls.node1_configfile, '--statefile', cls.node1_statefile, '--oneshot', '--debug'] + cls.node1_configfile = os.path.join(datadir, "node1.json") + cls.node1_statefile = os.path.join(datadir, "node1_state.json") + cls.node1_args = [ + script_path, + "--port", + str(UI_PORT + 1), + "--configfile", + cls.node1_configfile, + "--statefile", + cls.node1_statefile, + "--oneshot", + "--debug", + ] @classmethod def tearDownClass(cls): - logging.info('Stopping test') + logging.info("Stopping test") cls.thread_http.stop() def test_enabled(self): @@ -212,77 +233,77 @@ class Test(unittest.TestCase): # Test no 'Processing...' messages are shown without config node0_test_config = {} - with open(self.node0_configfile, 'w') as fp: + with open(self.node0_configfile, "w") as fp: json.dump(node0_test_config, fp, indent=4) result = subprocess.run(self.node0_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') - assert (count_lines_with(rv_stdout, 'Processing') == 0) + rv_stdout = result.stdout.decode().split("\n") + assert count_lines_with(rv_stdout, "Processing") == 0 # Test that enabled templates are processed node0_test_config = { - 'test_mode': True, - 'offers': [ + "test_mode": True, + "offers": [ { - 'name': 'offer example 1', - 'coin_from': 'Particl', - 'coin_to': 'Monero', - 'amount': 20, - 'minrate': 0.05, - 'ratetweakpercent': 5, - 'amount_variable': True, - 'address': -1, - 'min_coin_from_amt': 20, - 'max_coin_to_amt': -1 + "name": "offer example 1", + "coin_from": "Particl", + "coin_to": "Monero", + "amount": 20, + "minrate": 0.05, + "ratetweakpercent": 5, + "amount_variable": True, + "address": -1, + "min_coin_from_amt": 20, + "max_coin_to_amt": -1, }, ], - 'bids': [ + "bids": [ { - 'coin_from': 'PART', - 'coin_to': 'XMR', - 'amount': 10, - 'maxrate': 0.04, - 'amount_variable': True, - 'address': -1, - 'min_swap_amount': 0.1, - 'max_coin_from_balance': -1, - 'min_coin_to_balance': -1, + "coin_from": "PART", + "coin_to": "XMR", + "amount": 10, + "maxrate": 0.04, + "amount_variable": True, + "address": -1, + "min_swap_amount": 0.1, + "max_coin_from_balance": -1, + "min_coin_to_balance": -1, }, ], - 'stealthex': [ + "stealthex": [ { - 'coin_from': 'XMR', - 'coin_to': 'BTC', - 'min_balance_from': 1, - 'min_amount_tx': 1, - 'max_amount_tx': 5, - 'min_rate': 0.01, - 'refund_address': 'auto', - 'receive_address': 'auto', - 'api_key': 'API_KEY_HERE' + "coin_from": "XMR", + "coin_to": "BTC", + "min_balance_from": 1, + "min_amount_tx": 1, + "max_amount_tx": 5, + "min_rate": 0.01, + "refund_address": "auto", + "receive_address": "auto", + "api_key": "API_KEY_HERE", } ], } - with open(self.node0_configfile, 'w') as fp: + with open(self.node0_configfile, "w") as fp: json.dump(node0_test_config, fp, indent=4) result = subprocess.run(self.node0_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') - assert (count_lines_with(rv_stdout, 'Processing 1 offer template') == 1) - assert (count_lines_with(rv_stdout, 'Processing 1 bid template') == 1) - assert (count_lines_with(rv_stdout, 'Processing 1 stealthex template') == 1) + rv_stdout = result.stdout.decode().split("\n") + assert count_lines_with(rv_stdout, "Processing 1 offer template") == 1 + assert count_lines_with(rv_stdout, "Processing 1 bid template") == 1 + assert count_lines_with(rv_stdout, "Processing 1 stealthex template") == 1 # Test that disabled templates are not processed - node0_test_config['offers'][0]['enabled'] = False - node0_test_config['bids'][0]['enabled'] = False - node0_test_config['stealthex'][0]['enabled'] = False - with open(self.node0_configfile, 'w') as fp: + node0_test_config["offers"][0]["enabled"] = False + node0_test_config["bids"][0]["enabled"] = False + node0_test_config["stealthex"][0]["enabled"] = False + with open(self.node0_configfile, "w") as fp: json.dump(node0_test_config, fp, indent=4) result = subprocess.run(self.node0_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') - assert (count_lines_with(rv_stdout, 'Processing 0 offer templates') == 1) - assert (count_lines_with(rv_stdout, 'Processing 0 bid templates') == 1) - assert (count_lines_with(rv_stdout, 'Processing 0 stealthex templates') == 1) + rv_stdout = result.stdout.decode().split("\n") + assert count_lines_with(rv_stdout, "Processing 0 offer templates") == 1 + assert count_lines_with(rv_stdout, "Processing 0 bid templates") == 1 + assert count_lines_with(rv_stdout, "Processing 0 stealthex templates") == 1 def test_offers(self): @@ -296,247 +317,258 @@ class Test(unittest.TestCase): wait_for_offers(self.delay_event, 1, 0) node0_test1_config = { - 'offers': [ + "offers": [ { - 'name': 'offer example 1', - 'coin_from': 'Particl', - 'coin_to': 'Monero', - 'amount': 20, - 'minrate': 0.05, - 'ratetweakpercent': 5, - 'amount_variable': True, - 'address': -1, - 'min_coin_from_amt': 20, - 'max_coin_to_amt': -1, - 'min_swap_amount': 0.11, + "name": "offer example 1", + "coin_from": "Particl", + "coin_to": "Monero", + "amount": 20, + "minrate": 0.05, + "ratetweakpercent": 5, + "amount_variable": True, + "address": -1, + "min_coin_from_amt": 20, + "max_coin_to_amt": -1, + "min_swap_amount": 0.11, }, { - 'name': 'offer example 1_2', - 'coin_from': 'Particl', - 'coin_to': 'Monero', - 'amount': 21, - 'minrate': 0.07, - 'ratetweakpercent': 5, - 'amount_variable': True, - 'address': -1, - 'min_coin_from_amt': 21, - 'max_coin_to_amt': -1, - 'min_swap_amount': 0.12, - } + "name": "offer example 1_2", + "coin_from": "Particl", + "coin_to": "Monero", + "amount": 21, + "minrate": 0.07, + "ratetweakpercent": 5, + "amount_variable": True, + "address": -1, + "min_coin_from_amt": 21, + "max_coin_to_amt": -1, + "min_swap_amount": 0.12, + }, ], } - with open(self.node0_configfile, 'w') as fp: + with open(self.node0_configfile, "w") as fp: json.dump(node0_test1_config, fp, indent=4) - logging.info('Test that an offer is created') + logging.info("Test that an offer is created") result = subprocess.run(self.node0_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') - assert (len(get_created_offers(rv_stdout)) == 1) + rv_stdout = result.stdout.decode().split("\n") + assert len(get_created_offers(rv_stdout)) == 1 - offers = read_json_api(UI_PORT, 'offers') - assert (len(offers) == 1) - offer_min_bid_amount = float(offers[0]['min_bid_amount']) - assert (offer_min_bid_amount == 0.11 or offer_min_bid_amount == 0.12) + offers = read_json_api(UI_PORT, "offers") + assert len(offers) == 1 + offer_min_bid_amount = float(offers[0]["min_bid_amount"]) + assert offer_min_bid_amount == 0.11 or offer_min_bid_amount == 0.12 - logging.info('Test that an offer is not created while delaying') + logging.info("Test that an offer is not created while delaying") result = subprocess.run(self.node0_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') - assert (len(get_created_offers(rv_stdout)) == 0) + rv_stdout = result.stdout.decode().split("\n") + assert len(get_created_offers(rv_stdout)) == 0 with open(self.node0_statefile) as fs: node0_state = json.load(fs) - node0_state['delay_next_offer_before'] = 0 - with open(self.node0_statefile, 'w') as fp: + node0_state["delay_next_offer_before"] = 0 + with open(self.node0_statefile, "w") as fp: json.dump(node0_state, fp, indent=4) - logging.info('Test that the second offer is created when not delaying') + logging.info("Test that the second offer is created when not delaying") result = subprocess.run(self.node0_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') - assert (len(get_created_offers(rv_stdout)) == 1) + rv_stdout = result.stdout.decode().split("\n") + assert len(get_created_offers(rv_stdout)) == 1 with open(self.node0_statefile) as fs: node0_state = json.load(fs) - assert (len(node0_state['offers']['offer example 1']) == 1) - assert (len(node0_state['offers']['offer example 1_2']) == 1) + assert len(node0_state["offers"]["offer example 1"]) == 1 + assert len(node0_state["offers"]["offer example 1_2"]) == 1 - offers = read_json_api(UI_PORT, 'offers') - assert (len(offers) == 2) + offers = read_json_api(UI_PORT, "offers") + assert len(offers) == 2 - addr_bid_from = read_json_api(UI_PORT + 1, 'smsgaddresses/new')['new_address'] + addr_bid_from = read_json_api(UI_PORT + 1, "smsgaddresses/new")["new_address"] node1_test1_config = { - 'bids': [ + "bids": [ { - 'name': 'bid example 1', - 'coin_from': 'PART', - 'coin_to': 'XMR', - 'amount': 10, - 'maxrate': 0.06, - 'amount_variable': True, - 'address': addr_bid_from, - 'min_swap_amount': 0.1, - 'max_coin_from_balance': -1, - 'min_coin_to_balance': -1, - 'max_concurrent': 4, + "name": "bid example 1", + "coin_from": "PART", + "coin_to": "XMR", + "amount": 10, + "maxrate": 0.06, + "amount_variable": True, + "address": addr_bid_from, + "min_swap_amount": 0.1, + "max_coin_from_balance": -1, + "min_coin_to_balance": -1, + "max_concurrent": 4, }, { - 'coin_from': 'PART', - 'coin_to': 'XMR', - 'amount': 10, - 'maxrate': 0.04, - 'amount_variable': True, - 'address': -1, - 'min_swap_amount': 0.1, - 'max_coin_from_balance': -1, - 'min_coin_to_balance': -1, - } + "coin_from": "PART", + "coin_to": "XMR", + "amount": 10, + "maxrate": 0.04, + "amount_variable": True, + "address": -1, + "min_swap_amount": 0.1, + "max_coin_from_balance": -1, + "min_coin_to_balance": -1, + }, ], } - with open(self.node1_configfile, 'w') as fp: + with open(self.node1_configfile, "w") as fp: json.dump(node1_test1_config, fp, indent=4) wait_for_offers(self.delay_event, 1, 2) - logging.info('Test that a bid is created') + logging.info("Test that a bid is created") result = subprocess.run(self.node1_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') - assert (len(get_created_bids(rv_stdout)) == 1) + rv_stdout = result.stdout.decode().split("\n") + assert len(get_created_bids(rv_stdout)) == 1 - logging.info('Test no bids are created while delaying') + logging.info("Test no bids are created while delaying") result = subprocess.run(self.node1_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') - assert (count_lines_with(rv_stdout, 'Delaying bids until') == 1) + rv_stdout = result.stdout.decode().split("\n") + assert count_lines_with(rv_stdout, "Delaying bids until") == 1 with open(self.node1_statefile) as fs: node1_state = json.load(fs) - node1_state['delay_next_bid_before'] = 0 - with open(self.node1_statefile, 'w') as fp: + node1_state["delay_next_bid_before"] = 0 + with open(self.node1_statefile, "w") as fp: json.dump(node1_state, fp, indent=4) - logging.info('Test that a bid is not created if one already exists on that offer') + logging.info( + "Test that a bid is not created if one already exists on that offer" + ) result = subprocess.run(self.node1_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') - assert (count_lines_with(rv_stdout, 'Bid rate too low for offer') == 3) - assert (count_lines_with(rv_stdout, 'Already bidding on offer') == 1) + rv_stdout = result.stdout.decode().split("\n") + assert count_lines_with(rv_stdout, "Bid rate too low for offer") == 3 + assert count_lines_with(rv_stdout, "Already bidding on offer") == 1 - logging.info('Modifying node1 config') - node1_test1_config['bids'][0]['maxrate'] = 0.07 - node1_test1_config['bids'][0]['max_coin_from_balance'] = 100 - node1_test1_config['bids'][0]['min_coin_to_balance'] = 100 - node1_test1_config['bids'][0]['min_swap_amount'] = 9 - node1_test1_config['wallet_port_override'] = 12699 - node1_test1_config['test_mode'] = True - with open(self.node1_configfile, 'w') as fp: + logging.info("Modifying node1 config") + node1_test1_config["bids"][0]["maxrate"] = 0.07 + node1_test1_config["bids"][0]["max_coin_from_balance"] = 100 + node1_test1_config["bids"][0]["min_coin_to_balance"] = 100 + node1_test1_config["bids"][0]["min_swap_amount"] = 9 + node1_test1_config["wallet_port_override"] = 12699 + node1_test1_config["test_mode"] = True + with open(self.node1_configfile, "w") as fp: json.dump(node1_test1_config, fp, indent=4) self.thread_http.return_data = { - 'PART': { - 'balance': '0.0', - 'unconfirmed': '0.0', - 'expected_seed': True, - 'encrypted': False, - 'locked': False, - 'anon_balance': 0.0, - 'anon_pending': 0.0, - 'blind_balance': 0.0, - 'blind_unconfirmed': 0.0, - 'version': 23000300, - 'name': 'Particl', - 'blocks': 3556, - 'synced': '100.00' + "PART": { + "balance": "0.0", + "unconfirmed": "0.0", + "expected_seed": True, + "encrypted": False, + "locked": False, + "anon_balance": 0.0, + "anon_pending": 0.0, + "blind_balance": 0.0, + "blind_unconfirmed": 0.0, + "version": 23000300, + "name": "Particl", + "blocks": 3556, + "synced": "100.00", + }, + "XMR": { + "balance": "362299.12", + "unconfirmed": "0.0", + "expected_seed": True, + "encrypted": False, + "locked": False, + "main_address": "", + "version": 65562, + "name": "Monero", + "blocks": 10470, + "synced": "100.00", + "known_block_count": 10470, }, - 'XMR': { - 'balance': '362299.12', - 'unconfirmed': '0.0', - 'expected_seed': True, - 'encrypted': False, - 'locked': False, - 'main_address': '', - 'version': 65562, - 'name': 'Monero', - 'blocks': 10470, - 'synced': '100.00', - 'known_block_count': 10470 - } } - logging.info('Check max bid value') + logging.info("Check max bid value") result = subprocess.run(self.node1_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') + rv_stdout = result.stdout.decode().split("\n") possible_bids = get_possible_bids(rv_stdout) - assert (len(possible_bids) == 1) - assert (float(possible_bids[0]['amount_from']) == 10.0) + assert len(possible_bids) == 1 + assert float(possible_bids[0]["amount_from"]) == 10.0 - logging.info('Raise node1 bid0 value') - node1_test1_config['bids'][0]['amount'] = 50 - with open(self.node1_configfile, 'w') as fp: + logging.info("Raise node1 bid0 value") + node1_test1_config["bids"][0]["amount"] = 50 + with open(self.node1_configfile, "w") as fp: json.dump(node1_test1_config, fp, indent=4) delete_file(self.node1_statefile) # Check max_coin_from_balance (bids increase coin_from) result = subprocess.run(self.node1_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') + rv_stdout = result.stdout.decode().split("\n") possible_bids = get_possible_bids(rv_stdout) - assert (len(possible_bids) == 1) - assert (float(possible_bids[0]['amount_from']) == 21.0) + assert len(possible_bids) == 1 + assert float(possible_bids[0]["amount_from"]) == 21.0 # Test multiple bids are delayed result = subprocess.run(self.node1_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') - assert (count_lines_with(rv_stdout, 'Delaying bids until') == 1) + rv_stdout = result.stdout.decode().split("\n") + assert count_lines_with(rv_stdout, "Delaying bids until") == 1 delete_file(self.node1_statefile) - self.thread_http.return_data['PART']['balance'] = 100.0 + self.thread_http.return_data["PART"]["balance"] = 100.0 result = subprocess.run(self.node1_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') - assert (count_lines_with(rv_stdout, 'Bid amount would exceed maximum wallet total') == 1) + rv_stdout = result.stdout.decode().split("\n") + assert ( + count_lines_with(rv_stdout, "Bid amount would exceed maximum wallet total") + == 1 + ) - self.thread_http.return_data['PART']['balance'] = 90.0 + self.thread_http.return_data["PART"]["balance"] = 90.0 result = subprocess.run(self.node1_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') + rv_stdout = result.stdout.decode().split("\n") possible_bids = get_possible_bids(rv_stdout) - assert (len(possible_bids) == 1) - assert (math.isclose(float(possible_bids[0]['amount_from']), 10.0)) + assert len(possible_bids) == 1 + assert math.isclose(float(possible_bids[0]["amount_from"]), 10.0) # Check min_swap_amount delete_file(self.node1_statefile) - self.thread_http.return_data['PART']['balance'] = 95.0 + self.thread_http.return_data["PART"]["balance"] = 95.0 result = subprocess.run(self.node1_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') + rv_stdout = result.stdout.decode().split("\n") possible_bids = get_possible_bids(rv_stdout) - assert (count_lines_with(rv_stdout, 'Bid amount would exceed maximum wallet total') == 1) + assert ( + count_lines_with(rv_stdout, "Bid amount would exceed maximum wallet total") + == 1 + ) # Check min_coin_to_balance (bids decrease coin_to) - self.thread_http.return_data['PART']['balance'] = 0.0 - self.thread_http.return_data['XMR']['balance'] = 101.0 + self.thread_http.return_data["PART"]["balance"] = 0.0 + self.thread_http.return_data["XMR"]["balance"] = 101.0 result = subprocess.run(self.node1_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') + rv_stdout = result.stdout.decode().split("\n") possible_bids = get_possible_bids(rv_stdout) possible_bids = get_possible_bids(rv_stdout) - assert (len(possible_bids) == 1) - assert (float(possible_bids[0]['amount_from']) < 20.0) + assert len(possible_bids) == 1 + assert float(possible_bids[0]["amount_from"]) < 20.0 - logging.info('Adding mock data to node1 db for tests') + logging.info("Adding mock data to node1 db for tests") rows = [] - offers = read_json_api(UI_PORT, 'offers') + offers = read_json_api(UI_PORT, "offers") now = int(time.time()) for offer in offers: - rows.append((1, offer['addr_from'], 5, 5, now, now)) - db_path = '/tmp/test_persistent/client1/db_regtest.sqlite' + rows.append((1, offer["addr_from"], 5, 5, now, now)) + db_path = "/tmp/test_persistent/client1/db_regtest.sqlite" with sqlite3.connect(db_path) as dbc: c = dbc.cursor() - c.executemany('INSERT INTO knownidentities (active_ind, address, num_sent_bids_failed, num_recv_bids_failed, updated_at, created_at) VALUES (?,?,?,?,?,?)', rows) + c.executemany( + "INSERT INTO knownidentities (active_ind, address, num_sent_bids_failed, num_recv_bids_failed, updated_at, created_at) VALUES (?,?,?,?,?,?)", + rows, + ) dbc.commit() delete_file(self.node1_statefile) - self.thread_http.return_data['XMR']['balance'] = 10000.0 + self.thread_http.return_data["XMR"]["balance"] = 10000.0 result = subprocess.run(self.node1_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') - assert (len(get_possible_bids(get_possible_bids(rv_stdout))) == 0) - assert (count_lines_with(rv_stdout, 'too many failed bids') == 1) + rv_stdout = result.stdout.decode().split("\n") + assert len(get_possible_bids(get_possible_bids(rv_stdout))) == 0 + assert count_lines_with(rv_stdout, "too many failed bids") == 1 - ''' + """ TODO node0_test1_config['stealthex'] = [ { @@ -558,7 +590,7 @@ class Test(unittest.TestCase): result = subprocess.run(self.node0_args, stdout=subprocess.PIPE) rv_stdout = result.stdout.decode().split('\n') - ''' + """ def test_offer_amount_step(self): waitForServer(self.delay_event, UI_PORT + 0) @@ -574,48 +606,55 @@ class Test(unittest.TestCase): offer_min_amount = 20 min_coin_from_amt = 10 - xmr_wallet = read_json_api(UI_PORT + 0, 'wallets/xmr') - xmr_wallet_balance = float(xmr_wallet['balance']) + xmr_wallet = read_json_api(UI_PORT + 0, "wallets/xmr") + xmr_wallet_balance = float(xmr_wallet["balance"]) expect_balance = offer_min_amount * 2 + min_coin_from_amt + 1 if xmr_wallet_balance < expect_balance: post_json = { - 'value': expect_balance, - 'address': xmr_wallet['deposit_address'], - 'sweepall': False, + "value": expect_balance, + "address": xmr_wallet["deposit_address"], + "sweepall": False, } - json_rv = read_json_api(UI_PORT + 1, 'wallets/xmr/withdraw', post_json) - assert (len(json_rv['txid']) == 64) - wait_for_balance(self.delay_event, f'http://127.0.0.1:{UI_PORT + 0}/json/wallets/xmr', 'balance', expect_balance) + json_rv = read_json_api(UI_PORT + 1, "wallets/xmr/withdraw", post_json) + assert len(json_rv["txid"]) == 64 + wait_for_balance( + self.delay_event, + f"http://127.0.0.1:{UI_PORT + 0}/json/wallets/xmr", + "balance", + expect_balance, + ) - xmr_wallet_balance = float(read_json_api(UI_PORT + 0, 'wallets/xmr')['balance']) + xmr_wallet_balance = float( + read_json_api(UI_PORT + 0, "wallets/xmr")["balance"] + ) - assert (xmr_wallet_balance > offer_min_amount) - assert (xmr_wallet_balance < offer_amount) + assert xmr_wallet_balance > offer_min_amount + assert xmr_wallet_balance < offer_amount node0_test_config = { - 'offers': [ + "offers": [ { - 'name': 'test min amount', - 'coin_from': 'XMR', - 'coin_to': 'Particl', - 'amount': offer_amount, - 'amount_step': offer_min_amount, - 'minrate': 0.05, - 'amount_variable': True, - 'address': -1, - 'min_coin_from_amt': min_coin_from_amt, - 'max_coin_to_amt': -1 + "name": "test min amount", + "coin_from": "XMR", + "coin_to": "Particl", + "amount": offer_amount, + "amount_step": offer_min_amount, + "minrate": 0.05, + "amount_variable": True, + "address": -1, + "min_coin_from_amt": min_coin_from_amt, + "max_coin_to_amt": -1, } ], } - with open(self.node0_configfile, 'w') as fp: + with open(self.node0_configfile, "w") as fp: json.dump(node0_test_config, fp, indent=4) result = subprocess.run(self.node0_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') - assert (len(get_created_offers(rv_stdout)) == 1) + rv_stdout = result.stdout.decode().split("\n") + assert len(get_created_offers(rv_stdout)) == 1 def test_error_messages(self): waitForServer(self.delay_event, UI_PORT + 0) @@ -628,28 +667,33 @@ class Test(unittest.TestCase): wait_for_offers(self.delay_event, 1, 0) node0_test1_config = { - 'offers': [ + "offers": [ { - 'name': 'offer should fail', - 'coin_from': 'Particl', - 'coin_to': 'XMR', - 'amount': 200, - 'minrate': 0.05, - 'ratetweakpercent': 50000000, - 'amount_variable': True, - 'address': -1, - 'min_coin_from_amt': 20, - 'max_coin_to_amt': -1 + "name": "offer should fail", + "coin_from": "Particl", + "coin_to": "XMR", + "amount": 200, + "minrate": 0.05, + "ratetweakpercent": 50000000, + "amount_variable": True, + "address": -1, + "min_coin_from_amt": 20, + "max_coin_to_amt": -1, } ], } - with open(self.node0_configfile, 'w') as fp: + with open(self.node0_configfile, "w") as fp: json.dump(node0_test1_config, fp, indent=4) - logging.info('Test that an offer is not created') + logging.info("Test that an offer is not created") result = subprocess.run(self.node0_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') - assert (count_lines_with(rv_stdout, 'Error: Server failed to create offer: To amount above max') == 1) + rv_stdout = result.stdout.decode().split("\n") + assert ( + count_lines_with( + rv_stdout, "Error: Server failed to create offer: To amount above max" + ) + == 1 + ) def test_bid_tracking(self): @@ -664,179 +708,179 @@ class Test(unittest.TestCase): addrs = [] for i in range(2): - addrs.append(read_json_api(UI_PORT, 'smsgaddresses/new')['new_address']) + addrs.append(read_json_api(UI_PORT, "smsgaddresses/new")["new_address"]) node0_test2_config = { - 'offers': [ + "offers": [ { - 'name': 'offer example 1', - 'coin_from': 'Particl', - 'coin_to': 'Monero', - 'amount': 20, - 'minrate': 0.04, - 'ratetweakpercent': 5, - 'amount_variable': True, - 'address': addrs[0], - 'min_coin_from_amt': 20, - 'max_coin_to_amt': -1 + "name": "offer example 1", + "coin_from": "Particl", + "coin_to": "Monero", + "amount": 20, + "minrate": 0.04, + "ratetweakpercent": 5, + "amount_variable": True, + "address": addrs[0], + "min_coin_from_amt": 20, + "max_coin_to_amt": -1, }, { - 'name': 'offer example 1_2', - 'coin_from': 'Particl', - 'coin_to': 'Monero', - 'amount': 21, - 'minrate': 0.05, - 'ratetweakpercent': 5, - 'amount_variable': True, - 'address': addrs[1], - 'min_coin_from_amt': 21, - 'max_coin_to_amt': -1 + "name": "offer example 1_2", + "coin_from": "Particl", + "coin_to": "Monero", + "amount": 21, + "minrate": 0.05, + "ratetweakpercent": 5, + "amount_variable": True, + "address": addrs[1], + "min_coin_from_amt": 21, + "max_coin_to_amt": -1, }, { - 'name': 'offer example 1_3', - 'coin_from': 'Particl', - 'coin_to': 'Monero', - 'amount': 22, - 'minrate': 0.06, - 'ratetweakpercent': 5, - 'amount_variable': True, - 'address': 'auto', - 'min_coin_from_amt': 22, - 'max_coin_to_amt': -1 - } + "name": "offer example 1_3", + "coin_from": "Particl", + "coin_to": "Monero", + "amount": 22, + "minrate": 0.06, + "ratetweakpercent": 5, + "amount_variable": True, + "address": "auto", + "min_coin_from_amt": 22, + "max_coin_to_amt": -1, + }, ], } - with open(self.node0_configfile, 'w') as fp: + with open(self.node0_configfile, "w") as fp: json.dump(node0_test2_config, fp, indent=4) offer_ids = [] - logging.info('Create three offers') + logging.info("Create three offers") for i in range(3): if i > 0: with open(self.node0_statefile) as fs: node0_state = json.load(fs) - node0_state['delay_next_offer_before'] = 0 - with open(self.node0_statefile, 'w') as fp: + node0_state["delay_next_offer_before"] = 0 + with open(self.node0_statefile, "w") as fp: json.dump(node0_state, fp, indent=4) result = subprocess.run(self.node0_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') + rv_stdout = result.stdout.decode().split("\n") created_offers = get_created_offers(rv_stdout) - assert (len(get_created_offers(rv_stdout)) == 1) + assert len(get_created_offers(rv_stdout)) == 1 offer_ids.append(created_offers[0]) found_addrs = {} for offer_id in offer_ids: - offer = read_json_api(UI_PORT, f'offers/{offer_id}')[0] - found_addrs[offer['addr_from']] = found_addrs.get(offer['addr_from'], 0) + 1 + offer = read_json_api(UI_PORT, f"offers/{offer_id}")[0] + found_addrs[offer["addr_from"]] = found_addrs.get(offer["addr_from"], 0) + 1 for addr in addrs: - assert (found_addrs[addr] == 1) + assert found_addrs[addr] == 1 - addr_bid_from = read_json_api(UI_PORT + 1, 'smsgaddresses/new')['new_address'] + addr_bid_from = read_json_api(UI_PORT + 1, "smsgaddresses/new")["new_address"] node1_test1_config = { - 'bids': [ + "bids": [ { - 'name': 'bid example 1', - 'coin_from': 'PART', - 'coin_to': 'XMR', - 'amount': 50, - 'maxrate': 0.08, - 'amount_variable': False, - 'address': addr_bid_from, - 'min_swap_amount': 1, - 'max_coin_from_balance': -1, - 'min_coin_to_balance': -1 + "name": "bid example 1", + "coin_from": "PART", + "coin_to": "XMR", + "amount": 50, + "maxrate": 0.08, + "amount_variable": False, + "address": addr_bid_from, + "min_swap_amount": 1, + "max_coin_from_balance": -1, + "min_coin_to_balance": -1, } ], } - with open(self.node1_configfile, 'w') as fp: + with open(self.node1_configfile, "w") as fp: json.dump(node1_test1_config, fp, indent=4) wait_for_offers(self.delay_event, 1, 3) - logging.info('Check that no bids are created (offer values too low)') + logging.info("Check that no bids are created (offer values too low)") result = subprocess.run(self.node1_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') - assert (len(get_created_bids(rv_stdout)) == 0) - assert (count_lines_with(rv_stdout, 'Bid amount too high for offer') == 3) + rv_stdout = result.stdout.decode().split("\n") + assert len(get_created_bids(rv_stdout)) == 0 + assert count_lines_with(rv_stdout, "Bid amount too high for offer") == 3 - node1_test1_config['bids'][0]['amount_variable'] = True - with open(self.node1_configfile, 'w') as fp: + node1_test1_config["bids"][0]["amount_variable"] = True + with open(self.node1_configfile, "w") as fp: json.dump(node1_test1_config, fp, indent=4) - logging.info('Check that one bid is created at the best rate') + logging.info("Check that one bid is created at the best rate") result = subprocess.run(self.node1_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') + rv_stdout = result.stdout.decode().split("\n") created_bids = get_created_bids(rv_stdout) - assert (len(created_bids) == 1) + assert len(created_bids) == 1 - bid_id = created_bids[0].split(' ')[0] - bid = read_json_api(UI_PORT + 1, f'bids/{bid_id}') - assert (math.isclose(float(bid['bid_rate']), 0.04)) - assert (math.isclose(float(bid['amt_from']), 20.0)) - assert (bid['addr_from'] == addr_bid_from) + bid_id = created_bids[0].split(" ")[0] + bid = read_json_api(UI_PORT + 1, f"bids/{bid_id}") + assert math.isclose(float(bid["bid_rate"]), 0.04) + assert math.isclose(float(bid["amt_from"]), 20.0) + assert bid["addr_from"] == addr_bid_from - logging.info('Check that bids are delayed') + logging.info("Check that bids are delayed") result = subprocess.run(self.node1_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') - assert (count_lines_with(rv_stdout, 'Delaying bids until') == 1) - assert (len(get_created_bids(rv_stdout)) == 0) + rv_stdout = result.stdout.decode().split("\n") + assert count_lines_with(rv_stdout, "Delaying bids until") == 1 + assert len(get_created_bids(rv_stdout)) == 0 with open(self.node1_statefile) as fs: node1_state = json.load(fs) - node1_state['delay_next_bid_before'] = 0 - with open(self.node1_statefile, 'w') as fp: + node1_state["delay_next_bid_before"] = 0 + with open(self.node1_statefile, "w") as fp: json.dump(node1_state, fp, indent=4) - logging.info('Test that a bid is not created while one is active') + logging.info("Test that a bid is not created while one is active") result = subprocess.run(self.node1_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') - assert (len(get_created_bids(rv_stdout)) == 0) - assert (count_lines_with(rv_stdout, 'Max concurrent bids') == 1) + rv_stdout = result.stdout.decode().split("\n") + assert len(get_created_bids(rv_stdout)) == 0 + assert count_lines_with(rv_stdout, "Max concurrent bids") == 1 - logging.info('Waiting for bid to complete') + logging.info("Waiting for bid to complete") bid_complete: bool = False for i in range(60): self.delay_event.wait(5) - bid = read_json_api(UI_PORT + 1, f'bids/{bid_id}') - print('bid_state', bid['bid_state']) - if bid['bid_state'] == 'Completed': + bid = read_json_api(UI_PORT + 1, f"bids/{bid_id}") + print("bid_state", bid["bid_state"]) + if bid["bid_state"] == "Completed": bid_complete = True break assert bid_complete - logging.info('Test that a bid is created after one expires') + logging.info("Test that a bid is created after one expires") result = subprocess.run(self.node1_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') + rv_stdout = result.stdout.decode().split("\n") created_bids = get_created_bids(rv_stdout) - assert (len(created_bids) == 1) - assert (count_lines_with(rv_stdout, 'Marking bid inactive') == 1) + assert len(created_bids) == 1 + assert count_lines_with(rv_stdout, "Marking bid inactive") == 1 - logging.info('Test that two bids are created if max concurrent is raised') - node1_test1_config['bids'][0]['max_concurrent'] = 2 - with open(self.node1_configfile, 'w') as fp: + logging.info("Test that two bids are created if max concurrent is raised") + node1_test1_config["bids"][0]["max_concurrent"] = 2 + with open(self.node1_configfile, "w") as fp: json.dump(node1_test1_config, fp, indent=4) with open(self.node1_statefile) as fs: node1_state = json.load(fs) - node1_state['delay_next_bid_before'] = 0 - with open(self.node1_statefile, 'w') as fp: + node1_state["delay_next_bid_before"] = 0 + with open(self.node1_statefile, "w") as fp: json.dump(node1_state, fp, indent=4) result = subprocess.run(self.node1_args, stdout=subprocess.PIPE) - rv_stdout = result.stdout.decode().split('\n') + rv_stdout = result.stdout.decode().split("\n") created_bids = get_created_bids(rv_stdout) - assert (len(created_bids) == 1) + assert len(created_bids) == 1 - bid_id = created_bids[0].split(' ')[0] - bid = read_json_api(UI_PORT + 1, f'bids/{bid_id}') - assert (math.isclose(float(bid['bid_rate']), 0.05)) - assert (math.isclose(float(bid['amt_from']), 21.0)) - assert (bid['addr_from'] == addr_bid_from) + bid_id = created_bids[0].split(" ")[0] + bid = read_json_api(UI_PORT + 1, f"bids/{bid_id}") + assert math.isclose(float(bid["bid_rate"]), 0.05) + assert math.isclose(float(bid["amt_from"]), 21.0) + assert bid["addr_from"] == addr_bid_from -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/extended/test_wallet_init.py b/tests/basicswap/extended/test_wallet_init.py index 8dd1b85..fa8fd53 100644 --- a/tests/basicswap/extended/test_wallet_init.py +++ b/tests/basicswap/extended/test_wallet_init.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020-2022 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -36,7 +37,7 @@ from tests.basicswap.common_xmr import ( ) import basicswap.bin.run as runSystem -TEST_PATH = os.path.expanduser(os.getenv('TEST_PATH', '~/test_basicswap1')) +TEST_PATH = os.path.expanduser(os.getenv("TEST_PATH", "~/test_basicswap1")) logger = logging.getLogger() logger.level = logging.DEBUG @@ -52,21 +53,21 @@ class Test(unittest.TestCase): cls.delay_event = threading.Event() # Load both wallets from the same mnemonic - bins_path = os.path.join(TEST_PATH, 'bin') + bins_path = os.path.join(TEST_PATH, "bin") for i in range(2): - logging.info('Preparing node: %d.', i) - client_path = os.path.join(TEST_PATH, 'client{}'.format(i)) + logging.info("Preparing node: %d.", i) + client_path = os.path.join(TEST_PATH, "client{}".format(i)) try: shutil.rmtree(client_path) except Exception as ex: - logging.warning('setUpClass %s', str(ex)) + logging.warning("setUpClass %s", str(ex)) - run_prepare(i, client_path, bins_path, 'monero,bitcoin', mnemonics[0]) + run_prepare(i, client_path, bins_path, "monero,bitcoin", mnemonics[0]) def run_thread(self, client_id): - client_path = os.path.join(TEST_PATH, 'client{}'.format(client_id)) - testargs = ['basicswap-run', '-datadir=' + client_path, '-regtest'] - with patch.object(sys, 'argv', testargs): + client_path = os.path.join(TEST_PATH, "client{}".format(client_id)) + testargs = ["basicswap-run", "-datadir=" + client_path, "-regtest"] + with patch.object(sys, "argv", testargs): runSystem.main() def test_wallet(self): @@ -81,20 +82,25 @@ class Test(unittest.TestCase): try: waitForServer(self.delay_event, 12700) - wallets_0 = read_json_api(12700, 'wallets') - assert (wallets_0['PART']['expected_seed'] is True) - assert (wallets_0['XMR']['expected_seed'] is True) + wallets_0 = read_json_api(12700, "wallets") + assert wallets_0["PART"]["expected_seed"] is True + assert wallets_0["XMR"]["expected_seed"] is True waitForServer(self.delay_event, 12701) - wallets_1 = read_json_api(12701, 'wallets') + wallets_1 = read_json_api(12701, "wallets") - assert (wallets_0['PART']['expected_seed'] is True) - assert (wallets_1['XMR']['expected_seed'] is True) + assert wallets_0["PART"]["expected_seed"] is True + assert wallets_1["XMR"]["expected_seed"] is True # TODO: Check other coins - assert (wallets_0['PART']['deposit_address'] == wallets_1['1']['deposit_address']) - assert (wallets_0['XMR']['deposit_address'] == wallets_1['6']['deposit_address']) + assert ( + wallets_0["PART"]["deposit_address"] + == wallets_1["1"]["deposit_address"] + ) + assert ( + wallets_0["XMR"]["deposit_address"] == wallets_1["6"]["deposit_address"] + ) except Exception: traceback.print_exc() @@ -106,5 +112,5 @@ class Test(unittest.TestCase): p.join() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/extended/test_wallet_restore.py b/tests/basicswap/extended/test_wallet_restore.py index 7640a9f..67a688d 100644 --- a/tests/basicswap/extended/test_wallet_restore.py +++ b/tests/basicswap/extended/test_wallet_restore.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2022 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -50,10 +51,10 @@ from tests.basicswap.common import ( LTC_BASE_RPC_PORT, ) -PORT_OFS = int(os.getenv('PORT_OFS', 1)) -TEST_PATH = os.path.expanduser(os.getenv('TEST_PATH', '~/test_basicswap1')) -LITECOIN_RPC_PORT_BASE = int(os.getenv('LITECOIN_RPC_PORT_BASE', LTC_BASE_RPC_PORT)) -BITCOIN_RPC_PORT_BASE = int(os.getenv('BITCOIN_RPC_PORT_BASE', BTC_BASE_RPC_PORT)) +PORT_OFS = int(os.getenv("PORT_OFS", 1)) +TEST_PATH = os.path.expanduser(os.getenv("TEST_PATH", "~/test_basicswap1")) +LITECOIN_RPC_PORT_BASE = int(os.getenv("LITECOIN_RPC_PORT_BASE", LTC_BASE_RPC_PORT)) +BITCOIN_RPC_PORT_BASE = int(os.getenv("BITCOIN_RPC_PORT_BASE", BTC_BASE_RPC_PORT)) logger = logging.getLogger() logger.level = logging.DEBUG @@ -61,32 +62,44 @@ if not len(logger.handlers): logger.addHandler(logging.StreamHandler(sys.stdout)) -def callbtcnoderpc(node_id, method, params=[], wallet=None, base_rpc_port=BITCOIN_RPC_PORT_BASE): - auth = 'test_btc_{0}:test_btc_pwd_{0}'.format(node_id) +def callbtcnoderpc( + node_id, method, params=[], wallet=None, base_rpc_port=BITCOIN_RPC_PORT_BASE +): + auth = "test_btc_{0}:test_btc_pwd_{0}".format(node_id) return callrpc(base_rpc_port + node_id, auth, method, params, wallet) -def callltcnoderpc(node_id, method, params=[], wallet=None, base_rpc_port=LITECOIN_RPC_PORT_BASE): - auth = 'test_ltc_{0}:test_ltc_pwd_{0}'.format(node_id) +def callltcnoderpc( + node_id, method, params=[], wallet=None, base_rpc_port=LITECOIN_RPC_PORT_BASE +): + auth = "test_ltc_{0}:test_ltc_pwd_{0}".format(node_id) return callrpc(base_rpc_port + node_id, auth, method, params, wallet) def updateThread(self): while not self.delay_event.is_set(): - callbtcnoderpc(2, 'generatetoaddress', [1, self.btc_addr]) - callltcnoderpc(1, 'generatetoaddress', [1, self.ltc_addr]) + callbtcnoderpc(2, "generatetoaddress", [1, self.btc_addr]) + callltcnoderpc(1, "generatetoaddress", [1, self.ltc_addr]) self.delay_event.wait(2) def prepare_node(node_id, mnemonic): - logging.info('Preparing node: %d.', node_id) - bins_path = os.path.join(TEST_PATH, 'bin') - client_path = os.path.join(TEST_PATH, 'client{}'.format(node_id)) + logging.info("Preparing node: %d.", node_id) + bins_path = os.path.join(TEST_PATH, "bin") + client_path = os.path.join(TEST_PATH, "client{}".format(node_id)) try: shutil.rmtree(client_path) except Exception as ex: - logging.warning('setUpClass %s', str(ex)) - return run_prepare(node_id, client_path, bins_path, 'monero,bitcoin,litecoin', mnemonic, 3, use_rpcauth=True) + logging.warning("setUpClass %s", str(ex)) + return run_prepare( + node_id, + client_path, + bins_path, + "monero,bitcoin,litecoin", + mnemonic, + 3, + use_rpcauth=True, + ) class Test(TestBase): @@ -100,9 +113,9 @@ class Test(TestBase): cls.used_mnemonics.append(prepare_node(i, mnemonics[0] if i == 0 else None)) def run_thread(self, client_id): - client_path = os.path.join(TEST_PATH, 'client{}'.format(client_id)) - testargs = ['basicswap-run', '-datadir=' + client_path, '-regtest'] - with patch.object(sys, 'argv', testargs): + client_path = os.path.join(TEST_PATH, "client{}".format(client_id)) + testargs = ["basicswap-run", "-datadir=" + client_path, "-regtest"] + with patch.object(sys, "argv", testargs): runSystem.main() def finalise(self, processes): @@ -127,19 +140,25 @@ class Test(TestBase): waitForServer(self.delay_event, 12702) num_blocks = 500 # Mine enough to activate segwit - self.btc_addr = callbtcnoderpc(2, 'getnewaddress', ['mining_addr', 'bech32']) - logging.info('Mining %d Bitcoin blocks to %s', num_blocks, self.btc_addr) - callbtcnoderpc(2, 'generatetoaddress', [num_blocks, self.btc_addr]) + self.btc_addr = callbtcnoderpc( + 2, "getnewaddress", ["mining_addr", "bech32"] + ) + logging.info("Mining %d Bitcoin blocks to %s", num_blocks, self.btc_addr) + callbtcnoderpc(2, "generatetoaddress", [num_blocks, self.btc_addr]) num_blocks = 431 - self.ltc_addr = callltcnoderpc(1, 'getnewaddress', ['mining_addr', 'bech32'], wallet='wallet.dat') - logging.info('Mining %d Litecoin blocks to %s', num_blocks, self.ltc_addr) - callltcnoderpc(1, 'generatetoaddress', [num_blocks, self.ltc_addr]) + self.ltc_addr = callltcnoderpc( + 1, "getnewaddress", ["mining_addr", "bech32"], wallet="wallet.dat" + ) + logging.info("Mining %d Litecoin blocks to %s", num_blocks, self.ltc_addr) + callltcnoderpc(1, "generatetoaddress", [num_blocks, self.ltc_addr]) - mweb_addr = callltcnoderpc(1, 'getnewaddress', ['mweb_addr', 'mweb'], wallet='mweb') - callltcnoderpc(1, 'sendtoaddress', [mweb_addr, 1], wallet='wallet.dat') + mweb_addr = callltcnoderpc( + 1, "getnewaddress", ["mweb_addr", "mweb"], wallet="mweb" + ) + callltcnoderpc(1, "sendtoaddress", [mweb_addr, 1], wallet="wallet.dat") num_blocks = 69 - callltcnoderpc(1, 'generatetoaddress', [num_blocks, self.ltc_addr]) + callltcnoderpc(1, "generatetoaddress", [num_blocks, self.ltc_addr]) self.update_thread = threading.Thread(target=updateThread, args=(self,)) self.update_thread.start() @@ -147,36 +166,35 @@ class Test(TestBase): self.wait_for_particl_height(12701, num_blocks=3) data = { - 'addr_from': '-1', - 'coin_from': 'part', - 'coin_to': 'ltc', - 'amt_from': '1', - 'amt_to': '1', - 'lockhrs': '24', - 'automation_strat_id': 1} + "addr_from": "-1", + "coin_from": "part", + "coin_to": "ltc", + "amt_from": "1", + "amt_to": "1", + "lockhrs": "24", + "automation_strat_id": 1, + } - offer_id = post_json_api(12700, 'offers/new', data)['offer_id'] + post_json_api(12700, "offers/new", data)["offer_id"] summary = read_json_api(12700) - assert (summary['num_sent_offers'] == 1) + assert summary["num_sent_offers"] == 1 - logger.info('Waiting for offer') + logger.info("Waiting for offer") waitForNumOffers(self.delay_event, 12701, 1) - offers = read_json_api(12701, 'offers') + offers = read_json_api(12701, "offers") offer = offers[0] - data = { - 'offer_id': offer['offer_id'], - 'amount_from': offer['amount_from']} + data = {"offer_id": offer["offer_id"], "amount_from": offer["amount_from"]} - bid_id = post_json_api(12701, 'bids/new', data)['bid_id'] + bid_id = post_json_api(12701, "bids/new", data)["bid_id"] waitForNumBids(self.delay_event, 12700, 1) - waitForBidState(self.delay_event, 12700, bid_id, 'Completed', wait_for=120) - waitForBidState(self.delay_event, 12701, bid_id, 'Completed', wait_for=120) + waitForBidState(self.delay_event, 12700, bid_id, "Completed", wait_for=120) + waitForBidState(self.delay_event, 12701, bid_id, "Completed", wait_for=120) - logging.info('Starting a new node on the same mnemonic as the first') + logging.info("Starting a new node on the same mnemonic as the first") prepare_node(3, self.used_mnemonics[0]) processes.append(multiprocessing.Process(target=self.run_thread, args=(3,))) processes[-1].start() @@ -186,30 +204,32 @@ class Test(TestBase): # TODO: Attempt to detect past swaps - for coin in ('part', 'btc', 'ltc'): - logging.info(f'Checking {coin} balance') - original = read_json_api(12700, f'wallets/{coin}') - restored = read_json_api(12703, f'wallets/{coin}') - assert (float(original['balance']) + float(original['unconfirmed']) == float(restored['balance']) + float(restored['unconfirmed'])) + for coin in ("part", "btc", "ltc"): + logging.info(f"Checking {coin} balance") + original = read_json_api(12700, f"wallets/{coin}") + restored = read_json_api(12703, f"wallets/{coin}") + assert float(original["balance"]) + float( + original["unconfirmed"] + ) == float(restored["balance"]) + float(restored["unconfirmed"]) - wallets_original = read_json_api(12700, 'wallets') + wallets_original = read_json_api(12700, "wallets") # TODO: After restoring a new deposit address should be generated, should be automated # Swaps should use a new key path, not the external path - next_addr = read_json_api(12700, 'wallets/part/nextdepositaddr') - next_addr = read_json_api(12703, 'wallets/part/nextdepositaddr') - wallets_restored = read_json_api(12703, 'wallets') + _ = read_json_api(12700, "wallets/part/nextdepositaddr") + _ = read_json_api(12703, "wallets/part/nextdepositaddr") + wallets_restored = read_json_api(12703, "wallets") for k, w in wallets_original.items(): - assert (w['deposit_address'] == wallets_restored[k]['deposit_address']) + assert w["deposit_address"] == wallets_restored[k]["deposit_address"] except Exception as e: traceback.print_exc() self.finalise(processes) - logging.info('Test failed.') + logging.info("Test failed.") raise e self.finalise(processes) - logging.info('Test passed.') + logging.info("Test passed.") -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/extended/test_wow.py b/tests/basicswap/extended/test_wow.py index c260b5b..681f579 100644 --- a/tests/basicswap/extended/test_wow.py +++ b/tests/basicswap/extended/test_wow.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -# Copyright (c) 2024 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -30,9 +30,11 @@ from tests.basicswap.extended.test_dcr import ( NUM_NODES = 3 -WOW_BINDIR = os.path.expanduser(os.getenv('WOW_BINDIR', os.path.join(cfg.DEFAULT_TEST_BINDIR, 'wownero'))) -WOWD = os.getenv('WOWD', 'wownerod' + cfg.bin_suffix) -WOW_WALLET_RPC = os.getenv('WOW_WALLET', 'wownero-wallet-rpc' + cfg.bin_suffix) +WOW_BINDIR = os.path.expanduser( + os.getenv("WOW_BINDIR", os.path.join(cfg.DEFAULT_TEST_BINDIR, "wownero")) +) +WOWD = os.getenv("WOWD", "wownerod" + cfg.bin_suffix) +WOW_WALLET_RPC = os.getenv("WOW_WALLET", "wownero-wallet-rpc" + cfg.bin_suffix) WOW_BASE_PORT = 54932 WOW_BASE_RPC_PORT = 55932 @@ -41,45 +43,52 @@ WOW_BASE_ZMQ_PORT = 55972 def prepareWOWDataDir(datadir, node_id, conf_file): - node_dir = os.path.join(datadir, 'wow_' + str(node_id)) + node_dir = os.path.join(datadir, "wow_" + str(node_id)) if not os.path.exists(node_dir): os.makedirs(node_dir) cfg_file_path = os.path.join(node_dir, conf_file) if os.path.exists(cfg_file_path): return - with open(cfg_file_path, 'w+') as fp: - fp.write('regtest=1\n') - fp.write('log-level=4\n') - fp.write('keep-fakechain=1\n') - fp.write('data-dir={}\n'.format(node_dir)) - fp.write('fixed-difficulty=1\n') - fp.write('p2p-bind-port={}\n'.format(WOW_BASE_PORT + node_id)) - fp.write('rpc-bind-port={}\n'.format(WOW_BASE_RPC_PORT + node_id)) - fp.write('p2p-bind-ip=127.0.0.1\n') - fp.write('rpc-bind-ip=127.0.0.1\n') - fp.write('prune-blockchain=1\n') - fp.write('zmq-rpc-bind-port={}\n'.format(WOW_BASE_ZMQ_PORT + node_id)) - fp.write('zmq-rpc-bind-ip=127.0.0.1\n') + with open(cfg_file_path, "w+") as fp: + fp.write("regtest=1\n") + fp.write("log-level=4\n") + fp.write("keep-fakechain=1\n") + fp.write("data-dir={}\n".format(node_dir)) + fp.write("fixed-difficulty=1\n") + fp.write("p2p-bind-port={}\n".format(WOW_BASE_PORT + node_id)) + fp.write("rpc-bind-port={}\n".format(WOW_BASE_RPC_PORT + node_id)) + fp.write("p2p-bind-ip=127.0.0.1\n") + fp.write("rpc-bind-ip=127.0.0.1\n") + fp.write("prune-blockchain=1\n") + fp.write("zmq-rpc-bind-port={}\n".format(WOW_BASE_ZMQ_PORT + node_id)) + fp.write("zmq-rpc-bind-ip=127.0.0.1\n") for i in range(0, NUM_NODES): if node_id == i: continue - fp.write('add-exclusive-node=127.0.0.1:{}\n'.format(WOW_BASE_PORT + i)) + fp.write("add-exclusive-node=127.0.0.1:{}\n".format(WOW_BASE_PORT + i)) def waitForWOWNode(rpc_offset, max_tries=7, auth=None): for i in range(max_tries + 1): try: if auth is None: - callrpc_xmr(WOW_BASE_RPC_PORT + rpc_offset, 'get_block_count') + callrpc_xmr(WOW_BASE_RPC_PORT + rpc_offset, "get_block_count") else: - callrpc_xmr(WOW_BASE_WALLET_RPC_PORT + rpc_offset, 'get_languages', auth=auth) + callrpc_xmr( + WOW_BASE_WALLET_RPC_PORT + rpc_offset, "get_languages", auth=auth + ) return except Exception as ex: if i < max_tries: - logging.warning('Can\'t connect to WOW%s RPC: %s. Retrying in %d second/s.', '' if auth is None else ' wallet', str(ex), (i + 1)) + logging.warning( + "Can't connect to WOW%s RPC: %s. Retrying in %d second/s.", + "" if auth is None else " wallet", + str(ex), + (i + 1), + ) time.sleep(i + 1) - raise ValueError('waitForWOWNode failed') + raise ValueError("waitForWOWNode failed") class Test(BaseTest): @@ -96,15 +105,22 @@ class Test(BaseTest): def prepareExtraCoins(cls): pass num_blocks = 300 - cls.wow_addr = cls.callwownodewallet(cls, 1, 'get_address')['address'] - if callrpc_xmr(WOW_BASE_RPC_PORT + 1, 'get_block_count')['count'] < num_blocks: - logging.info('Mining %d Wownero blocks to %s.', num_blocks, cls.wow_addr) - callrpc_xmr(WOW_BASE_RPC_PORT + 1, 'generateblocks', {'wallet_address': cls.wow_addr, 'amount_of_blocks': num_blocks}) - logging.info('WOW blocks: %d', callrpc_xmr(WOW_BASE_RPC_PORT + 1, 'get_block_count')['count']) + cls.wow_addr = cls.callwownodewallet(cls, 1, "get_address")["address"] + if callrpc_xmr(WOW_BASE_RPC_PORT + 1, "get_block_count")["count"] < num_blocks: + logging.info("Mining %d Wownero blocks to %s.", num_blocks, cls.wow_addr) + callrpc_xmr( + WOW_BASE_RPC_PORT + 1, + "generateblocks", + {"wallet_address": cls.wow_addr, "amount_of_blocks": num_blocks}, + ) + logging.info( + "WOW blocks: %d", + callrpc_xmr(WOW_BASE_RPC_PORT + 1, "get_block_count")["count"], + ) @classmethod def tearDownClass(cls): - logging.info('Finalising Wownero Test') + logging.info("Finalising Wownero Test") super(Test, cls).tearDownClass() stopDaemons(cls.wow_daemons) @@ -115,38 +131,51 @@ class Test(BaseTest): super(Test, cls).coins_loop() if cls.wow_addr is not None: - callrpc_xmr(WOW_BASE_RPC_PORT + 0, 'generateblocks', {'wallet_address': cls.wow_addr, 'amount_of_blocks': 1}) + callrpc_xmr( + WOW_BASE_RPC_PORT + 0, + "generateblocks", + {"wallet_address": cls.wow_addr, "amount_of_blocks": 1}, + ) @classmethod def prepareExtraDataDir(cls, i): if not cls.restore_instance: - prepareWOWDataDir(cfg.TEST_DATADIRS, i, 'wownerod.conf') + prepareWOWDataDir(cfg.TEST_DATADIRS, i, "wownerod.conf") - node_dir = os.path.join(cfg.TEST_DATADIRS, 'wow_' + str(i)) + node_dir = os.path.join(cfg.TEST_DATADIRS, "wow_" + str(i)) cls.wow_daemons.append(startXmrDaemon(node_dir, WOW_BINDIR, WOWD)) - logging.info('Started %s %d', WOWD, cls.wow_daemons[-1].handle.pid) + logging.info("Started %s %d", WOWD, cls.wow_daemons[-1].handle.pid) waitForWOWNode(i) opts = [ - '--daemon-address=127.0.0.1:{}'.format(WOW_BASE_RPC_PORT + i), - '--no-dns', - '--rpc-bind-port={}'.format(WOW_BASE_WALLET_RPC_PORT + i), - '--wallet-dir={}'.format(os.path.join(node_dir, 'wallets')), - '--log-file={}'.format(os.path.join(node_dir, 'wallet.log')), - '--rpc-login=test{0}:test_pass{0}'.format(i), - '--wow-shared-ringdb-dir={}'.format(os.path.join(node_dir, 'shared-ringdb')), - '--allow-mismatched-daemon-version', + "--daemon-address=127.0.0.1:{}".format(WOW_BASE_RPC_PORT + i), + "--no-dns", + "--rpc-bind-port={}".format(WOW_BASE_WALLET_RPC_PORT + i), + "--wallet-dir={}".format(os.path.join(node_dir, "wallets")), + "--log-file={}".format(os.path.join(node_dir, "wallet.log")), + "--rpc-login=test{0}:test_pass{0}".format(i), + "--wow-shared-ringdb-dir={}".format( + os.path.join(node_dir, "shared-ringdb") + ), + "--allow-mismatched-daemon-version", ] - cls.wow_daemons.append(startXmrWalletDaemon(node_dir, WOW_BINDIR, WOW_WALLET_RPC, opts=opts)) + cls.wow_daemons.append( + startXmrWalletDaemon(node_dir, WOW_BINDIR, WOW_WALLET_RPC, opts=opts) + ) - cls.wow_wallet_auth.append(('test{0}'.format(i), 'test_pass{0}'.format(i))) + cls.wow_wallet_auth.append(("test{0}".format(i), "test_pass{0}".format(i))) waitForWOWNode(i, auth=cls.wow_wallet_auth[i]) if not cls.restore_instance: - logging.info('Creating WOW wallet %i', i) - cls.callwownodewallet(cls, i, 'create_wallet', {'filename': 'testwallet', 'language': 'English'}) - cls.callwownodewallet(cls, i, 'open_wallet', {'filename': 'testwallet'}) + logging.info("Creating WOW wallet %i", i) + cls.callwownodewallet( + cls, + i, + "create_wallet", + {"filename": "testwallet", "language": "English"}, + ) + cls.callwownodewallet(cls, i, "open_wallet", {"filename": "testwallet"}) @classmethod def addPIDInfo(cls, sc, i): @@ -154,20 +183,25 @@ class Test(BaseTest): @classmethod def addCoinSettings(cls, settings, datadir, node_id): - settings['chainclients']['wownero'] = { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': WOW_BASE_RPC_PORT + node_id, - 'walletrpcport': WOW_BASE_WALLET_RPC_PORT + node_id, - 'walletrpcuser': 'test' + str(node_id), - 'walletrpcpassword': 'test_pass' + str(node_id), - 'walletfile': 'testwallet', - 'datadir': os.path.join(datadir, 'xmr_' + str(node_id)), - 'bindir': WOW_BINDIR, + settings["chainclients"]["wownero"] = { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": WOW_BASE_RPC_PORT + node_id, + "walletrpcport": WOW_BASE_WALLET_RPC_PORT + node_id, + "walletrpcuser": "test" + str(node_id), + "walletrpcpassword": "test_pass" + str(node_id), + "walletfile": "testwallet", + "datadir": os.path.join(datadir, "xmr_" + str(node_id)), + "bindir": WOW_BINDIR, } def callwownodewallet(self, node_id, method, params=None): - return callrpc_xmr(WOW_BASE_WALLET_RPC_PORT + node_id, method, params, auth=self.wow_wallet_auth[node_id]) + return callrpc_xmr( + WOW_BASE_WALLET_RPC_PORT + node_id, + method, + params, + auth=self.wow_wallet_auth[node_id], + ) def test_01_ads_part_coin(self): run_test_ads_success_path(self, Coins.PART, self.test_coin) diff --git a/tests/basicswap/extended/test_xmr_persistent.py b/tests/basicswap/extended/test_xmr_persistent.py index f47841e..b27320a 100644 --- a/tests/basicswap/extended/test_xmr_persistent.py +++ b/tests/basicswap/extended/test_xmr_persistent.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021-2024 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -60,22 +61,24 @@ from basicswap.interface.dcr.rpc import callrpc as callrpc_dcr import basicswap.bin.run as runSystem -test_path = os.path.expanduser(os.getenv('TEST_PATH', '/tmp/test_persistent')) -RESET_TEST = make_boolean(os.getenv('RESET_TEST', 'false')) +test_path = os.path.expanduser(os.getenv("TEST_PATH", "/tmp/test_persistent")) +RESET_TEST = make_boolean(os.getenv("RESET_TEST", "false")) -PORT_OFS = int(os.getenv('PORT_OFS', 1)) +PORT_OFS = int(os.getenv("PORT_OFS", 1)) UI_PORT = 12700 + PORT_OFS -PARTICL_RPC_PORT_BASE = int(os.getenv('PARTICL_RPC_PORT_BASE', BASE_RPC_PORT)) -BITCOIN_RPC_PORT_BASE = int(os.getenv('BITCOIN_RPC_PORT_BASE', BTC_BASE_RPC_PORT)) -LITECOIN_RPC_PORT_BASE = int(os.getenv('LITECOIN_RPC_PORT_BASE', LTC_BASE_RPC_PORT)) -BITCOINCASH_RPC_PORT_BASE = int(os.getenv('BITCOINCASH_RPC_PORT_BASE', BCH_BASE_RPC_PORT)) -DECRED_WALLET_RPC_PORT_BASE = int(os.getenv('DECRED_WALLET_RPC_PORT_BASE', 9210)) -XMR_BASE_RPC_PORT = int(os.getenv('XMR_BASE_RPC_PORT', XMR_BASE_RPC_PORT)) -TEST_COINS_LIST = os.getenv('TEST_COINS_LIST', 'bitcoin,monero') +PARTICL_RPC_PORT_BASE = int(os.getenv("PARTICL_RPC_PORT_BASE", BASE_RPC_PORT)) +BITCOIN_RPC_PORT_BASE = int(os.getenv("BITCOIN_RPC_PORT_BASE", BTC_BASE_RPC_PORT)) +LITECOIN_RPC_PORT_BASE = int(os.getenv("LITECOIN_RPC_PORT_BASE", LTC_BASE_RPC_PORT)) +BITCOINCASH_RPC_PORT_BASE = int( + os.getenv("BITCOINCASH_RPC_PORT_BASE", BCH_BASE_RPC_PORT) +) +DECRED_WALLET_RPC_PORT_BASE = int(os.getenv("DECRED_WALLET_RPC_PORT_BASE", 9210)) +XMR_BASE_RPC_PORT = int(os.getenv("XMR_BASE_RPC_PORT", XMR_BASE_RPC_PORT)) +TEST_COINS_LIST = os.getenv("TEST_COINS_LIST", "bitcoin,monero") -NUM_NODES = int(os.getenv('NUM_NODES', 3)) -EXTRA_CONFIG_JSON = json.loads(os.getenv('EXTRA_CONFIG_JSON', '{}')) +NUM_NODES = int(os.getenv("NUM_NODES", 3)) +EXTRA_CONFIG_JSON = json.loads(os.getenv("EXTRA_CONFIG_JSON", "{}")) logger = logging.getLogger() logger.level = logging.DEBUG @@ -83,28 +86,54 @@ if not len(logger.handlers): logger.addHandler(logging.StreamHandler(sys.stdout)) -def callpartrpc(node_id, method, params=[], wallet=None, base_rpc_port=PARTICL_RPC_PORT_BASE + PORT_OFS): - auth = 'test_part_{0}:test_part_pwd_{0}'.format(node_id) +def callpartrpc( + node_id, + method, + params=[], + wallet=None, + base_rpc_port=PARTICL_RPC_PORT_BASE + PORT_OFS, +): + auth = "test_part_{0}:test_part_pwd_{0}".format(node_id) return callrpc(base_rpc_port + node_id, auth, method, params, wallet) -def callbtcrpc(node_id, method, params=[], wallet=None, base_rpc_port=BITCOIN_RPC_PORT_BASE + PORT_OFS): - auth = 'test_btc_{0}:test_btc_pwd_{0}'.format(node_id) +def callbtcrpc( + node_id, + method, + params=[], + wallet=None, + base_rpc_port=BITCOIN_RPC_PORT_BASE + PORT_OFS, +): + auth = "test_btc_{0}:test_btc_pwd_{0}".format(node_id) return callrpc(base_rpc_port + node_id, auth, method, params, wallet) -def callltcrpc(node_id, method, params=[], wallet=None, base_rpc_port=LITECOIN_RPC_PORT_BASE + PORT_OFS): - auth = 'test_ltc_{0}:test_ltc_pwd_{0}'.format(node_id) +def callltcrpc( + node_id, + method, + params=[], + wallet=None, + base_rpc_port=LITECOIN_RPC_PORT_BASE + PORT_OFS, +): + auth = "test_ltc_{0}:test_ltc_pwd_{0}".format(node_id) return callrpc(base_rpc_port + node_id, auth, method, params, wallet) -def calldcrrpc(node_id, method, params=[], wallet=None, base_rpc_port=DECRED_WALLET_RPC_PORT_BASE): - auth = 'user:dcr_pwd' +def calldcrrpc( + node_id, method, params=[], wallet=None, base_rpc_port=DECRED_WALLET_RPC_PORT_BASE +): + auth = "user:dcr_pwd" return callrpc_dcr(base_rpc_port + node_id, auth, method, params) -def callbchrpc(node_id, method, params=[], wallet=None, base_rpc_port=BITCOINCASH_RPC_PORT_BASE + PORT_OFS): - auth = 'test_bch_{0}:test_bch_pwd_{0}'.format(node_id) +def callbchrpc( + node_id, + method, + params=[], + wallet=None, + base_rpc_port=BITCOINCASH_RPC_PORT_BASE + PORT_OFS, +): + auth = "test_bch_{0}:test_bch_pwd_{0}".format(node_id) return callrpc(base_rpc_port + node_id, auth, method, params, wallet) @@ -112,27 +141,32 @@ def updateThread(cls): while not cls.delay_event.is_set(): try: if cls.btc_addr is not None: - callbtcrpc(0, 'generatetoaddress', [1, cls.btc_addr]) + callbtcrpc(0, "generatetoaddress", [1, cls.btc_addr]) if cls.ltc_addr is not None: - callltcrpc(0, 'generatetoaddress', [1, cls.ltc_addr]) + callltcrpc(0, "generatetoaddress", [1, cls.ltc_addr]) if cls.bch_addr is not None: - callbchrpc(0, 'generatetoaddress', [1, cls.bch_addr]) + callbchrpc(0, "generatetoaddress", [1, cls.bch_addr]) except Exception as e: - print('updateThread error', str(e)) + print("updateThread error", str(e)) cls.delay_event.wait(random.randrange(cls.update_min, cls.update_max)) def updateThreadXMR(cls): xmr_auth = None - if os.getenv('XMR_RPC_USER', '') != '': - xmr_auth = (os.getenv('XMR_RPC_USER', ''), os.getenv('XMR_RPC_PWD', '')) + if os.getenv("XMR_RPC_USER", "") != "": + xmr_auth = (os.getenv("XMR_RPC_USER", ""), os.getenv("XMR_RPC_PWD", "")) while not cls.delay_event.is_set(): try: if cls.xmr_addr is not None: - callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'generateblocks', {'wallet_address': cls.xmr_addr, 'amount_of_blocks': 1}, auth=xmr_auth) + callrpc_xmr( + XMR_BASE_RPC_PORT + 1, + "generateblocks", + {"wallet_address": cls.xmr_addr, "amount_of_blocks": 1}, + auth=xmr_auth, + ) except Exception as e: - print('updateThreadXMR error', str(e)) + print("updateThreadXMR error", str(e)) cls.delay_event.wait(random.randrange(cls.xmr_update_min, cls.xmr_update_max)) @@ -143,24 +177,30 @@ def updateThreadDCR(cls): num_passed: int = 0 for i in range(30): try: - calldcrrpc(0, 'purchaseticket', [cls.dcr_acc, 0.1, 0]) + calldcrrpc(0, "purchaseticket", [cls.dcr_acc, 0.1, 0]) num_passed += 1 if num_passed >= 5: break cls.delay_event.wait(0.1) except Exception as e: - if 'double spend' in str(e): + if "double spend" in str(e): pass else: - logging.warning('updateThreadDCR purchaseticket {}'.format(e)) + logging.warning("updateThreadDCR purchaseticket {}".format(e)) cls.delay_event.wait(0.5) try: if num_passed >= 5: - calldcrrpc(0, 'generate', [1,]) + calldcrrpc( + 0, + "generate", + [ + 1, + ], + ) except Exception as e: - logging.warning('updateThreadDCR generate {}'.format(e)) + logging.warning("updateThreadDCR generate {}".format(e)) except Exception as e: - print('updateThreadDCR error', str(e)) + print("updateThreadDCR error", str(e)) cls.delay_event.wait(random.randrange(cls.dcr_update_min, cls.dcr_update_max)) @@ -169,13 +209,13 @@ class Test(unittest.TestCase): def setUpClass(cls): super(Test, cls).setUpClass() - cls.update_min = int(os.getenv('UPDATE_THREAD_MIN_WAIT', '1')) + cls.update_min = int(os.getenv("UPDATE_THREAD_MIN_WAIT", "1")) cls.update_max = cls.update_min * 4 - cls.xmr_update_min = int(os.getenv('XMR_UPDATE_THREAD_MIN_WAIT', '1')) + cls.xmr_update_min = int(os.getenv("XMR_UPDATE_THREAD_MIN_WAIT", "1")) cls.xmr_update_max = cls.xmr_update_min * 4 - cls.dcr_update_min = int(os.getenv('DCR_UPDATE_THREAD_MIN_WAIT', '1')) + cls.dcr_update_min = int(os.getenv("DCR_UPDATE_THREAD_MIN_WAIT", "1")) cls.dcr_update_max = cls.dcr_update_min * 4 cls.delay_event = threading.Event() @@ -187,100 +227,181 @@ class Test(unittest.TestCase): cls.ltc_addr = None cls.bch_addr = None cls.xmr_addr = None - cls.dcr_addr = 'SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH' + cls.dcr_addr = "SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH" cls.dcr_acc = None random.seed(time.time()) if os.path.exists(test_path) and not RESET_TEST: - logging.info(f'Continuing with existing directory: {test_path}') + logging.info(f"Continuing with existing directory: {test_path}") else: - logging.info('Preparing %d nodes.', NUM_NODES) - prepare_nodes(NUM_NODES, TEST_COINS_LIST, True, {'min_sequence_lock_seconds': 60}, PORT_OFS) + logging.info("Preparing %d nodes.", NUM_NODES) + prepare_nodes( + NUM_NODES, + TEST_COINS_LIST, + True, + {"min_sequence_lock_seconds": 60}, + PORT_OFS, + ) - signal.signal(signal.SIGINT, lambda signal, frame: cls.signal_handler(cls, signal, frame)) + signal.signal( + signal.SIGINT, lambda signal, frame: cls.signal_handler(cls, signal, frame) + ) def signal_handler(self, sig, frame): - logging.info('signal {} detected.'.format(sig)) + logging.info("signal {} detected.".format(sig)) self.delay_event.set() def run_thread(self, client_id): - client_path = os.path.join(test_path, 'client{}'.format(client_id)) - testargs = ['basicswap-run', '-datadir=' + client_path, '-regtest'] - with patch.object(sys, 'argv', testargs): + client_path = os.path.join(test_path, "client{}".format(client_id)) + testargs = ["basicswap-run", "-datadir=" + client_path, "-regtest"] + with patch.object(sys, "argv", testargs): runSystem.main() def start_processes(self): self.delay_event.clear() for i in range(NUM_NODES): - self.processes.append(multiprocessing.Process(target=self.run_thread, args=(i,))) + self.processes.append( + multiprocessing.Process(target=self.run_thread, args=(i,)) + ) self.processes[-1].start() for i in range(NUM_NODES): waitForServer(self.delay_event, UI_PORT + i) - wallets = read_json_api(UI_PORT + 1, 'wallets') + wallets = read_json_api(UI_PORT + 1, "wallets") xmr_auth = None - if os.getenv('XMR_RPC_USER', '') != '': - xmr_auth = (os.getenv('XMR_RPC_USER', ''), os.getenv('XMR_RPC_PWD', '')) + if os.getenv("XMR_RPC_USER", "") != "": + xmr_auth = (os.getenv("XMR_RPC_USER", ""), os.getenv("XMR_RPC_PWD", "")) - self.xmr_addr = wallets['XMR']['main_address'] + self.xmr_addr = wallets["XMR"]["main_address"] num_blocks = 100 - if callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'get_block_count', auth=xmr_auth)['count'] < num_blocks: - logging.info('Mining {} Monero blocks to {}.'.format(num_blocks, self.xmr_addr)) - callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'generateblocks', {'wallet_address': self.xmr_addr, 'amount_of_blocks': num_blocks}, auth=xmr_auth) - logging.info('XMR blocks: %d', callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'get_block_count', auth=xmr_auth)['count']) + if ( + callrpc_xmr(XMR_BASE_RPC_PORT + 1, "get_block_count", auth=xmr_auth)[ + "count" + ] + < num_blocks + ): + logging.info( + "Mining {} Monero blocks to {}.".format(num_blocks, self.xmr_addr) + ) + callrpc_xmr( + XMR_BASE_RPC_PORT + 1, + "generateblocks", + {"wallet_address": self.xmr_addr, "amount_of_blocks": num_blocks}, + auth=xmr_auth, + ) + logging.info( + "XMR blocks: %d", + callrpc_xmr(XMR_BASE_RPC_PORT + 1, "get_block_count", auth=xmr_auth)[ + "count" + ], + ) - self.btc_addr = callbtcrpc(0, 'getnewaddress', ['mining_addr', 'bech32']) + self.btc_addr = callbtcrpc(0, "getnewaddress", ["mining_addr", "bech32"]) num_blocks: int = 500 # Mine enough to activate segwit - if callbtcrpc(0, 'getblockcount') < num_blocks: - logging.info('Mining %d Bitcoin blocks to %s', num_blocks, self.btc_addr) - callbtcrpc(0, 'generatetoaddress', [num_blocks, self.btc_addr]) - logging.info('BTC blocks: %d', callbtcrpc(0, 'getblockcount')) + if callbtcrpc(0, "getblockcount") < num_blocks: + logging.info("Mining %d Bitcoin blocks to %s", num_blocks, self.btc_addr) + callbtcrpc(0, "generatetoaddress", [num_blocks, self.btc_addr]) + logging.info("BTC blocks: %d", callbtcrpc(0, "getblockcount")) - if 'litecoin' in TEST_COINS_LIST: - self.ltc_addr = callltcrpc(0, 'getnewaddress', ['mining_addr'], wallet='wallet.dat') + if "litecoin" in TEST_COINS_LIST: + self.ltc_addr = callltcrpc( + 0, "getnewaddress", ["mining_addr"], wallet="wallet.dat" + ) num_blocks: int = 431 - have_blocks: int = callltcrpc(0, 'getblockcount') + have_blocks: int = callltcrpc(0, "getblockcount") if have_blocks < 500: - logging.info('Mining %d Litecoin blocks to %s', num_blocks, self.ltc_addr) - callltcrpc(0, 'generatetoaddress', [num_blocks - have_blocks, self.ltc_addr], wallet='wallet.dat') + logging.info( + "Mining %d Litecoin blocks to %s", num_blocks, self.ltc_addr + ) + callltcrpc( + 0, + "generatetoaddress", + [num_blocks - have_blocks, self.ltc_addr], + wallet="wallet.dat", + ) # https://github.com/litecoin-project/litecoin/issues/807 # Block 432 is when MWEB activates. It requires a peg-in. You'll need to generate an mweb address and send some coins to it. Then it will allow you to mine the next block. - mweb_addr = callltcrpc(0, 'getnewaddress', ['mweb_addr', 'mweb'], wallet='mweb') - callltcrpc(0, 'sendtoaddress', [mweb_addr, 1.0], wallet='wallet.dat') + mweb_addr = callltcrpc( + 0, "getnewaddress", ["mweb_addr", "mweb"], wallet="mweb" + ) + callltcrpc(0, "sendtoaddress", [mweb_addr, 1.0], wallet="wallet.dat") num_blocks = 69 - have_blocks: int = callltcrpc(0, 'getblockcount') - callltcrpc(0, 'generatetoaddress', [500 - have_blocks, self.ltc_addr], wallet='wallet.dat') + have_blocks: int = callltcrpc(0, "getblockcount") + callltcrpc( + 0, + "generatetoaddress", + [500 - have_blocks, self.ltc_addr], + wallet="wallet.dat", + ) - if 'decred' in TEST_COINS_LIST: + if "decred" in TEST_COINS_LIST: if RESET_TEST: - addr = calldcrrpc(0, 'getnewaddress') + _ = calldcrrpc(0, "getnewaddress") # assert (addr == self.dcr_addr) - self.dcr_acc = calldcrrpc(0, 'getaccount', [self.dcr_addr, ]) - addr = calldcrrpc(0, 'generate', [110,]) + self.dcr_acc = calldcrrpc( + 0, + "getaccount", + [ + self.dcr_addr, + ], + ) + calldcrrpc( + 0, + "generate", + [ + 110, + ], + ) else: - self.dcr_acc = calldcrrpc(0, 'getaccount', [self.dcr_addr, ]) + self.dcr_acc = calldcrrpc( + 0, + "getaccount", + [ + self.dcr_addr, + ], + ) - self.update_thread_dcr = threading.Thread(target=updateThreadDCR, args=(self,)) + self.update_thread_dcr = threading.Thread( + target=updateThreadDCR, args=(self,) + ) self.update_thread_dcr.start() - if 'bitcoincash' in TEST_COINS_LIST: - self.bch_addr = callbchrpc(0, 'getnewaddress', ['mining_addr'], wallet='wallet.dat') + if "bitcoincash" in TEST_COINS_LIST: + self.bch_addr = callbchrpc( + 0, "getnewaddress", ["mining_addr"], wallet="wallet.dat" + ) num_blocks: int = 200 - have_blocks: int = callbchrpc(0, 'getblockcount') + have_blocks: int = callbchrpc(0, "getblockcount") if have_blocks < num_blocks: - logging.info('Mining %d Bitcoincash blocks to %s', num_blocks - have_blocks, self.bch_addr) - callbchrpc(0, 'generatetoaddress', [num_blocks - have_blocks, self.bch_addr], wallet='wallet.dat') + logging.info( + "Mining %d Bitcoincash blocks to %s", + num_blocks - have_blocks, + self.bch_addr, + ) + callbchrpc( + 0, + "generatetoaddress", + [num_blocks - have_blocks, self.bch_addr], + wallet="wallet.dat", + ) if RESET_TEST: # Lower output split threshold for more stakeable outputs for i in range(NUM_NODES): - callpartrpc(i, 'walletsettings', ['stakingoptions', {'stakecombinethreshold': 100, 'stakesplitthreshold': 200}]) + callpartrpc( + i, + "walletsettings", + [ + "stakingoptions", + {"stakecombinethreshold": 100, "stakesplitthreshold": 200}, + ], + ) self.update_thread = threading.Thread(target=updateThread, args=(self,)) self.update_thread.start() @@ -289,21 +410,21 @@ class Test(unittest.TestCase): # Wait for height, or sequencelock is thrown off by genesis blocktime num_blocks = 3 - logging.info('Waiting for Particl chain height %d', num_blocks) + logging.info("Waiting for Particl chain height %d", num_blocks) for i in range(60): if self.delay_event.is_set(): - raise ValueError('Test stopped.') - particl_blocks = callpartrpc(0, 'getblockcount') - print('particl_blocks', particl_blocks) + raise ValueError("Test stopped.") + particl_blocks = callpartrpc(0, "getblockcount") + print("particl_blocks", particl_blocks) if particl_blocks >= num_blocks: break self.delay_event.wait(1) - logging.info('PART blocks: %d', callpartrpc(0, 'getblockcount')) + logging.info("PART blocks: %d", callpartrpc(0, "getblockcount")) assert particl_blocks >= num_blocks @classmethod def tearDownClass(cls): - logging.info('Stopping test') + logging.info("Stopping test") cls.delay_event.set() if cls.update_thread: cls.update_thread.join() @@ -328,9 +449,9 @@ class Test(unittest.TestCase): waitForServer(self.delay_event, UI_PORT + 1) while not self.delay_event.is_set(): - logging.info('Looping indefinitely, ctrl+c to exit.') + logging.info("Looping indefinitely, ctrl+c to exit.") self.delay_event.wait(10) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/mnemonics.py b/tests/basicswap/mnemonics.py index 653a7a8..8da6a6c 100644 --- a/tests/basicswap/mnemonics.py +++ b/tests/basicswap/mnemonics.py @@ -2,11 +2,12 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. mnemonics = [ - 'abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb', - 'actuel comédie poésie noble facile éprouver brave cellule rotule académie hilarant chambre', - 'ちしき いてざ きおち あしあと ぽちぶくろ こえる さつえい むえき あける ほんき むさぼる ねいろ', + "abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb", + "actuel comédie poésie noble facile éprouver brave cellule rotule académie hilarant chambre", + "ちしき いてざ きおち あしあと ぽちぶくろ こえる さつえい むえき あける ほんき むさぼる ねいろ", ] diff --git a/tests/basicswap/selenium/test_offer.py b/tests/basicswap/selenium/test_offer.py index 9dd39d9..09f146f 100644 --- a/tests/basicswap/selenium/test_offer.py +++ b/tests/basicswap/selenium/test_offer.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2023-2024 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -18,106 +19,125 @@ from util import get_driver def test_offer(driver): - node1_url = 'http://localhost:12701' - node2_url = 'http://localhost:12702' + node1_url = "http://localhost:12701" - driver.get(node1_url + '/newoffer') + driver.get(node1_url + "/newoffer") time.sleep(1) - select = Select(driver.find_element(By.ID, 'coin_from')) - select.select_by_visible_text('Bitcoin') - select = Select(driver.find_element(By.ID, 'coin_to')) - select.select_by_visible_text('Monero') + select = Select(driver.find_element(By.ID, "coin_from")) + select.select_by_visible_text("Bitcoin") + select = Select(driver.find_element(By.ID, "coin_to")) + select.select_by_visible_text("Monero") - amt_from = driver.find_element(By.NAME, 'amt_from') - amt_to = driver.find_element(By.NAME, 'amt_to') - rate = driver.find_element(By.ID, 'rate') - amt_from.send_keys('1') - amt_to.send_keys('2') + amt_from = driver.find_element(By.NAME, "amt_from") + amt_to = driver.find_element(By.NAME, "amt_to") + rate = driver.find_element(By.ID, "rate") + amt_from.send_keys("1") + amt_to.send_keys("2") amt_from.click() time.sleep(0.5) - rate_value = rate.get_attribute('value') - assert (float(rate_value) == 2.0) + rate_value = rate.get_attribute("value") + assert float(rate_value) == 2.0 rate.clear() - rate.send_keys('3') + rate.send_keys("3") amt_from.click() time.sleep(0.5) - amt_to_value = amt_to.get_attribute('value') - assert (float(amt_to_value) == 3.0) + amt_to_value = amt_to.get_attribute("value") + assert float(amt_to_value) == 3.0 amt_from.clear() - amt_from.send_keys('2') + amt_from.send_keys("2") amt_to.click() time.sleep(0.5) - amt_to_value = amt_to.get_attribute('value') - assert (float(amt_to_value) == 6.0) + amt_to_value = amt_to.get_attribute("value") + assert float(amt_to_value) == 6.0 amt_from.clear() amt_to.clear() rate.clear() - amt_to.send_keys('2') - rate.send_keys('2') + amt_to.send_keys("2") + rate.send_keys("2") amt_to.click() time.sleep(0.2) - amt_from_value = amt_from.get_attribute('value') - assert (float(amt_from_value) == 1.0) + amt_from_value = amt_from.get_attribute("value") + assert float(amt_from_value) == 1.0 - driver.find_element(By.NAME, 'continue').click() - WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'check_offer'))).click() - WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'submit_offer'))).click() + driver.find_element(By.NAME, "continue").click() + WebDriverWait(driver, 20).until( + EC.element_to_be_clickable((By.NAME, "check_offer")) + ).click() + WebDriverWait(driver, 20).until( + EC.element_to_be_clickable((By.NAME, "submit_offer")) + ).click() time.sleep(1) offer_link = driver.find_element(By.XPATH, "//a[contains(text(),'Sent Offer')]") - offer1_id = offer_link.text.split(' ')[2] + offer1_id = offer_link.text.split(" ")[2] - driver.get(node1_url + '/newoffer') + driver.get(node1_url + "/newoffer") time.sleep(1) - select = Select(driver.find_element(By.ID, 'coin_from')) - select.select_by_visible_text('Particl') - select = Select(driver.find_element(By.ID, 'coin_to')) - select.select_by_visible_text('Monero') + select = Select(driver.find_element(By.ID, "coin_from")) + select.select_by_visible_text("Particl") + select = Select(driver.find_element(By.ID, "coin_to")) + select.select_by_visible_text("Monero") - driver.find_element(By.NAME, 'amt_from').send_keys('3') - driver.find_element(By.NAME, 'amt_to').send_keys('4') + driver.find_element(By.NAME, "amt_from").send_keys("3") + driver.find_element(By.NAME, "amt_to").send_keys("4") - driver.find_element(By.NAME, 'continue').click() - WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'check_offer'))).click() - WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'submit_offer'))).click() + driver.find_element(By.NAME, "continue").click() + WebDriverWait(driver, 20).until( + EC.element_to_be_clickable((By.NAME, "check_offer")) + ).click() + WebDriverWait(driver, 20).until( + EC.element_to_be_clickable((By.NAME, "submit_offer")) + ).click() time.sleep(1) offer_link = driver.find_element(By.XPATH, "//a[contains(text(),'Sent Offer')]") - offer2_id = offer_link.text.split(' ')[2] + offer2_id = offer_link.text.split(" ")[2] - driver.get(node1_url + '/offer/' + offer1_id) - WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'repeat_offer'))).click() - WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'check_offer'))).click() - WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'submit_offer'))).click() + driver.get(node1_url + "/offer/" + offer1_id) + WebDriverWait(driver, 20).until( + EC.element_to_be_clickable((By.NAME, "repeat_offer")) + ).click() + WebDriverWait(driver, 20).until( + EC.element_to_be_clickable((By.NAME, "check_offer")) + ).click() + WebDriverWait(driver, 20).until( + EC.element_to_be_clickable((By.NAME, "submit_offer")) + ).click() time.sleep(1) offer_link = driver.find_element(By.XPATH, "//a[contains(text(),'Sent Offer')]") - offer3_id = offer_link.text.split(' ')[2] + offer3_id = offer_link.text.split(" ")[2] - offer3_json = json.loads(urlopen(node1_url + '/json/offers/' + offer3_id).read())[0] - assert (offer3_json['coin_from'] == 'Bitcoin') - assert (offer3_json['coin_to'] == 'Monero') + offer3_json = json.loads(urlopen(node1_url + "/json/offers/" + offer3_id).read())[0] + assert offer3_json["coin_from"] == "Bitcoin" + assert offer3_json["coin_to"] == "Monero" - driver.get(node1_url + '/offer/' + offer2_id) - WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'repeat_offer'))).click() + driver.get(node1_url + "/offer/" + offer2_id) + WebDriverWait(driver, 20).until( + EC.element_to_be_clickable((By.NAME, "repeat_offer")) + ).click() time.sleep(1) # Add time for setupCustomSelect to fire - WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'check_offer'))).click() - WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'submit_offer'))).click() + WebDriverWait(driver, 20).until( + EC.element_to_be_clickable((By.NAME, "check_offer")) + ).click() + WebDriverWait(driver, 20).until( + EC.element_to_be_clickable((By.NAME, "submit_offer")) + ).click() time.sleep(1) offer_link = driver.find_element(By.XPATH, "//a[contains(text(),'Sent Offer')]") - offer4_id = offer_link.text.split(' ')[2] + offer4_id = offer_link.text.split(" ")[2] - offer4_json = json.loads(urlopen(node1_url + '/json/offers/' + offer4_id).read())[0] - assert (offer4_json['coin_from'] == 'Particl') - assert (offer4_json['coin_to'] == 'Monero') + offer4_json = json.loads(urlopen(node1_url + "/json/offers/" + offer4_id).read())[0] + assert offer4_json["coin_from"] == "Particl" + assert offer4_json["coin_to"] == "Monero" - print('Test Passed!') + print("Test Passed!") def run_tests(): @@ -128,5 +148,5 @@ def run_tests(): driver.close() -if __name__ == '__main__': +if __name__ == "__main__": run_tests() diff --git a/tests/basicswap/selenium/test_recover_chain_b_lock_tx.py b/tests/basicswap/selenium/test_recover_chain_b_lock_tx.py index b57c388..2162fe1 100644 --- a/tests/basicswap/selenium/test_recover_chain_b_lock_tx.py +++ b/tests/basicswap/selenium/test_recover_chain_b_lock_tx.py @@ -13,196 +13,229 @@ from selenium.webdriver.support.select import Select from selenium.webdriver.support import expected_conditions as EC from util import ( - BSX_0_PORT, BSX_1_PORT, + BSX_0_PORT, + BSX_1_PORT, click_option, get_driver, ) from tests.basicswap.util import read_json_api -base_url = 'http://localhost' +base_url = "http://localhost" def recover_chain_b_lock_tx(driver, offer_data, offerer_port, bidder_port): - print('Test case: {} -> {}'.format(offer_data['coin_from'], offer_data['coin_to'])) - offerer_url = f'{base_url}:{offerer_port}' - bidder_url = f'{base_url}:{bidder_port}' + print("Test case: {} -> {}".format(offer_data["coin_from"], offer_data["coin_to"])) + offerer_url = f"{base_url}:{offerer_port}" + bidder_url = f"{base_url}:{bidder_port}" - rv = read_json_api(offerer_port, 'offers/new', offer_data) - offer0_id = rv['offer_id'] + rv = read_json_api(offerer_port, "offers/new", offer_data) + offer0_id = rv["offer_id"] for i in range(10): - rv = read_json_api(bidder_port, f'offers/{offer0_id}') + rv = read_json_api(bidder_port, f"offers/{offer0_id}") if len(rv) > 0: break - print('Bidder: Waiting for offer') + print("Bidder: Waiting for offer") time.sleep(1) - bid_data = { - 'offer_id': offer0_id, - 'amount_from': 1.0} - rv = read_json_api(bidder_port, 'bids/new', bid_data) - bid0_id = rv['bid_id'] + bid_data = {"offer_id": offer0_id, "amount_from": 1.0} + rv = read_json_api(bidder_port, "bids/new", bid_data) + bid0_id = rv["bid_id"] bid_state = None for i in range(10): - rv = read_json_api(offerer_port, f'bids/{bid0_id}') - if 'error' not in rv: - bid_state = rv['bid_state'] - if bid_state == 'Received': + rv = read_json_api(offerer_port, f"bids/{bid0_id}") + if "error" not in rv: + bid_state = rv["bid_state"] + if bid_state == "Received": break - print('Offerer: Waiting for bid') + print("Offerer: Waiting for bid") time.sleep(2) - assert (bid_state == 'Received') + assert bid_state == "Received" # Set BID_STOP_AFTER_COIN_B_LOCK (13) debugind - rv = read_json_api(offerer_port, f'bids/{bid0_id}', {'debugind': 13}) - assert ('error' not in rv) + rv = read_json_api(offerer_port, f"bids/{bid0_id}", {"debugind": 13}) + assert "error" not in rv # Accept bid - rv = read_json_api(offerer_port, f'bids/{bid0_id}', {'accept': 1}) - assert ('error' not in rv) + rv = read_json_api(offerer_port, f"bids/{bid0_id}", {"accept": 1}) + assert "error" not in rv for i in range(100): - rv = read_json_api(bidder_port, f'bids/{bid0_id}') - bid_state = rv['bid_state'] - if bid_state == 'Scriptless coin locked': + rv = read_json_api(bidder_port, f"bids/{bid0_id}") + bid_state = rv["bid_state"] + if bid_state == "Scriptless coin locked": break - print('Bidder: Waiting for state') + print("Bidder: Waiting for state") time.sleep(5) - assert (bid_state == 'Scriptless coin locked') + assert bid_state == "Scriptless coin locked" for i in range(100): - rv = read_json_api(offerer_port, f'bids/{bid0_id}') - bid_state = rv['bid_state'] - if bid_state == 'Stalled (debug)': + rv = read_json_api(offerer_port, f"bids/{bid0_id}") + bid_state = rv["bid_state"] + if bid_state == "Stalled (debug)": break - print('Offerer: Waiting for state') + print("Offerer: Waiting for state") time.sleep(5) - assert (bid_state == 'Stalled (debug)') + assert bid_state == "Stalled (debug)" # Show bid state history - rv = read_json_api(offerer_port, f'bids/{bid0_id}/states') - assert (len(rv) > 1) + rv = read_json_api(offerer_port, f"bids/{bid0_id}/states") + assert len(rv) > 1 - url = f'{bidder_url}/bid/{bid0_id}' + url = f"{bidder_url}/bid/{bid0_id}" driver.get(url) - btn_more_info = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'show_txns'))) + btn_more_info = WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.NAME, "show_txns")) + ) btn_more_info.click() - WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'hide_txns'))) - bidder_localkeyhalf = driver.find_element(By.ID, 'localkeyhalf').text - print('Bidder keyhalf', bidder_localkeyhalf) + WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, "hide_txns"))) + bidder_localkeyhalf = driver.find_element(By.ID, "localkeyhalf").text + print("Bidder keyhalf", bidder_localkeyhalf) try: - driver.find_element(By.ID, 'remotekeyhalf') + driver.find_element(By.ID, "remotekeyhalf") except Exception: pass else: - raise ValueError('Nodes should not have remotekeyhalves yet.') + raise ValueError("Nodes should not have remotekeyhalves yet.") - url = f'{offerer_url}/bid/{bid0_id}' + url = f"{offerer_url}/bid/{bid0_id}" driver.get(url) - btn_more_info = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'show_txns'))) + btn_more_info = WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.NAME, "show_txns")) + ) btn_more_info.click() - WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'hide_txns'))) - offerer_localkeyhalf = driver.find_element(By.ID, 'localkeyhalf').text - print('Offerer keyhalf', offerer_localkeyhalf) + WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, "hide_txns"))) + offerer_localkeyhalf = driver.find_element(By.ID, "localkeyhalf").text + print("Offerer keyhalf", offerer_localkeyhalf) - print('Trying with the local key in place of remote') - btn_edit = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'edit_bid'))) + print("Trying with the local key in place of remote") + btn_edit = WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.NAME, "edit_bid")) + ) btn_edit.click() - btn_submit = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'edit_bid_submit'))) - kbs_other = driver.find_element(By.ID, 'kbs_other') + btn_submit = WebDriverWait(driver, 20).until( + EC.element_to_be_clickable((By.NAME, "edit_bid_submit")) + ) + kbs_other = driver.find_element(By.ID, "kbs_other") kbs_other.send_keys(offerer_localkeyhalf) btn_submit.click() - btn_edit = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'edit_bid'))) - elements = driver.find_elements(By.CLASS_NAME, 'error_msg') - expect_err_msg: str = 'Provided key matches local key' - assert (any(expect_err_msg in el.text for el in elements)) - print('Found expected error: ' + expect_err_msg) + btn_edit = WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.NAME, "edit_bid")) + ) + elements = driver.find_elements(By.CLASS_NAME, "error_msg") + expect_err_msg: str = "Provided key matches local key" + assert any(expect_err_msg in el.text for el in elements) + print("Found expected error: " + expect_err_msg) - print('Trying with incorrect key') - btn_edit = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'edit_bid'))) + print("Trying with incorrect key") + btn_edit = WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.NAME, "edit_bid")) + ) btn_edit.click() - btn_submit = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'edit_bid_submit'))) - kbs_other = driver.find_element(By.ID, 'kbs_other') + btn_submit = WebDriverWait(driver, 20).until( + EC.element_to_be_clickable((By.NAME, "edit_bid_submit")) + ) + kbs_other = driver.find_element(By.ID, "kbs_other") last_byte = bidder_localkeyhalf[-2:] - invalid_byte = '01' if last_byte == '00' else '00' + invalid_byte = "01" if last_byte == "00" else "00" kbs_other.send_keys(bidder_localkeyhalf[:-2] + invalid_byte) btn_submit.click() - btn_edit = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'edit_bid'))) - elements = driver.find_elements(By.CLASS_NAME, 'error_msg') - expect_err_msg: str = 'Summed key does not match expected wallet' - assert (any(expect_err_msg in el.text for el in elements)) - print('Found expected error: ' + expect_err_msg) + btn_edit = WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.NAME, "edit_bid")) + ) + elements = driver.find_elements(By.CLASS_NAME, "error_msg") + expect_err_msg: str = "Summed key does not match expected wallet" + assert any(expect_err_msg in el.text for el in elements) + print("Found expected error: " + expect_err_msg) - print('Trying with correct key') + print("Trying with correct key") btn_edit.click() - btn_submit = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'edit_bid_submit'))) + btn_submit = WebDriverWait(driver, 20).until( + EC.element_to_be_clickable((By.NAME, "edit_bid_submit")) + ) lock_tx_b_depth = -1 for i in range(100): # Check the non-stalled node - rv = read_json_api(bidder_port, f'bids/{bid0_id}', {'show_extra': True}) - for tx in rv['txns']: - if tx['type'] == 'Chain B Lock' and tx['confirms'] is not None: - lock_tx_b_depth = tx['confirms'] + rv = read_json_api(bidder_port, f"bids/{bid0_id}", {"show_extra": True}) + for tx in rv["txns"]: + if tx["type"] == "Chain B Lock" and tx["confirms"] is not None: + lock_tx_b_depth = tx["confirms"] break if lock_tx_b_depth >= 10: break - print(f'Waiting for lock tx B depth, have {lock_tx_b_depth}') + print(f"Waiting for lock tx B depth, have {lock_tx_b_depth}") time.sleep(2) - kbs_other = driver.find_element(By.ID, 'kbs_other') + kbs_other = driver.find_element(By.ID, "kbs_other") kbs_other.send_keys(bidder_localkeyhalf) btn_submit.click() - btn_edit = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'edit_bid'))) - elements = driver.find_elements(By.CLASS_NAME, 'infomsg') - expect_msg: str = 'Bid edited' - assert (any(expect_msg in el.text for el in elements)) - print('Found expected message: ' + expect_msg) + btn_edit = WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.NAME, "edit_bid")) + ) + elements = driver.find_elements(By.CLASS_NAME, "infomsg") + expect_msg: str = "Bid edited" + assert any(expect_msg in el.text for el in elements) + print("Found expected message: " + expect_msg) - print('Trying with nodes reversed (should fail as already spent)') # But should sum to the expected wallet key - url = f'{bidder_url}/bid/{bid0_id}' + print( + "Trying with nodes reversed (should fail as already spent)" + ) # But should sum to the expected wallet key + url = f"{bidder_url}/bid/{bid0_id}" driver.get(url) - btn_edit = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'edit_bid'))) + btn_edit = WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.NAME, "edit_bid")) + ) btn_edit.click() - btn_submit = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'edit_bid_submit'))) + btn_submit = WebDriverWait(driver, 20).until( + EC.element_to_be_clickable((By.NAME, "edit_bid_submit")) + ) driver.get(url) - btn_edit = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'edit_bid'))) + btn_edit = WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.NAME, "edit_bid")) + ) btn_edit.click() - btn_submit = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'edit_bid_submit'))) + btn_submit = WebDriverWait(driver, 20).until( + EC.element_to_be_clickable((By.NAME, "edit_bid_submit")) + ) - kbs_other = driver.find_element(By.ID, 'kbs_other') + kbs_other = driver.find_element(By.ID, "kbs_other") kbs_other.send_keys(offerer_localkeyhalf) btn_submit.click() - btn_edit = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'edit_bid'))) + btn_edit = WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.NAME, "edit_bid")) + ) # In log: "Balance is too low, checking for existing spend" # Should error here, but the code can't tell where the tx was sent, and treats any existing send as correct. - elements = driver.find_elements(By.CLASS_NAME, 'infomsg') - expect_msg: str = 'Bid edited' - assert (any(expect_msg in el.text for el in elements)) + elements = driver.find_elements(By.CLASS_NAME, "infomsg") + expect_msg: str = "Bid edited" + assert any(expect_msg in el.text for el in elements) def enable_debug_ui(driver): for port in (BSX_0_PORT, BSX_1_PORT): - url = f'{base_url}:{port}/settings' + url = f"{base_url}:{port}/settings" driver.get(url) - driver.find_element(By.ID, 'general-tab').click() + driver.find_element(By.ID, "general-tab").click() - btn_apply_general = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'apply_general'))) + btn_apply_general = WebDriverWait(driver, 10).until( + EC.element_to_be_clickable((By.NAME, "apply_general")) + ) - el = driver.find_element(By.NAME, 'debugmode') + el = driver.find_element(By.NAME, "debugmode") selected_option = Select(el).first_selected_option - if selected_option.text != 'True': - click_option(el, 'True') + if selected_option.text != "True": + click_option(el, "True") - el = driver.find_element(By.NAME, 'debugui') + el = driver.find_element(By.NAME, "debugui") selected_option = Select(el).first_selected_option - if selected_option.text != 'True': - click_option(el, 'True') + if selected_option.text != "True": + click_option(el, "True") btn_apply_general.click() @@ -213,25 +246,27 @@ def run_tests(): enable_debug_ui(driver) offer_data = { - 'coin_from': 'BTC', - 'coin_to': 'XMR', - 'amt_from': 1.0, - 'amt_to': 2.0, - 'lockhrs': 24} + "coin_from": "BTC", + "coin_to": "XMR", + "amt_from": 1.0, + "amt_to": 2.0, + "lockhrs": 24, + } recover_chain_b_lock_tx(driver, offer_data, BSX_0_PORT, BSX_1_PORT) offer_data = { - 'coin_from': 'XMR', - 'coin_to': 'BTC', - 'amt_from': 1.0, - 'amt_to': 2.0, - 'lockhrs': 24} + "coin_from": "XMR", + "coin_to": "BTC", + "amt_from": 1.0, + "amt_to": 2.0, + "lockhrs": 24, + } recover_chain_b_lock_tx(driver, offer_data, BSX_1_PORT, BSX_0_PORT) - print('Test Passed!') + print("Test Passed!") finally: driver.close() -if __name__ == '__main__': +if __name__ == "__main__": run_tests() diff --git a/tests/basicswap/selenium/test_settings.py b/tests/basicswap/selenium/test_settings.py index 8393b4d..9a8241d 100644 --- a/tests/basicswap/selenium/test_settings.py +++ b/tests/basicswap/selenium/test_settings.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2022-2024 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -14,7 +15,7 @@ from selenium.webdriver.support.select import Select from selenium.webdriver.support import expected_conditions as EC from util import ( - BSX_0_PORT, BSX_1_PORT, + BSX_0_PORT, click_option, get_driver, ) @@ -22,118 +23,121 @@ from basicswap.ui.page_offers import default_chart_api_key def test_settings(driver): - base_url = f'http://localhost:{BSX_0_PORT}' - node2_url = f'http://localhost:{BSX_1_PORT}' + base_url = f"http://localhost:{BSX_0_PORT}" - url = base_url + '/settings' + url = base_url + "/settings" driver.get(url) - driver.find_element(By.ID, 'general-tab').click() + driver.find_element(By.ID, "general-tab").click() wait = WebDriverWait(driver, 10) - btn_apply_general = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_general'))) + btn_apply_general = wait.until( + EC.element_to_be_clickable((By.NAME, "apply_general")) + ) - el = driver.find_element(By.NAME, 'debugmode') + el = driver.find_element(By.NAME, "debugmode") selected_option = Select(el).first_selected_option - assert (selected_option.text == 'True') - click_option(el, 'False') + assert selected_option.text == "True" + click_option(el, "False") - el = driver.find_element(By.NAME, 'debugui') + el = driver.find_element(By.NAME, "debugui") selected_option = Select(el).first_selected_option - assert (selected_option.text == 'False') - click_option(el, 'True') + assert selected_option.text == "False" + click_option(el, "True") btn_apply_general.click() time.sleep(1) - settings_path_0 = '/tmp/test_persistent/client0/basicswap.json' + settings_path_0 = "/tmp/test_persistent/client0/basicswap.json" with open(settings_path_0) as fs: settings = json.load(fs) - assert (settings['debug'] is False) - assert (settings['debug_ui'] is True) + assert settings["debug"] is False + assert settings["debug_ui"] is True - el = driver.find_element(By.NAME, 'showchart') + el = driver.find_element(By.NAME, "showchart") selected_option = Select(el).first_selected_option - assert (selected_option.text == 'True') - click_option(el, 'False') + assert selected_option.text == "True" + click_option(el, "False") - difficult_text = '`~!@#$%^&*()-_=+[{}]\\|;:\'",<>./? ' - el = driver.find_element(By.NAME, 'chartapikey') + difficult_text = "`~!@#$%^&*()-_=+[{}]\\|;:'\",<>./? " + el = driver.find_element(By.NAME, "chartapikey") el.clear() el.send_keys(difficult_text) - btn_apply_chart = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_chart'))) + btn_apply_chart = wait.until(EC.element_to_be_clickable((By.NAME, "apply_chart"))) btn_apply_chart.click() time.sleep(1) with open(settings_path_0) as fs: settings = json.load(fs) - assert (settings['show_chart'] is False) - chart_api_key = bytes.fromhex(settings.get('chart_api_key_enc', '')).decode('utf-8') - assert (chart_api_key == difficult_text) + assert settings["show_chart"] is False + chart_api_key = bytes.fromhex(settings.get("chart_api_key_enc", "")).decode("utf-8") + assert chart_api_key == difficult_text hex_text = default_chart_api_key - el = driver.find_element(By.NAME, 'chartapikey') + el = driver.find_element(By.NAME, "chartapikey") el.clear() el.send_keys(hex_text) - btn_apply_chart = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_chart'))) + btn_apply_chart = wait.until(EC.element_to_be_clickable((By.NAME, "apply_chart"))) btn_apply_chart.click() time.sleep(1) - el = driver.find_element(By.NAME, 'chartapikey') - assert el.get_property('value') == hex_text + el = driver.find_element(By.NAME, "chartapikey") + assert el.get_property("value") == hex_text with open(settings_path_0) as fs: settings = json.load(fs) - assert (settings.get('chart_api_key') == hex_text) + assert settings.get("chart_api_key") == hex_text # Reset - btn_apply_general = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_general'))) - click_option(driver.find_element(By.NAME, 'debugmode'), 'True') - click_option(driver.find_element(By.NAME, 'debugui'), 'False') + btn_apply_general = wait.until( + EC.element_to_be_clickable((By.NAME, "apply_general")) + ) + click_option(driver.find_element(By.NAME, "debugmode"), "True") + click_option(driver.find_element(By.NAME, "debugui"), "False") btn_apply_general.click() - btn_apply_chart = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_chart'))) - click_option(driver.find_element(By.NAME, 'showchart'), 'True') + btn_apply_chart = wait.until(EC.element_to_be_clickable((By.NAME, "apply_chart"))) + click_option(driver.find_element(By.NAME, "showchart"), "True") btn_apply_chart.click() time.sleep(1) # Apply XMR settings with blank nodes list - driver.find_element(By.ID, 'coins-tab').click() - btn_apply_monero = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_monero'))) - el = driver.find_element(By.NAME, 'remotedaemonurls_monero') + driver.find_element(By.ID, "coins-tab").click() + btn_apply_monero = wait.until(EC.element_to_be_clickable((By.NAME, "apply_monero"))) + el = driver.find_element(By.NAME, "remotedaemonurls_monero") el.clear() btn_apply_monero.click() time.sleep(1) with open(settings_path_0) as fs: settings = json.load(fs) - assert (len(settings['chainclients']['monero']['remote_daemon_urls']) == 0) + assert len(settings["chainclients"]["monero"]["remote_daemon_urls"]) == 0 - btn_apply_monero = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_monero'))) - el = driver.find_element(By.NAME, 'remotedaemonurls_monero') + btn_apply_monero = wait.until(EC.element_to_be_clickable((By.NAME, "apply_monero"))) + el = driver.find_element(By.NAME, "remotedaemonurls_monero") el.clear() - el.send_keys('node.xmr.to:18081\nnode1.xmr.to:18082') + el.send_keys("node.xmr.to:18081\nnode1.xmr.to:18082") btn_apply_monero.click() time.sleep(1) with open(settings_path_0) as fs: settings = json.load(fs) - remotedaemonurls = settings['chainclients']['monero']['remote_daemon_urls'] - assert (len(remotedaemonurls) == 2) + remotedaemonurls = settings["chainclients"]["monero"]["remote_daemon_urls"] + assert len(remotedaemonurls) == 2 - btn_apply_monero = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_monero'))) - el = driver.find_element(By.NAME, 'remotedaemonurls_monero') + btn_apply_monero = wait.until(EC.element_to_be_clickable((By.NAME, "apply_monero"))) + el = driver.find_element(By.NAME, "remotedaemonurls_monero") el.clear() btn_apply_monero.click() time.sleep(1) with open(settings_path_0) as fs: settings = json.load(fs) - assert (len(settings['chainclients']['monero']['remote_daemon_urls']) == 0) + assert len(settings["chainclients"]["monero"]["remote_daemon_urls"]) == 0 - print('Test Passed!') + print("Test Passed!") def run_tests(): @@ -144,5 +148,5 @@ def run_tests(): driver.close() -if __name__ == '__main__': +if __name__ == "__main__": run_tests() diff --git a/tests/basicswap/selenium/test_swap_direction.py b/tests/basicswap/selenium/test_swap_direction.py index bd20497..c06c6cc 100644 --- a/tests/basicswap/selenium/test_swap_direction.py +++ b/tests/basicswap/selenium/test_swap_direction.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2022-2023 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -17,47 +18,48 @@ from util import get_driver def test_swap_dir(driver): node_1_port = 12701 node_2_port = 12702 - node1_url = f'http://localhost:{node_1_port}' - node2_url = f'http://localhost:{node_2_port}' + node1_url = f"http://localhost:{node_1_port}" + node2_url = f"http://localhost:{node_2_port}" offer_data = { - 'addr_from': -1, - 'coin_from': 'PART', - 'coin_to': 'XMR', - 'amt_from': 1, - 'amt_to': 2, - 'lockhrs': 24} - rv = read_json_api(node_1_port, 'offers/new', offer_data) - offer0_id = rv['offer_id'] + "addr_from": -1, + "coin_from": "PART", + "coin_to": "XMR", + "amt_from": 1, + "amt_to": 2, + "lockhrs": 24, + } + read_json_api(node_1_port, "offers/new", offer_data) offer_data = { - 'addr_from': -1, - 'coin_from': 'PART', - 'coin_to': 'BTC', - 'amt_from': 3, - 'amt_to': 4, - 'lockhrs': 24} - rv = read_json_api(node_1_port, 'offers/new', offer_data) - offer0_id = rv['offer_id'] + "addr_from": -1, + "coin_from": "PART", + "coin_to": "BTC", + "amt_from": 3, + "amt_to": 4, + "lockhrs": 24, + } + read_json_api(node_1_port, "offers/new", offer_data) # Wait for offer to propagate - offers_api_1 = read_json_api(node_1_port, 'offers') - print('offers_api_1', offers_api_1) + offers_api_1 = read_json_api(node_1_port, "offers") + print("offers_api_1", offers_api_1) - offers_api_2 = read_json_api(node_2_port, 'offers') + offers_api_2 = read_json_api(node_2_port, "offers") while len(offers_api_2) < 1: - rv = read_json_api(node_2_port, 'offers') - print('offers_api_2', offers_api_2) + offers_api_2 = read_json_api(node_2_port, "offers") + time.sleep(0.1) + print("offers_api_2", offers_api_2) - driver.get(f'{node1_url}/offers') + driver.get(f"{node1_url}/offers") time.sleep(1) - driver.get(f'{node2_url}/offers') + driver.get(f"{node2_url}/offers") time.sleep(300) - raise ValueError('TODO') + raise ValueError("TODO") - print('Test Passed!') + print("Test Passed!") def run_tests(): @@ -68,5 +70,5 @@ def run_tests(): driver.close() -if __name__ == '__main__': +if __name__ == "__main__": run_tests() diff --git a/tests/basicswap/selenium/test_wallets.py b/tests/basicswap/selenium/test_wallets.py index 9e06fd9..1b71ef5 100644 --- a/tests/basicswap/selenium/test_wallets.py +++ b/tests/basicswap/selenium/test_wallets.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2022-2024 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -16,109 +17,113 @@ from util import get_driver def test_wallets(driver): - base_url = 'http://localhost:12701' - node2_url = 'http://localhost:12702' + base_url = "http://localhost:12701" + node2_url = "http://localhost:12702" # Check json coins data - coins = json.loads(urlopen(base_url + '/json/coins').read()) - part_coin = [f for f in coins if f['ticker'] == 'PART'][0] - part_id = part_coin['id'] - assert (part_id == 1) + coins = json.loads(urlopen(base_url + "/json/coins").read()) + part_coin = [f for f in coins if f["ticker"] == "PART"][0] + part_id = part_coin["id"] + assert part_id == 1 # Check 404 pages - url = base_url + '/unknown' + url = base_url + "/unknown" driver.get(url) - p1 = driver.find_element(By.TAG_NAME, 'body') - assert ('Error 404' in p1.text) + p1 = driver.find_element(By.TAG_NAME, "body") + assert "Error 404" in p1.text - url = base_url + '/static/nothing.png' + url = base_url + "/static/nothing.png" driver.get(url) - p1 = driver.find_element(By.TAG_NAME, 'body') - assert ('Error 404' in p1.text) + p1 = driver.find_element(By.TAG_NAME, "body") + assert "Error 404" in p1.text - url = base_url + '/wallet' + url = base_url + "/wallet" driver.get(url) - h2 = driver.find_element(By.TAG_NAME, 'h2') - assert ('Error' in h2.text) - p1 = driver.find_element(By.TAG_NAME, 'p') - assert ('Wallet not specified' in p1.text) + h2 = driver.find_element(By.TAG_NAME, "h2") + assert "Error" in h2.text + p1 = driver.find_element(By.TAG_NAME, "p") + assert "Wallet not specified" in p1.text - url = base_url + '/wallet/NOCOIN' + url = base_url + "/wallet/NOCOIN" driver.get(url) - h2 = driver.find_element(By.TAG_NAME, 'h2') - assert ('Error' in h2.text) - p1 = driver.find_element(By.TAG_NAME, 'p') - assert ('Unknown coin' in p1.text) + h2 = driver.find_element(By.TAG_NAME, "h2") + assert "Error" in h2.text + p1 = driver.find_element(By.TAG_NAME, "p") + assert "Unknown coin" in p1.text - driver.get(base_url + '/wallets') + driver.get(base_url + "/wallets") time.sleep(1) driver.refresh() - driver.find_element(By.ID, 'refresh').click() + driver.find_element(By.ID, "refresh").click() time.sleep(1) driver.refresh() - print('Finding deposit address of node 2') - driver.get(node2_url + '/wallet/PART') - e = driver.find_element(By.ID, 'deposit_address') + print("Finding deposit address of node 2") + driver.get(node2_url + "/wallet/PART") + e = driver.find_element(By.ID, "deposit_address") node2_deposit_address = e.text - print('Withdrawing from node 1') - driver.get(base_url + '/wallet/PART') - driver.find_element(By.NAME, f'to_{part_id}').send_keys(node2_deposit_address) - driver.find_element(By.NAME, f'amt_{part_id}').send_keys('10') - driver.find_element(By.NAME, f'withdraw_{part_id}').click() + print("Withdrawing from node 1") + driver.get(base_url + "/wallet/PART") + driver.find_element(By.NAME, f"to_{part_id}").send_keys(node2_deposit_address) + driver.find_element(By.NAME, f"amt_{part_id}").send_keys("10") + driver.find_element(By.NAME, f"withdraw_{part_id}").click() driver.switch_to.alert.accept() time.sleep(1) - elements = driver.find_elements(By.CLASS_NAME, 'infomsg') - assert (len(elements) == 1) + elements = driver.find_elements(By.CLASS_NAME, "infomsg") + assert len(elements) == 1 e = elements[0] - assert ('Withdrew 10 rtPART (plain to plain) to address' in e.text) + assert "Withdrew 10 rtPART (plain to plain) to address" in e.text - print('Locking UTXO') - driver.get(base_url + '/rpc') - el = driver.find_element(By.NAME, 'coin_type') - for option in el.find_elements(By.TAG_NAME, 'option'): - if option.text == 'Particl': + print("Locking UTXO") + driver.get(base_url + "/rpc") + el = driver.find_element(By.NAME, "coin_type") + for option in el.find_elements(By.TAG_NAME, "option"): + if option.text == "Particl": option.click() break - driver.find_element(By.NAME, 'cmd').send_keys('listunspent') - driver.find_element(By.NAME, 'apply').click() + driver.find_element(By.NAME, "cmd").send_keys("listunspent") + driver.find_element(By.NAME, "apply").click() time.sleep(1) - text_value = driver.find_element(By.NAME, 'result').text - utxos = json.loads(text_value.split('\n', 1)[1]) + text_value = driver.find_element(By.NAME, "result").text + utxos = json.loads(text_value.split("\n", 1)[1]) - lock_utxos = [{'txid': utxos[0]['txid'], 'vout': utxos[0]['vout']}] - driver.find_element(By.NAME, 'cmd').send_keys('lockunspent false "{}"'.format(dumpje(lock_utxos))) - driver.find_element(By.NAME, 'apply').click() + lock_utxos = [{"txid": utxos[0]["txid"], "vout": utxos[0]["vout"]}] + driver.find_element(By.NAME, "cmd").send_keys( + 'lockunspent false "{}"'.format(dumpje(lock_utxos)) + ) + driver.find_element(By.NAME, "apply").click() - print('Check for locked UTXO count') - driver.get(base_url + '/wallet/PART') + print("Check for locked UTXO count") + driver.get(base_url + "/wallet/PART") found = False for i in range(5): try: - el = driver.find_element(By.ID, 'locked_utxos') + el = driver.find_element(By.ID, "locked_utxos") found = True break except Exception: continue - driver.find_element(By.ID, 'refresh').click() + driver.find_element(By.ID, "refresh").click() time.sleep(2) found = True - assert (found) + assert found driver.refresh() - print('Unlocking UTXO') - driver.get(base_url + '/rpc') - el = driver.find_element(By.NAME, 'coin_type') - for option in el.find_elements(By.TAG_NAME, 'option'): - if option.text == 'Particl': + print("Unlocking UTXO") + driver.get(base_url + "/rpc") + el = driver.find_element(By.NAME, "coin_type") + for option in el.find_elements(By.TAG_NAME, "option"): + if option.text == "Particl": option.click() break - driver.find_element(By.NAME, 'cmd').send_keys('lockunspent true "{}"'.format(dumpje(lock_utxos))) - driver.find_element(By.NAME, 'apply').click() + driver.find_element(By.NAME, "cmd").send_keys( + 'lockunspent true "{}"'.format(dumpje(lock_utxos)) + ) + driver.find_element(By.NAME, "apply").click() - print('Test Passed!') + print("Test Passed!") def run_tests(): @@ -129,5 +134,5 @@ def run_tests(): driver.close() -if __name__ == '__main__': +if __name__ == "__main__": run_tests() diff --git a/tests/basicswap/selenium/util.py b/tests/basicswap/selenium/util.py index 00c089c..a166a25 100644 --- a/tests/basicswap/selenium/util.py +++ b/tests/basicswap/selenium/util.py @@ -10,31 +10,34 @@ import os from selenium.webdriver.common.by import By -BSX_0_PORT = int(os.getenv('BSX_0_PORT', 12701)) -BSX_1_PORT = int(os.getenv('BSX_1_PORT', BSX_0_PORT + 1)) -BSX_2_PORT = int(os.getenv('BSX_1_PORT', BSX_0_PORT + 2)) +BSX_0_PORT = int(os.getenv("BSX_0_PORT", 12701)) +BSX_1_PORT = int(os.getenv("BSX_1_PORT", BSX_0_PORT + 1)) +BSX_2_PORT = int(os.getenv("BSX_1_PORT", BSX_0_PORT + 2)) -BSX_SELENIUM_DRIVER = os.getenv('BSX_SELENIUM_DRIVER', 'firefox') +BSX_SELENIUM_DRIVER = os.getenv("BSX_SELENIUM_DRIVER", "firefox") def get_driver(): - if BSX_SELENIUM_DRIVER == 'firefox': + if BSX_SELENIUM_DRIVER == "firefox": from selenium.webdriver import Firefox, FirefoxOptions + driver = Firefox(options=FirefoxOptions()) - elif BSX_SELENIUM_DRIVER == 'chrome': + elif BSX_SELENIUM_DRIVER == "chrome": from selenium.webdriver import Chrome, ChromeOptions + driver = Chrome(options=ChromeOptions()) - elif BSX_SELENIUM_DRIVER == 'safari': + elif BSX_SELENIUM_DRIVER == "safari": from selenium.webdriver import Safari, SafariOptions + driver = Safari(options=SafariOptions()) else: - raise ValueError('Unknown driver ' + BSX_SELENIUM_DRIVER) + raise ValueError("Unknown driver " + BSX_SELENIUM_DRIVER) return driver def click_option(el, option_text): - for option in el.find_elements(By.TAG_NAME, 'option'): + for option in el.find_elements(By.TAG_NAME, "option"): if option.text == option_text: option.click() break diff --git a/tests/basicswap/test_bch_xmr.py b/tests/basicswap/test_bch_xmr.py index c1c29fd..fd247bb 100644 --- a/tests/basicswap/test_bch_xmr.py +++ b/tests/basicswap/test_bch_xmr.py @@ -47,13 +47,17 @@ from .test_xmr import test_delay_event, callnoderpc from coincurve.ecdsaotves import ( ecdsaotves_enc_sign, ecdsaotves_enc_verify, - ecdsaotves_dec_sig + ecdsaotves_dec_sig, ) -BITCOINCASH_BINDIR = os.path.expanduser(os.getenv('BITCOINCASH_BINDIR', os.path.join(cfg.DEFAULT_TEST_BINDIR, 'bitcoincash'))) -BITCOINCASHD = os.getenv('BITCOINCASHD', 'bitcoind' + cfg.bin_suffix) -BITCOINCASH_CLI = os.getenv('BITCOINCASH_CLI', 'bitcoin-cli' + cfg.bin_suffix) -BITCOINCASH_TX = os.getenv('BITCOINCASH_TX', 'bitcoin-tx' + cfg.bin_suffix) +BITCOINCASH_BINDIR = os.path.expanduser( + os.getenv( + "BITCOINCASH_BINDIR", os.path.join(cfg.DEFAULT_TEST_BINDIR, "bitcoincash") + ) +) +BITCOINCASHD = os.getenv("BITCOINCASHD", "bitcoind" + cfg.bin_suffix) +BITCOINCASH_CLI = os.getenv("BITCOINCASH_CLI", "bitcoin-cli" + cfg.bin_suffix) +BITCOINCASH_TX = os.getenv("BITCOINCASH_TX", "bitcoin-tx" + cfg.bin_suffix) BCH_BASE_PORT = 41792 BCH_BASE_RPC_PORT = 42792 @@ -63,12 +67,19 @@ BCH_BASE_TOR_PORT = 43732 logger = logging.getLogger() -bch_lock_spend_tx = '0200000001bfc6bbb47851441c7827059ae337a06aa9064da7f9537eb9243e45766c3dd34c00000000d8473045022100a0161ea14d3b41ed41250c8474fc8ec6ce1cab8df7f401e69ecf77c2ab63d82102207a2a57ddf2ea400e09ea059f3b261da96f5098858b17239931f3cc2fb929bb2a4c8ec3519dc4519d02e80300c600cc949d00ce00d18800cf00d28800d000d39d00cb641976a91481ec21969399d15c26af089d5db437ead066c5ba88ac00cd788821024ffcc0481629866671d89f05f3da813a2aacec1b52e69b8c0c586b665f5d4574ba6752b27523aa20df65a90e9becc316ff5aca44d4e06dfaade56622f32bafa197aba706c5e589758700cd87680000000001251cde06000000001976a91481ec21969399d15c26af089d5db437ead066c5ba88ac00000000' -bch_lock_script = 'c3519dc4519d02e80300c600cc949d00ce00d18800cf00d28800d000d39d00cb641976a91481ec21969399d15c26af089d5db437ead066c5ba88ac00cd788821024ffcc0481629866671d89f05f3da813a2aacec1b52e69b8c0c586b665f5d4574ba6752b27523aa20df65a90e9becc316ff5aca44d4e06dfaade56622f32bafa197aba706c5e589758700cd8768' -bch_lock_spend_script = '473045022100a0161ea14d3b41ed41250c8474fc8ec6ce1cab8df7f401e69ecf77c2ab63d82102207a2a57ddf2ea400e09ea059f3b261da96f5098858b17239931f3cc2fb929bb2a4c8ec3519dc4519d02e80300c600cc949d00ce00d18800cf00d28800d000d39d00cb641976a91481ec21969399d15c26af089d5db437ead066c5ba88ac00cd788821024ffcc0481629866671d89f05f3da813a2aacec1b52e69b8c0c586b665f5d4574ba6752b27523aa20df65a90e9becc316ff5aca44d4e06dfaade56622f32bafa197aba706c5e589758700cd8768' -bch_lock_swipe_script = '4c8fc3519dc4519d02e80300c600cc949d00ce00d18800cf00d28800d000d39d00cb641976a9141ab50aedd2e48297073f0f6eef46f97b37c9354e88ac00cd7888210234fe304a5b129b8265c177c92aa40b7840e8303f8b0fcca2359023163c7c2768ba670120b27523aa20191b09e40d1277fa14fea1e9b41e4fcc4528c9cb77e39e1b7b1a0b3332180cb78700cd8768' +bch_lock_spend_tx = "0200000001bfc6bbb47851441c7827059ae337a06aa9064da7f9537eb9243e45766c3dd34c00000000d8473045022100a0161ea14d3b41ed41250c8474fc8ec6ce1cab8df7f401e69ecf77c2ab63d82102207a2a57ddf2ea400e09ea059f3b261da96f5098858b17239931f3cc2fb929bb2a4c8ec3519dc4519d02e80300c600cc949d00ce00d18800cf00d28800d000d39d00cb641976a91481ec21969399d15c26af089d5db437ead066c5ba88ac00cd788821024ffcc0481629866671d89f05f3da813a2aacec1b52e69b8c0c586b665f5d4574ba6752b27523aa20df65a90e9becc316ff5aca44d4e06dfaade56622f32bafa197aba706c5e589758700cd87680000000001251cde06000000001976a91481ec21969399d15c26af089d5db437ead066c5ba88ac00000000" +bch_lock_script = "c3519dc4519d02e80300c600cc949d00ce00d18800cf00d28800d000d39d00cb641976a91481ec21969399d15c26af089d5db437ead066c5ba88ac00cd788821024ffcc0481629866671d89f05f3da813a2aacec1b52e69b8c0c586b665f5d4574ba6752b27523aa20df65a90e9becc316ff5aca44d4e06dfaade56622f32bafa197aba706c5e589758700cd8768" +bch_lock_spend_script = "473045022100a0161ea14d3b41ed41250c8474fc8ec6ce1cab8df7f401e69ecf77c2ab63d82102207a2a57ddf2ea400e09ea059f3b261da96f5098858b17239931f3cc2fb929bb2a4c8ec3519dc4519d02e80300c600cc949d00ce00d18800cf00d28800d000d39d00cb641976a91481ec21969399d15c26af089d5db437ead066c5ba88ac00cd788821024ffcc0481629866671d89f05f3da813a2aacec1b52e69b8c0c586b665f5d4574ba6752b27523aa20df65a90e9becc316ff5aca44d4e06dfaade56622f32bafa197aba706c5e589758700cd8768" +bch_lock_swipe_script = "4c8fc3519dc4519d02e80300c600cc949d00ce00d18800cf00d28800d000d39d00cb641976a9141ab50aedd2e48297073f0f6eef46f97b37c9354e88ac00cd7888210234fe304a5b129b8265c177c92aa40b7840e8303f8b0fcca2359023163c7c2768ba670120b27523aa20191b09e40d1277fa14fea1e9b41e4fcc4528c9cb77e39e1b7b1a0b3332180cb78700cd8768" -coin_settings = {'rpcport': 0, 'rpcauth': 'none', 'blocks_confirmed': 1, 'conf_target': 1, 'use_segwit': False, 'connection_type': 'rpc'} +coin_settings = { + "rpcport": 0, + "rpcauth": "none", + "blocks_confirmed": 1, + "conf_target": 1, + "use_segwit": False, + "connection_type": "rpc", +} class TestXmrBchSwapInterface(unittest.TestCase): @@ -79,12 +90,16 @@ class TestXmrBchSwapInterface(unittest.TestCase): ci.extractScriptLockScriptValues(script_bytes) script_bytes = CScript(bytes.fromhex(bch_lock_spend_script)) - signature, mining_fee, out_1, out_2, public_key, timelock = ci.extractScriptLockScriptValuesFromScriptSig(script_bytes) - ensure(signature is not None, 'signature not present') + signature, mining_fee, out_1, out_2, public_key, timelock = ( + ci.extractScriptLockScriptValuesFromScriptSig(script_bytes) + ) + ensure(signature is not None, "signature not present") script_bytes = CScript(bytes.fromhex(bch_lock_swipe_script)) - signature, mining_fee, out_1, out_2, public_key, timelock = ci.extractScriptLockScriptValuesFromScriptSig(script_bytes) - ensure(signature is None, 'signature present') + signature, mining_fee, out_1, out_2, public_key, timelock = ( + ci.extractScriptLockScriptValuesFromScriptSig(script_bytes) + ) + ensure(signature is None, "signature present") class TestBCH(BasicSwapTest): @@ -100,26 +115,47 @@ class TestBCH(BasicSwapTest): @classmethod def prepareExtraDataDir(cls, i): if not cls.restore_instance: - data_dir = prepareDataDir(cfg.TEST_DATADIRS, i, 'bitcoin.conf', 'bch_', base_p2p_port=BCH_BASE_PORT, base_rpc_port=BCH_BASE_RPC_PORT) + data_dir = prepareDataDir( + cfg.TEST_DATADIRS, + i, + "bitcoin.conf", + "bch_", + base_p2p_port=BCH_BASE_PORT, + base_rpc_port=BCH_BASE_RPC_PORT, + ) # Rewrite conf file - config_filename: str = os.path.join(cfg.TEST_DATADIRS, 'bch_' + str(i), 'bitcoin.conf') - with open(config_filename, 'r') as fp: + config_filename: str = os.path.join( + cfg.TEST_DATADIRS, "bch_" + str(i), "bitcoin.conf" + ) + with open(config_filename, "r") as fp: lines = fp.readlines() - with open(config_filename, 'w') as fp: + with open(config_filename, "w") as fp: for line in lines: - if not line.startswith('findpeers'): + if not line.startswith("findpeers"): fp.write(line) - if os.path.exists(os.path.join(BITCOINCASH_BINDIR, 'bitcoin-wallet')): + if os.path.exists(os.path.join(BITCOINCASH_BINDIR, "bitcoin-wallet")): try: - callrpc_cli(BITCOINCASH_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat create', 'bitcoin-wallet') + callrpc_cli( + BITCOINCASH_BINDIR, + data_dir, + "regtest", + "-wallet=wallet.dat create", + "bitcoin-wallet", + ) except Exception as e: - logging.warning('bch: bitcoin-wallet create failed') + logging.warning("bch: bitcoin-wallet create failed") raise e - cls.bch_daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, 'bch_' + str(i)), BITCOINCASH_BINDIR, BITCOINCASHD)) - logging.info('BCH: Started %s %d', BITCOINCASHD, cls.bch_daemons[-1].handle.pid) + cls.bch_daemons.append( + startDaemon( + os.path.join(cfg.TEST_DATADIRS, "bch_" + str(i)), + BITCOINCASH_BINDIR, + BITCOINCASHD, + ) + ) + logging.info("BCH: Started %s %d", BITCOINCASHD, cls.bch_daemons[-1].handle.pid) waitForRPC(make_rpc_func(i, base_rpc_port=BCH_BASE_RPC_PORT), test_delay_event) @classmethod @@ -128,24 +164,36 @@ class TestBCH(BasicSwapTest): @classmethod def prepareExtraCoins(cls): - cls.bch_addr = callnoderpc(0, 'getnewaddress', ['mining_addr'], base_rpc_port=BCH_BASE_RPC_PORT, wallet='wallet.dat') + cls.bch_addr = callnoderpc( + 0, + "getnewaddress", + ["mining_addr"], + base_rpc_port=BCH_BASE_RPC_PORT, + wallet="wallet.dat", + ) if not cls.restore_instance: num_blocks: int = 200 - logging.info('Mining %d BitcoinCash blocks to %s', num_blocks, cls.bch_addr) - callnoderpc(0, 'generatetoaddress', [num_blocks, cls.bch_addr], base_rpc_port=BCH_BASE_RPC_PORT, wallet='wallet.dat') + logging.info("Mining %d BitcoinCash blocks to %s", num_blocks, cls.bch_addr) + callnoderpc( + 0, + "generatetoaddress", + [num_blocks, cls.bch_addr], + base_rpc_port=BCH_BASE_RPC_PORT, + wallet="wallet.dat", + ) @classmethod def addCoinSettings(cls, settings, datadir, node_id): - settings['chainclients']['bitcoincash'] = { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': BCH_BASE_RPC_PORT + node_id, - 'rpcuser': 'test' + str(node_id), - 'rpcpassword': 'test_pass' + str(node_id), - 'datadir': os.path.join(datadir, 'bch_' + str(node_id)), - 'bindir': BITCOINCASH_BINDIR, - 'use_segwit': False, + settings["chainclients"]["bitcoincash"] = { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": BCH_BASE_RPC_PORT + node_id, + "rpcuser": "test" + str(node_id), + "rpcpassword": "test_pass" + str(node_id), + "datadir": os.path.join(datadir, "bch_" + str(node_id)), + "bindir": BITCOINCASH_BINDIR, + "use_segwit": False, } @classmethod @@ -154,60 +202,88 @@ class TestBCH(BasicSwapTest): ci0 = cls.swap_clients[0].ci(cls.test_coin) try: if cls.bch_addr is not None: - ci0.rpc_wallet('generatetoaddress', [1, cls.bch_addr]) + ci0.rpc_wallet("generatetoaddress", [1, cls.bch_addr]) except Exception as e: - logging.warning('coins_loop generate {}'.format(e)) + logging.warning("coins_loop generate {}".format(e)) @classmethod def tearDownClass(cls): - logging.info('Finalising Bitcoincash Test') + logging.info("Finalising Bitcoincash Test") super(TestBCH, cls).tearDownClass() stopDaemons(cls.bch_daemons) cls.bch_daemons.clear() def mineBlock(self, num_blocks=1): - self.callnoderpc('generatetoaddress', [num_blocks, self.bch_addr]) + self.callnoderpc("generatetoaddress", [num_blocks, self.bch_addr]) def check_softfork_active(self, feature_name): return True def test_001_nested_segwit(self): - logging.info('---------- Test {} p2sh nested segwit'.format(self.test_coin.name)) - logging.info('Skipped') + logging.info( + "---------- Test {} p2sh nested segwit".format(self.test_coin.name) + ) + logging.info("Skipped") def test_002_native_segwit(self): - logging.info('---------- Test {} p2sh native segwit'.format(self.test_coin.name)) - logging.info('Skipped') + logging.info( + "---------- Test {} p2sh native segwit".format(self.test_coin.name) + ) + logging.info("Skipped") def test_003_cltv(self): - logging.info('---------- Test {} cltv'.format(self.test_coin.name)) + logging.info("---------- Test {} cltv".format(self.test_coin.name)) ci = self.swap_clients[0].ci(self.test_coin) - self.check_softfork_active('bip65') + self.check_softfork_active("bip65") - chain_height = self.callnoderpc('getblockcount') - script = CScript([chain_height + 3, OP_CHECKLOCKTIMEVERIFY, ]) + chain_height = self.callnoderpc("getblockcount") + script = CScript( + [ + chain_height + 3, + OP_CHECKLOCKTIMEVERIFY, + ] + ) script_dest = ci.getScriptDest(script) tx = CTransaction() tx.nVersion = ci.txVersion() tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest)) tx_hex = ToHex(tx) - tx_funded = ci.rpc_wallet('fundrawtransaction', [tx_hex]) - utxo_pos = 0 if tx_funded['changepos'] == 1 else 1 - tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex'] - txid = ci.rpc('sendrawtransaction', [tx_signed, ]) + tx_funded = ci.rpc_wallet("fundrawtransaction", [tx_hex]) + utxo_pos = 0 if tx_funded["changepos"] == 1 else 1 + tx_signed = ci.rpc_wallet( + "signrawtransactionwithwallet", + [ + tx_funded["hex"], + ], + )["hex"] + txid = ci.rpc( + "sendrawtransaction", + [ + tx_signed, + ], + ) - addr_out = ci.rpc_wallet('getnewaddress', ['cltv test']) + addr_out = ci.rpc_wallet("getnewaddress", ["cltv test"]) pkh = ci.decodeAddress(addr_out) script_out = ci.getScriptForPubkeyHash(pkh) tx_spend = CTransaction() tx_spend.nVersion = ci.txVersion() tx_spend.nLockTime = chain_height + 3 - tx_spend.vin.append(CTxIn(COutPoint(int(txid, 16), utxo_pos), scriptSig=CScript([script,]))) + tx_spend.vin.append( + CTxIn( + COutPoint(int(txid, 16), utxo_pos), + scriptSig=CScript( + [ + script, + ] + ), + ) + ) tx_spend.vout.append(ci.txoType()(ci.make_int(1.0999), script_out)) tx_spend_hex = ToHex(tx_spend) @@ -216,116 +292,205 @@ class TestBCH(BasicSwapTest): for tx_hex in [tx_spend_invalid_hex, tx_spend_hex]: try: - txid = self.callnoderpc('sendrawtransaction', [tx_hex, ]) + txid = self.callnoderpc( + "sendrawtransaction", + [ + tx_hex, + ], + ) except Exception as e: - assert ('non-final' in str(e)) + assert "non-final" in str(e) else: - assert False, 'Should fail' + assert False, "Should fail" self.mineBlock(5) try: - txid = ci.rpc('sendrawtransaction', [tx_spend_invalid_hex, ]) + txid = ci.rpc( + "sendrawtransaction", + [ + tx_spend_invalid_hex, + ], + ) except Exception as e: - assert ('Locktime requirement not satisfied' in str(e)) + assert "Locktime requirement not satisfied" in str(e) else: - assert False, 'Should fail' + assert False, "Should fail" - txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ]) + txid = ci.rpc( + "sendrawtransaction", + [ + tx_spend_hex, + ], + ) self.mineBlock() - ro = ci.rpc_wallet('listreceivedbyaddress', [0, ]) + ro = ci.rpc_wallet( + "listreceivedbyaddress", + [ + 0, + ], + ) sum_addr = 0 for entry in ro: - if entry['address'] == addr_out: - sum_addr += entry['amount'] - assert (sum_addr == 1.0999) + if entry["address"] == addr_out: + sum_addr += entry["amount"] + assert sum_addr == 1.0999 # Ensure tx was mined - tx_wallet = ci.rpc_wallet('gettransaction', [txid, ]) - assert (len(tx_wallet['blockhash']) == 64) + tx_wallet = ci.rpc_wallet( + "gettransaction", + [ + txid, + ], + ) + assert len(tx_wallet["blockhash"]) == 64 def test_004_csv(self): - logging.info('---------- Test {} csv'.format(self.test_coin.name)) + logging.info("---------- Test {} csv".format(self.test_coin.name)) - swap_clients = self.swap_clients ci = self.swap_clients[0].ci(self.test_coin) - self.check_softfork_active('csv') + self.check_softfork_active("csv") - script = CScript([3, OP_CHECKSEQUENCEVERIFY, ]) + script = CScript( + [ + 3, + OP_CHECKSEQUENCEVERIFY, + ] + ) script_dest = ci.getScriptDest(script) tx = CTransaction() tx.nVersion = ci.txVersion() tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest)) tx_hex = ToHex(tx) - tx_funded = ci.rpc_wallet('fundrawtransaction', [tx_hex]) - utxo_pos = 0 if tx_funded['changepos'] == 1 else 1 - tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex'] - txid = ci.rpc('sendrawtransaction', [tx_signed, ]) + tx_funded = ci.rpc_wallet("fundrawtransaction", [tx_hex]) + utxo_pos = 0 if tx_funded["changepos"] == 1 else 1 + tx_signed = ci.rpc_wallet( + "signrawtransactionwithwallet", + [ + tx_funded["hex"], + ], + )["hex"] + txid = ci.rpc( + "sendrawtransaction", + [ + tx_signed, + ], + ) - addr_out = ci.rpc_wallet('getnewaddress', ['csv test']) + addr_out = ci.rpc_wallet("getnewaddress", ["csv test"]) pkh = ci.decodeAddress(addr_out) script_out = ci.getScriptForPubkeyHash(pkh) # Double check output type - prev_tx = ci.rpc('decoderawtransaction', [tx_signed, ]) - assert (prev_tx['vout'][utxo_pos]['scriptPubKey']['type'] == 'scripthash') + prev_tx = ci.rpc( + "decoderawtransaction", + [ + tx_signed, + ], + ) + assert prev_tx["vout"][utxo_pos]["scriptPubKey"]["type"] == "scripthash" tx_spend = CTransaction() tx_spend.nVersion = ci.txVersion() - tx_spend.vin.append(CTxIn(COutPoint(int(txid, 16), utxo_pos), - nSequence=3, - scriptSig=CScript([script,]))) + tx_spend.vin.append( + CTxIn( + COutPoint(int(txid, 16), utxo_pos), + nSequence=3, + scriptSig=CScript( + [ + script, + ] + ), + ) + ) tx_spend.vout.append(ci.txoType()(ci.make_int(1.0999), script_out)) tx_spend_hex = ToHex(tx_spend) try: - txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ]) + txid = ci.rpc( + "sendrawtransaction", + [ + tx_spend_hex, + ], + ) except Exception as e: - assert ('non-BIP68-final' in str(e)) + assert "non-BIP68-final" in str(e) else: - assert False, 'Should fail' + assert False, "Should fail" self.mineBlock(3) - txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ]) + txid = ci.rpc( + "sendrawtransaction", + [ + tx_spend_hex, + ], + ) self.mineBlock(1) - ro = ci.rpc_wallet('listreceivedbyaddress', [0, ]) + ro = ci.rpc_wallet( + "listreceivedbyaddress", + [ + 0, + ], + ) sum_addr = 0 for entry in ro: - if entry['address'] == addr_out: - sum_addr += entry['amount'] - assert (sum_addr == 1.0999) + if entry["address"] == addr_out: + sum_addr += entry["amount"] + assert sum_addr == 1.0999 # Ensure tx was mined - tx_wallet = ci.rpc_wallet('gettransaction', [txid, ]) - assert (len(tx_wallet['blockhash']) == 64) + tx_wallet = ci.rpc_wallet( + "gettransaction", + [ + txid, + ], + ) + assert len(tx_wallet["blockhash"]) == 64 def test_005_watchonly(self): - logging.info('---------- Test {} watchonly'.format(self.test_coin.name)) + logging.info("---------- Test {} watchonly".format(self.test_coin.name)) ci = self.swap_clients[0].ci(self.test_coin) ci1 = self.swap_clients[1].ci(self.test_coin) - addr = ci.rpc_wallet('getnewaddress', ['watchonly test']) - ro = ci1.rpc_wallet('importaddress', [addr, '', False]) - txid = ci.rpc_wallet('sendtoaddress', [addr, 1.0]) - tx_hex = ci.rpc('getrawtransaction', [txid, ]) - ci1.rpc_wallet('sendrawtransaction', [tx_hex, ]) - ro = ci1.rpc_wallet('gettransaction', [txid, ]) - assert (ro['txid'] == txid) + addr = ci.rpc_wallet("getnewaddress", ["watchonly test"]) + ro = ci1.rpc_wallet("importaddress", [addr, "", False]) + txid = ci.rpc_wallet("sendtoaddress", [addr, 1.0]) + tx_hex = ci.rpc( + "getrawtransaction", + [ + txid, + ], + ) + ci1.rpc_wallet( + "sendrawtransaction", + [ + tx_hex, + ], + ) + ro = ci1.rpc_wallet( + "gettransaction", + [ + txid, + ], + ) + assert ro["txid"] == txid def test_006_getblock_verbosity(self): super().test_006_getblock_verbosity() def test_007_hdwallet(self): - logging.info('---------- Test {} hdwallet'.format(self.test_coin.name)) + logging.info("---------- Test {} hdwallet".format(self.test_coin.name)) - test_seed = '8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b' - test_wif = self.swap_clients[0].ci(self.test_coin).encodeKey(bytes.fromhex(test_seed)) + test_seed = "8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b" + test_wif = ( + self.swap_clients[0].ci(self.test_coin).encodeKey(bytes.fromhex(test_seed)) + ) new_wallet_name = random.randbytes(10).hex() - self.callnoderpc('createwallet', [new_wallet_name]) - self.callnoderpc('sethdseed', [True, test_wif], wallet=new_wallet_name) - addr = self.callnoderpc('getnewaddress', wallet=new_wallet_name) - self.callnoderpc('unloadwallet', [new_wallet_name]) - assert (addr == 'bchreg:qqxr67wf5ltty5jvm44zryywmpt7ntdaa50carjt59') + self.callnoderpc("createwallet", [new_wallet_name]) + self.callnoderpc("sethdseed", [True, test_wif], wallet=new_wallet_name) + addr = self.callnoderpc("getnewaddress", wallet=new_wallet_name) + self.callnoderpc("unloadwallet", [new_wallet_name]) + assert addr == "bchreg:qqxr67wf5ltty5jvm44zryywmpt7ntdaa50carjt59" def test_008_gettxout(self): super().test_008_gettxout() @@ -334,7 +499,7 @@ class TestBCH(BasicSwapTest): super().test_009_scantxoutset() def test_010_txn_size(self): - logging.info('---------- Test {} txn_size'.format(Coins.BCH)) + logging.info("---------- Test {} txn_size".format(Coins.BCH)) swap_clients = self.swap_clients ci = swap_clients[0].ci(Coins.BCH) @@ -343,7 +508,7 @@ class TestBCH(BasicSwapTest): amount: int = ci.make_int(random.uniform(0.1, 2.0), r=1) # Record unspents before createSCLockTx as the used ones will be locked - unspents = ci.rpc('listunspent') + unspents = ci.rpc("listunspent") # fee_rate is in sats/B fee_rate: int = 1 @@ -355,29 +520,28 @@ class TestBCH(BasicSwapTest): B = ci.getPubkey(b) mining_fee = 1000 - timelock = 2 b_receive = ci.getNewAddress() a_refund = ci.getNewAddress() refundExtraArgs = dict() lockExtraArgs = dict() - refundExtraArgs['mining_fee'] = 1000 - refundExtraArgs['out_1'] = ci.addressToLockingBytecode(a_refund) - refundExtraArgs['out_2'] = ci.addressToLockingBytecode(b_receive) - refundExtraArgs['public_key'] = B - refundExtraArgs['timelock'] = 5 + refundExtraArgs["mining_fee"] = 1000 + refundExtraArgs["out_1"] = ci.addressToLockingBytecode(a_refund) + refundExtraArgs["out_2"] = ci.addressToLockingBytecode(b_receive) + refundExtraArgs["public_key"] = B + refundExtraArgs["timelock"] = 5 refund_lock_tx_script = pi.genScriptLockTxScript(ci, A, B, **refundExtraArgs) # will make use of this in `createSCLockRefundTx` - refundExtraArgs['refund_lock_tx_script'] = refund_lock_tx_script + refundExtraArgs["refund_lock_tx_script"] = refund_lock_tx_script # lock script - lockExtraArgs['mining_fee'] = 1000 - lockExtraArgs['out_1'] = ci.addressToLockingBytecode(b_receive) - lockExtraArgs['out_2'] = ci.scriptToP2SH32LockingBytecode(refund_lock_tx_script) - lockExtraArgs['public_key'] = A - lockExtraArgs['timelock'] = 2 + lockExtraArgs["mining_fee"] = 1000 + lockExtraArgs["out_1"] = ci.addressToLockingBytecode(b_receive) + lockExtraArgs["out_2"] = ci.scriptToP2SH32LockingBytecode(refund_lock_tx_script) + lockExtraArgs["public_key"] = A + lockExtraArgs["timelock"] = 2 lock_tx_script = pi.genScriptLockTxScript(ci, A, B, **lockExtraArgs) @@ -386,36 +550,35 @@ class TestBCH(BasicSwapTest): lock_tx = ci.signTxWithWallet(lock_tx) print(lock_tx.hex()) - unspents_after = ci.rpc('listunspent') - assert (len(unspents) > len(unspents_after)) + unspents_after = ci.rpc("listunspent") + assert len(unspents) > len(unspents_after) - tx_decoded = ci.rpc('decoderawtransaction', [lock_tx.hex()]) - txid = tx_decoded['txid'] + tx_decoded = ci.rpc("decoderawtransaction", [lock_tx.hex()]) + txid = tx_decoded["txid"] - vsize = tx_decoded['size'] + vsize = tx_decoded["size"] expect_fee_int = round(fee_rate * vsize) - expect_fee = ci.format_amount(expect_fee_int) out_value: int = 0 - for txo in tx_decoded['vout']: - if 'value' in txo: - out_value += ci.make_int(txo['value']) + for txo in tx_decoded["vout"]: + if "value" in txo: + out_value += ci.make_int(txo["value"]) in_value: int = 0 - for txi in tx_decoded['vin']: + for txi in tx_decoded["vin"]: for utxo in unspents: - if 'vout' not in utxo: + if "vout" not in utxo: continue - if utxo['txid'] == txi['txid'] and utxo['vout'] == txi['vout']: - in_value += ci.make_int(utxo['amount']) + if utxo["txid"] == txi["txid"] and utxo["vout"] == txi["vout"]: + in_value += ci.make_int(utxo["amount"]) break fee_value = in_value - out_value - ci.rpc('sendrawtransaction', [lock_tx.hex()]) - rv = ci.rpc('gettransaction', [txid]) - wallet_tx_fee = -ci.make_int(rv['fee']) + ci.rpc("sendrawtransaction", [lock_tx.hex()]) + rv = ci.rpc("gettransaction", [txid]) + wallet_tx_fee = -ci.make_int(rv["fee"]) - assert (wallet_tx_fee == fee_value) - assert (wallet_tx_fee == expect_fee_int) + assert wallet_tx_fee == fee_value + assert wallet_tx_fee == expect_fee_int pkh_out = ci.decodeAddress(b_receive) @@ -425,126 +588,219 @@ class TestBCH(BasicSwapTest): aAdaptorSig = ecdsaotves_enc_sign(a, B, msg) # alice verifies the adaptor signature - assert (ecdsaotves_enc_verify(A, B, msg, aAdaptorSig)) + assert ecdsaotves_enc_verify(A, B, msg, aAdaptorSig) # alice decrypts the adaptor signature aAdaptorSig_dec = ecdsaotves_dec_sig(b, aAdaptorSig) fee_info = {} - lock_spend_tx = ci.createSCLockSpendTx(lock_tx, lock_tx_script, pkh_out, mining_fee, fee_info=fee_info, ves=aAdaptorSig_dec) - vsize_estimated: int = fee_info['vsize'] + lock_spend_tx = ci.createSCLockSpendTx( + lock_tx, + lock_tx_script, + pkh_out, + mining_fee, + fee_info=fee_info, + ves=aAdaptorSig_dec, + ) + vsize_estimated: int = fee_info["vsize"] - tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()]) - print('lock_spend_tx', lock_spend_tx.hex(), '\n', 'tx_decoded', tx_decoded) - txid = tx_decoded['txid'] + tx_decoded = ci.rpc("decoderawtransaction", [lock_spend_tx.hex()]) + print("lock_spend_tx", lock_spend_tx.hex(), "\n", "tx_decoded", tx_decoded) + txid = tx_decoded["txid"] - tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()]) - vsize_actual: int = tx_decoded['size'] + tx_decoded = ci.rpc("decoderawtransaction", [lock_spend_tx.hex()]) + vsize_actual: int = tx_decoded["size"] - assert (vsize_actual <= vsize_estimated and vsize_estimated - vsize_actual < 4) - assert (ci.rpc('sendrawtransaction', [lock_spend_tx.hex()]) == txid) + assert vsize_actual <= vsize_estimated and vsize_estimated - vsize_actual < 4 + assert ci.rpc("sendrawtransaction", [lock_spend_tx.hex()]) == txid expect_size: int = ci.xmr_swap_a_lock_spend_tx_vsize() - assert (expect_size >= vsize_actual) - assert (expect_size - vsize_actual < 10) + assert expect_size >= vsize_actual + assert expect_size - vsize_actual < 10 def test_011_p2sh(self): # Not used in bsx for native-segwit coins - logging.info('---------- Test {} p2sh'.format(self.test_coin.name)) + logging.info("---------- Test {} p2sh".format(self.test_coin.name)) - swap_clients = self.swap_clients ci = self.swap_clients[0].ci(self.test_coin) - script = CScript([2, 2, OP_EQUAL, ]) + script = CScript( + [ + 2, + 2, + OP_EQUAL, + ] + ) script_dest = ci.get_p2sh_script_pubkey(script) tx = CTransaction() tx.nVersion = ci.txVersion() tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest)) tx_hex = ToHex(tx) - tx_funded = ci.rpc_wallet('fundrawtransaction', [tx_hex]) - utxo_pos = 0 if tx_funded['changepos'] == 1 else 1 - tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex'] - txid = ci.rpc('sendrawtransaction', [tx_signed, ]) + tx_funded = ci.rpc_wallet("fundrawtransaction", [tx_hex]) + utxo_pos = 0 if tx_funded["changepos"] == 1 else 1 + tx_signed = ci.rpc_wallet( + "signrawtransactionwithwallet", + [ + tx_funded["hex"], + ], + )["hex"] + txid = ci.rpc( + "sendrawtransaction", + [ + tx_signed, + ], + ) - addr_out = ci.rpc_wallet('getnewaddress', ['csv test']) + addr_out = ci.rpc_wallet("getnewaddress", ["csv test"]) pkh = ci.decodeAddress(addr_out) script_out = ci.getScriptForPubkeyHash(pkh) # Double check output type - prev_tx = ci.rpc('decoderawtransaction', [tx_signed, ]) - assert (prev_tx['vout'][utxo_pos]['scriptPubKey']['type'] == 'scripthash') + prev_tx = ci.rpc( + "decoderawtransaction", + [ + tx_signed, + ], + ) + assert prev_tx["vout"][utxo_pos]["scriptPubKey"]["type"] == "scripthash" tx_spend = CTransaction() tx_spend.nVersion = ci.txVersion() - tx_spend.vin.append(CTxIn(COutPoint(int(txid, 16), utxo_pos), - scriptSig=CScript([script,]))) + tx_spend.vin.append( + CTxIn( + COutPoint(int(txid, 16), utxo_pos), + scriptSig=CScript( + [ + script, + ] + ), + ) + ) tx_spend.vout.append(ci.txoType()(ci.make_int(1.0999), script_out)) tx_spend_hex = ToHex(tx_spend) - txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ]) + txid = ci.rpc( + "sendrawtransaction", + [ + tx_spend_hex, + ], + ) self.mineBlock(1) - ro = ci.rpc_wallet('listreceivedbyaddress', [0, ]) + ro = ci.rpc_wallet( + "listreceivedbyaddress", + [ + 0, + ], + ) sum_addr = 0 for entry in ro: - if entry['address'] == addr_out: - sum_addr += entry['amount'] - assert (sum_addr == 1.0999) + if entry["address"] == addr_out: + sum_addr += entry["amount"] + assert sum_addr == 1.0999 # Ensure tx was mined - tx_wallet = ci.rpc_wallet('gettransaction', [txid, ]) - assert (len(tx_wallet['blockhash']) == 64) + tx_wallet = ci.rpc_wallet( + "gettransaction", + [ + txid, + ], + ) + assert len(tx_wallet["blockhash"]) == 64 def test_011_p2sh32(self): # Not used in bsx for native-segwit coins - logging.info('---------- Test {} p2sh32'.format(self.test_coin.name)) + logging.info("---------- Test {} p2sh32".format(self.test_coin.name)) - swap_clients = self.swap_clients ci = self.swap_clients[0].ci(self.test_coin) - script = CScript([2, 2, OP_EQUAL, ]) + script = CScript( + [ + 2, + 2, + OP_EQUAL, + ] + ) script_dest = ci.scriptToP2SH32LockingBytecode(script) tx = CTransaction() tx.nVersion = ci.txVersion() tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest)) tx_hex = ToHex(tx) - tx_funded = ci.rpc_wallet('fundrawtransaction', [tx_hex]) - utxo_pos = 0 if tx_funded['changepos'] == 1 else 1 - tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex'] - txid = ci.rpc('sendrawtransaction', [tx_signed, ]) + tx_funded = ci.rpc_wallet("fundrawtransaction", [tx_hex]) + utxo_pos = 0 if tx_funded["changepos"] == 1 else 1 + tx_signed = ci.rpc_wallet( + "signrawtransactionwithwallet", + [ + tx_funded["hex"], + ], + )["hex"] + txid = ci.rpc( + "sendrawtransaction", + [ + tx_signed, + ], + ) - addr_out = ci.rpc_wallet('getnewaddress', ['csv test']) + addr_out = ci.rpc_wallet("getnewaddress", ["csv test"]) pkh = ci.decodeAddress(addr_out) script_out = ci.getScriptForPubkeyHash(pkh) # Double check output type - prev_tx = ci.rpc('decoderawtransaction', [tx_signed, ]) - assert (prev_tx['vout'][utxo_pos]['scriptPubKey']['type'] == 'scripthash') + prev_tx = ci.rpc( + "decoderawtransaction", + [ + tx_signed, + ], + ) + assert prev_tx["vout"][utxo_pos]["scriptPubKey"]["type"] == "scripthash" tx_spend = CTransaction() tx_spend.nVersion = ci.txVersion() - tx_spend.vin.append(CTxIn(COutPoint(int(txid, 16), utxo_pos), - scriptSig=CScript([script,]))) + tx_spend.vin.append( + CTxIn( + COutPoint(int(txid, 16), utxo_pos), + scriptSig=CScript( + [ + script, + ] + ), + ) + ) tx_spend.vout.append(ci.txoType()(ci.make_int(1.0999), script_out)) tx_spend_hex = ToHex(tx_spend) - txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ]) + txid = ci.rpc( + "sendrawtransaction", + [ + tx_spend_hex, + ], + ) self.mineBlock(1) - ro = ci.rpc_wallet('listreceivedbyaddress', [0, ]) + ro = ci.rpc_wallet( + "listreceivedbyaddress", + [ + 0, + ], + ) sum_addr = 0 for entry in ro: - if entry['address'] == addr_out: - sum_addr += entry['amount'] - assert (sum_addr == 1.0999) + if entry["address"] == addr_out: + sum_addr += entry["amount"] + assert sum_addr == 1.0999 # Ensure tx was mined - tx_wallet = ci.rpc_wallet('gettransaction', [txid, ]) - assert (len(tx_wallet['blockhash']) == 64) + tx_wallet = ci.rpc_wallet( + "gettransaction", + [ + txid, + ], + ) + assert len(tx_wallet["blockhash"]) == 64 def test_012_p2sh_p2wsh(self): - logging.info('---------- Test {} p2sh-p2wsh'.format(self.test_coin.name)) - logging.info('Skipped') + logging.info("---------- Test {} p2sh-p2wsh".format(self.test_coin.name)) + logging.info("Skipped") def test_01_a_full_swap(self): super().test_01_a_full_swap() @@ -564,12 +820,16 @@ class TestBCH(BasicSwapTest): super().test_02_a_leader_recover_a_lock_tx() def test_03_a_follower_recover_a_lock_tx(self): - self.do_test_03_follower_recover_a_lock_tx(self.test_coin_from, Coins.XMR, with_mercy=True) + self.do_test_03_follower_recover_a_lock_tx( + self.test_coin_from, Coins.XMR, with_mercy=True + ) def test_03_b_follower_recover_a_lock_tx_reverse(self): self.prepare_balance(Coins.BCH, 100.0, 1801, 1800) self.prepare_balance(Coins.XMR, 100.0, 1800, 1801) - self.do_test_03_follower_recover_a_lock_tx(Coins.XMR, self.test_coin_from, lock_value=12, with_mercy=True) + self.do_test_03_follower_recover_a_lock_tx( + Coins.XMR, self.test_coin_from, lock_value=12, with_mercy=True + ) def test_03_c_follower_recover_a_lock_tx_to_part(self): super().test_03_c_follower_recover_a_lock_tx_to_part() @@ -610,8 +870,8 @@ class TestBCH(BasicSwapTest): def test_06_preselect_inputs(self): tla_from = self.test_coin.name - logging.info('---------- Test {} Preselected inputs'.format(tla_from)) - logging.info('Skipped') + logging.info("---------- Test {} Preselected inputs".format(tla_from)) + logging.info("Skipped") def test_07_expire_stuck_accepted(self): super().test_07_expire_stuck_accepted() diff --git a/tests/basicswap/test_btc_xmr.py b/tests/basicswap/test_btc_xmr.py index ab2ec0f..ecb1f7a 100644 --- a/tests/basicswap/test_btc_xmr.py +++ b/tests/basicswap/test_btc_xmr.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021-2024 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -24,7 +25,6 @@ from basicswap.basicswap_util import ( ) from basicswap.util import ( make_int, - format_amount, ) from basicswap.interface.base import Curves from tests.basicswap.util import ( @@ -71,33 +71,39 @@ class TestFunctions(BaseTest): return callnoderpc(node_id, method, params, wallet, self.base_rpc_port) def mineBlock(self, num_blocks=1): - self.callnoderpc('generatetoaddress', [num_blocks, self.btc_addr]) + self.callnoderpc("generatetoaddress", [num_blocks, self.btc_addr]) def check_softfork_active(self, feature_name): - deploymentinfo = self.callnoderpc('getdeploymentinfo') - assert (deploymentinfo['deployments'][feature_name]['active'] is True) + deploymentinfo = self.callnoderpc("getdeploymentinfo") + assert deploymentinfo["deployments"][feature_name]["active"] is True def getBalance(self, js_wallets, coin) -> float: if coin == Coins.PART_BLIND: - coin_ticker: str = 'PART' - balance_type: str = 'blind_balance' - unconfirmed_name: str = 'blind_unconfirmed' + coin_ticker: str = "PART" + balance_type: str = "blind_balance" + unconfirmed_name: str = "blind_unconfirmed" elif coin == Coins.PART_ANON: - coin_ticker: str = 'PART' - balance_type: str = 'anon_balance' - unconfirmed_name: str = 'anon_pending' + coin_ticker: str = "PART" + balance_type: str = "anon_balance" + unconfirmed_name: str = "anon_pending" elif coin == Coins.NAV: coin_wallet = js_wallets[coin.name] - return float(coin_wallet['balance']) + float(coin_wallet['unconfirmed']) + float(coin_wallet['immature']) + return ( + float(coin_wallet["balance"]) + + float(coin_wallet["unconfirmed"]) + + float(coin_wallet["immature"]) + ) else: coin_ticker: str = coin.name - balance_type: str = 'balance' - unconfirmed_name: str = 'unconfirmed' + balance_type: str = "balance" + unconfirmed_name: str = "unconfirmed" - return float(js_wallets[coin_ticker][balance_type]) + float(js_wallets[coin_ticker][unconfirmed_name]) + return float(js_wallets[coin_ticker][balance_type]) + float( + js_wallets[coin_ticker][unconfirmed_name] + ) def do_test_01_full_swap(self, coin_from: Coins, coin_to: Coins) -> None: - logging.info('---------- Test {} to {}'.format(coin_from.name, coin_to.name)) + logging.info("---------- Test {} to {}".format(coin_from.name, coin_to.name)) # Offerer sends the offer # Bidder sends the bid @@ -111,119 +117,185 @@ class TestFunctions(BaseTest): ci_part0 = swap_clients[id_offerer].ci(Coins.PART) ci_part1 = swap_clients[id_bidder].ci(Coins.PART) - self.prepare_balance(coin_from, 100.0, 1800 + id_offerer, 1801 if reverse_bid else 1800) + self.prepare_balance( + coin_from, 100.0, 1800 + id_offerer, 1801 if reverse_bid else 1800 + ) # Leader sends the initial (chain a) lock tx. # Follower sends the participate (chain b) lock tx. id_leader: int = id_bidder if reverse_bid else id_offerer id_follower: int = id_offerer if reverse_bid else id_bidder - logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}') + logging.info( + f"Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}" + ) - js_0 = read_json_api(1800 + id_offerer, 'wallets') - node0_from_before: float = self.getBalance(js_0, coin_from) + # js_0 = read_json_api(1800 + id_offerer, 'wallets') + # node0_from_before: float = self.getBalance(js_0, coin_from) - js_1 = read_json_api(1800 + id_bidder, 'wallets') + js_1 = read_json_api(1800 + id_bidder, "wallets") node1_from_before: float = self.getBalance(js_1, coin_from) - node0_sent_messages_before: int = ci_part0.rpc('smsgoutbox', ['count',])['num_messages'] - node1_sent_messages_before: int = ci_part1.rpc('smsgoutbox', ['count',])['num_messages'] + node0_sent_messages_before: int = ci_part0.rpc( + "smsgoutbox", + [ + "count", + ], + )["num_messages"] + node1_sent_messages_before: int = ci_part1.rpc( + "smsgoutbox", + [ + "count", + ], + )["num_messages"] amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) - offer_id = swap_clients[id_offerer].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP) + offer_id = swap_clients[id_offerer].postOffer( + coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP + ) wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id) - offer = swap_clients[id_bidder].listOffers(filters={'offer_id': offer_id})[0] - assert (offer.offer_id == offer_id) + offer = swap_clients[id_bidder].listOffers(filters={"offer_id": offer_id})[0] + assert offer.offer_id == offer_id - post_json = {'with_extra_info': True} - offer0 = read_json_api(1800 + id_offerer, f'offers/{offer_id.hex()}', post_json)[0] - offer1 = read_json_api(1800 + id_offerer, f'offers/{offer_id.hex()}', post_json)[0] - assert ('lock_time_1' in offer0) - assert ('lock_time_1' in offer1) + post_json = {"with_extra_info": True} + offer0 = read_json_api( + 1800 + id_offerer, f"offers/{offer_id.hex()}", post_json + )[0] + offer1 = read_json_api( + 1800 + id_offerer, f"offers/{offer_id.hex()}", post_json + )[0] + assert "lock_time_1" in offer0 + assert "lock_time_1" in offer1 bid_id = swap_clients[id_bidder].postXmrBid(offer_id, offer.amount_from) - wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED) + wait_for_bid( + test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED + ) - bid0 = read_json_api(1800 + id_offerer, f'bids/{bid_id.hex()}') - bid1 = read_json_api(1800 + id_bidder, f'bids/{bid_id.hex()}') + bid0 = read_json_api(1800 + id_offerer, f"bids/{bid_id.hex()}") + bid1 = read_json_api(1800 + id_bidder, f"bids/{bid_id.hex()}") tolerance = 1 - assert (bid0['ticker_from'] == ci_from.ticker()) - assert (bid1['ticker_from'] == ci_from.ticker()) - assert (bid0['ticker_to'] == ci_to.ticker()) - assert (bid1['ticker_to'] == ci_to.ticker()) - assert (abs(ci_from.make_int(bid0['amt_from']) - amt_swap) <= tolerance) - assert (abs(ci_from.make_int(bid1['amt_from']) - amt_swap) <= tolerance) - assert (abs(ci_to.make_int(bid0['bid_rate']) - rate_swap) <= tolerance) - assert (abs(ci_to.make_int(bid1['bid_rate']) - rate_swap) <= tolerance) - assert (bid0['reverse_bid'] == reverse_bid) - assert (bid1['reverse_bid'] == reverse_bid) + assert bid0["ticker_from"] == ci_from.ticker() + assert bid1["ticker_from"] == ci_from.ticker() + assert bid0["ticker_to"] == ci_to.ticker() + assert bid1["ticker_to"] == ci_to.ticker() + assert abs(ci_from.make_int(bid0["amt_from"]) - amt_swap) <= tolerance + assert abs(ci_from.make_int(bid1["amt_from"]) - amt_swap) <= tolerance + assert abs(ci_to.make_int(bid0["bid_rate"]) - rate_swap) <= tolerance + assert abs(ci_to.make_int(bid1["bid_rate"]) - rate_swap) <= tolerance + assert bid0["reverse_bid"] == reverse_bid + assert bid1["reverse_bid"] == reverse_bid found: bool = False - bids0 = read_json_api(1800 + id_offerer, 'bids') + bids0 = read_json_api(1800 + id_offerer, "bids") for bid in bids0: - if bid['bid_id'] != bid_id.hex(): + if bid["bid_id"] != bid_id.hex(): continue - assert (bid['amount_from'] == bid1['amt_from']) - assert (bid['bid_rate'] == bid1['bid_rate']) + assert bid["amount_from"] == bid1["amt_from"] + assert bid["bid_rate"] == bid1["bid_rate"] found = True break - assert (found) + assert found swap_clients[id_offerer].acceptBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.SWAP_COMPLETED, wait_for=(self.extra_wait_time + 180)) - wait_for_bid(test_delay_event, swap_clients[id_bidder], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=(self.extra_wait_time + 30)) + wait_for_bid( + test_delay_event, + swap_clients[id_offerer], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=(self.extra_wait_time + 180), + ) + wait_for_bid( + test_delay_event, + swap_clients[id_bidder], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=(self.extra_wait_time + 30), + ) amount_from = float(ci_from.format_amount(amt_swap)) - js_1_after = read_json_api(1800 + id_bidder, 'wallets') + js_1_after = read_json_api(1800 + id_bidder, "wallets") node1_from_after = self.getBalance(js_1_after, coin_from) if coin_from is not Coins.PART: # TODO: staking - assert (node1_from_after > node1_from_before + (amount_from - 0.05)) + assert node1_from_after > node1_from_before + (amount_from - 0.05) - js_0_after = read_json_api(1800 + id_offerer, 'wallets') - node0_from_after: float = self.getBalance(js_0_after, coin_from) # TODO: Discard block rewards + # js_0_after = read_json_api(1800 + id_offerer, 'wallets') + # node0_from_after: float = self.getBalance(js_0_after, coin_from) # assert (node0_from_after < node0_from_before - amount_from) scale_from = ci_from.exp() - amount_to = int((amt_swap * rate_swap) // (10 ** scale_from)) + amount_to = int((amt_swap * rate_swap) // (10**scale_from)) amount_to_float = float(ci_to.format_amount(amount_to)) node1_to_after: float = self.getBalance(js_1_after, coin_to) node1_to_before: float = self.getBalance(js_1, coin_to) if False: # TODO: set stakeaddress and xmr rewards to non wallet addresses - assert (node1_to_after < node1_to_before - amount_to_float) + assert node1_to_after < node1_to_before - amount_to_float - node0_sent_messages_after: int = ci_part0.rpc('smsgoutbox', ['count',])['num_messages'] - node1_sent_messages_after: int = ci_part1.rpc('smsgoutbox', ['count',])['num_messages'] - node0_sent_messages: int = node0_sent_messages_after - node0_sent_messages_before - node1_sent_messages: int = node1_sent_messages_after - node1_sent_messages_before - split_msgs: int = 2 if (ci_from.curve_type() != Curves.secp256k1 or ci_to.curve_type() != Curves.secp256k1) else 0 - assert (node0_sent_messages == (3 + split_msgs if reverse_bid else 4 + split_msgs)) - assert (node1_sent_messages == (4 + split_msgs if reverse_bid else 2 + split_msgs)) + node0_sent_messages_after: int = ci_part0.rpc( + "smsgoutbox", + [ + "count", + ], + )["num_messages"] + node1_sent_messages_after: int = ci_part1.rpc( + "smsgoutbox", + [ + "count", + ], + )["num_messages"] + node0_sent_messages: int = ( + node0_sent_messages_after - node0_sent_messages_before + ) + node1_sent_messages: int = ( + node1_sent_messages_after - node1_sent_messages_before + ) + split_msgs: int = ( + 2 + if ( + ci_from.curve_type() != Curves.secp256k1 + or ci_to.curve_type() != Curves.secp256k1 + ) + else 0 + ) + assert node0_sent_messages == ( + 3 + split_msgs if reverse_bid else 4 + split_msgs + ) + assert node1_sent_messages == ( + 4 + split_msgs if reverse_bid else 2 + split_msgs + ) - post_json = {'show_extra': True} - bid0 = read_json_api(1800 + id_offerer, f'bids/{bid_id.hex()}', post_json) - bid1 = read_json_api(1800 + id_bidder, f'bids/{bid_id.hex()}', post_json) + post_json = {"show_extra": True} + bid0 = read_json_api(1800 + id_offerer, f"bids/{bid_id.hex()}", post_json) + bid1 = read_json_api(1800 + id_bidder, f"bids/{bid_id.hex()}", post_json) chain_a_lock_txid = None chain_b_lock_txid = None - for tx in bid0['txns']: - if tx['type'] == 'Chain A Lock Spend': - chain_a_lock_txid = tx['txid'] - elif tx['type'] == 'Chain B Lock Spend': - chain_b_lock_txid = tx['txid'] - for tx in bid1['txns']: - if not chain_a_lock_txid and tx['type'] == 'Chain A Lock Spend': - chain_a_lock_txid = tx['txid'] - elif not chain_b_lock_txid and tx['type'] == 'Chain B Lock Spend': - chain_b_lock_txid = tx['txid'] - assert (chain_a_lock_txid is not None) - assert (chain_b_lock_txid is not None) + for tx in bid0["txns"]: + if tx["type"] == "Chain A Lock Spend": + chain_a_lock_txid = tx["txid"] + elif tx["type"] == "Chain B Lock Spend": + chain_b_lock_txid = tx["txid"] + for tx in bid1["txns"]: + if not chain_a_lock_txid and tx["type"] == "Chain A Lock Spend": + chain_a_lock_txid = tx["txid"] + elif not chain_b_lock_txid and tx["type"] == "Chain B Lock Spend": + chain_b_lock_txid = tx["txid"] + assert chain_a_lock_txid is not None + assert chain_b_lock_txid is not None - def do_test_02_leader_recover_a_lock_tx(self, coin_from: Coins, coin_to: Coins, lock_value: int = 32) -> None: - logging.info('---------- Test {} to {} leader recovers coin a lock tx'.format(coin_from.name, coin_to.name)) + def do_test_02_leader_recover_a_lock_tx( + self, coin_from: Coins, coin_to: Coins, lock_value: int = 32 + ) -> None: + logging.info( + "---------- Test {} to {} leader recovers coin a lock tx".format( + coin_from.name, coin_to.name + ) + ) id_offerer: int = self.node_a_id id_bidder: int = self.node_b_id @@ -235,37 +307,69 @@ class TestFunctions(BaseTest): id_leader: int = id_bidder if reverse_bid else id_offerer id_follower: int = id_offerer if reverse_bid else id_bidder - logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}') + logging.info( + f"Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}" + ) - js_wl_before = read_json_api(1800 + id_leader, 'wallets') - wl_from_before = self.getBalance(js_wl_before, coin_from) + # js_wl_before = read_json_api(1800 + id_leader, 'wallets') + # wl_from_before = self.getBalance(js_wl_before, coin_from) amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) offer_id = swap_clients[id_offerer].postOffer( - coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, - lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=lock_value) + coin_from, + coin_to, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, + lock_value=lock_value, + ) wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id) offer = swap_clients[id_bidder].getOffer(offer_id) bid_id = swap_clients[id_bidder].postXmrBid(offer_id, offer.amount_from) - wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED) + wait_for_bid( + test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED + ) - swap_clients[id_follower].setBidDebugInd(bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK) + swap_clients[id_follower].setBidDebugInd( + bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK + ) swap_clients[id_offerer].acceptBid(bid_id) leader_sent_bid: bool = True if reverse_bid else False - wait_for_bid(test_delay_event, swap_clients[id_leader], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=leader_sent_bid, wait_for=(self.extra_wait_time + 180)) - wait_for_bid(test_delay_event, swap_clients[id_follower], bid_id, [BidStates.BID_STALLED_FOR_TEST, BidStates.XMR_SWAP_FAILED], sent=(not leader_sent_bid), wait_for=(self.extra_wait_time + 30)) - - js_wl_after = read_json_api(1800 + id_leader, 'wallets') - wl_from_after = self.getBalance(js_wl_after, coin_from) + wait_for_bid( + test_delay_event, + swap_clients[id_leader], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + sent=leader_sent_bid, + wait_for=(self.extra_wait_time + 180), + ) + wait_for_bid( + test_delay_event, + swap_clients[id_follower], + bid_id, + [BidStates.BID_STALLED_FOR_TEST, BidStates.XMR_SWAP_FAILED], + sent=(not leader_sent_bid), + wait_for=(self.extra_wait_time + 30), + ) # TODO: Discard block rewards + # js_wl_after = read_json_api(1800 + id_leader, 'wallets') + # wl_from_after = self.getBalance(js_wl_after, coin_from) # assert (node0_from_before - node0_from_after < 0.02) - def do_test_03_follower_recover_a_lock_tx(self, coin_from, coin_to, lock_value: int = 32, with_mercy: bool = False): - logging.info('---------- Test {} to {} follower recovers coin a lock tx{}'.format(coin_from.name, coin_to.name, ' (with mercy tx)' if with_mercy else '')) + def do_test_03_follower_recover_a_lock_tx( + self, coin_from, coin_to, lock_value: int = 32, with_mercy: bool = False + ): + logging.info( + "---------- Test {} to {} follower recovers coin a lock tx{}".format( + coin_from.name, coin_to.name, " (with mercy tx)" if with_mercy else "" + ) + ) # Leader is too slow to recover the coin a lock tx and follower swipes it # Coin B lock tx remains unspent unless a mercy output revealing the follower's keyshare is sent @@ -280,46 +384,85 @@ class TestFunctions(BaseTest): id_leader: int = id_bidder if reverse_bid else id_offerer id_follower: int = id_offerer if reverse_bid else id_bidder - logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}') + logging.info( + f"Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}" + ) - swap_clients[id_follower].ci(coin_from if reverse_bid else coin_to)._altruistic = with_mercy - - js_w0_before = read_json_api(1800 + id_offerer, 'wallets') - js_w1_before = read_json_api(1800 + id_bidder, 'wallets') + swap_clients[id_follower].ci( + coin_from if reverse_bid else coin_to + )._altruistic = with_mercy amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) offer_id = swap_clients[id_offerer].postOffer( - coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, - lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=lock_value) + coin_from, + coin_to, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, + lock_value=lock_value, + ) wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id) offer = swap_clients[id_bidder].getOffer(offer_id) bid_id = swap_clients[id_bidder].postXmrBid(offer_id, offer.amount_from) - wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED) + wait_for_bid( + test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED + ) - debug_type = DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND2 if with_mercy else DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND + debug_type = ( + DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND2 + if with_mercy + else DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND + ) swap_clients[id_leader].setBidDebugInd(bid_id, debug_type) - debug_type = DebugTypes.BID_DONT_SPEND_COIN_B_LOCK if with_mercy else DebugTypes.BID_STOP_AFTER_COIN_A_LOCK + debug_type = ( + DebugTypes.BID_DONT_SPEND_COIN_B_LOCK + if with_mercy + else DebugTypes.BID_STOP_AFTER_COIN_A_LOCK + ) swap_clients[id_follower].setBidDebugInd(bid_id, debug_type) - swap_clients[id_leader].setBidDebugInd(bid_id, DebugTypes.WAIT_FOR_COIN_B_LOCK_BEFORE_REFUND, False) - swap_clients[id_follower].setBidDebugInd(bid_id, DebugTypes.WAIT_FOR_COIN_B_LOCK_BEFORE_REFUND, False) + swap_clients[id_leader].setBidDebugInd( + bid_id, DebugTypes.WAIT_FOR_COIN_B_LOCK_BEFORE_REFUND, False + ) + swap_clients[id_follower].setBidDebugInd( + bid_id, DebugTypes.WAIT_FOR_COIN_B_LOCK_BEFORE_REFUND, False + ) swap_clients[id_offerer].acceptBid(bid_id) leader_sent_bid: bool = True if reverse_bid else False - expect_state = (BidStates.XMR_SWAP_NOSCRIPT_TX_REDEEMED, BidStates.SWAP_COMPLETED) if with_mercy else BidStates.BID_STALLED_FOR_TEST - wait_for_bid(test_delay_event, swap_clients[id_leader], bid_id, expect_state, wait_for=(self.extra_wait_time + 180), sent=leader_sent_bid) - wait_for_bid(test_delay_event, swap_clients[id_follower], bid_id, BidStates.XMR_SWAP_FAILED_SWIPED, wait_for=(self.extra_wait_time + 80), sent=(not leader_sent_bid)) + expect_state = ( + (BidStates.XMR_SWAP_NOSCRIPT_TX_REDEEMED, BidStates.SWAP_COMPLETED) + if with_mercy + else BidStates.BID_STALLED_FOR_TEST + ) + wait_for_bid( + test_delay_event, + swap_clients[id_leader], + bid_id, + expect_state, + wait_for=(self.extra_wait_time + 180), + sent=leader_sent_bid, + ) + wait_for_bid( + test_delay_event, + swap_clients[id_follower], + bid_id, + BidStates.XMR_SWAP_FAILED_SWIPED, + wait_for=(self.extra_wait_time + 80), + sent=(not leader_sent_bid), + ) - js_w1_after = read_json_api(1800 + id_bidder, 'wallets') - - node1_from_before = self.getBalance(js_w1_before, coin_from) - node1_from_after = self.getBalance(js_w1_after, coin_from) - amount_from = float(format_amount(amt_swap, 8)) - # TODO: Discard block rewards + # TODO: Exclude block rewards + # js_w1_after = read_json_api(1800 + id_bidder, 'wallets') + # node1_from_before = self.getBalance(js_w1_before, coin_from) + # node1_from_after = self.getBalance(js_w1_after, coin_from) + # amount_from = float(format_amount(amt_swap, 8)) # assert (node1_from_after - node1_from_before > (amount_from - 0.02)) swap_clients[id_offerer].abandonBid(bid_id) @@ -327,8 +470,14 @@ class TestFunctions(BaseTest): wait_for_none_active(test_delay_event, 1800 + id_offerer) wait_for_none_active(test_delay_event, 1800 + id_bidder) - def do_test_04_follower_recover_b_lock_tx(self, coin_from, coin_to, lock_value: int = 32): - logging.info('---------- Test {} to {} follower recovers coin b lock tx'.format(coin_from.name, coin_to.name)) + def do_test_04_follower_recover_b_lock_tx( + self, coin_from, coin_to, lock_value: int = 32 + ): + logging.info( + "---------- Test {} to {} follower recovers coin b lock tx".format( + coin_from.name, coin_to.name + ) + ) id_offerer: int = self.node_a_id id_bidder: int = self.node_b_id @@ -342,55 +491,102 @@ class TestFunctions(BaseTest): id_bidder: int = id_bidder id_leader: int = id_bidder if reverse_bid else id_offerer id_follower: int = id_offerer if reverse_bid else id_bidder - logging.info(f'Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}') + logging.info( + f"Offerer, bidder, leader, follower: {id_offerer}, {id_bidder}, {id_leader}, {id_follower}" + ) - js_w0_before = read_json_api(1800 + id_offerer, 'wallets') - js_w1_before = read_json_api(1800 + id_bidder, 'wallets') + js_w0_before = read_json_api(1800 + id_offerer, "wallets") + js_w1_before = read_json_api(1800 + id_bidder, "wallets") amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) - logging.info(f'amount from, rate, amount to: {amt_swap}, {rate_swap}, {amt_swap * rate_swap}') + logging.info( + f"amount from, rate, amount to: {amt_swap}, {rate_swap}, {amt_swap * rate_swap}" + ) offer_id = swap_clients[id_offerer].postOffer( - coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, - lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=lock_value) + coin_from, + coin_to, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, + lock_value=lock_value, + ) wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id) offer = swap_clients[id_bidder].getOffer(offer_id) bid_id = swap_clients[id_bidder].postXmrBid(offer_id, offer.amount_from) - wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED) + wait_for_bid( + test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED + ) - swap_clients[id_follower].setBidDebugInd(bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK) + swap_clients[id_follower].setBidDebugInd( + bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK + ) swap_clients[id_offerer].acceptBid(bid_id) leader_sent_bid: bool = True if reverse_bid else False - wait_for_bid(test_delay_event, swap_clients[id_leader], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=(self.extra_wait_time + 200), sent=leader_sent_bid) - wait_for_bid(test_delay_event, swap_clients[id_follower], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=(not leader_sent_bid), wait_for=(self.extra_wait_time + 30)) + wait_for_bid( + test_delay_event, + swap_clients[id_leader], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + wait_for=(self.extra_wait_time + 200), + sent=leader_sent_bid, + ) + wait_for_bid( + test_delay_event, + swap_clients[id_follower], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + sent=(not leader_sent_bid), + wait_for=(self.extra_wait_time + 30), + ) - js_w0_after = read_json_api(1800 + id_offerer, 'wallets') - js_w1_after = read_json_api(1800 + id_bidder, 'wallets') + js_w0_after = read_json_api(1800 + id_offerer, "wallets") + js_w1_after = read_json_api(1800 + id_bidder, "wallets") node0_from_before = self.getBalance(js_w0_before, coin_from) node0_from_after = self.getBalance(js_w0_after, coin_from) - logging.info('node0 end coin_from balance {}, diff {}'.format(node0_from_after, node0_from_after - node0_from_before)) + logging.info( + "node0 end coin_from balance {}, diff {}".format( + node0_from_after, node0_from_after - node0_from_before + ) + ) node0_to_before = self.getBalance(js_w0_before, coin_to) node0_to_after = self.getBalance(js_w0_after, coin_to) - logging.info('node0 end coin_to balance {}, diff {}'.format(node0_to_after, node0_to_after - node0_to_before)) + logging.info( + "node0 end coin_to balance {}, diff {}".format( + node0_to_after, node0_to_after - node0_to_before + ) + ) max_fee_from: float = 0.1 if coin_from == Coins.PART_ANON else 0.02 if coin_from != Coins.PART: # TODO: Discard block rewards - assert (node0_from_before - node0_from_after < max_fee_from) + assert node0_from_before - node0_from_after < max_fee_from node1_from_before = self.getBalance(js_w1_before, coin_from) node1_from_after = self.getBalance(js_w1_after, coin_from) - logging.info('node1 end coin_from balance {}, diff {}'.format(node1_from_after, node1_from_after - node1_from_before)) + logging.info( + "node1 end coin_from balance {}, diff {}".format( + node1_from_after, node1_from_after - node1_from_before + ) + ) node1_to_before = self.getBalance(js_w1_before, coin_to) node1_to_after = self.getBalance(js_w1_after, coin_to) - logging.info('node1 end coin_to balance {}, diff {}'.format(node1_to_after, node1_to_after - node1_to_before)) + logging.info( + "node1 end coin_to balance {}, diff {}".format( + node1_to_after, node1_to_after - node1_to_before + ) + ) max_fee_to: float = 0.1 if coin_to == Coins.PART_ANON else 0.02 - assert (node1_to_before - node1_to_after < max_fee_to) + assert node1_to_before - node1_to_after < max_fee_to def do_test_05_self_bid(self, coin_from, coin_to): - logging.info('---------- Test {} to {} same client'.format(coin_from.name, coin_to.name)) + logging.info( + "---------- Test {} to {} same client".format(coin_from.name, coin_to.name) + ) id_both: int = self.node_b_id @@ -401,106 +597,212 @@ class TestFunctions(BaseTest): amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) - offer_id = swap_clients[id_both].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, auto_accept_bids=True) + offer_id = swap_clients[id_both].postOffer( + coin_from, + coin_to, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + auto_accept_bids=True, + ) bid_id = swap_clients[id_both].postXmrBid(offer_id, amt_swap) - wait_for_bid(test_delay_event, swap_clients[id_both], bid_id, BidStates.SWAP_COMPLETED, wait_for=(self.extra_wait_time + 180)) + wait_for_bid( + test_delay_event, + swap_clients[id_both], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=(self.extra_wait_time + 180), + ) class BasicSwapTest(TestFunctions): def test_001_nested_segwit(self): # p2sh-p2wpkh - logging.info('---------- Test {} p2sh nested segwit'.format(self.test_coin_from.name)) + logging.info( + "---------- Test {} p2sh nested segwit".format(self.test_coin_from.name) + ) ci = self.swap_clients[0].ci(self.test_coin_from) - addr_p2sh_segwit = ci.rpc_wallet('getnewaddress', ['segwit test', 'p2sh-segwit']) - addr_info = ci.rpc_wallet('getaddressinfo', [addr_p2sh_segwit, ]) - assert addr_info['script'] == 'witness_v0_keyhash' + addr_p2sh_segwit = ci.rpc_wallet( + "getnewaddress", ["segwit test", "p2sh-segwit"] + ) + addr_info = ci.rpc_wallet( + "getaddressinfo", + [ + addr_p2sh_segwit, + ], + ) + assert addr_info["script"] == "witness_v0_keyhash" - txid = ci.rpc_wallet('sendtoaddress', [addr_p2sh_segwit, 1.0]) + txid = ci.rpc_wallet("sendtoaddress", [addr_p2sh_segwit, 1.0]) assert len(txid) == 64 self.mineBlock() - ro = ci.rpc('scantxoutset', ['start', ['addr({})'.format(addr_p2sh_segwit)]]) - assert (len(ro['unspents']) == 1) - assert (ro['unspents'][0]['txid'] == txid) + ro = ci.rpc("scantxoutset", ["start", ["addr({})".format(addr_p2sh_segwit)]]) + assert len(ro["unspents"]) == 1 + assert ro["unspents"][0]["txid"] == txid - tx_wallet = ci.rpc_wallet('gettransaction', [txid, ])['hex'] - tx = ci.rpc('decoderawtransaction', [tx_wallet, ]) + tx_wallet = ci.rpc_wallet( + "gettransaction", + [ + txid, + ], + )["hex"] + tx = ci.rpc( + "decoderawtransaction", + [ + tx_wallet, + ], + ) prevout_n = -1 - for txo in tx['vout']: - if addr_p2sh_segwit == txo['scriptPubKey']['address']: - prevout_n = txo['n'] + for txo in tx["vout"]: + if addr_p2sh_segwit == txo["scriptPubKey"]["address"]: + prevout_n = txo["n"] break assert prevout_n > -1 - tx_funded = ci.rpc('createrawtransaction', [[{'txid': txid, 'vout': prevout_n}], {addr_p2sh_segwit: 0.99}]) - tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded, ])['hex'] - tx_funded_decoded = ci.rpc('decoderawtransaction', [tx_funded, ]) - tx_signed_decoded = ci.rpc('decoderawtransaction', [tx_signed, ]) - assert tx_funded_decoded['txid'] != tx_signed_decoded['txid'] + tx_funded = ci.rpc( + "createrawtransaction", + [[{"txid": txid, "vout": prevout_n}], {addr_p2sh_segwit: 0.99}], + ) + tx_signed = ci.rpc_wallet( + "signrawtransactionwithwallet", + [ + tx_funded, + ], + )["hex"] + tx_funded_decoded = ci.rpc( + "decoderawtransaction", + [ + tx_funded, + ], + ) + tx_signed_decoded = ci.rpc( + "decoderawtransaction", + [ + tx_signed, + ], + ) + assert tx_funded_decoded["txid"] != tx_signed_decoded["txid"] # Add scriptsig for txids to match - addr_p2sh_segwit_info = ci.rpc_wallet('getaddressinfo', [addr_p2sh_segwit, ]) + addr_p2sh_segwit_info = ci.rpc_wallet( + "getaddressinfo", + [ + addr_p2sh_segwit, + ], + ) decoded_tx = FromHex(CTransaction(), tx_funded) - decoded_tx.vin[0].scriptSig = bytes.fromhex('16' + addr_p2sh_segwit_info['hex']) + decoded_tx.vin[0].scriptSig = bytes.fromhex("16" + addr_p2sh_segwit_info["hex"]) txid_with_scriptsig = decoded_tx.rehash() - assert txid_with_scriptsig == tx_signed_decoded['txid'] + assert txid_with_scriptsig == tx_signed_decoded["txid"] def test_002_native_segwit(self): # p2wpkh - logging.info('---------- Test {} p2sh native segwit'.format(self.test_coin_from.name)) + logging.info( + "---------- Test {} p2sh native segwit".format(self.test_coin_from.name) + ) ci = self.swap_clients[0].ci(self.test_coin_from) - addr_segwit = ci.rpc_wallet('getnewaddress', ['segwit test', 'bech32']) - addr_info = ci.rpc_wallet('getaddressinfo', [addr_segwit, ]) - assert addr_info['iswitness'] is True + addr_segwit = ci.rpc_wallet("getnewaddress", ["segwit test", "bech32"]) + addr_info = ci.rpc_wallet( + "getaddressinfo", + [ + addr_segwit, + ], + ) + assert addr_info["iswitness"] is True - txid = ci.rpc_wallet('sendtoaddress', [addr_segwit, 1.0]) + txid = ci.rpc_wallet("sendtoaddress", [addr_segwit, 1.0]) assert len(txid) == 64 - tx_wallet = ci.rpc_wallet('gettransaction', [txid, ])['hex'] - tx = ci.rpc('decoderawtransaction', [tx_wallet, ]) + tx_wallet = ci.rpc_wallet( + "gettransaction", + [ + txid, + ], + )["hex"] + tx = ci.rpc( + "decoderawtransaction", + [ + tx_wallet, + ], + ) self.mineBlock() - ro = ci.rpc('scantxoutset', ['start', ['addr({})'.format(addr_segwit)]]) - assert (len(ro['unspents']) == 1) - assert (ro['unspents'][0]['txid'] == txid) + ro = ci.rpc("scantxoutset", ["start", ["addr({})".format(addr_segwit)]]) + assert len(ro["unspents"]) == 1 + assert ro["unspents"][0]["txid"] == txid prevout_n = -1 - for txo in tx['vout']: - if addr_segwit == txo['scriptPubKey']['address']: - prevout_n = txo['n'] + for txo in tx["vout"]: + if addr_segwit == txo["scriptPubKey"]["address"]: + prevout_n = txo["n"] break assert prevout_n > -1 - tx_funded = ci.rpc('createrawtransaction', [[{'txid': txid, 'vout': prevout_n}], {addr_segwit: 0.99}]) - tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded, ])['hex'] - tx_funded_decoded = ci.rpc('decoderawtransaction', [tx_funded, ]) - tx_signed_decoded = ci.rpc('decoderawtransaction', [tx_signed, ]) - assert tx_funded_decoded['txid'] == tx_signed_decoded['txid'] + tx_funded = ci.rpc( + "createrawtransaction", + [[{"txid": txid, "vout": prevout_n}], {addr_segwit: 0.99}], + ) + tx_signed = ci.rpc_wallet( + "signrawtransactionwithwallet", + [ + tx_funded, + ], + )["hex"] + tx_funded_decoded = ci.rpc( + "decoderawtransaction", + [ + tx_funded, + ], + ) + tx_signed_decoded = ci.rpc( + "decoderawtransaction", + [ + tx_signed, + ], + ) + assert tx_funded_decoded["txid"] == tx_signed_decoded["txid"] def test_003_cltv(self): - logging.info('---------- Test {} cltv'.format(self.test_coin_from.name)) + logging.info("---------- Test {} cltv".format(self.test_coin_from.name)) ci = self.swap_clients[0].ci(self.test_coin_from) - self.check_softfork_active('bip65') + self.check_softfork_active("bip65") - chain_height = self.callnoderpc('getblockcount') - script = CScript([chain_height + 3, OP_CHECKLOCKTIMEVERIFY, ]) + chain_height = self.callnoderpc("getblockcount") + script = CScript( + [ + chain_height + 3, + OP_CHECKLOCKTIMEVERIFY, + ] + ) script_dest = ci.getScriptDest(script) tx = CTransaction() tx.nVersion = ci.txVersion() tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest)) tx_hex = ToHex(tx) - tx_funded = ci.rpc_wallet('fundrawtransaction', [tx_hex]) - utxo_pos = 0 if tx_funded['changepos'] == 1 else 1 - tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex'] - txid = ci.rpc('sendrawtransaction', [tx_signed, ]) + tx_funded = ci.rpc_wallet("fundrawtransaction", [tx_hex]) + utxo_pos = 0 if tx_funded["changepos"] == 1 else 1 + tx_signed = ci.rpc_wallet( + "signrawtransactionwithwallet", + [ + tx_funded["hex"], + ], + )["hex"] + txid = ci.rpc( + "sendrawtransaction", + [ + tx_signed, + ], + ) - addr_out = ci.rpc_wallet('getnewaddress', ['cltv test', 'bech32']) + addr_out = ci.rpc_wallet("getnewaddress", ["cltv test", "bech32"]) pkh = ci.decodeSegwitAddress(addr_out) script_out = ci.getScriptForPubkeyHash(pkh) @@ -510,7 +812,9 @@ class BasicSwapTest(TestFunctions): tx_spend.vin.append(CTxIn(COutPoint(int(txid, 16), utxo_pos))) tx_spend.vout.append(ci.txoType()(ci.make_int(1.0999), script_out)) tx_spend.wit.vtxinwit.append(CTxInWitness()) - tx_spend.wit.vtxinwit[0].scriptWitness.stack = [script, ] + tx_spend.wit.vtxinwit[0].scriptWitness.stack = [ + script, + ] tx_spend_hex = ToHex(tx_spend) tx_spend.nLockTime = chain_height + 2 @@ -518,181 +822,315 @@ class BasicSwapTest(TestFunctions): for tx_hex in [tx_spend_invalid_hex, tx_spend_hex]: try: - txid = self.callnoderpc('sendrawtransaction', [tx_hex, ]) + txid = self.callnoderpc( + "sendrawtransaction", + [ + tx_hex, + ], + ) except Exception as e: - assert ('non-final' in str(e)) + assert "non-final" in str(e) else: - assert False, 'Should fail' + assert False, "Should fail" self.mineBlock(5) try: - txid = ci.rpc('sendrawtransaction', [tx_spend_invalid_hex, ]) + txid = ci.rpc( + "sendrawtransaction", + [ + tx_spend_invalid_hex, + ], + ) except Exception as e: - assert ('Locktime requirement not satisfied' in str(e)) + assert "Locktime requirement not satisfied" in str(e) else: - assert False, 'Should fail' + assert False, "Should fail" - txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ]) + txid = ci.rpc( + "sendrawtransaction", + [ + tx_spend_hex, + ], + ) self.mineBlock() - ro = ci.rpc_wallet('listreceivedbyaddress', [0, ]) + ro = ci.rpc_wallet( + "listreceivedbyaddress", + [ + 0, + ], + ) sum_addr = 0 for entry in ro: - if entry['address'] == addr_out: - sum_addr += entry['amount'] - assert (sum_addr == 1.0999) + if entry["address"] == addr_out: + sum_addr += entry["amount"] + assert sum_addr == 1.0999 # Ensure tx was mined - tx_wallet = ci.rpc_wallet('gettransaction', [txid, ]) - assert (len(tx_wallet['blockhash']) == 64) + tx_wallet = ci.rpc_wallet( + "gettransaction", + [ + txid, + ], + ) + assert len(tx_wallet["blockhash"]) == 64 def test_004_csv(self): - logging.info('---------- Test {} csv'.format(self.test_coin_from.name)) - swap_clients = self.swap_clients + logging.info("---------- Test {} csv".format(self.test_coin_from.name)) ci = self.swap_clients[0].ci(self.test_coin_from) - self.check_softfork_active('csv') + self.check_softfork_active("csv") - script = CScript([3, OP_CHECKSEQUENCEVERIFY, ]) + script = CScript( + [ + 3, + OP_CHECKSEQUENCEVERIFY, + ] + ) script_dest = ci.getScriptDest(script) tx = CTransaction() tx.nVersion = ci.txVersion() tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest)) tx_hex = ToHex(tx) - tx_funded = ci.rpc_wallet('fundrawtransaction', [tx_hex]) - utxo_pos = 0 if tx_funded['changepos'] == 1 else 1 - tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex'] - txid = ci.rpc('sendrawtransaction', [tx_signed, ]) + tx_funded = ci.rpc_wallet("fundrawtransaction", [tx_hex]) + utxo_pos = 0 if tx_funded["changepos"] == 1 else 1 + tx_signed = ci.rpc_wallet( + "signrawtransactionwithwallet", + [ + tx_funded["hex"], + ], + )["hex"] + txid = ci.rpc( + "sendrawtransaction", + [ + tx_signed, + ], + ) - addr_out = ci.rpc_wallet('getnewaddress', ['csv test', 'bech32']) + addr_out = ci.rpc_wallet("getnewaddress", ["csv test", "bech32"]) pkh = ci.decodeSegwitAddress(addr_out) script_out = ci.getScriptForPubkeyHash(pkh) # Double check output type - prev_tx = ci.rpc('decoderawtransaction', [tx_signed, ]) - assert (prev_tx['vout'][utxo_pos]['scriptPubKey']['type'] == 'witness_v0_scripthash') + prev_tx = ci.rpc( + "decoderawtransaction", + [ + tx_signed, + ], + ) + assert ( + prev_tx["vout"][utxo_pos]["scriptPubKey"]["type"] == "witness_v0_scripthash" + ) tx_spend = CTransaction() tx_spend.nVersion = ci.txVersion() - tx_spend.vin.append(CTxIn(COutPoint(int(txid, 16), utxo_pos), - nSequence=3)) + tx_spend.vin.append(CTxIn(COutPoint(int(txid, 16), utxo_pos), nSequence=3)) tx_spend.vout.append(ci.txoType()(ci.make_int(1.0999), script_out)) tx_spend.wit.vtxinwit.append(CTxInWitness()) - tx_spend.wit.vtxinwit[0].scriptWitness.stack = [script, ] + tx_spend.wit.vtxinwit[0].scriptWitness.stack = [ + script, + ] tx_spend_hex = ToHex(tx_spend) try: - txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ]) + txid = ci.rpc( + "sendrawtransaction", + [ + tx_spend_hex, + ], + ) except Exception as e: - assert ('non-BIP68-final' in str(e)) + assert "non-BIP68-final" in str(e) else: - assert False, 'Should fail' + assert False, "Should fail" self.mineBlock(3) - txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ]) + txid = ci.rpc( + "sendrawtransaction", + [ + tx_spend_hex, + ], + ) self.mineBlock(1) - ro = ci.rpc_wallet('listreceivedbyaddress', [0, ]) + ro = ci.rpc_wallet( + "listreceivedbyaddress", + [ + 0, + ], + ) sum_addr = 0 for entry in ro: - if entry['address'] == addr_out: - sum_addr += entry['amount'] - assert (sum_addr == 1.0999) + if entry["address"] == addr_out: + sum_addr += entry["amount"] + assert sum_addr == 1.0999 # Ensure tx was mined - tx_wallet = ci.rpc_wallet('gettransaction', [txid, ]) - assert (len(tx_wallet['blockhash']) == 64) + tx_wallet = ci.rpc_wallet( + "gettransaction", + [ + txid, + ], + ) + assert len(tx_wallet["blockhash"]) == 64 def test_005_watchonly(self): - logging.info('---------- Test {} watchonly'.format(self.test_coin_from.name)) + logging.info("---------- Test {} watchonly".format(self.test_coin_from.name)) ci = self.swap_clients[0].ci(self.test_coin_from) ci1 = self.swap_clients[1].ci(self.test_coin_from) - addr = ci.rpc_wallet('getnewaddress', ['watchonly test', 'bech32']) - ro = ci1.rpc_wallet('importaddress', [addr, '', False]) - txid = ci.rpc_wallet('sendtoaddress', [addr, 1.0]) - tx_hex = ci.rpc('getrawtransaction', [txid, ]) - ci1.rpc_wallet('sendrawtransaction', [tx_hex, ]) - ro = ci1.rpc_wallet('gettransaction', [txid, ]) - assert (ro['txid'] == txid) - balances = ci1.rpc_wallet('getbalances') - assert (balances['watchonly']['trusted'] + balances['watchonly']['untrusted_pending'] >= 1.0) + addr = ci.rpc_wallet("getnewaddress", ["watchonly test", "bech32"]) + ro = ci1.rpc_wallet("importaddress", [addr, "", False]) + txid = ci.rpc_wallet("sendtoaddress", [addr, 1.0]) + tx_hex = ci.rpc( + "getrawtransaction", + [ + txid, + ], + ) + ci1.rpc_wallet( + "sendrawtransaction", + [ + tx_hex, + ], + ) + ro = ci1.rpc_wallet( + "gettransaction", + [ + txid, + ], + ) + assert ro["txid"] == txid + balances = ci1.rpc_wallet("getbalances") + assert ( + balances["watchonly"]["trusted"] + + balances["watchonly"]["untrusted_pending"] + >= 1.0 + ) def test_006_getblock_verbosity(self): - logging.info('---------- Test {} getblock verbosity'.format(self.test_coin_from.name)) + logging.info( + "---------- Test {} getblock verbosity".format(self.test_coin_from.name) + ) - best_hash = self.callnoderpc('getbestblockhash') - block = self.callnoderpc('getblock', [best_hash, 2]) - assert ('vin' in block['tx'][0]) + best_hash = self.callnoderpc("getbestblockhash") + block = self.callnoderpc("getblock", [best_hash, 2]) + assert "vin" in block["tx"][0] def test_007_hdwallet(self): - logging.info('---------- Test {} hdwallet'.format(self.test_coin_from.name)) + logging.info("---------- Test {} hdwallet".format(self.test_coin_from.name)) ci = self.swap_clients[0].ci(self.test_coin_from) - test_seed = '8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b' - test_wif = self.swap_clients[0].ci(self.test_coin_from).encodeKey(bytes.fromhex(test_seed)) + test_seed = "8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b" + test_wif = ( + self.swap_clients[0] + .ci(self.test_coin_from) + .encodeKey(bytes.fromhex(test_seed)) + ) new_wallet_name = random.randbytes(10).hex() # wallet_name, wallet_name, blank, passphrase, avoid_reuse, descriptors - self.callnoderpc('createwallet', [new_wallet_name, False, True, '', False, False]) - self.callnoderpc('sethdseed', [True, test_wif], wallet=new_wallet_name) - addr = self.callnoderpc('getnewaddress', wallet=new_wallet_name) - self.callnoderpc('unloadwallet', [new_wallet_name]) - assert (addr == 'bcrt1qps7hnjd866e9ynxadgseprkc2l56m00dvwargr') + self.callnoderpc( + "createwallet", [new_wallet_name, False, True, "", False, False] + ) + self.callnoderpc("sethdseed", [True, test_wif], wallet=new_wallet_name) + addr = self.callnoderpc("getnewaddress", wallet=new_wallet_name) + self.callnoderpc("unloadwallet", [new_wallet_name]) + assert addr == "bcrt1qps7hnjd866e9ynxadgseprkc2l56m00dvwargr" self.swap_clients[0].initialiseWallet(Coins.BTC, raise_errors=True) assert self.swap_clients[0].checkWalletSeed(Coins.BTC) is True for i in range(1500): - ci.rpc_wallet('getnewaddress') + ci.rpc_wallet("getnewaddress") assert self.swap_clients[0].checkWalletSeed(Coins.BTC) is True - rv = read_json_api(1800, 'getcoinseed', {'coin': 'XMR'}) - assert (rv['address'] == '47H7UDLzYEsR28BWttxp59SP1UVSxs4VKDJYSfmz7Wd4Fue5VWuoV9x9eejunwzVSmHWN37gBkaAPNf9VD4bTvwQKsBVWyK') + rv = read_json_api(1800, "getcoinseed", {"coin": "XMR"}) + assert ( + rv["address"] + == "47H7UDLzYEsR28BWttxp59SP1UVSxs4VKDJYSfmz7Wd4Fue5VWuoV9x9eejunwzVSmHWN37gBkaAPNf9VD4bTvwQKsBVWyK" + ) def test_008_gettxout(self): - logging.info('---------- Test {} gettxout'.format(self.test_coin_from.name)) + logging.info("---------- Test {} gettxout".format(self.test_coin_from.name)) swap_client = self.swap_clients[0] ci = swap_client.ci(self.test_coin_from) - addr_1 = ci.rpc_wallet('getnewaddress', ['gettxout test 1',]) - txid = ci.rpc_wallet('sendtoaddress', [addr_1, 1.0]) + addr_1 = ci.rpc_wallet( + "getnewaddress", + [ + "gettxout test 1", + ], + ) + txid = ci.rpc_wallet("sendtoaddress", [addr_1, 1.0]) assert len(txid) == 64 self.mineBlock() - unspents = ci.rpc_wallet('listunspent', [0, 999999999, [addr_1,]]) - assert (len(unspents) == 1) + unspents = ci.rpc_wallet( + "listunspent", + [ + 0, + 999999999, + [ + addr_1, + ], + ], + ) + assert len(unspents) == 1 utxo = unspents[0] - txout = ci.rpc('gettxout', [utxo['txid'], utxo['vout']]) - if 'address' in txout['scriptPubKey']: - assert (addr_1 == txout['scriptPubKey']['address']) + txout = ci.rpc("gettxout", [utxo["txid"], utxo["vout"]]) + if "address" in txout["scriptPubKey"]: + assert addr_1 == txout["scriptPubKey"]["address"] else: - assert (addr_1 in txout['scriptPubKey']['addresses']) + assert addr_1 in txout["scriptPubKey"]["addresses"] # Spend - addr_2 = ci.rpc_wallet('getnewaddress', ['gettxout test 2',]) - tx_funded = ci.rpc('createrawtransaction', [[{'txid': utxo['txid'], 'vout': utxo['vout']}], {addr_2: 0.99}]) - tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded,])['hex'] - ci.rpc('sendrawtransaction', [tx_signed,]) + addr_2 = ci.rpc_wallet( + "getnewaddress", + [ + "gettxout test 2", + ], + ) + tx_funded = ci.rpc( + "createrawtransaction", + [[{"txid": utxo["txid"], "vout": utxo["vout"]}], {addr_2: 0.99}], + ) + tx_signed = ci.rpc_wallet( + "signrawtransactionwithwallet", + [ + tx_funded, + ], + )["hex"] + ci.rpc( + "sendrawtransaction", + [ + tx_signed, + ], + ) # utxo should be unavailable when spent in the mempool - txout = ci.rpc('gettxout', [utxo['txid'], utxo['vout']]) - assert (txout is None) + txout = ci.rpc("gettxout", [utxo["txid"], utxo["vout"]]) + assert txout is None def test_009_scantxoutset(self): - logging.info('---------- Test {} scantxoutset'.format(self.test_coin_from.name)) + logging.info("---------- Test {} scantxoutset".format(self.test_coin_from.name)) ci = self.swap_clients[0].ci(self.test_coin_from) - addr_1 = ci.rpc_wallet('getnewaddress', ['scantxoutset test', ]) - txid = ci.rpc_wallet('sendtoaddress', [addr_1, 1.0]) + addr_1 = ci.rpc_wallet( + "getnewaddress", + [ + "scantxoutset test", + ], + ) + txid = ci.rpc_wallet("sendtoaddress", [addr_1, 1.0]) assert len(txid) == 64 self.mineBlock() - ro = ci.rpc('scantxoutset', ['start', ['addr({})'.format(addr_1)]]) - assert (len(ro['unspents']) == 1) - assert (ro['unspents'][0]['txid'] == txid) + ro = ci.rpc("scantxoutset", ["start", ["addr({})".format(addr_1)]]) + assert len(ro["unspents"]) == 1 + assert ro["unspents"][0]["txid"] == txid def test_010_txn_size(self): - logging.info('---------- Test {} txn_size'.format(self.test_coin_from.name)) + logging.info("---------- Test {} txn_size".format(self.test_coin_from.name)) swap_clients = self.swap_clients ci = swap_clients[0].ci(self.test_coin_from) @@ -701,7 +1139,7 @@ class BasicSwapTest(TestFunctions): amount: int = ci.make_int(random.uniform(0.1, 2.0), r=1) # Record unspents before createSCLockTx as the used ones will be locked - unspents = ci.rpc_wallet('listunspent') + unspents = ci.rpc_wallet("listunspent") # fee_rate is in sats/kvB fee_rate: int = 1000 @@ -717,62 +1155,63 @@ class BasicSwapTest(TestFunctions): lock_tx = ci.fundSCLockTx(lock_tx, fee_rate) lock_tx = ci.signTxWithWallet(lock_tx) - unspents_after = ci.rpc_wallet('listunspent') - assert (len(unspents) > len(unspents_after)) + unspents_after = ci.rpc_wallet("listunspent") + assert len(unspents) > len(unspents_after) - tx_decoded = ci.rpc('decoderawtransaction', [lock_tx.hex()]) - txid = tx_decoded['txid'] + tx_decoded = ci.rpc("decoderawtransaction", [lock_tx.hex()]) + txid = tx_decoded["txid"] - vsize = tx_decoded['vsize'] + vsize = tx_decoded["vsize"] expect_fee_int = round(fee_rate * vsize / 1000) - expect_fee = ci.format_amount(expect_fee_int) out_value: int = 0 - for txo in tx_decoded['vout']: - if 'value' in txo: - out_value += ci.make_int(txo['value']) + for txo in tx_decoded["vout"]: + if "value" in txo: + out_value += ci.make_int(txo["value"]) in_value: int = 0 - for txi in tx_decoded['vin']: + for txi in tx_decoded["vin"]: for utxo in unspents: - if 'vout' not in utxo: + if "vout" not in utxo: continue - if utxo['txid'] == txi['txid'] and utxo['vout'] == txi['vout']: - in_value += ci.make_int(utxo['amount']) + if utxo["txid"] == txi["txid"] and utxo["vout"] == txi["vout"]: + in_value += ci.make_int(utxo["amount"]) break fee_value = in_value - out_value - ci.rpc('sendrawtransaction', [lock_tx.hex()]) - rv = ci.rpc_wallet('gettransaction', [txid]) - wallet_tx_fee = -ci.make_int(rv['fee']) + ci.rpc("sendrawtransaction", [lock_tx.hex()]) + rv = ci.rpc_wallet("gettransaction", [txid]) + wallet_tx_fee = -ci.make_int(rv["fee"]) - assert (wallet_tx_fee == fee_value) - assert (wallet_tx_fee == expect_fee_int) + assert wallet_tx_fee == fee_value + assert wallet_tx_fee == expect_fee_int addr_out = ci.getNewAddress(True) pkh_out = ci.decodeAddress(addr_out) fee_info = {} - lock_spend_tx = ci.createSCLockSpendTx(lock_tx, lock_tx_script, pkh_out, fee_rate, fee_info=fee_info) - vsize_estimated: int = fee_info['vsize'] + lock_spend_tx = ci.createSCLockSpendTx( + lock_tx, lock_tx_script, pkh_out, fee_rate, fee_info=fee_info + ) + vsize_estimated: int = fee_info["vsize"] - tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()]) - txid = tx_decoded['txid'] + tx_decoded = ci.rpc("decoderawtransaction", [lock_spend_tx.hex()]) + txid = tx_decoded["txid"] witness_stack = [ - b'', + b"", ci.signTx(a, lock_spend_tx, 0, lock_tx_script, amount), ci.signTx(b, lock_spend_tx, 0, lock_tx_script, amount), lock_tx_script, ] lock_spend_tx = ci.setTxSignature(lock_spend_tx, witness_stack) - tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()]) - vsize_actual: int = tx_decoded['vsize'] + tx_decoded = ci.rpc("decoderawtransaction", [lock_spend_tx.hex()]) + vsize_actual: int = tx_decoded["vsize"] - assert (vsize_actual <= vsize_estimated and vsize_estimated - vsize_actual < 4) - assert (ci.rpc('sendrawtransaction', [lock_spend_tx.hex()]) == txid) + assert vsize_actual <= vsize_estimated and vsize_estimated - vsize_actual < 4 + assert ci.rpc("sendrawtransaction", [lock_spend_tx.hex()]) == txid expect_vsize: int = ci.xmr_swap_a_lock_spend_tx_vsize() - assert (expect_vsize >= vsize_actual) - assert (expect_vsize - vsize_actual < 10) + assert expect_vsize >= vsize_actual + assert expect_vsize - vsize_actual < 10 # Test chain b (no-script) lock tx size v = ci.getNewSecretKey() @@ -781,111 +1220,199 @@ class BasicSwapTest(TestFunctions): lock_tx_b_txid = ci.publishBLockTx(v, S, amount, fee_rate) addr_out = ci.getNewAddress(True) - lock_tx_b_spend_txid = ci.spendBLockTx(lock_tx_b_txid, addr_out, v, s, amount, fee_rate, 0) + lock_tx_b_spend_txid = ci.spendBLockTx( + lock_tx_b_txid, addr_out, v, s, amount, fee_rate, 0 + ) lock_tx_b_spend = ci.getTransaction(lock_tx_b_spend_txid) if lock_tx_b_spend is None: lock_tx_b_spend = ci.getWalletTransaction(lock_tx_b_spend_txid) - lock_tx_b_spend_decoded = ci.rpc('decoderawtransaction', [lock_tx_b_spend.hex()]) + lock_tx_b_spend_decoded = ci.rpc( + "decoderawtransaction", [lock_tx_b_spend.hex()] + ) expect_vsize: int = ci.xmr_swap_b_lock_spend_tx_vsize() - assert (expect_vsize >= lock_tx_b_spend_decoded['vsize']) - assert (expect_vsize - lock_tx_b_spend_decoded['vsize'] < 10) + assert expect_vsize >= lock_tx_b_spend_decoded["vsize"] + assert expect_vsize - lock_tx_b_spend_decoded["vsize"] < 10 def test_011_p2sh(self): # Not used in bsx for native-segwit coins - logging.info('---------- Test {} p2sh'.format(self.test_coin_from.name)) + logging.info("---------- Test {} p2sh".format(self.test_coin_from.name)) - swap_clients = self.swap_clients ci = self.swap_clients[0].ci(self.test_coin_from) - script = CScript([2, 2, OP_EQUAL, ]) + script = CScript( + [ + 2, + 2, + OP_EQUAL, + ] + ) script_dest = ci.get_p2sh_script_pubkey(script) tx = CTransaction() tx.nVersion = ci.txVersion() tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest)) tx_hex = ToHex(tx) - tx_funded = ci.rpc_wallet('fundrawtransaction', [tx_hex]) - utxo_pos = 0 if tx_funded['changepos'] == 1 else 1 - tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex'] - txid = ci.rpc('sendrawtransaction', [tx_signed, ]) + tx_funded = ci.rpc_wallet("fundrawtransaction", [tx_hex]) + utxo_pos = 0 if tx_funded["changepos"] == 1 else 1 + tx_signed = ci.rpc_wallet( + "signrawtransactionwithwallet", + [ + tx_funded["hex"], + ], + )["hex"] + txid = ci.rpc( + "sendrawtransaction", + [ + tx_signed, + ], + ) - addr_out = ci.rpc_wallet('getnewaddress', ['csv test', 'bech32']) + addr_out = ci.rpc_wallet("getnewaddress", ["csv test", "bech32"]) pkh = ci.decodeSegwitAddress(addr_out) script_out = ci.getScriptForPubkeyHash(pkh) # Double check output type - prev_tx = ci.rpc('decoderawtransaction', [tx_signed, ]) - assert (prev_tx['vout'][utxo_pos]['scriptPubKey']['type'] == 'scripthash') + prev_tx = ci.rpc( + "decoderawtransaction", + [ + tx_signed, + ], + ) + assert prev_tx["vout"][utxo_pos]["scriptPubKey"]["type"] == "scripthash" tx_spend = CTransaction() tx_spend.nVersion = ci.txVersion() - tx_spend.vin.append(CTxIn(COutPoint(int(txid, 16), utxo_pos), - scriptSig=CScript([script,]))) + tx_spend.vin.append( + CTxIn( + COutPoint(int(txid, 16), utxo_pos), + scriptSig=CScript( + [ + script, + ] + ), + ) + ) tx_spend.vout.append(ci.txoType()(ci.make_int(1.0999), script_out)) tx_spend_hex = ToHex(tx_spend) - txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ]) + txid = ci.rpc( + "sendrawtransaction", + [ + tx_spend_hex, + ], + ) self.mineBlock(1) - ro = ci.rpc_wallet('listreceivedbyaddress', [0, ]) + ro = ci.rpc_wallet( + "listreceivedbyaddress", + [ + 0, + ], + ) sum_addr = 0 for entry in ro: - if entry['address'] == addr_out: - sum_addr += entry['amount'] - assert (sum_addr == 1.0999) + if entry["address"] == addr_out: + sum_addr += entry["amount"] + assert sum_addr == 1.0999 # Ensure tx was mined - tx_wallet = ci.rpc_wallet('gettransaction', [txid, ]) - assert (len(tx_wallet['blockhash']) == 64) + tx_wallet = ci.rpc_wallet( + "gettransaction", + [ + txid, + ], + ) + assert len(tx_wallet["blockhash"]) == 64 def test_012_p2sh_p2wsh(self): # Not used in bsx for native-segwit coins - logging.info('---------- Test {} p2sh-p2wsh'.format(self.test_coin_from.name)) + logging.info("---------- Test {} p2sh-p2wsh".format(self.test_coin_from.name)) - swap_clients = self.swap_clients ci = self.swap_clients[0].ci(self.test_coin_from) - script = CScript([2, 2, OP_EQUAL, ]) + script = CScript( + [ + 2, + 2, + OP_EQUAL, + ] + ) script_dest = ci.getP2SHP2WSHDest(script) tx = CTransaction() tx.nVersion = ci.txVersion() tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest)) tx_hex = ToHex(tx) - tx_funded = ci.rpc_wallet('fundrawtransaction', [tx_hex]) - utxo_pos = 0 if tx_funded['changepos'] == 1 else 1 - tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex'] - txid = ci.rpc('sendrawtransaction', [tx_signed, ]) + tx_funded = ci.rpc_wallet("fundrawtransaction", [tx_hex]) + utxo_pos = 0 if tx_funded["changepos"] == 1 else 1 + tx_signed = ci.rpc_wallet( + "signrawtransactionwithwallet", + [ + tx_funded["hex"], + ], + )["hex"] + txid = ci.rpc( + "sendrawtransaction", + [ + tx_signed, + ], + ) - addr_out = ci.rpc_wallet('getnewaddress', ['csv test', 'bech32']) + addr_out = ci.rpc_wallet("getnewaddress", ["csv test", "bech32"]) pkh = ci.decodeSegwitAddress(addr_out) script_out = ci.getScriptForPubkeyHash(pkh) # Double check output type - prev_tx = ci.rpc('decoderawtransaction', [tx_signed, ]) - assert (prev_tx['vout'][utxo_pos]['scriptPubKey']['type'] == 'scripthash') + prev_tx = ci.rpc( + "decoderawtransaction", + [ + tx_signed, + ], + ) + assert prev_tx["vout"][utxo_pos]["scriptPubKey"]["type"] == "scripthash" tx_spend = CTransaction() tx_spend.nVersion = ci.txVersion() - tx_spend.vin.append(CTxIn(COutPoint(int(txid, 16), utxo_pos), - scriptSig=ci.getP2SHP2WSHScriptSig(script))) + tx_spend.vin.append( + CTxIn( + COutPoint(int(txid, 16), utxo_pos), + scriptSig=ci.getP2SHP2WSHScriptSig(script), + ) + ) tx_spend.vout.append(ci.txoType()(ci.make_int(1.0999), script_out)) tx_spend.wit.vtxinwit.append(CTxInWitness()) - tx_spend.wit.vtxinwit[0].scriptWitness.stack = [script, ] + tx_spend.wit.vtxinwit[0].scriptWitness.stack = [ + script, + ] tx_spend_hex = ToHex(tx_spend) - txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ]) + txid = ci.rpc( + "sendrawtransaction", + [ + tx_spend_hex, + ], + ) self.mineBlock(1) - ro = ci.rpc_wallet('listreceivedbyaddress', [0, ]) + ro = ci.rpc_wallet( + "listreceivedbyaddress", + [ + 0, + ], + ) sum_addr = 0 for entry in ro: - if entry['address'] == addr_out: - sum_addr += entry['amount'] - assert (sum_addr == 1.0999) + if entry["address"] == addr_out: + sum_addr += entry["amount"] + assert sum_addr == 1.0999 # Ensure tx was mined - tx_wallet = ci.rpc_wallet('gettransaction', [txid, ]) - assert (len(tx_wallet['blockhash']) == 64) + tx_wallet = ci.rpc_wallet( + "gettransaction", + [ + txid, + ], + ) + assert len(tx_wallet["blockhash"]) == 64 def test_01_a_full_swap(self): if not self.has_segwit: @@ -948,14 +1475,18 @@ class BasicSwapTest(TestFunctions): def test_03_e_follower_recover_a_lock_tx_mercy_release(self): if not self.has_segwit: return - self.do_test_03_follower_recover_a_lock_tx(self.test_coin_from, Coins.XMR, with_mercy=True) + self.do_test_03_follower_recover_a_lock_tx( + self.test_coin_from, Coins.XMR, with_mercy=True + ) def test_03_f_follower_recover_a_lock_tx_mercy_release_reverse(self): if not self.has_segwit: return self.prepare_balance(Coins.XMR, 100.0, 1800, 1801) self.prepare_balance(self.test_coin_from, 100.0, 1801, 1800) - self.do_test_03_follower_recover_a_lock_tx(Coins.XMR, self.test_coin_from, with_mercy=True) + self.do_test_03_follower_recover_a_lock_tx( + Coins.XMR, self.test_coin_from, with_mercy=True + ) def test_04_a_follower_recover_b_lock_tx(self): if not self.has_segwit: @@ -998,43 +1529,60 @@ class BasicSwapTest(TestFunctions): def test_06_preselect_inputs(self): tla_from = self.test_coin_from.name - logging.info('---------- Test {} Preselected inputs'.format(tla_from)) + logging.info("---------- Test {} Preselected inputs".format(tla_from)) swap_clients = self.swap_clients self.prepare_balance(self.test_coin_from, 100.0, 1802, 1800) - js_w2 = read_json_api(1802, 'wallets') - assert (float(js_w2[tla_from]['balance']) >= 100.0) + js_w2 = read_json_api(1802, "wallets") + assert float(js_w2[tla_from]["balance"]) >= 100.0 - js_w2 = read_json_api(1802, 'wallets') + js_w2 = read_json_api(1802, "wallets") post_json = { - 'value': float(js_w2[tla_from]['balance']), - 'address': read_json_api(1802, 'wallets/{}/nextdepositaddr'.format(tla_from.lower())), - 'subfee': True, + "value": float(js_w2[tla_from]["balance"]), + "address": read_json_api( + 1802, "wallets/{}/nextdepositaddr".format(tla_from.lower()) + ), + "subfee": True, } - json_rv = read_json_api(1802, 'wallets/{}/withdraw'.format(tla_from.lower()), post_json) - wait_for_balance(test_delay_event, 'http://127.0.0.1:1802/json/wallets/{}'.format(tla_from.lower()), 'balance', 10.0) - assert (len(json_rv['txid']) == 64) + json_rv = read_json_api( + 1802, "wallets/{}/withdraw".format(tla_from.lower()), post_json + ) + wait_for_balance( + test_delay_event, + "http://127.0.0.1:1802/json/wallets/{}".format(tla_from.lower()), + "balance", + 10.0, + ) + assert len(json_rv["txid"]) == 64 # Create prefunded ITX ci = swap_clients[2].ci(self.test_coin_from) ci_to = swap_clients[2].ci(Coins.XMR) pi = swap_clients[2].pi(SwapTypes.XMR_SWAP) - js_w2 = read_json_api(1802, 'wallets') - swap_value = ci.make_int(js_w2[tla_from]['balance']) - assert (swap_value > ci.make_int(95)) + js_w2 = read_json_api(1802, "wallets") + swap_value = ci.make_int(js_w2[tla_from]["balance"]) + assert swap_value > ci.make_int(95) itx = pi.getFundedInitiateTxTemplate(ci, swap_value, True) itx_decoded = ci.describeTx(itx.hex()) n = pi.findMockVout(ci, itx_decoded) - value_after_subfee = ci.make_int(itx_decoded['vout'][n]['value']) - assert (value_after_subfee < swap_value) + value_after_subfee = ci.make_int(itx_decoded["vout"][n]["value"]) + assert value_after_subfee < swap_value swap_value = value_after_subfee wait_for_unspent(test_delay_event, ci, swap_value) - extra_options = {'prefunded_itx': itx} + extra_options = {"prefunded_itx": itx} rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) - offer_id = swap_clients[2].postOffer(self.test_coin_from, Coins.XMR, swap_value, rate_swap, swap_value, SwapTypes.XMR_SWAP, extra_options=extra_options) + offer_id = swap_clients[2].postOffer( + self.test_coin_from, + Coins.XMR, + swap_value, + rate_swap, + swap_value, + SwapTypes.XMR_SWAP, + extra_options=extra_options, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -1043,23 +1591,45 @@ class BasicSwapTest(TestFunctions): wait_for_bid(test_delay_event, swap_clients[2], bid_id, BidStates.BID_RECEIVED) swap_clients[2].acceptBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[2], bid_id, BidStates.SWAP_COMPLETED, wait_for=120) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=120) + wait_for_bid( + test_delay_event, + swap_clients[2], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=120, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=120, + ) # Verify expected inputs were used bid, _, _, _, _ = swap_clients[2].getXmrBidAndOffer(bid_id) - assert (bid.xmr_a_lock_tx) - wtx = ci.rpc_wallet('gettransaction', [bid.xmr_a_lock_tx.txid.hex(),]) - itx_after = ci.describeTx(wtx['hex']) - assert (len(itx_after['vin']) == len(itx_decoded['vin'])) - for i, txin in enumerate(itx_decoded['vin']): - txin_after = itx_after['vin'][i] - assert (txin['txid'] == txin_after['txid']) - assert (txin['vout'] == txin_after['vout']) + assert bid.xmr_a_lock_tx + wtx = ci.rpc_wallet( + "gettransaction", + [ + bid.xmr_a_lock_tx.txid.hex(), + ], + ) + itx_after = ci.describeTx(wtx["hex"]) + assert len(itx_after["vin"]) == len(itx_decoded["vin"]) + for i, txin in enumerate(itx_decoded["vin"]): + txin_after = itx_after["vin"][i] + assert txin["txid"] == txin_after["txid"] + assert txin["vout"] == txin_after["vout"] def test_07_expire_stuck_accepted(self): coin_from, coin_to = (self.test_coin_from, Coins.XMR) - logging.info('---------- Test {} to {} expires bid stuck on accepted'.format(coin_from.name, coin_to.name)) + logging.info( + "---------- Test {} to {} expires bid stuck on accepted".format( + coin_from.name, coin_to.name + ) + ) swap_clients = self.swap_clients ci_to = swap_clients[0].ci(coin_to) @@ -1067,7 +1637,15 @@ class BasicSwapTest(TestFunctions): amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) - offer_id = swap_clients[0].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, auto_accept_bids=True) + offer_id = swap_clients[0].postOffer( + coin_from, + coin_to, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + auto_accept_bids=True, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) bid_id = swap_clients[1].postXmrBid(offer_id, amt_swap) swap_clients[1].abandonBid(bid_id) @@ -1078,14 +1656,20 @@ class BasicSwapTest(TestFunctions): old_check_expired_seconds = swap_clients[0].check_expired_seconds swap_clients[0].check_expired_seconds = 1 - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_TIMEDOUT, wait_for=180) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_TIMEDOUT, + wait_for=180, + ) finally: swap_clients[0].check_expired_seconds = old_check_expired_seconds swap_clients[0].setMockTimeOffset(0) def test_08_insufficient_funds(self): tla_from = self.test_coin_from.name - logging.info('---------- Test {} Insufficient Funds'.format(tla_from)) + logging.info("---------- Test {} Insufficient Funds".format(tla_from)) swap_clients = self.swap_clients coin_from = self.test_coin_from coin_to = Coins.XMR @@ -1099,24 +1683,45 @@ class BasicSwapTest(TestFunctions): ci_from = swap_clients[id_offerer].ci(coin_from) ci_to = swap_clients[id_bidder].ci(coin_to) - jsw = read_json_api(1800 + id_offerer, 'wallets') + jsw = read_json_api(1800 + id_offerer, "wallets") balance_from_before: float = self.getBalance(jsw, coin_from) amt_swap: int = ci_from.make_int(balance_from_before, r=1) rate_swap: int = ci_to.make_int(2.0, r=1) - offer_id = swap_clients[id_offerer].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, auto_accept_bids=True) + offer_id = swap_clients[id_offerer].postOffer( + coin_from, + coin_to, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + auto_accept_bids=True, + ) wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id) bid_id = swap_clients[id_bidder].postXmrBid(offer_id, amt_swap) - event = wait_for_event(test_delay_event, swap_clients[id_offerer], Concepts.BID, bid_id, event_type=EventLogTypes.ERROR, wait_for=60) - assert ('Insufficient funds' in event.event_msg) + event = wait_for_event( + test_delay_event, + swap_clients[id_offerer], + Concepts.BID, + bid_id, + event_type=EventLogTypes.ERROR, + wait_for=60, + ) + assert "Insufficient funds" in event.event_msg - wait_for_bid(test_delay_event, swap_clients[id_offerer], bid_id, BidStates.BID_RECEIVED, wait_for=20) + wait_for_bid( + test_delay_event, + swap_clients[id_offerer], + bid_id, + BidStates.BID_RECEIVED, + wait_for=20, + ) def test_08_insufficient_funds_rev(self): tla_from = self.test_coin_from.name - logging.info('---------- Test {} Insufficient Funds (reverse)'.format(tla_from)) + logging.info("---------- Test {} Insufficient Funds (reverse)".format(tla_from)) swap_clients = self.swap_clients coin_from = Coins.XMR coin_to = self.test_coin_from @@ -1130,22 +1735,44 @@ class BasicSwapTest(TestFunctions): ci_from = swap_clients[id_offerer].ci(coin_from) ci_to = swap_clients[id_bidder].ci(coin_to) - jsw = read_json_api(1800 + id_bidder, 'wallets') + jsw = read_json_api(1800 + id_bidder, "wallets") balance_to_before: float = self.getBalance(jsw, coin_to) amt_swap: int = ci_from.make_int(balance_to_before, r=1) rate_swap: int = ci_to.make_int(1.0, r=1) amt_swap -= 1 - offer_id = swap_clients[id_offerer].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, auto_accept_bids=True) + offer_id = swap_clients[id_offerer].postOffer( + coin_from, + coin_to, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + auto_accept_bids=True, + ) wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id) bid_id = swap_clients[id_bidder].postXmrBid(offer_id, amt_swap) - event = wait_for_event(test_delay_event, swap_clients[id_bidder], Concepts.BID, bid_id, event_type=EventLogTypes.ERROR, wait_for=60) - assert ('Insufficient funds' in event.event_msg) + event = wait_for_event( + test_delay_event, + swap_clients[id_bidder], + Concepts.BID, + bid_id, + event_type=EventLogTypes.ERROR, + wait_for=60, + ) + assert "Insufficient funds" in event.event_msg - wait_for_bid(test_delay_event, swap_clients[id_bidder], bid_id, BidStates.BID_ERROR, sent=True, wait_for=20) + wait_for_bid( + test_delay_event, + swap_clients[id_bidder], + bid_id, + BidStates.BID_ERROR, + sent=True, + wait_for=20, + ) class TestBTC(BasicSwapTest): @@ -1156,46 +1783,56 @@ class TestBTC(BasicSwapTest): def test_009_wallet_encryption(self): - for coin in ('btc', 'part', 'xmr'): - jsw = read_json_api(1800, f'wallets/{coin}') - assert (jsw['encrypted'] is False) - assert (jsw['locked'] is False) + for coin in ("btc", "part", "xmr"): + jsw = read_json_api(1800, f"wallets/{coin}") + assert jsw["encrypted"] is False + assert jsw["locked"] is False - read_json_api(1800, 'setpassword', {'oldpassword': '', 'newpassword': 'notapassword123'}) + read_json_api( + 1800, "setpassword", {"oldpassword": "", "newpassword": "notapassword123"} + ) # Entire system is locked with Particl wallet - jsw = read_json_api(1800, 'wallets/btc') - assert ('Coin must be unlocked' in jsw['error']) + jsw = read_json_api(1800, "wallets/btc") + assert "Coin must be unlocked" in jsw["error"] - read_json_api(1800, 'unlock', {'coin': 'part', 'password': 'notapassword123'}) + read_json_api(1800, "unlock", {"coin": "part", "password": "notapassword123"}) - for coin in ('btc', 'xmr'): - jsw = read_json_api(1800, f'wallets/{coin}') - assert (jsw['encrypted'] is True) - assert (jsw['locked'] is True) + for coin in ("btc", "xmr"): + jsw = read_json_api(1800, f"wallets/{coin}") + assert jsw["encrypted"] is True + assert jsw["locked"] is True - read_json_api(1800, 'lock', {'coin': 'part'}) - jsw = read_json_api(1800, 'wallets/part') - assert ('Coin must be unlocked' in jsw['error']) + read_json_api(1800, "lock", {"coin": "part"}) + jsw = read_json_api(1800, "wallets/part") + assert "Coin must be unlocked" in jsw["error"] - read_json_api(1800, 'setpassword', {'oldpassword': 'notapassword123', 'newpassword': 'notapassword456'}) - read_json_api(1800, 'unlock', {'password': 'notapassword456'}) + read_json_api( + 1800, + "setpassword", + {"oldpassword": "notapassword123", "newpassword": "notapassword456"}, + ) + read_json_api(1800, "unlock", {"password": "notapassword456"}) - for coin in ('part', 'btc', 'xmr'): - jsw = read_json_api(1800, f'wallets/{coin}') - assert (jsw['encrypted'] is True) - assert (jsw['locked'] is False) + for coin in ("part", "btc", "xmr"): + jsw = read_json_api(1800, f"wallets/{coin}") + assert jsw["encrypted"] is True + assert jsw["locked"] is False def test_01_full_swap(self): abandon_all_swaps(test_delay_event, self.swap_clients[0]) wait_for_none_active(test_delay_event, 1800) - js_0 = read_json_api(1800, 'wallets') - if not js_0['PART']['encrypted']: - read_json_api(1800, 'setpassword', {'oldpassword': '', 'newpassword': 'notapassword123'}) - read_json_api(1800, 'unlock', {'password': 'notapassword123'}) - js_0 = read_json_api(1800, 'wallets') - assert (js_0['PART']['encrypted'] is True) - assert (js_0['PART']['locked'] is False) + js_0 = read_json_api(1800, "wallets") + if not js_0["PART"]["encrypted"]: + read_json_api( + 1800, + "setpassword", + {"oldpassword": "", "newpassword": "notapassword123"}, + ) + read_json_api(1800, "unlock", {"password": "notapassword123"}) + js_0 = read_json_api(1800, "wallets") + assert js_0["PART"]["encrypted"] is True + assert js_0["PART"]["locked"] is False super().test_01_a_full_swap() @@ -1229,19 +1866,27 @@ class TestBTC_PARTB(TestFunctions): def test_03_a_follower_recover_a_lock_tx(self): self.prepare_balance(self.test_coin_to, 100.0, 1801, 1800) - self.do_test_03_follower_recover_a_lock_tx(self.test_coin_from, self.test_coin_to) + self.do_test_03_follower_recover_a_lock_tx( + self.test_coin_from, self.test_coin_to + ) def test_03_b_follower_recover_a_lock_tx_reverse(self): self.prepare_balance(self.test_coin_to, 100.0, 1800, 1800) - self.do_test_03_follower_recover_a_lock_tx(self.test_coin_to, self.test_coin_from, lock_value=12) + self.do_test_03_follower_recover_a_lock_tx( + self.test_coin_to, self.test_coin_from, lock_value=12 + ) def test_04_a_follower_recover_b_lock_tx(self): self.prepare_balance(self.test_coin_to, 100.0, 1801, 1800) - self.do_test_04_follower_recover_b_lock_tx(self.test_coin_from, self.test_coin_to) + self.do_test_04_follower_recover_b_lock_tx( + self.test_coin_from, self.test_coin_to + ) def test_04_b_follower_recover_b_lock_tx_reverse(self): self.prepare_balance(self.test_coin_to, 100.0, 1800, 1800) - self.do_test_04_follower_recover_b_lock_tx(self.test_coin_to, self.test_coin_from) + self.do_test_04_follower_recover_b_lock_tx( + self.test_coin_to, self.test_coin_from + ) class TestBTC_PARTA(TestBTC_PARTB): @@ -1249,5 +1894,5 @@ class TestBTC_PARTA(TestBTC_PARTB): test_coin_to = Coins.PART_ANON -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/test_ltc_xmr.py b/tests/basicswap/test_ltc_xmr.py index d78ee88..3bdb656 100644 --- a/tests/basicswap/test_ltc_xmr.py +++ b/tests/basicswap/test_ltc_xmr.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021-2024 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -40,64 +41,112 @@ class TestLTC(BasicSwapTest): base_rpc_port = LTC_BASE_RPC_PORT def mineBlock(self, num_blocks=1): - self.callnoderpc('generatetoaddress', [num_blocks, self.ltc_addr]) + self.callnoderpc("generatetoaddress", [num_blocks, self.ltc_addr]) def check_softfork_active(self, feature_name): - deploymentinfo = self.callnoderpc('getblockchaininfo') - assert (deploymentinfo['softforks'][feature_name]['active'] is True) + deploymentinfo = self.callnoderpc("getblockchaininfo") + assert deploymentinfo["softforks"][feature_name]["active"] is True def test_001_nested_segwit(self): - logging.info('---------- Test {} p2sh nested segwit'.format(self.test_coin_from.name)) - logging.info('Skipped') + logging.info( + "---------- Test {} p2sh nested segwit".format(self.test_coin_from.name) + ) + logging.info("Skipped") def test_002_native_segwit(self): - logging.info('---------- Test {} p2sh native segwit'.format(self.test_coin_from.name)) + logging.info( + "---------- Test {} p2sh native segwit".format(self.test_coin_from.name) + ) ci = self.swap_clients[0].ci(self.test_coin_from) - addr_segwit = ci.rpc_wallet('getnewaddress', ['segwit test', 'bech32']) - addr_info = ci.rpc_wallet('getaddressinfo', [addr_segwit, ]) - assert addr_info['iswitness'] is True + addr_segwit = ci.rpc_wallet("getnewaddress", ["segwit test", "bech32"]) + addr_info = ci.rpc_wallet( + "getaddressinfo", + [ + addr_segwit, + ], + ) + assert addr_info["iswitness"] is True - txid = ci.rpc_wallet('sendtoaddress', [addr_segwit, 1.0]) + txid = ci.rpc_wallet("sendtoaddress", [addr_segwit, 1.0]) assert len(txid) == 64 - tx_wallet = ci.rpc_wallet('gettransaction', [txid, ])['hex'] - tx = ci.rpc('decoderawtransaction', [tx_wallet, ]) + tx_wallet = ci.rpc_wallet( + "gettransaction", + [ + txid, + ], + )["hex"] + tx = ci.rpc( + "decoderawtransaction", + [ + tx_wallet, + ], + ) self.mineBlock() - ro = ci.rpc('scantxoutset', ['start', ['addr({})'.format(addr_segwit)]]) - assert (len(ro['unspents']) == 1) - assert (ro['unspents'][0]['txid'] == txid) + ro = ci.rpc("scantxoutset", ["start", ["addr({})".format(addr_segwit)]]) + assert len(ro["unspents"]) == 1 + assert ro["unspents"][0]["txid"] == txid prevout_n = -1 - for txo in tx['vout']: - if addr_segwit in txo['scriptPubKey']['addresses']: - prevout_n = txo['n'] + for txo in tx["vout"]: + if addr_segwit in txo["scriptPubKey"]["addresses"]: + prevout_n = txo["n"] break assert prevout_n > -1 - tx_funded = ci.rpc('createrawtransaction', [[{'txid': txid, 'vout': prevout_n}], {addr_segwit: 0.99}]) - tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded, ])['hex'] - tx_funded_decoded = ci.rpc('decoderawtransaction', [tx_funded, ]) - tx_signed_decoded = ci.rpc('decoderawtransaction', [tx_signed, ]) - assert tx_funded_decoded['txid'] == tx_signed_decoded['txid'] + tx_funded = ci.rpc( + "createrawtransaction", + [[{"txid": txid, "vout": prevout_n}], {addr_segwit: 0.99}], + ) + tx_signed = ci.rpc_wallet( + "signrawtransactionwithwallet", + [ + tx_funded, + ], + )["hex"] + tx_funded_decoded = ci.rpc( + "decoderawtransaction", + [ + tx_funded, + ], + ) + tx_signed_decoded = ci.rpc( + "decoderawtransaction", + [ + tx_signed, + ], + ) + assert tx_funded_decoded["txid"] == tx_signed_decoded["txid"] def test_007_hdwallet(self): - logging.info('---------- Test {} hdwallet'.format(self.test_coin_from.name)) + logging.info("---------- Test {} hdwallet".format(self.test_coin_from.name)) - test_seed = '8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b' - test_wif = self.swap_clients[0].ci(self.test_coin_from).encodeKey(bytes.fromhex(test_seed)) + test_seed = "8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b" + test_wif = ( + self.swap_clients[0] + .ci(self.test_coin_from) + .encodeKey(bytes.fromhex(test_seed)) + ) new_wallet_name = random.randbytes(10).hex() - self.callnoderpc('createwallet', [new_wallet_name]) - self.callnoderpc('sethdseed', [True, test_wif], wallet=new_wallet_name) - addr = self.callnoderpc('getnewaddress', wallet=new_wallet_name) - self.callnoderpc('unloadwallet', [new_wallet_name]) - assert (addr == 'rltc1qps7hnjd866e9ynxadgseprkc2l56m00djr82la') + self.callnoderpc("createwallet", [new_wallet_name]) + self.callnoderpc("sethdseed", [True, test_wif], wallet=new_wallet_name) + addr = self.callnoderpc("getnewaddress", wallet=new_wallet_name) + self.callnoderpc("unloadwallet", [new_wallet_name]) + assert addr == "rltc1qps7hnjd866e9ynxadgseprkc2l56m00djr82la" def test_20_btc_coin(self): - logging.info('---------- Test BTC to {}'.format(self.test_coin_from.name)) + logging.info("---------- Test BTC to {}".format(self.test_coin_from.name)) swap_clients = self.swap_clients - offer_id = swap_clients[0].postOffer(Coins.BTC, self.test_coin_from, 100 * COIN, 0.1 * COIN, 100 * COIN, SwapTypes.SELLER_FIRST) + offer_id = swap_clients[0].postOffer( + Coins.BTC, + self.test_coin_from, + 100 * COIN, + 0.1 * COIN, + 100 * COIN, + SwapTypes.SELLER_FIRST, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -107,147 +156,187 @@ class TestLTC(BasicSwapTest): swap_clients[0].acceptBid(bid_id) wait_for_in_progress(test_delay_event, swap_clients[1], bid_id, sent=True) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=60, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=60, + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 def test_21_mweb(self): - logging.info('---------- Test MWEB {}'.format(self.test_coin_from.name)) + logging.info("---------- Test MWEB {}".format(self.test_coin_from.name)) swap_clients = self.swap_clients ci0 = swap_clients[0].ci(self.test_coin_from) ci1 = swap_clients[1].ci(self.test_coin_from) - mweb_addr_0 = ci0.rpc_wallet('getnewaddress', ['mweb addr test 0', 'mweb']) - mweb_addr_1 = ci1.rpc_wallet('getnewaddress', ['mweb addr test 1', 'mweb']) + mweb_addr_0 = ci0.rpc_wallet("getnewaddress", ["mweb addr test 0", "mweb"]) + mweb_addr_1 = ci1.rpc_wallet("getnewaddress", ["mweb addr test 1", "mweb"]) - addr_info0 = ci0.rpc_wallet('getaddressinfo', [mweb_addr_0,]) - assert (addr_info0['ismweb'] is True) + addr_info0 = ci0.rpc_wallet( + "getaddressinfo", + [ + mweb_addr_0, + ], + ) + assert addr_info0["ismweb"] is True - addr_info1 = ci1.rpc_wallet('getaddressinfo', [mweb_addr_1,]) - assert (addr_info1['ismweb'] is True) + addr_info1 = ci1.rpc_wallet( + "getaddressinfo", + [ + mweb_addr_1, + ], + ) + assert addr_info1["ismweb"] is True - trusted_before = ci0.rpc_wallet('getbalances')['mine']['trusted'] - ci0.rpc_wallet('sendtoaddress', [mweb_addr_0, 10.0]) - assert (trusted_before - float(ci0.rpc_wallet('getbalances')['mine']['trusted']) < 0.1) + trusted_before = ci0.rpc_wallet("getbalances")["mine"]["trusted"] + ci0.rpc_wallet("sendtoaddress", [mweb_addr_0, 10.0]) + assert ( + trusted_before - float(ci0.rpc_wallet("getbalances")["mine"]["trusted"]) + < 0.1 + ) try: pause_event.clear() # Stop mining - ci0.rpc_wallet('sendtoaddress', [mweb_addr_1, 10.0]) + ci0.rpc_wallet("sendtoaddress", [mweb_addr_1, 10.0]) found_unconfirmed: bool = False for i in range(20): test_delay_event.wait(1) - ltc_wallet = read_json_api(TEST_HTTP_PORT + 1, 'wallets/ltc') - if float(ltc_wallet['unconfirmed']) == 10.0: + ltc_wallet = read_json_api(TEST_HTTP_PORT + 1, "wallets/ltc") + if float(ltc_wallet["unconfirmed"]) == 10.0: found_unconfirmed = True break finally: pause_event.set() - assert (found_unconfirmed) + assert found_unconfirmed self.mineBlock() - txns = ci0.rpc_wallet('listtransactions') - - utxos = ci0.rpc_wallet('listunspent') - balances = ci0.rpc_wallet('getbalances') - wi = ci0.rpc_wallet('getwalletinfo') - - txid = ci0.rpc_wallet('sendtoaddress', [mweb_addr_1, 10.0]) + ci0.rpc_wallet("sendtoaddress", [mweb_addr_1, 10.0]) self.mineBlock() - txns = ci1.rpc_wallet('listtransactions') - - utxos = ci1.rpc_wallet('listunspent') - balances = ci1.rpc_wallet('getbalances') - wi = ci1.rpc_wallet('getwalletinfo') + utxos = ci1.rpc_wallet("listunspent") mweb_tx = None for utxo in utxos: - if utxo.get('address', '') == mweb_addr_1: + if utxo.get("address", "") == mweb_addr_1: mweb_tx = utxo - assert (mweb_tx is not None) + assert mweb_tx is not None - tx = ci1.rpc_wallet('gettransaction', [mweb_tx['txid'],]) - - blockhash = tx['blockhash'] - block3 = ci1.rpc('getblock', [blockhash, 3]) - block0 = ci1.rpc('getblock', [blockhash, 0]) - - require_amount: int = ci1.make_int(1) unspent_addr = ci1.getUnspentsByAddr() - assert (len(unspent_addr) > 0) + assert len(unspent_addr) > 0 for addr, _ in unspent_addr.items(): - if 'mweb1' in addr: - raise ValueError('getUnspentsByAddr should exclude mweb UTXOs.') + if "mweb1" in addr: + raise ValueError("getUnspentsByAddr should exclude mweb UTXOs.") # TODO def test_22_mweb_balance(self): - logging.info('---------- Test MWEB balance {}'.format(self.test_coin_from.name)) + logging.info("---------- Test MWEB balance {}".format(self.test_coin_from.name)) swap_clients = self.swap_clients ci_mweb = swap_clients[0].ci(Coins.LTC_MWEB) mweb_addr_0 = ci_mweb.getNewAddress() - addr_info0 = ci_mweb.rpc_wallet('getaddressinfo', [mweb_addr_0,]) - assert (addr_info0['ismweb'] is True) + addr_info0 = ci_mweb.rpc_wallet( + "getaddressinfo", + [ + mweb_addr_0, + ], + ) + assert addr_info0["ismweb"] is True - ltc_addr = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc/nextdepositaddr') - ltc_mweb_addr = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc_mweb/nextdepositaddr') - ltc_mweb_addr2 = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc/newmwebaddress') + ltc_addr = read_json_api(TEST_HTTP_PORT + 0, "wallets/ltc/nextdepositaddr") + ltc_mweb_addr = read_json_api( + TEST_HTTP_PORT + 0, "wallets/ltc_mweb/nextdepositaddr" + ) + ltc_mweb_addr2 = read_json_api(TEST_HTTP_PORT + 0, "wallets/ltc/newmwebaddress") - assert (ci_mweb.rpc_wallet('getaddressinfo', [ltc_addr,])['ismweb'] is False) - assert (ci_mweb.rpc_wallet('getaddressinfo', [ltc_mweb_addr,])['ismweb'] is True) - assert (ci_mweb.rpc_wallet('getaddressinfo', [ltc_mweb_addr2,])['ismweb'] is True) + assert ( + ci_mweb.rpc_wallet( + "getaddressinfo", + [ + ltc_addr, + ], + )["ismweb"] + is False + ) + assert ( + ci_mweb.rpc_wallet( + "getaddressinfo", + [ + ltc_mweb_addr, + ], + )["ismweb"] + is True + ) + assert ( + ci_mweb.rpc_wallet( + "getaddressinfo", + [ + ltc_mweb_addr2, + ], + )["ismweb"] + is True + ) post_json = { - 'value': 10, - 'address': ltc_mweb_addr, - 'subfee': False, + "value": 10, + "address": ltc_mweb_addr, + "subfee": False, } - json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc/withdraw', post_json) - assert (len(json_rv['txid']) == 64) + json_rv = read_json_api(TEST_HTTP_PORT + 0, "wallets/ltc/withdraw", post_json) + assert len(json_rv["txid"]) == 64 self.mineBlock() - json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc', post_json) - assert (json_rv['mweb_balance'] == 10.0) - mweb_address = json_rv['mweb_address'] + json_rv = read_json_api(TEST_HTTP_PORT + 0, "wallets/ltc", post_json) + assert json_rv["mweb_balance"] == 10.0 + mweb_address = json_rv["mweb_address"] post_json = { - 'value': 11, - 'address': mweb_address, - 'subfee': False, + "value": 11, + "address": mweb_address, + "subfee": False, } - json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc/withdraw', post_json) - assert (len(json_rv['txid']) == 64) + json_rv = read_json_api(TEST_HTTP_PORT + 0, "wallets/ltc/withdraw", post_json) + assert len(json_rv["txid"]) == 64 self.mineBlock() - json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc_mweb', post_json) - assert (json_rv['mweb_balance'] == 21.0) - assert (json_rv['mweb_address'] == mweb_address) - ltc_address = json_rv['deposit_address'] + json_rv = read_json_api(TEST_HTTP_PORT + 0, "wallets/ltc_mweb", post_json) + assert json_rv["mweb_balance"] == 21.0 + assert json_rv["mweb_address"] == mweb_address + ltc_address = json_rv["deposit_address"] # Check that spending the mweb balance takes from the correct wallet post_json = { - 'value': 1, - 'address': ltc_address, - 'subfee': False, - 'type_from': 'mweb', + "value": 1, + "address": ltc_address, + "subfee": False, + "type_from": "mweb", } - json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc/withdraw', post_json) - assert (len(json_rv['txid']) == 64) + json_rv = read_json_api(TEST_HTTP_PORT + 0, "wallets/ltc/withdraw", post_json) + assert len(json_rv["txid"]) == 64 - json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc', post_json) - assert (json_rv['mweb_balance'] <= 20.0) + json_rv = read_json_api(TEST_HTTP_PORT + 0, "wallets/ltc", post_json) + assert json_rv["mweb_balance"] <= 20.0 -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/test_other.py b/tests/basicswap/test_other.py index 0c1f753..f57a404 100644 --- a/tests/basicswap/test_other.py +++ b/tests/basicswap/test_other.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019-2024 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -18,9 +19,9 @@ from coincurve.ecdsaotves import ( ecdsaotves_enc_sign, ecdsaotves_enc_verify, ecdsaotves_dec_sig, - ecdsaotves_rec_enc_key) -from coincurve.keys import ( - PrivateKey) + ecdsaotves_rec_enc_key, +) +from coincurve.keys import PrivateKey from basicswap.contrib.mnemonic import Mnemonic from basicswap.util import i2b, h2b @@ -36,14 +37,14 @@ from basicswap.interface.xmr import XMRInterface from tests.basicswap.mnemonics import mnemonics from tests.basicswap.util import REQUIRED_SETTINGS -from basicswap.basicswap_util import ( - TxLockTypes) +from basicswap.basicswap_util import TxLockTypes from basicswap.util import ( make_int, SerialiseNum, format_amount, DeserialiseNum, - validate_amount) + validate_amount, +) from basicswap.messages_npb import ( BidMessage, ) @@ -56,8 +57,9 @@ class Test(unittest.TestCase): def test_case(v, nb=None): b = SerialiseNum(v) if nb is not None: - assert (len(b) == nb) - assert (v == DeserialiseNum(b)) + assert len(b) == nb + assert v == DeserialiseNum(b) + test_case(0, 1) test_case(1, 1) test_case(16, 1) @@ -70,104 +72,106 @@ class Test(unittest.TestCase): test_case(4194642) def test_sequence(self): - coin_settings = {'rpcport': 0, 'rpcauth': 'none'} + coin_settings = {"rpcport": 0, "rpcauth": "none"} coin_settings.update(REQUIRED_SETTINGS) - ci = BTCInterface(coin_settings, 'regtest') + ci = BTCInterface(coin_settings, "regtest") time_val = 48 * 60 * 60 encoded = ci.getExpectedSequence(TxLockTypes.SEQUENCE_LOCK_TIME, time_val) decoded = ci.decodeSequence(encoded) - assert (decoded >= time_val) - assert (decoded <= time_val + 512) + assert decoded >= time_val + assert decoded <= time_val + 512 time_val = 24 * 60 encoded = ci.getExpectedSequence(TxLockTypes.SEQUENCE_LOCK_TIME, time_val) decoded = ci.decodeSequence(encoded) - assert (decoded >= time_val) - assert (decoded <= time_val + 512) + assert decoded >= time_val + assert decoded <= time_val + 512 blocks_val = 123 encoded = ci.getExpectedSequence(TxLockTypes.SEQUENCE_LOCK_BLOCKS, blocks_val) decoded = ci.decodeSequence(encoded) - assert (decoded == blocks_val) + assert decoded == blocks_val def test_make_int(self): def test_case(vs, vf, expect_int): i = make_int(vs) - assert (i == expect_int and isinstance(i, int)) + assert i == expect_int and isinstance(i, int) i = make_int(vf) - assert (i == expect_int and isinstance(i, int)) + assert i == expect_int and isinstance(i, int) vs_out = format_amount(i, 8) # Strip for i in range(7): - if vs_out[-1] == '0': + if vs_out[-1] == "0": vs_out = vs_out[:-1] - if '.' in vs: - assert (vs_out == vs) + if "." in vs: + assert vs_out == vs else: - assert (vs_out[:-2] == vs) - test_case('0', 0, 0) - test_case('1', 1, 100000000) - test_case('10', 10, 1000000000) - test_case('0.00899999', 0.00899999, 899999) - test_case('899999.0', 899999.0, 89999900000000) - test_case('899999.00899999', 899999.00899999, 89999900899999) - test_case('0.0', 0.0, 0) - test_case('1.0', 1.0, 100000000) - test_case('1.1', 1.1, 110000000) - test_case('1.2', 1.2, 120000000) - test_case('0.00899991', 0.00899991, 899991) - test_case('0.0089999', 0.0089999, 899990) - test_case('0.0089991', 0.0089991, 899910) - test_case('0.123', 0.123, 12300000) - test_case('123000.000123', 123000.000123, 12300000012300) + assert vs_out[:-2] == vs + + test_case("0", 0, 0) + test_case("1", 1, 100000000) + test_case("10", 10, 1000000000) + test_case("0.00899999", 0.00899999, 899999) + test_case("899999.0", 899999.0, 89999900000000) + test_case("899999.00899999", 899999.00899999, 89999900899999) + test_case("0.0", 0.0, 0) + test_case("1.0", 1.0, 100000000) + test_case("1.1", 1.1, 110000000) + test_case("1.2", 1.2, 120000000) + test_case("0.00899991", 0.00899991, 899991) + test_case("0.0089999", 0.0089999, 899990) + test_case("0.0089991", 0.0089991, 899910) + test_case("0.123", 0.123, 12300000) + test_case("123000.000123", 123000.000123, 12300000012300) try: - make_int('0.123456789') - assert (False) + make_int("0.123456789") + assert False except Exception as e: - assert (str(e) == 'Mantissa too long') - validate_amount('0.12345678') + assert str(e) == "Mantissa too long" + validate_amount("0.12345678") # floor - assert (make_int('0.123456789', r=-1) == 12345678) + assert make_int("0.123456789", r=-1) == 12345678 # Round up - assert (make_int('0.123456789', r=1) == 12345679) + assert make_int("0.123456789", r=1) == 12345679 def test_make_int12(self): def test_case(vs, vf, expect_int): i = make_int(vs, 12) - assert (i == expect_int and isinstance(i, int)) + assert i == expect_int and isinstance(i, int) i = make_int(vf, 12) - assert (i == expect_int and isinstance(i, int)) + assert i == expect_int and isinstance(i, int) vs_out = format_amount(i, 12) # Strip for i in range(7): - if vs_out[-1] == '0': + if vs_out[-1] == "0": vs_out = vs_out[:-1] - if '.' in vs: - assert (vs_out == vs) + if "." in vs: + assert vs_out == vs else: - assert (vs_out[:-2] == vs) - test_case('0.123456789', 0.123456789, 123456789000) - test_case('0.123456789123', 0.123456789123, 123456789123) + assert vs_out[:-2] == vs + + test_case("0.123456789", 0.123456789, 123456789000) + test_case("0.123456789123", 0.123456789123, 123456789123) try: - make_int('0.1234567891234', 12) - assert (False) + make_int("0.1234567891234", 12) + assert False except Exception as e: - assert (str(e) == 'Mantissa too long') - validate_amount('0.123456789123', 12) + assert str(e) == "Mantissa too long" + validate_amount("0.123456789123", 12) try: - validate_amount('0.1234567891234', 12) - assert (False) + validate_amount("0.1234567891234", 12) + assert False except Exception as e: - assert ('Too many decimal places' in str(e)) + assert "Too many decimal places" in str(e) try: validate_amount(0.1234567891234, 12) - assert (False) + assert False except Exception as e: - assert ('Too many decimal places' in str(e)) + assert "Too many decimal places" in str(e) def test_ed25519(self): privkey = edu.get_secret() @@ -175,12 +179,12 @@ class Test(unittest.TestCase): privkey_bytes = i2b(privkey) pubkey_test = ed25519_get_pubkey(privkey_bytes) - assert (pubkey == pubkey_test) + assert pubkey == pubkey_test def test_ecdsa_otves(self): - coin_settings = {'rpcport': 0, 'rpcauth': 'none'} + coin_settings = {"rpcport": 0, "rpcauth": "none"} coin_settings.update(REQUIRED_SETTINGS) - ci = BTCInterface(coin_settings, 'regtest') + ci = BTCInterface(coin_settings, "regtest") vk_sign = ci.getNewSecretKey() vk_encrypt = ci.getNewSecretKey() @@ -190,79 +194,79 @@ class Test(unittest.TestCase): cipher_text = ecdsaotves_enc_sign(vk_sign, pk_encrypt, sign_hash) - assert (ecdsaotves_enc_verify(pk_sign, pk_encrypt, sign_hash, cipher_text)) + assert ecdsaotves_enc_verify(pk_sign, pk_encrypt, sign_hash, cipher_text) sig = ecdsaotves_dec_sig(vk_encrypt, cipher_text) - assert (ci.verifySig(pk_sign, sign_hash, sig)) + assert ci.verifySig(pk_sign, sign_hash, sig) recovered_key = ecdsaotves_rec_enc_key(pk_encrypt, cipher_text, sig) - assert (vk_encrypt == recovered_key) + assert vk_encrypt == recovered_key def test_sign(self): - coin_settings = {'rpcport': 0, 'rpcauth': 'none'} + coin_settings = {"rpcport": 0, "rpcauth": "none"} coin_settings.update(REQUIRED_SETTINGS) - ci = BTCInterface(coin_settings, 'regtest') + ci = BTCInterface(coin_settings, "regtest") vk = ci.getNewSecretKey() pk = ci.getPubkey(vk) - message = 'test signing message' - message_hash = hashlib.sha256(bytes(message, 'utf-8')).digest() + message = "test signing message" + message_hash = hashlib.sha256(bytes(message, "utf-8")).digest() eck = PrivateKey(vk) - sig = eck.sign(message.encode('utf-8')) + sig = eck.sign(message.encode("utf-8")) ci.verifySig(pk, message_hash, sig) def test_sign_compact(self): - coin_settings = {'rpcport': 0, 'rpcauth': 'none'} + coin_settings = {"rpcport": 0, "rpcauth": "none"} coin_settings.update(REQUIRED_SETTINGS) - ci = BTCInterface(coin_settings, 'regtest') + ci = BTCInterface(coin_settings, "regtest") vk = ci.getNewSecretKey() pk = ci.getPubkey(vk) - sig = ci.signCompact(vk, 'test signing message') - assert (len(sig) == 64) - ci.verifyCompactSig(pk, 'test signing message', sig) + sig = ci.signCompact(vk, "test signing message") + assert len(sig) == 64 + ci.verifyCompactSig(pk, "test signing message", sig) # Nonce is set deterministically (using default libsecp256k1 method rfc6979) - sig2 = ci.signCompact(vk, 'test signing message') - assert (sig == sig2) + sig2 = ci.signCompact(vk, "test signing message") + assert sig == sig2 def test_sign_recoverable(self): - coin_settings = {'rpcport': 0, 'rpcauth': 'none'} + coin_settings = {"rpcport": 0, "rpcauth": "none"} coin_settings.update(REQUIRED_SETTINGS) - ci = BTCInterface(coin_settings, 'regtest') + ci = BTCInterface(coin_settings, "regtest") vk = ci.getNewSecretKey() pk = ci.getPubkey(vk) - sig = ci.signRecoverable(vk, 'test signing message') - assert (len(sig) == 65) - pk_rec = ci.verifySigAndRecover(sig, 'test signing message') - assert (pk == pk_rec) + sig = ci.signRecoverable(vk, "test signing message") + assert len(sig) == 65 + pk_rec = ci.verifySigAndRecover(sig, "test signing message") + assert pk == pk_rec # Nonce is set deterministically (using default libsecp256k1 method rfc6979) - sig2 = ci.signRecoverable(vk, 'test signing message') - assert (sig == sig2) + sig2 = ci.signRecoverable(vk, "test signing message") + assert sig == sig2 def test_pubkey_to_address(self): - coin_settings = {'rpcport': 0, 'rpcauth': 'none'} + coin_settings = {"rpcport": 0, "rpcauth": "none"} coin_settings.update(REQUIRED_SETTINGS) - ci = BTCInterface(coin_settings, 'regtest') - pk = h2b('02c26a344e7d21bcc6f291532679559f2fd234c881271ff98714855edc753763a6') + ci = BTCInterface(coin_settings, "regtest") + pk = h2b("02c26a344e7d21bcc6f291532679559f2fd234c881271ff98714855edc753763a6") addr = ci.pubkey_to_address(pk) - assert (addr == 'mj6SdSxmWRmdDqR5R3FfZmRiLmQfQAsLE8') + assert addr == "mj6SdSxmWRmdDqR5R3FfZmRiLmQfQAsLE8" def test_dleag(self): - coin_settings = {'rpcport': 0, 'walletrpcport': 0, 'walletrpcauth': 'none'} + coin_settings = {"rpcport": 0, "walletrpcport": 0, "walletrpcauth": "none"} coin_settings.update(REQUIRED_SETTINGS) - ci = XMRInterface(coin_settings, 'regtest') + ci = XMRInterface(coin_settings, "regtest") key = ci.getNewSecretKey() proof = ci.proveDLEAG(key) - assert (ci.verifyDLEAG(proof)) + assert ci.verifyDLEAG(proof) def test_rate(self): scale_from = 8 @@ -270,53 +274,58 @@ class Test(unittest.TestCase): amount_from = make_int(100, scale_from) rate = make_int(0.1, scale_to) - amount_to = int((amount_from * rate) // (10 ** scale_from)) - assert ('100.00000000' == format_amount(amount_from, scale_from)) - assert ('10.000000000000' == format_amount(amount_to, scale_to)) + amount_to = int((amount_from * rate) // (10**scale_from)) + assert "100.00000000" == format_amount(amount_from, scale_from) + assert "10.000000000000" == format_amount(amount_to, scale_to) rate_check = make_int((amount_to / amount_from), scale_from) - assert (rate == rate_check) + assert rate == rate_check scale_from = 12 scale_to = 8 amount_from = make_int(1, scale_from) rate = make_int(12, scale_to) - amount_to = int((amount_from * rate) // (10 ** scale_from)) - assert ('1.000000000000' == format_amount(amount_from, scale_from)) - assert ('12.00000000' == format_amount(amount_to, scale_to)) + amount_to = int((amount_from * rate) // (10**scale_from)) + assert "1.000000000000" == format_amount(amount_from, scale_from) + assert "12.00000000" == format_amount(amount_to, scale_to) rate_check = make_int((amount_to / amount_from), scale_from) - assert (rate == rate_check) + assert rate == rate_check scale_from = 8 scale_to = 8 amount_from = make_int(0.073, scale_from) amount_to = make_int(10, scale_to) rate = make_int(amount_to / amount_from, scale_to, r=1) - amount_to_recreate = int((amount_from * rate) // (10 ** scale_from)) - assert ('10.00000000' == format_amount(amount_to_recreate, scale_to)) + amount_to_recreate = int((amount_from * rate) // (10**scale_from)) + assert "10.00000000" == format_amount(amount_to_recreate, scale_to) scale_from = 8 scale_to = 12 amount_from = make_int(10.0, scale_from) amount_to = make_int(0.06935, scale_to) rate = make_int(amount_to / amount_from, scale_from, r=1) - amount_to_recreate = int((amount_from * rate) // (10 ** scale_from)) - assert ('0.069350000000' == format_amount(amount_to_recreate, scale_to)) + amount_to_recreate = int((amount_from * rate) // (10**scale_from)) + assert "0.069350000000" == format_amount(amount_to_recreate, scale_to) scale_from = 12 scale_to = 8 amount_from = make_int(0.06935, scale_from) amount_to = make_int(10.0, scale_to) rate = make_int(amount_to / amount_from, scale_from, r=1) - amount_to_recreate = int((amount_from * rate) // (10 ** scale_from)) - assert ('10.00000000' == format_amount(amount_to_recreate, scale_to)) + amount_to_recreate = int((amount_from * rate) // (10**scale_from)) + assert "10.00000000" == format_amount(amount_to_recreate, scale_to) - coin_settings = {'rpcport': 0, 'rpcauth': 'none', 'walletrpcport': 0, 'walletrpcauth': 'none'} + coin_settings = { + "rpcport": 0, + "rpcauth": "none", + "walletrpcport": 0, + "walletrpcauth": "none", + } coin_settings.update(REQUIRED_SETTINGS) - ci_xmr = XMRInterface(coin_settings, 'regtest') - ci_btc = BTCInterface(coin_settings, 'regtest') + ci_xmr = XMRInterface(coin_settings, "regtest") + ci_btc = BTCInterface(coin_settings, "regtest") for i in range(10000): test_pairs = random.randint(0, 3) @@ -362,55 +371,73 @@ class Test(unittest.TestCase): amount_to = random.randint(10000, 2100000000 * ci_to.COIN()) offer_rate = ci_from.make_int(amount_to / amount_from, r=1) - amount_to_from_rate: int = int((int(amount_from) * offer_rate) // (10 ** scale_from)) + amount_to_from_rate: int = int( + (int(amount_from) * offer_rate) // (10**scale_from) + ) scale_from = 24 offer_rate = make_int(amount_to, scale_from) // amount_from - amount_to_from_rate: int = int((int(amount_from) * offer_rate) // (10 ** scale_from)) + amount_to_from_rate: int = int( + (int(amount_from) * offer_rate) // (10**scale_from) + ) if abs(amount_to - amount_to_from_rate) == 1: offer_rate += 1 - offer_rate_human_read: int = int(offer_rate // (10 ** (scale_from - ci_from.exp()))) - amount_to_from_rate: int = int((int(amount_from) * offer_rate) // (10 ** scale_from)) + offer_rate_human_read: int = int( + offer_rate // (10 ** (scale_from - ci_from.exp())) + ) + amount_to_from_rate: int = int( + (int(amount_from) * offer_rate) // (10**scale_from) + ) if amount_to != amount_to_from_rate: - print('from exp, amount', ci_from.exp(), amount_from) - print('to exp, amount', ci_to.exp(), amount_to) - print('amount_to_from_rate', amount_to_from_rate) - raise ValueError('Bad amount_to') + print("from exp, amount", ci_from.exp(), amount_from) + print("to exp, amount", ci_to.exp(), amount_to) + print("offer_rate_human_read", offer_rate_human_read) + print("amount_to_from_rate", amount_to_from_rate) + raise ValueError("Bad amount_to") scale_to = 24 reversed_rate = make_int(amount_from, scale_to) // amount_to - amount_from_from_rate: int = int((int(amount_to) * reversed_rate) // (10 ** scale_to)) + amount_from_from_rate: int = int( + (int(amount_to) * reversed_rate) // (10**scale_to) + ) if abs(amount_from - amount_from_from_rate) == 1: reversed_rate += 1 - amount_from_from_rate: int = int((int(amount_to) * reversed_rate) // (10 ** scale_to)) + amount_from_from_rate: int = int( + (int(amount_to) * reversed_rate) // (10**scale_to) + ) if amount_from != amount_from_from_rate: - print('from exp, amount', ci_from.exp(), amount_from) - print('to exp, amount', ci_to.exp(), amount_to) - print('amount_from_from_rate', amount_from_from_rate) - raise ValueError('Bad amount_from') + print("from exp, amount", ci_from.exp(), amount_from) + print("to exp, amount", ci_to.exp(), amount_to) + print("amount_from_from_rate", amount_from_from_rate) + raise ValueError("Bad amount_from") def test_rfc2440(self): - password = 'test' - salt = bytes.fromhex('B7A94A7E4988630E') + password = "test" + salt = bytes.fromhex("B7A94A7E4988630E") password_hash = rfc2440_hash_password(password, salt=salt) - assert (password_hash == '16:B7A94A7E4988630E6095334BA67F06FBA509B2A7136A04C9C1B430F539') + assert ( + password_hash + == "16:B7A94A7E4988630E6095334BA67F06FBA509B2A7136A04C9C1B430F539" + ) def test_ripemd160(self): - input_data = b'hash this' - assert (ripemd160(input_data).hex() == 'd5443a154f167e2c1332f6de72cfb4c6ab9c8c17') + input_data = b"hash this" + assert ripemd160(input_data).hex() == "d5443a154f167e2c1332f6de72cfb4c6ab9c8c17" def test_hash160(self): # hash160 is RIPEMD(SHA256(data)) - input_data = b'hash this' - assert (hash160(input_data).hex() == '072985b3583a4a71f548494a5e1d5f6b00d0fe13') - assert (hash160_btc(input_data).hex() == '072985b3583a4a71f548494a5e1d5f6b00d0fe13') + input_data = b"hash this" + assert hash160(input_data).hex() == "072985b3583a4a71f548494a5e1d5f6b00d0fe13" + assert ( + hash160_btc(input_data).hex() == "072985b3583a4a71f548494a5e1d5f6b00d0fe13" + ) def test_protobuf(self): msg_buf = BidMessage() @@ -420,37 +447,37 @@ class Test(unittest.TestCase): msg_buf_2 = BidMessage() msg_buf_2.from_bytes(serialised_msg) - assert (msg_buf_2.protocol_version == 2) - assert (msg_buf_2.time_valid == 1024) - assert (msg_buf_2.amount == 0) - assert (msg_buf_2.pkhash_buyer is not None) - assert (len(msg_buf_2.pkhash_buyer) == 0) + assert msg_buf_2.protocol_version == 2 + assert msg_buf_2.time_valid == 1024 + assert msg_buf_2.amount == 0 + assert msg_buf_2.pkhash_buyer is not None + assert len(msg_buf_2.pkhash_buyer) == 0 # Decode only the first field msg_buf_3 = BidMessage() msg_buf_3.from_bytes(serialised_msg[:2]) - assert (msg_buf_3.protocol_version == 2) - assert (msg_buf_3.time_valid == 0) + assert msg_buf_3.protocol_version == 2 + assert msg_buf_3.time_valid == 0 try: - msg_buf_4 = BidMessage(doesnotexist=1) + _ = BidMessage(doesnotexist=1) except Exception as e: - assert ('unexpected keyword argument' in str(e)) + assert "unexpected keyword argument" in str(e) else: - raise ValueError('Should have errored.') + raise ValueError("Should have errored.") def test_is_private_ip_address(self): test_addresses = [ - ('localhost', True), - ('127.0.0.1', True), - ('10.0.0.0', True), - ('172.16.0.0', True), - ('192.168.0.0', True), - ('20.87.245.0', False), - ('particl.io', False), + ("localhost", True), + ("127.0.0.1", True), + ("10.0.0.0", True), + ("172.16.0.0", True), + ("192.168.0.0", True), + ("20.87.245.0", False), + ("particl.io", False), ] for addr, is_private in test_addresses: - assert (is_private_ip_address(addr) is is_private) + assert is_private_ip_address(addr) is is_private def test_varint(self): test_vectors = [ @@ -467,8 +494,8 @@ class Test(unittest.TestCase): ] for i, expect_length in test_vectors: b = encode_varint(i) - assert (len(b) == expect_length) - assert (decode_varint(b) == (i, expect_length)) + assert len(b) == expect_length + assert decode_varint(b) == (i, expect_length) def test_base58(self): kv = edu.get_secret() @@ -477,55 +504,58 @@ class Test(unittest.TestCase): Ks = edu.encodepoint(edf.scalarmult_B(ks)) addr = xmr_encode_address(Kv, Ks) - assert (addr.startswith('4')) + assert addr.startswith("4") addr = xmr_encode_address(Kv, Ks, 4146) - assert (addr.startswith('Wo')) + assert addr.startswith("Wo") def test_blake256(self): test_vectors = [ - ('716f6e863f744b9ac22c97ec7b76ea5f5908bc5b2f67c61510bfc4751384ea7a', b''), - ('7576698ee9cad30173080678e5965916adbb11cb5245d386bf1ffda1cb26c9d7', b'The quick brown fox jumps over the lazy dog'), + ("716f6e863f744b9ac22c97ec7b76ea5f5908bc5b2f67c61510bfc4751384ea7a", b""), + ( + "7576698ee9cad30173080678e5965916adbb11cb5245d386bf1ffda1cb26c9d7", + b"The quick brown fox jumps over the lazy dog", + ), ] for expect_hash, data in test_vectors: - assert (blake256(data).hex() == expect_hash) + assert blake256(data).hex() == expect_hash def test_extkey(self): - test_key = 'XPARHAr37YxmFP8wyjkaHAQWmp84GiyLikL7EL8j9BCx4LkB8Q1Bw5Kr8sA1GA3Ym53zNLcaxxFHr6u81JVTeCaD61c6fKS1YRAuti8Zu5SzJCjh' - test_key_c0 = 'XPARHAt1XMcNYAwP5wEnQXknBAkGSzaetdZt2eoJZehdB4WXfV1xbSjpgHe44AivmumcSejW5KaYx6L5M6MyR1WyXrsWTwaiUEfHq2RrqCfXj3ZW' - test_key_c0_p = 'PPARTKPL4rp5WLnrYP6jZfuRjx6jrmvbsz5QdHofPfFqJdm918mQwdPLq6Dd9TkdbQeKUqjbHWkyzWe7Pftd7itzm7ETEoUMq4cbG4fY9FKH1YSU' - test_key_c0h = 'XPARHAt1XMcNgWbv48LwoQbjs1bC8kCXKomzvJLRT5xmbQ2GKf9e8Vfr1MMcfiWJC34RyDp5HvAfjeiNyLDfkFm1UrRCrPkVC9GGaAWa3nXMWew8' + test_key = "XPARHAr37YxmFP8wyjkaHAQWmp84GiyLikL7EL8j9BCx4LkB8Q1Bw5Kr8sA1GA3Ym53zNLcaxxFHr6u81JVTeCaD61c6fKS1YRAuti8Zu5SzJCjh" + test_key_c0 = "XPARHAt1XMcNYAwP5wEnQXknBAkGSzaetdZt2eoJZehdB4WXfV1xbSjpgHe44AivmumcSejW5KaYx6L5M6MyR1WyXrsWTwaiUEfHq2RrqCfXj3ZW" + test_key_c0_p = "PPARTKPL4rp5WLnrYP6jZfuRjx6jrmvbsz5QdHofPfFqJdm918mQwdPLq6Dd9TkdbQeKUqjbHWkyzWe7Pftd7itzm7ETEoUMq4cbG4fY9FKH1YSU" + test_key_c0h = "XPARHAt1XMcNgWbv48LwoQbjs1bC8kCXKomzvJLRT5xmbQ2GKf9e8Vfr1MMcfiWJC34RyDp5HvAfjeiNyLDfkFm1UrRCrPkVC9GGaAWa3nXMWew8" ek_data = decodeAddress(test_key)[4:] ek = ExtKeyPair() ek.decode(ek_data) - assert (ek.encode_v() == ek_data) + assert ek.encode_v() == ek_data m_0 = ek.derive(0) ek_c0_data = decodeAddress(test_key_c0)[4:] - assert (m_0.encode_v() == ek_c0_data) + assert m_0.encode_v() == ek_c0_data child_no: int = 0 | (1 << 31) m_0h = ek.derive(child_no) ek_c0h_data = decodeAddress(test_key_c0h)[4:] - assert (m_0h.encode_v() == ek_c0h_data) + assert m_0h.encode_v() == ek_c0h_data ek.neuter() - assert (ek.has_key() is False) + assert ek.has_key() is False m_0 = ek.derive(0) ek_c0_p_data = decodeAddress(test_key_c0_p)[4:] - assert (m_0.encode_p() == ek_c0_p_data) + assert m_0.encode_p() == ek_c0_p_data def test_mnemonic(self): - entropy0: bytes = Mnemonic('english').to_entropy(mnemonics[0]) - assert (entropy0.hex() == '0002207e9b744ea2d7ab41702f31f000') - mnemonic_recovered: str = Mnemonic('english').to_mnemonic(entropy0) - assert (mnemonic_recovered == mnemonics[0]) + entropy0: bytes = Mnemonic("english").to_entropy(mnemonics[0]) + assert entropy0.hex() == "0002207e9b744ea2d7ab41702f31f000" + mnemonic_recovered: str = Mnemonic("english").to_mnemonic(entropy0) + assert mnemonic_recovered == mnemonics[0] -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/test_partblind_xmr.py b/tests/basicswap/test_partblind_xmr.py index 1268e64..9fbfe8e 100644 --- a/tests/basicswap/test_partblind_xmr.py +++ b/tests/basicswap/test_partblind_xmr.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021-2023 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -51,45 +52,65 @@ class Test(BaseTest): def setUpClass(cls): super(Test, cls).setUpClass() - js_0 = read_json_api(1800, 'wallets/part') - node0_blind_before = js_0['blind_balance'] + js_0['blind_unconfirmed'] + js_0 = read_json_api(1800, "wallets/part") + node0_blind_before = js_0["blind_balance"] + js_0["blind_unconfirmed"] post_json = { - 'value': 100, - 'address': js_0['stealth_address'], - 'subfee': False, - 'type_to': 'blind', + "value": 100, + "address": js_0["stealth_address"], + "subfee": False, + "type_to": "blind", } - json_rv = json.loads(post_json_req('http://127.0.0.1:1800/json/wallets/part/withdraw', post_json)) - assert (len(json_rv['txid']) == 64) + json_rv = json.loads( + post_json_req("http://127.0.0.1:1800/json/wallets/part/withdraw", post_json) + ) + assert len(json_rv["txid"]) == 64 - logging.info('Waiting for blind balance') - wait_for_balance(test_delay_event, 'http://127.0.0.1:1800/json/wallets/part', 'blind_balance', 100.0 + node0_blind_before) - js_0 = read_json_api(1800, 'wallets/part') + logging.info("Waiting for blind balance") + wait_for_balance( + test_delay_event, + "http://127.0.0.1:1800/json/wallets/part", + "blind_balance", + 100.0 + node0_blind_before, + ) + js_0 = read_json_api(1800, "wallets/part") def ensure_balance(self, coin_type, node_id, amount): - tla = 'PART' - js_w = read_json_api(1800 + node_id, 'wallets') - print('js_w', js_w) - if float(js_w[tla]['blind_balance']) < amount: + tla = "PART" + js_w = read_json_api(1800 + node_id, "wallets") + print("js_w", js_w) + if float(js_w[tla]["blind_balance"]) < amount: post_json = { - 'value': amount, - 'type_to': 'blind', - 'address': js_w[tla]['stealth_address'], - 'subfee': False, + "value": amount, + "type_to": "blind", + "address": js_w[tla]["stealth_address"], + "subfee": False, } - json_rv = read_json_api(1800, 'wallets/{}/withdraw'.format(tla.lower()), post_json) - assert (len(json_rv['txid']) == 64) - wait_for_balance(test_delay_event, 'http://127.0.0.1:{}/json/wallets/{}'.format(1800 + node_id, tla.lower()), 'blind_balance', amount) + json_rv = read_json_api( + 1800, "wallets/{}/withdraw".format(tla.lower()), post_json + ) + assert len(json_rv["txid"]) == 64 + wait_for_balance( + test_delay_event, + "http://127.0.0.1:{}/json/wallets/{}".format( + 1800 + node_id, tla.lower() + ), + "blind_balance", + amount, + ) def getBalance(self, js_wallets): - return float(js_wallets[Coins.PART.name]['blind_balance']) + float(js_wallets[Coins.PART.name]['blind_unconfirmed']) + return float(js_wallets[Coins.PART.name]["blind_balance"]) + float( + js_wallets[Coins.PART.name]["blind_unconfirmed"] + ) def getXmrBalance(self, js_wallets): - return float(js_wallets[Coins.XMR.name]['unconfirmed']) + float(js_wallets[Coins.XMR.name]['balance']) + return float(js_wallets[Coins.XMR.name]["unconfirmed"]) + float( + js_wallets[Coins.XMR.name]["balance"] + ) def test_010_txn_size(self): - logging.info('---------- Test {} txn_size'.format(self.test_coin_from.name)) + logging.info("---------- Test {} txn_size".format(self.test_coin_from.name)) self.ensure_balance(self.test_coin_from, 0, 100.0) @@ -101,20 +122,21 @@ class Test(BaseTest): nonlocal ci i = 0 while not delay_event.is_set(): - unspents = ci.rpc_wallet('listunspentblind') + unspents = ci.rpc_wallet("listunspentblind") if len(unspents) >= 1: return delay_event.wait(delay_time) i += 1 if i > iterations: - raise ValueError('wait_for_unspents timed out') + raise ValueError("wait_for_unspents timed out") + wait_for_unspents(test_delay_event) amount: int = ci.make_int(random.uniform(0.1, 2.0), r=1) # Record unspents before createSCLockTx as the used ones will be locked - unspents = ci.rpc_wallet('listunspentblind') - locked_utxos_before = ci.rpc_wallet('listlockunspent') + unspents = ci.rpc_wallet("listunspentblind") + locked_utxos_before = ci.rpc_wallet("listlockunspent") # fee_rate is in sats/kvB fee_rate: int = 1000 @@ -131,53 +153,61 @@ class Test(BaseTest): lock_tx = ci.fundSCLockTx(lock_tx, fee_rate, vkbv) lock_tx = ci.signTxWithWallet(lock_tx) - unspents_after = ci.rpc_wallet('listunspentblind') - locked_utxos_after = ci.rpc_wallet('listlockunspent') + unspents_after = ci.rpc_wallet("listunspentblind") + locked_utxos_after = ci.rpc_wallet("listlockunspent") - assert (len(unspents) > len(unspents_after)) - assert (len(locked_utxos_after) > len(locked_utxos_before)) - lock_tx_decoded = ci.rpc_wallet('decoderawtransaction', [lock_tx.hex()]) - txid = lock_tx_decoded['txid'] + assert len(unspents) > len(unspents_after) + assert len(locked_utxos_after) > len(locked_utxos_before) + lock_tx_decoded = ci.rpc_wallet("decoderawtransaction", [lock_tx.hex()]) + txid = lock_tx_decoded["txid"] - vsize = lock_tx_decoded['vsize'] + vsize = lock_tx_decoded["vsize"] expect_fee_int = round(fee_rate * vsize / 1000) - expect_fee = ci.format_amount(expect_fee_int) - ci.rpc_wallet('sendrawtransaction', [lock_tx.hex()]) - rv = ci.rpc_wallet('gettransaction', [txid]) - wallet_tx_fee = -ci.make_int(rv['details'][0]['fee']) + ci.rpc_wallet("sendrawtransaction", [lock_tx.hex()]) + rv = ci.rpc_wallet("gettransaction", [txid]) + wallet_tx_fee = -ci.make_int(rv["details"][0]["fee"]) - assert (wallet_tx_fee >= expect_fee_int) - assert (wallet_tx_fee - expect_fee_int < 20) + assert wallet_tx_fee >= expect_fee_int + assert wallet_tx_fee - expect_fee_int < 20 addr_out = ci.getNewAddress(True) - addrinfo = ci.rpc_wallet('getaddressinfo', [addr_out,]) - pk_out = bytes.fromhex(addrinfo['pubkey']) + addrinfo = ci.rpc_wallet( + "getaddressinfo", + [ + addr_out, + ], + ) + pk_out = bytes.fromhex(addrinfo["pubkey"]) fee_info = {} - lock_spend_tx = ci.createSCLockSpendTx(lock_tx, lock_tx_script, pk_out, fee_rate, vkbv, fee_info=fee_info) - vsize_estimated: int = fee_info['vsize'] + lock_spend_tx = ci.createSCLockSpendTx( + lock_tx, lock_tx_script, pk_out, fee_rate, vkbv, fee_info=fee_info + ) + vsize_estimated: int = fee_info["vsize"] - spend_tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()]) - txid = spend_tx_decoded['txid'] + spend_tx_decoded = ci.rpc("decoderawtransaction", [lock_spend_tx.hex()]) + txid = spend_tx_decoded["txid"] nonce = ci.getScriptLockTxNonce(vkbv) output_n, _ = ci.findOutputByNonce(lock_tx_decoded, nonce) - assert (output_n is not None) - valueCommitment = bytes.fromhex(lock_tx_decoded['vout'][output_n]['valueCommitment']) + assert output_n is not None + valueCommitment = bytes.fromhex( + lock_tx_decoded["vout"][output_n]["valueCommitment"] + ) witness_stack = [ - b'', + b"", ci.signTx(a, lock_spend_tx, 0, lock_tx_script, valueCommitment), ci.signTx(b, lock_spend_tx, 0, lock_tx_script, valueCommitment), lock_tx_script, ] lock_spend_tx = ci.setTxSignature(lock_spend_tx, witness_stack) - tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()]) - vsize_actual: int = tx_decoded['vsize'] + tx_decoded = ci.rpc("decoderawtransaction", [lock_spend_tx.hex()]) + vsize_actual: int = tx_decoded["vsize"] # Note: The fee is set allowing 9 bytes for the encoded fee amount, causing a small overestimate - assert (vsize_actual <= vsize_estimated and vsize_estimated - vsize_actual < 10) - assert (ci.rpc('sendrawtransaction', [lock_spend_tx.hex()]) == txid) + assert vsize_actual <= vsize_estimated and vsize_estimated - vsize_actual < 10 + assert ci.rpc("sendrawtransaction", [lock_spend_tx.hex()]) == txid # Test chain b (no-script) lock tx size v = ci.getNewSecretKey() @@ -189,40 +219,50 @@ class Test(BaseTest): lock_tx_b_spend_txid = None for i in range(20): try: - lock_tx_b_spend_txid = ci.spendBLockTx(lock_tx_b_txid, addr_out, v, s, amount, fee_rate, 0) + lock_tx_b_spend_txid = ci.spendBLockTx( + lock_tx_b_txid, addr_out, v, s, amount, fee_rate, 0 + ) break except Exception as e: - print('spendBLockTx failed', str(e)) + print("spendBLockTx failed", str(e)) test_delay_event.wait(2) - assert (lock_tx_b_spend_txid is not None) + assert lock_tx_b_spend_txid is not None lock_tx_b_spend = ci.getTransaction(lock_tx_b_spend_txid) if lock_tx_b_spend is None: lock_tx_b_spend = ci.getWalletTransaction(lock_tx_b_spend_txid) - lock_tx_b_spend_decoded = ci.rpc('decoderawtransaction', [lock_tx_b_spend.hex()]) + lock_tx_b_spend_decoded = ci.rpc( + "decoderawtransaction", [lock_tx_b_spend.hex()] + ) expect_vsize: int = ci.xmr_swap_b_lock_spend_tx_vsize() - assert (expect_vsize >= lock_tx_b_spend_decoded['vsize']) - assert (expect_vsize - lock_tx_b_spend_decoded['vsize'] < 10) + assert expect_vsize >= lock_tx_b_spend_decoded["vsize"] + assert expect_vsize - lock_tx_b_spend_decoded["vsize"] < 10 def test_01_part_xmr(self): - logging.info('---------- Test PARTct to XMR') + logging.info("---------- Test PARTct to XMR") swap_clients = self.swap_clients - js_0 = read_json_api(1800, 'wallets/part') - assert (float(js_0['blind_balance']) > 10.0) - node0_blind_before = js_0['blind_balance'] + js_0['blind_unconfirmed'] + js_0 = read_json_api(1800, "wallets/part") + assert float(js_0["blind_balance"]) > 10.0 + node0_blind_before = js_0["blind_balance"] + js_0["blind_unconfirmed"] - js_1 = read_json_api(1801, 'wallets/part') - node1_blind_before = js_1['blind_balance'] + js_1['blind_unconfirmed'] + js_1 = read_json_api(1801, "wallets/part") + node1_blind_before = js_1["blind_balance"] + js_1["blind_unconfirmed"] - js_0_xmr = read_json_api(1800, 'wallets/xmr') - js_1_xmr = read_json_api(1801, 'wallets/xmr') + js_1_xmr = read_json_api(1801, "wallets/xmr") amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1) rate_swap = make_int(random.uniform(0.2, 20.0), scale=12, r=1) - offer_id = swap_clients[0].postOffer(Coins.PART_BLIND, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP) + offer_id = swap_clients[0].postOffer( + Coins.PART_BLIND, + Coins.XMR, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) - offers = swap_clients[0].listOffers(filters={'offer_id': offer_id}) + offers = swap_clients[0].listOffers(filters={"offer_id": offer_id}) offer = offers[0] bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from) @@ -231,40 +271,60 @@ class Test(BaseTest): swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=180, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + ) amount_from = float(format_amount(amt_swap, 8)) - js_1 = read_json_api(1801, 'wallets/part') - node1_blind_after = js_1['blind_balance'] + js_1['blind_unconfirmed'] - assert (node1_blind_after > node1_blind_before + (amount_from - 0.05)) + js_1 = read_json_api(1801, "wallets/part") + node1_blind_after = js_1["blind_balance"] + js_1["blind_unconfirmed"] + assert node1_blind_after > node1_blind_before + (amount_from - 0.05) - js_0 = read_json_api(1800, 'wallets/part') - node0_blind_after = js_0['blind_balance'] + js_0['blind_unconfirmed'] - assert (node0_blind_after < node0_blind_before - amount_from) + js_0 = read_json_api(1800, "wallets/part") + node0_blind_after = js_0["blind_balance"] + js_0["blind_unconfirmed"] + assert node0_blind_after < node0_blind_before - amount_from - js_0_xmr_after = read_json_api(1800, 'wallets/xmr') - js_1_xmr_after = read_json_api(1801, 'wallets/xmr') + js_1_xmr_after = read_json_api(1801, "wallets/xmr") scale_from = 8 - amount_to = int((amt_swap * rate_swap) // (10 ** scale_from)) + amount_to = int((amt_swap * rate_swap) // (10**scale_from)) amount_to_float = float(format_amount(amount_to, 12)) - node1_xmr_after = float(js_1_xmr_after['unconfirmed']) + float(js_1_xmr_after['balance']) - node1_xmr_before = float(js_1_xmr['unconfirmed']) + float(js_1_xmr['balance']) - assert (node1_xmr_after > node1_xmr_before + (amount_to_float - 0.02)) + node1_xmr_after = float(js_1_xmr_after["unconfirmed"]) + float( + js_1_xmr_after["balance"] + ) + node1_xmr_before = float(js_1_xmr["unconfirmed"]) + float(js_1_xmr["balance"]) + assert node1_xmr_after > node1_xmr_before + (amount_to_float - 0.02) def test_02_leader_recover_a_lock_tx(self): - logging.info('---------- Test PARTct to XMR leader recovers coin a lock tx') + logging.info("---------- Test PARTct to XMR leader recovers coin a lock tx") swap_clients = self.swap_clients - js_w0_before = read_json_api(1800, 'wallets') + js_w0_before = read_json_api(1800, "wallets") node0_blind_before = self.getBalance(js_w0_before) amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1) rate_swap = make_int(random.uniform(0.2, 20.0), scale=12, r=1) offer_id = swap_clients[0].postOffer( - Coins.PART_BLIND, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, - lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=12) + Coins.PART_BLIND, + Coins.XMR, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, + lock_value=12, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -273,31 +333,49 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) bid, xmr_swap = swap_clients[0].getXmrBid(bid_id) - assert (xmr_swap) + assert xmr_swap swap_clients[1].setBidDebugInd(bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK) swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=180) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, [BidStates.BID_STALLED_FOR_TEST, BidStates.XMR_SWAP_FAILED], sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + wait_for=180, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + [BidStates.BID_STALLED_FOR_TEST, BidStates.XMR_SWAP_FAILED], + sent=True, + ) - js_w0_after = read_json_api(1800, 'wallets') + js_w0_after = read_json_api(1800, "wallets") node0_blind_after = self.getBalance(js_w0_after) - assert (node0_blind_before - node0_blind_after < 0.02) + assert node0_blind_before - node0_blind_after < 0.02 def test_03_follower_recover_a_lock_tx(self): - logging.info('---------- Test PARTct to XMR follower recovers coin a lock tx') + logging.info("---------- Test PARTct to XMR follower recovers coin a lock tx") swap_clients = self.swap_clients - js_w0_before = read_json_api(1800, 'wallets') - js_w1_before = read_json_api(1801, 'wallets') + js_w1_before = read_json_api(1801, "wallets") amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1) rate_swap = make_int(random.uniform(0.2, 20.0), scale=12, r=1) offer_id = swap_clients[0].postOffer( - Coins.PART_BLIND, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, - lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=32) + Coins.PART_BLIND, + Coins.XMR, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, + lock_value=32, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -306,22 +384,37 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) bid, xmr_swap = swap_clients[0].getXmrBid(bid_id) - assert (xmr_swap) + assert xmr_swap swap_clients[1].setBidDebugInd(bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK) - swap_clients[0].setBidDebugInd(bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND) + swap_clients[0].setBidDebugInd( + bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND + ) swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_STALLED_FOR_TEST, wait_for=180) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_SWIPED, wait_for=80, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.BID_STALLED_FOR_TEST, + wait_for=180, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.XMR_SWAP_FAILED_SWIPED, + wait_for=80, + sent=True, + ) - js_w1_after = read_json_api(1801, 'wallets') + js_w1_after = read_json_api(1801, "wallets") node1_blind_before = self.getBalance(js_w1_before) node1_blind_after = self.getBalance(js_w1_after) amount_from = float(format_amount(amt_swap, 8)) - assert (node1_blind_after - node1_blind_before > (amount_from - 0.02)) + assert node1_blind_after - node1_blind_before > (amount_from - 0.02) swap_clients[0].abandonBid(bid_id) swap_clients[1].abandonBid(bid_id) @@ -329,20 +422,29 @@ class Test(BaseTest): wait_for_none_active(test_delay_event, 1800) wait_for_none_active(test_delay_event, 1801) - data = parse.urlencode({ - 'chainbkeysplit': True - }).encode() - offerer_key = json.loads(urlopen('http://127.0.0.1:1800/json/bids/{}'.format(bid_id.hex()), data=data).read())['splitkey'] + data = parse.urlencode({"chainbkeysplit": True}).encode() + offerer_key = json.loads( + urlopen( + "http://127.0.0.1:1800/json/bids/{}".format(bid_id.hex()), data=data + ).read() + )["splitkey"] - data = parse.urlencode({ - 'spendchainblocktx': True, - 'remote_key': offerer_key - }).encode() - redeemed_txid = json.loads(urlopen('http://127.0.0.1:1801/json/bids/{}'.format(bid_id.hex()), data=data).read())['txid'] - assert (len(redeemed_txid) == 64) + data = parse.urlencode( + {"spendchainblocktx": True, "remote_key": offerer_key} + ).encode() + redeemed_txid = json.loads( + urlopen( + "http://127.0.0.1:1801/json/bids/{}".format(bid_id.hex()), data=data + ).read() + )["txid"] + assert len(redeemed_txid) == 64 def do_test_04_follower_recover_b_lock_tx(self, coin_from, coin_to): - logging.info('---------- Test {} to {} follower recovers coin b lock tx'.format(coin_from.name, coin_to.name)) + logging.info( + "---------- Test {} to {} follower recovers coin b lock tx".format( + coin_from.name, coin_to.name + ) + ) swap_clients = self.swap_clients ci_from = swap_clients[0].ci(coin_from) @@ -351,8 +453,15 @@ class Test(BaseTest): amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) offer_id = swap_clients[0].postOffer( - coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, - lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=28) + coin_from, + coin_to, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, + lock_value=28, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -361,36 +470,50 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) bid, xmr_swap = swap_clients[0].getXmrBid(bid_id) - assert (xmr_swap) + assert xmr_swap swap_clients[1].setBidDebugInd(bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK) swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=180) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + wait_for=180, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + sent=True, + ) def test_04_follower_recover_b_lock_tx(self): - js_w0_before = read_json_api(1800, 'wallets') - js_w1_before = read_json_api(1801, 'wallets') + js_w0_before = read_json_api(1800, "wallets") + js_w1_before = read_json_api(1801, "wallets") self.do_test_04_follower_recover_b_lock_tx(self.test_coin_from, Coins.XMR) - js_w0_after = read_json_api(1800, 'wallets') - js_w1_after = read_json_api(1801, 'wallets') + js_w0_after = read_json_api(1800, "wallets") + js_w1_after = read_json_api(1801, "wallets") node0_blind_before = self.getBalance(js_w0_before) node0_blind_after = self.getBalance(js_w0_after) - assert (node0_blind_before - node0_blind_after < 0.02) + assert node0_blind_before - node0_blind_after < 0.02 node1_xmr_before = self.getXmrBalance(js_w1_before) node1_xmr_after = self.getXmrBalance(js_w1_after) - assert (node1_xmr_before - node1_xmr_after < 0.02) + assert node1_xmr_before - node1_xmr_after < 0.02 def test_04_follower_recover_b_lock_tx_from_part(self): self.ensure_balance(self.test_coin_from, 1, 50.0) self.do_test_04_follower_recover_b_lock_tx(Coins.PART, self.test_coin_from) def do_test_05_self_bid(self, coin_from, coin_to): - logging.info('---------- Test {} to {} same client'.format(coin_from.name, coin_to.name)) + logging.info( + "---------- Test {} to {} same client".format(coin_from.name, coin_to.name) + ) swap_clients = self.swap_clients ci_to = swap_clients[0].ci(coin_to) @@ -400,10 +523,24 @@ class Test(BaseTest): amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) - offer_id = swap_clients[1].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, auto_accept_bids=True) + offer_id = swap_clients[1].postOffer( + coin_from, + coin_to, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + auto_accept_bids=True, + ) bid_id = swap_clients[1].postXmrBid(offer_id, amt_swap) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=180) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=180, + ) def test_05_self_bid(self): if not self.has_segwit: @@ -419,45 +556,58 @@ class Test(BaseTest): self.do_test_05_self_bid(Coins.PART, self.test_coin_from) def test_06_preselect_inputs(self): - raise ValueError('TODO') + raise ValueError("TODO") tla_from = self.test_coin_from.name - logging.info('---------- Test {} Preselected inputs'.format(tla_from)) + logging.info("---------- Test {} Preselected inputs".format(tla_from)) swap_clients = self.swap_clients # Prepare balance self.ensure_balance(self.test_coin_from, 2, 100.0) - js_w2 = read_json_api(1802, 'wallets') + js_w2 = read_json_api(1802, "wallets") post_json = { - 'value': float(js_w2['PART']['blind_balance']), - 'type_from': 'blind', - 'type_to': 'blind', - 'address': js_w2['PART']['stealth_address'], - 'subfee': True, + "value": float(js_w2["PART"]["blind_balance"]), + "type_from": "blind", + "type_to": "blind", + "address": js_w2["PART"]["stealth_address"], + "subfee": True, } - json_rv = read_json_api(1802, 'wallets/{}/withdraw'.format('part'), post_json) - wait_for_balance(test_delay_event, 'http://127.0.0.1:1802/json/wallets/{}'.format('part'), 'blind_balance', 10.0) - assert (len(json_rv['txid']) == 64) + json_rv = read_json_api(1802, "wallets/{}/withdraw".format("part"), post_json) + wait_for_balance( + test_delay_event, + "http://127.0.0.1:1802/json/wallets/{}".format("part"), + "blind_balance", + 10.0, + ) + assert len(json_rv["txid"]) == 64 # Create prefunded ITX ci = swap_clients[2].ci(self.test_coin_from) ci_to = swap_clients[2].ci(Coins.XMR) pi = swap_clients[2].pi(SwapTypes.XMR_SWAP) - js_w2 = read_json_api(1802, 'wallets') - swap_value = ci.make_int(js_w2['PART']['blind_balance']) - assert (swap_value > ci.make_int(95)) + js_w2 = read_json_api(1802, "wallets") + swap_value = ci.make_int(js_w2["PART"]["blind_balance"]) + assert swap_value > ci.make_int(95) itx = pi.getFundedInitiateTxTemplate(ci, swap_value, True) itx_decoded = ci.describeTx(itx.hex()) n = pi.findMockVout(ci, itx_decoded) - value_after_subfee = ci.make_int(itx_decoded['vout'][n]['value']) - assert (value_after_subfee < swap_value) + value_after_subfee = ci.make_int(itx_decoded["vout"][n]["value"]) + assert value_after_subfee < swap_value swap_value = value_after_subfee wait_for_unspent(test_delay_event, ci, swap_value) - extra_options = {'prefunded_itx': itx} + extra_options = {"prefunded_itx": itx} rate_swap = ci_to.make_int(random.uniform(0.2, 20.0)) - offer_id = swap_clients[2].postOffer(self.test_coin_from, Coins.XMR, swap_value, rate_swap, swap_value, SwapTypes.XMR_SWAP, extra_options=extra_options) + offer_id = swap_clients[2].postOffer( + self.test_coin_from, + Coins.XMR, + swap_value, + rate_swap, + swap_value, + SwapTypes.XMR_SWAP, + extra_options=extra_options, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -466,20 +616,38 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[2], bid_id, BidStates.BID_RECEIVED) swap_clients[2].acceptBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[2], bid_id, BidStates.SWAP_COMPLETED, wait_for=120) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=120) + wait_for_bid( + test_delay_event, + swap_clients[2], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=120, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=120, + ) # Verify expected inputs were used bid, _, _, _, _ = swap_clients[2].getXmrBidAndOffer(bid_id) - assert (bid.xmr_a_lock_tx) - wtx = ci.rpc_wallet('gettransaction', [bid.xmr_a_lock_tx.txid.hex(),]) - itx_after = ci.describeTx(wtx['hex']) - assert (len(itx_after['vin']) == len(itx_decoded['vin'])) - for i, txin in enumerate(itx_decoded['vin']): - txin_after = itx_after['vin'][i] - assert (txin['txid'] == txin_after['txid']) - assert (txin['vout'] == txin_after['vout']) + assert bid.xmr_a_lock_tx + wtx = ci.rpc_wallet( + "gettransaction", + [ + bid.xmr_a_lock_tx.txid.hex(), + ], + ) + itx_after = ci.describeTx(wtx["hex"]) + assert len(itx_after["vin"]) == len(itx_decoded["vin"]) + for i, txin in enumerate(itx_decoded["vin"]): + txin_after = itx_after["vin"][i] + assert txin["txid"] == txin_after["txid"] + assert txin["vout"] == txin_after["vout"] -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/test_reload.py b/tests/basicswap/test_reload.py index 20f694b..a4a7a50 100644 --- a/tests/basicswap/test_reload.py +++ b/tests/basicswap/test_reload.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019-2023 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -41,7 +42,7 @@ from tests.basicswap.common_xmr import ( ) import basicswap.bin.run as runSystem -TEST_PATH = os.path.expanduser(os.getenv('TEST_PATH', '~/test_basicswap1')) +TEST_PATH = os.path.expanduser(os.getenv("TEST_PATH", "~/test_basicswap1")) delay_event = threading.Event() logger = logging.getLogger() @@ -51,22 +52,22 @@ if not len(logger.handlers): def btcRpc(client_no, cmd): - bin_path = os.path.join(TEST_PATH, 'bin', 'bitcoin') - data_path = os.path.join(TEST_PATH, 'client{}'.format(client_no), 'bitcoin') - return callrpc_cli(bin_path, data_path, 'regtest', cmd, 'bitcoin-cli') + bin_path = os.path.join(TEST_PATH, "bin", "bitcoin") + data_path = os.path.join(TEST_PATH, "client{}".format(client_no), "bitcoin") + return callrpc_cli(bin_path, data_path, "regtest", cmd, "bitcoin-cli") def partRpc(client_no, cmd): - bin_path = os.path.join(TEST_PATH, 'bin', 'particl') - data_path = os.path.join(TEST_PATH, 'client{}'.format(client_no), 'particl') - return callrpc_cli(bin_path, data_path, 'regtest', cmd, 'particl-cli') + bin_path = os.path.join(TEST_PATH, "bin", "particl") + data_path = os.path.join(TEST_PATH, "client{}".format(client_no), "particl") + return callrpc_cli(bin_path, data_path, "regtest", cmd, "particl-cli") def updateThread(): - btc_addr = btcRpc(0, 'getnewaddress mining_addr bech32') + btc_addr = btcRpc(0, "getnewaddress mining_addr bech32") while not delay_event.is_set(): - btcRpc(0, 'generatetoaddress {} {}'.format(1, btc_addr)) + btcRpc(0, "generatetoaddress {} {}".format(1, btc_addr)) delay_event.wait(5) @@ -75,30 +76,34 @@ class Test(unittest.TestCase): def setUpClass(cls): super(Test, cls).setUpClass() - prepare_nodes(3, 'bitcoin') + prepare_nodes(3, "bitcoin") def run_thread(self, client_id): - client_path = os.path.join(TEST_PATH, 'client{}'.format(client_id)) - testargs = ['basicswap-run', '-datadir=' + client_path, '-regtest'] - with patch.object(sys, 'argv', testargs): + client_path = os.path.join(TEST_PATH, "client{}".format(client_id)) + testargs = ["basicswap-run", "-datadir=" + client_path, "-regtest"] + with patch.object(sys, "argv", testargs): runSystem.main() - def wait_for_node_height(self, port=12701, wallet_ticker='part', wait_for_blocks=3): + def wait_for_node_height(self, port=12701, wallet_ticker="part", wait_for_blocks=3): # Wait for height, or sequencelock is thrown off by genesis blocktime - logging.info(f'Waiting for {wallet_ticker} chain height {wait_for_blocks} at port {port}', ) + logging.info( + f"Waiting for {wallet_ticker} chain height {wait_for_blocks} at port {port}", + ) for i in range(60): if delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") try: - wallet = read_json_api(port, f'wallets/{wallet_ticker}') - node_blocks = wallet['blocks'] - print(f'{wallet_ticker} node_blocks {node_blocks}') + wallet = read_json_api(port, f"wallets/{wallet_ticker}") + node_blocks = wallet["blocks"] + print(f"{wallet_ticker} node_blocks {node_blocks}") if node_blocks >= wait_for_blocks: return except Exception as e: - print('Error reading wallets', str(e)) + print("Error reading wallets", str(e)) delay_event.wait(1) - raise ValueError(f'wait_for_node_height timed out, {wallet_ticker}, {wait_for_blocks}, {port}') + raise ValueError( + f"wait_for_node_height timed out, {wallet_ticker}, {wait_for_blocks}, {port}" + ) def test_reload(self): global stop_test @@ -110,58 +115,55 @@ class Test(unittest.TestCase): try: waitForServer(delay_event, 12700) - partRpc(0, 'reservebalance false') # WakeThreadStakeMiner + partRpc(0, "reservebalance false") # WakeThreadStakeMiner self.wait_for_node_height() num_blocks = 500 - btc_addr = btcRpc(1, 'getnewaddress mining_addr bech32') - logging.info('Mining %d Bitcoin blocks to %s', num_blocks, btc_addr) - btcRpc(1, 'generatetoaddress {} {}'.format(num_blocks, btc_addr)) - self.wait_for_node_height(12700, 'btc', num_blocks) + btc_addr = btcRpc(1, "getnewaddress mining_addr bech32") + logging.info("Mining %d Bitcoin blocks to %s", num_blocks, btc_addr) + btcRpc(1, "generatetoaddress {} {}".format(num_blocks, btc_addr)) + self.wait_for_node_height(12700, "btc", num_blocks) data = { - 'addr_from': '-1', - 'coin_from': 'PART', - 'coin_to': '2', - 'amt_from': '1', - 'amt_to': '1', - 'lockhrs': '24'} + "addr_from": "-1", + "coin_from": "PART", + "coin_to": "2", + "amt_from": "1", + "amt_to": "1", + "lockhrs": "24", + } - offer_id = post_json_api(12700, 'offers/new', data)['offer_id'] + offer_id = post_json_api(12700, "offers/new", data)["offer_id"] summary = read_json_api(12700) - assert (summary['num_sent_offers'] == 1) + assert summary["num_sent_offers"] == 1 except Exception: traceback.print_exc() - sentoffers = read_json_api(12700, 'sentoffers', {'active': True}) - assert sentoffers[0]['offer_id'] == offer_id + sentoffers = read_json_api(12700, "sentoffers", {"active": True}) + assert sentoffers[0]["offer_id"] == offer_id - logger.info('Waiting for offer:') + logger.info("Waiting for offer:") waitForNumOffers(delay_event, 12701, 1) - offers = read_json_api(12701, 'offers') + offers = read_json_api(12701, "offers") offer = offers[0] - data = { - 'offer_id': offer['offer_id'], - 'amount_from': offer['amount_from']} + data = {"offer_id": offer["offer_id"], "amount_from": offer["amount_from"]} - bid_id = post_json_api(12701, 'bids/new', data) + post_json_api(12701, "bids/new", data) waitForNumBids(delay_event, 12700, 1) - bids = read_json_api(12700, 'bids') + bids = read_json_api(12700, "bids") bid = bids[0] - data = { - 'accept': True - } - rv = post_json_api(12700, 'bids/{}'.format(bid['bid_id']), data) - assert (rv['bid_state'] == 'Accepted') + data = {"accept": True} + rv = post_json_api(12700, "bids/{}".format(bid["bid_id"]), data) + assert rv["bid_state"] == "Accepted" waitForNumSwapping(delay_event, 12701, 1) - logger.info('Restarting client:') + logger.info("Restarting client:") c1 = processes[1] c1.terminate() c1.join() @@ -170,19 +172,19 @@ class Test(unittest.TestCase): waitForServer(delay_event, 12701) rv = read_json_api(12701) - assert (rv['num_swapping'] == 1) + assert rv["num_swapping"] == 1 update_thread = threading.Thread(target=updateThread) update_thread.start() - logger.info('Completing swap:') + logger.info("Completing swap:") for i in range(240): delay_event.wait(5) - rv = read_json_api(12700, 'bids/{}'.format(bid['bid_id'])) - if rv['bid_state'] == 'Completed': + rv = read_json_api(12700, "bids/{}".format(bid["bid_id"])) + if rv["bid_state"] == "Completed": break - assert (rv['bid_state'] == 'Completed') + assert rv["bid_state"] == "Completed" delay_event.set() update_thread.join() @@ -192,5 +194,5 @@ class Test(unittest.TestCase): p.join() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/test_run.py b/tests/basicswap/test_run.py index 9af3624..89aac3b 100644 --- a/tests/basicswap/test_run.py +++ b/tests/basicswap/test_run.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2019-2024 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -77,119 +78,200 @@ class Test(BaseTest): cls.start_pivx_nodes = False super(Test, cls).setUpClass() - btc_addr1 = callnoderpc(1, 'getnewaddress', ['initial funds', 'bech32'], base_rpc_port=BTC_BASE_RPC_PORT) - ltc_addr1 = callnoderpc(1, 'getnewaddress', ['initial funds', 'bech32'], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat') + btc_addr1 = callnoderpc( + 1, + "getnewaddress", + ["initial funds", "bech32"], + base_rpc_port=BTC_BASE_RPC_PORT, + ) + ltc_addr1 = callnoderpc( + 1, + "getnewaddress", + ["initial funds", "bech32"], + base_rpc_port=LTC_BASE_RPC_PORT, + wallet="wallet.dat", + ) - callnoderpc(0, 'sendtoaddress', [btc_addr1, 1000], base_rpc_port=BTC_BASE_RPC_PORT) - callnoderpc(0, 'sendtoaddress', [ltc_addr1, 1000], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat') + callnoderpc( + 0, "sendtoaddress", [btc_addr1, 1000], base_rpc_port=BTC_BASE_RPC_PORT + ) + callnoderpc( + 0, + "sendtoaddress", + [ltc_addr1, 1000], + base_rpc_port=LTC_BASE_RPC_PORT, + wallet="wallet.dat", + ) - wait_for_balance(test_delay_event, 'http://127.0.0.1:1801/json/wallets/btc', 'balance', 1000.0) - wait_for_balance(test_delay_event, 'http://127.0.0.1:1801/json/wallets/ltc', 'balance', 1000.0) + wait_for_balance( + test_delay_event, + "http://127.0.0.1:1801/json/wallets/btc", + "balance", + 1000.0, + ) + wait_for_balance( + test_delay_event, + "http://127.0.0.1:1801/json/wallets/ltc", + "balance", + 1000.0, + ) # Wait for height, or sequencelock is thrown off by genesis blocktime cls.waitForParticlHeight(3) @classmethod def tearDownClass(cls): - logging.info('Finalising test') + logging.info("Finalising test") super(Test, cls).tearDownClass() def getBalance(self, js_wallets, coin_type): ci = self.swap_clients[0].ci(coin_type) - ticker = chainparams[coin_type]['ticker'] + ticker = chainparams[coin_type]["ticker"] coin_wallet = js_wallets[ticker] - rv = float(coin_wallet['balance']) - rv += float(coin_wallet['unconfirmed']) - if 'immature' in coin_wallet: - rv += float(coin_wallet['immature']) + rv = float(coin_wallet["balance"]) + rv += float(coin_wallet["unconfirmed"]) + if "immature" in coin_wallet: + rv += float(coin_wallet["immature"]) return ci.make_int(rv) def test_001_js_coins(self): - js_coins = read_json_api(1800, 'coins') + js_coins = read_json_api(1800, "coins") for c in Coins: - coin = next((x for x in js_coins if x['id'] == int(c)), None) - if c in (Coins.PART, Coins.BTC, Coins.LTC, Coins.PART_ANON, Coins.PART_BLIND): - assert (coin['active'] is True) + coin = next((x for x in js_coins if x["id"] == int(c)), None) + if c in ( + Coins.PART, + Coins.BTC, + Coins.LTC, + Coins.PART_ANON, + Coins.PART_BLIND, + ): + assert coin["active"] is True else: - assert (coin['active'] is False) + assert coin["active"] is False if c in (Coins.PART_ANON, Coins.PART_BLIND): - assert (coin['ticker'] == 'PART') + assert coin["ticker"] == "PART" def test_002_lookup_rates(self): rv = self.swap_clients[0].lookupRates(Coins.BTC, Coins.PART) - assert ('coingecko' in rv) + assert "coingecko" in rv rv = self.swap_clients[0].lookupRates(Coins.LTC, Coins.BTC) - assert ('coingecko' in rv) + assert "coingecko" in rv - rv = read_json_api(1800, 'rateslist?from=PART&to=BTC') + rv = read_json_api(1800, "rateslist?from=PART&to=BTC") assert len(rv) == 1 def test_003_api(self): - logging.info('---------- Test API') + logging.info("---------- Test API") - help_output = read_json_api(1800, 'help') - assert ('getcoinseed' in help_output['commands']) + help_output = read_json_api(1800, "help") + assert "getcoinseed" in help_output["commands"] - rv = read_json_api(1800, 'getcoinseed') - assert (rv['error'] == 'No post data') + rv = read_json_api(1800, "getcoinseed") + assert rv["error"] == "No post data" - rv = read_json_api(1800, 'getcoinseed', {'coin': 'PART'}) - assert ('seed is set from the Basicswap mnemonic' in rv['error']) + rv = read_json_api(1800, "getcoinseed", {"coin": "PART"}) + assert "seed is set from the Basicswap mnemonic" in rv["error"] - rv = read_json_api(1800, 'getcoinseed', {'coin': 'BTC'}) - assert (rv['seed'] == '8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b') - assert (rv['seed_id'] == '3da5c0af91879e8ce97d9a843874601c08688078') + rv = read_json_api(1800, "getcoinseed", {"coin": "BTC"}) + assert ( + rv["seed"] + == "8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b" + ) + assert rv["seed_id"] == "3da5c0af91879e8ce97d9a843874601c08688078" - rv = read_json_api(1800, 'identities/ppCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F', {'set_label': 'test 1'}) - assert (len(rv) == 1) - assert (rv[0]['address'] == 'ppCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F') - assert (rv[0]['label'] == 'test 1') - rv = read_json_api(1800, 'identities/ppCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F', {'set_label': 'test 2'}) - assert (len(rv) == 1) - assert (rv[0]['address'] == 'ppCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F') - assert (rv[0]['label'] == 'test 2') + rv = read_json_api( + 1800, + "identities/ppCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F", + {"set_label": "test 1"}, + ) + assert len(rv) == 1 + assert rv[0]["address"] == "ppCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F" + assert rv[0]["label"] == "test 1" + rv = read_json_api( + 1800, + "identities/ppCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F", + {"set_label": "test 2"}, + ) + assert len(rv) == 1 + assert rv[0]["address"] == "ppCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F" + assert rv[0]["label"] == "test 2" - rv = read_json_api(1800, 'identities/pPCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F', {'set_label': 'test 3'}) - assert (rv['error'] == 'Invalid identity address') + rv = read_json_api( + 1800, + "identities/pPCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F", + {"set_label": "test 3"}, + ) + assert rv["error"] == "Invalid identity address" - rv = read_json_api(1800, 'identities/ppCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F', {'set_note': 'note 1'}) - assert (len(rv) == 1) - assert (rv[0]['address'] == 'ppCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F') - assert (rv[0]['label'] == 'test 2') - assert (rv[0]['note'] == 'note 1') + rv = read_json_api( + 1800, + "identities/ppCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F", + {"set_note": "note 1"}, + ) + assert len(rv) == 1 + assert rv[0]["address"] == "ppCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F" + assert rv[0]["label"] == "test 2" + assert rv[0]["note"] == "note 1" - rv = read_json_api(1800, 'identities/ppCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F', {'set_automation_override': 1}) - assert (len(rv) == 1) - assert (rv[0]['automation_override'] == 1) + rv = read_json_api( + 1800, + "identities/ppCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F", + {"set_automation_override": 1}, + ) + assert len(rv) == 1 + assert rv[0]["automation_override"] == 1 - rv = read_json_api(1800, 'identities/ppCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F', {'set_visibility_override': 'hide'}) - assert (len(rv) == 1) - assert (rv[0]['visibility_override'] == 1) + rv = read_json_api( + 1800, + "identities/ppCsRro5po7Yu6kyu5XjSyr3A1PPdk9j1F", + {"set_visibility_override": "hide"}, + ) + assert len(rv) == 1 + assert rv[0]["visibility_override"] == 1 - rv = read_json_api(1800, 'automationstrategies') - assert (len(rv) == 2) + rv = read_json_api(1800, "automationstrategies") + assert len(rv) == 2 - rv = read_json_api(1800, 'automationstrategies/1') - assert (rv['label'] == 'Accept All') + rv = read_json_api(1800, "automationstrategies/1") + assert rv["label"] == "Accept All" - sx_addr = read_json_api(1800, 'wallets/part/newstealthaddress') - assert (callnoderpc(0, 'getaddressinfo', [sx_addr, ])['isstealthaddress'] is True) + sx_addr = read_json_api(1800, "wallets/part/newstealthaddress") + assert ( + callnoderpc( + 0, + "getaddressinfo", + [ + sx_addr, + ], + )["isstealthaddress"] + is True + ) - rv = read_json_api(1800, 'wallets/part') - assert ('locked_utxos' in rv) + rv = read_json_api(1800, "wallets/part") + assert "locked_utxos" in rv - rv = read_json_api(1800, 'validateamount', {'coin': 'part', 'amount': 0.000000015}) - assert ('Mantissa too long' in rv['error']) + rv = read_json_api( + 1800, "validateamount", {"coin": "part", "amount": 0.000000015} + ) + assert "Mantissa too long" in rv["error"] - rv = read_json_api(1800, 'validateamount', {'coin': 'part', 'amount': 0.000000015, 'method': 'roundoff'}) - assert (rv == '0.00000002') + rv = read_json_api( + 1800, + "validateamount", + {"coin": "part", "amount": 0.000000015, "method": "roundoff"}, + ) + assert rv == "0.00000002" - rv = read_json_api(1800, 'validateamount', {'coin': 'part', 'amount': 0.000000015, 'method': 'rounddown'}) - assert (rv == '0.00000001') + rv = read_json_api( + 1800, + "validateamount", + {"coin": "part", "amount": 0.000000015, "method": "rounddown"}, + ) + assert rv == "0.00000001" def test_004_validateSwapType(self): - logging.info('---------- Test validateSwapType') + logging.info("---------- Test validateSwapType") sc = self.swap_clients[0] @@ -213,31 +295,56 @@ class Test(BaseTest): for case in should_pass: sc.validateSwapType(case[0], case[1], case[2]) for case in should_fail: - self.assertRaises(ValueError, sc.validateSwapType, case[0], case[1], case[2]) + self.assertRaises( + ValueError, sc.validateSwapType, case[0], case[1], case[2] + ) def test_003_cltv(self): test_coin_from = Coins.PART - logging.info('---------- Test {} cltv'.format(test_coin_from.name)) + logging.info("---------- Test {} cltv".format(test_coin_from.name)) ci = self.swap_clients[0].ci(test_coin_from) - deploymentinfo = callnoderpc(0, 'getdeploymentinfo') - bip65_active = deploymentinfo['deployments']['bip65']['active'] - assert (bip65_active) + deploymentinfo = callnoderpc(0, "getdeploymentinfo") + bip65_active = deploymentinfo["deployments"]["bip65"]["active"] + assert bip65_active - chain_height = callnoderpc(0, 'getblockcount') - script = CScript([chain_height + 3, OP_CHECKLOCKTIMEVERIFY, ]) + chain_height = callnoderpc(0, "getblockcount") + script = CScript( + [ + chain_height + 3, + OP_CHECKLOCKTIMEVERIFY, + ] + ) script_dest = ci.getScriptDest(script) tx = CTransaction() tx.nVersion = ci.txVersion() tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest)) tx_hex = ToHex(tx) - tx_funded = callnoderpc(0, 'fundrawtransaction', [tx_hex]) - utxo_pos = 0 if tx_funded['changepos'] == 1 else 1 - tx_signed = callnoderpc(0, 'signrawtransactionwithwallet', [tx_funded['hex'], ])['hex'] - txid = callnoderpc(0, 'sendrawtransaction', [tx_signed, ]) + tx_funded = callnoderpc(0, "fundrawtransaction", [tx_hex]) + utxo_pos = 0 if tx_funded["changepos"] == 1 else 1 + tx_signed = callnoderpc( + 0, + "signrawtransactionwithwallet", + [ + tx_funded["hex"], + ], + )["hex"] + txid = callnoderpc( + 0, + "sendrawtransaction", + [ + tx_signed, + ], + ) - addr_out = callnoderpc(0, 'getnewaddress', ['cltv test', ]) + addr_out = callnoderpc( + 0, + "getnewaddress", + [ + "cltv test", + ], + ) pkh = ci.decodeAddress(addr_out) script_out = ci.getScriptForPubkeyHash(pkh) @@ -247,7 +354,9 @@ class Test(BaseTest): tx_spend.vin.append(CTxIn(COutPoint(int(txid, 16), utxo_pos))) tx_spend.vout.append(ci.txoType()(ci.make_int(1.0999), script_out)) tx_spend.wit.vtxinwit.append(CTxInWitness()) - tx_spend.wit.vtxinwit[0].scriptWitness.stack = [script, ] + tx_spend.wit.vtxinwit[0].scriptWitness.stack = [ + script, + ] tx_spend_hex = ToHex(tx_spend) tx_spend.nLockTime = chain_height + 2 @@ -255,76 +364,151 @@ class Test(BaseTest): for tx_hex in [tx_spend_invalid_hex, tx_spend_hex]: try: - txid = callnoderpc(0, 'sendrawtransaction', [tx_hex, ]) + txid = callnoderpc( + 0, + "sendrawtransaction", + [ + tx_hex, + ], + ) except Exception as e: - assert ('non-final' in str(e)) + assert "non-final" in str(e) else: - assert False, 'Should fail' + assert False, "Should fail" self.waitForParticlHeight(chain_height + 3) try: - txid = callnoderpc(0, 'sendrawtransaction', [tx_spend_invalid_hex, ]) + txid = callnoderpc( + 0, + "sendrawtransaction", + [ + tx_spend_invalid_hex, + ], + ) except Exception as e: - assert ('Locktime requirement not satisfied' in str(e)) + assert "Locktime requirement not satisfied" in str(e) else: - assert False, 'Should fail' + assert False, "Should fail" - chain_height = callnoderpc(0, 'getblockcount') - txid = callnoderpc(0, 'sendrawtransaction', [tx_spend_hex, ]) - ro = callnoderpc(0, 'listreceivedbyaddress', [0, ]) + chain_height = callnoderpc(0, "getblockcount") + txid = callnoderpc( + 0, + "sendrawtransaction", + [ + tx_spend_hex, + ], + ) + ro = callnoderpc( + 0, + "listreceivedbyaddress", + [ + 0, + ], + ) sum_addr = 0 for entry in ro: - if entry['address'] == addr_out: - sum_addr += entry['amount'] - assert (sum_addr == 1.0999) + if entry["address"] == addr_out: + sum_addr += entry["amount"] + assert sum_addr == 1.0999 # Ensure tx was mined for i in range(5): self.waitForParticlHeight(chain_height + i) - tx_wallet = callnoderpc(0, 'gettransaction', [txid, ]) - if 'blockhash' in tx_wallet: + tx_wallet = callnoderpc( + 0, + "gettransaction", + [ + txid, + ], + ) + if "blockhash" in tx_wallet: break - assert (len(tx_wallet['blockhash']) == 64) + assert len(tx_wallet["blockhash"]) == 64 def test_01_verifyrawtransaction(self): - txn = '0200000001eb6e5c4ebba4efa32f40c7314cad456a64008e91ee30b2dd0235ab9bb67fbdbb01000000ee47304402200956933242dde94f6cf8f195a470f8d02aef21ec5c9b66c5d3871594bdb74c9d02201d7e1b440de8f4da672d689f9e37e98815fb63dbc1706353290887eb6e8f7235012103dc1b24feb32841bc2f4375da91fa97834e5983668c2a39a6b7eadb60e7033f9d205a803b28fe2f86c17db91fa99d7ed2598f79b5677ffe869de2e478c0d1c02cc7514c606382012088a8201fe90717abb84b481c2a59112414ae56ec8acc72273642ca26cc7a5812fdc8f68876a914225fbfa4cb725b75e511810ac4d6f74069bdded26703520140b27576a914207eb66b2fd6ed9924d6217efc7fa7b38dfabe666888acffffffff01e0167118020000001976a9140044e188928710cecba8311f1cf412135b98145c88ac00000000' + txn = "0200000001eb6e5c4ebba4efa32f40c7314cad456a64008e91ee30b2dd0235ab9bb67fbdbb01000000ee47304402200956933242dde94f6cf8f195a470f8d02aef21ec5c9b66c5d3871594bdb74c9d02201d7e1b440de8f4da672d689f9e37e98815fb63dbc1706353290887eb6e8f7235012103dc1b24feb32841bc2f4375da91fa97834e5983668c2a39a6b7eadb60e7033f9d205a803b28fe2f86c17db91fa99d7ed2598f79b5677ffe869de2e478c0d1c02cc7514c606382012088a8201fe90717abb84b481c2a59112414ae56ec8acc72273642ca26cc7a5812fdc8f68876a914225fbfa4cb725b75e511810ac4d6f74069bdded26703520140b27576a914207eb66b2fd6ed9924d6217efc7fa7b38dfabe666888acffffffff01e0167118020000001976a9140044e188928710cecba8311f1cf412135b98145c88ac00000000" prevout = { - 'txid': 'bbbd7fb69bab3502ddb230ee918e00646a45ad4c31c7402fa3efa4bb4e5c6eeb', - 'vout': 1, - 'scriptPubKey': 'a9143d37191e8b864222d14952a14c85504677a0581d87', - 'redeemScript': '6382012088a8201fe90717abb84b481c2a59112414ae56ec8acc72273642ca26cc7a5812fdc8f68876a914225fbfa4cb725b75e511810ac4d6f74069bdded26703520140b27576a914207eb66b2fd6ed9924d6217efc7fa7b38dfabe666888ac', - 'amount': 1.0} - ro = callnoderpc(0, 'verifyrawtransaction', [txn, [prevout, ]]) - assert (ro['inputs_valid'] is False) - assert (ro['validscripts'] == 1) + "txid": "bbbd7fb69bab3502ddb230ee918e00646a45ad4c31c7402fa3efa4bb4e5c6eeb", + "vout": 1, + "scriptPubKey": "a9143d37191e8b864222d14952a14c85504677a0581d87", + "redeemScript": "6382012088a8201fe90717abb84b481c2a59112414ae56ec8acc72273642ca26cc7a5812fdc8f68876a914225fbfa4cb725b75e511810ac4d6f74069bdded26703520140b27576a914207eb66b2fd6ed9924d6217efc7fa7b38dfabe666888ac", + "amount": 1.0, + } + ro = callnoderpc( + 0, + "verifyrawtransaction", + [ + txn, + [ + prevout, + ], + ], + ) + assert ro["inputs_valid"] is False + assert ro["validscripts"] == 1 - prevout['amount'] = 100.0 - ro = callnoderpc(0, 'verifyrawtransaction', [txn, [prevout, ]]) - assert (ro['inputs_valid'] is True) - assert (ro['validscripts'] == 1) + prevout["amount"] = 100.0 + ro = callnoderpc( + 0, + "verifyrawtransaction", + [ + txn, + [ + prevout, + ], + ], + ) + assert ro["inputs_valid"] is True + assert ro["validscripts"] == 1 - txn = 'a000000000000128e8ba6a28673f2ebb5fd983b27a791fd1888447a47638b3cd8bfdd3f54a6f1e0100000000a90040000101e0c69a3b000000001976a9146c0f1ea47ca2bf84ed87bf3aa284e18748051f5788ac04473044022026b01f3a90e46883949404141467b741cd871722a4aaae8ddc8c4d6ab6fb1c77022047a2f3be2dcbe4c51837d2d5e0329aaa8a13a8186b03186b127cc51185e4f3ab012103dc1b24feb32841bc2f4375da91fa97834e5983668c2a39a6b7eadb60e7033f9d0100606382012088a8201fe90717abb84b481c2a59112414ae56ec8acc72273642ca26cc7a5812fdc8f68876a914207eb66b2fd6ed9924d6217efc7fa7b38dfabe666703a90040b27576a914225fbfa4cb725b75e511810ac4d6f74069bdded26888ac' + txn = "a000000000000128e8ba6a28673f2ebb5fd983b27a791fd1888447a47638b3cd8bfdd3f54a6f1e0100000000a90040000101e0c69a3b000000001976a9146c0f1ea47ca2bf84ed87bf3aa284e18748051f5788ac04473044022026b01f3a90e46883949404141467b741cd871722a4aaae8ddc8c4d6ab6fb1c77022047a2f3be2dcbe4c51837d2d5e0329aaa8a13a8186b03186b127cc51185e4f3ab012103dc1b24feb32841bc2f4375da91fa97834e5983668c2a39a6b7eadb60e7033f9d0100606382012088a8201fe90717abb84b481c2a59112414ae56ec8acc72273642ca26cc7a5812fdc8f68876a914207eb66b2fd6ed9924d6217efc7fa7b38dfabe666703a90040b27576a914225fbfa4cb725b75e511810ac4d6f74069bdded26888ac" prevout = { - 'txid': '1e6f4af5d3fd8bcdb33876a4478488d11f797ab283d95fbb2e3f67286abae828', - 'vout': 1, - 'scriptPubKey': 'a914129aee070317bbbd57062288849e85cf57d15c2687', - 'redeemScript': '6382012088a8201fe90717abb84b481c2a59112414ae56ec8acc72273642ca26cc7a5812fdc8f68876a914207eb66b2fd6ed9924d6217efc7fa7b38dfabe666703a90040b27576a914225fbfa4cb725b75e511810ac4d6f74069bdded26888ac', - 'amount': 1.0} - ro = callnoderpc(0, 'verifyrawtransaction', [txn, [prevout, ]]) - assert (ro['inputs_valid'] is False) - assert (ro['validscripts'] == 0) # Amount covered by signature + "txid": "1e6f4af5d3fd8bcdb33876a4478488d11f797ab283d95fbb2e3f67286abae828", + "vout": 1, + "scriptPubKey": "a914129aee070317bbbd57062288849e85cf57d15c2687", + "redeemScript": "6382012088a8201fe90717abb84b481c2a59112414ae56ec8acc72273642ca26cc7a5812fdc8f68876a914207eb66b2fd6ed9924d6217efc7fa7b38dfabe666703a90040b27576a914225fbfa4cb725b75e511810ac4d6f74069bdded26888ac", + "amount": 1.0, + } + ro = callnoderpc( + 0, + "verifyrawtransaction", + [ + txn, + [ + prevout, + ], + ], + ) + assert ro["inputs_valid"] is False + assert ro["validscripts"] == 0 # Amount covered by signature - prevout['amount'] = 90.0 - ro = callnoderpc(0, 'verifyrawtransaction', [txn, [prevout, ]]) - assert (ro['inputs_valid'] is True) - assert (ro['validscripts'] == 1) + prevout["amount"] = 90.0 + ro = callnoderpc( + 0, + "verifyrawtransaction", + [ + txn, + [ + prevout, + ], + ], + ) + assert ro["inputs_valid"] is True + assert ro["validscripts"] == 1 def test_02_part_ltc(self): - logging.info('---------- Test PART to LTC') + logging.info("---------- Test PART to LTC") swap_clients = self.swap_clients swap_value = 100 * COIN - offer_id = swap_clients[0].postOffer(Coins.PART, Coins.LTC, swap_value, 0.1 * COIN, swap_value, SwapTypes.SELLER_FIRST) + offer_id = swap_clients[0].postOffer( + Coins.PART, + Coins.LTC, + swap_value, + 0.1 * COIN, + swap_value, + SwapTypes.SELLER_FIRST, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -336,40 +520,74 @@ class Test(BaseTest): wait_for_in_progress(test_delay_event, swap_clients[1], bid_id, sent=True) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=80) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=30) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=80, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=30, + ) # Verify lock tx spends are found in the expected wallets bid, offer = swap_clients[0].getBidAndOffer(bid_id) max_fee: int = 1000 itx_spend = bid.initiate_tx.spend_txid.hex() ci_node_1_from = swap_clients[1].ci(Coins.PART) - wtx = ci_node_1_from.rpc_wallet('gettransaction', [itx_spend,]) - assert (swap_value - ci_node_1_from.make_int(wtx['details'][0]['amount']) < max_fee) + wtx = ci_node_1_from.rpc_wallet( + "gettransaction", + [ + itx_spend, + ], + ) + assert ( + swap_value - ci_node_1_from.make_int(wtx["details"][0]["amount"]) < max_fee + ) ci_node_0_to = swap_clients[0].ci(Coins.LTC) ptx_spend = bid.participate_tx.spend_txid.hex() - wtx = ci_node_0_to.rpc_wallet('gettransaction', [ptx_spend,]) - assert (bid.amount_to - ci_node_0_to.make_int(wtx['details'][0]['amount']) < max_fee) + wtx = ci_node_0_to.rpc_wallet( + "gettransaction", + [ + ptx_spend, + ], + ) + assert ( + bid.amount_to - ci_node_0_to.make_int(wtx["details"][0]["amount"]) < max_fee + ) bid_id_hex = bid_id.hex() - path = f'bids/{bid_id_hex}/states' + path = f"bids/{bid_id_hex}/states" offerer_states = read_json_api(1800, path) bidder_states = read_json_api(1801, path) - assert (compare_bid_states(offerer_states, self.states_offerer_sh[0]) is True) - assert (compare_bid_states(bidder_states, self.states_bidder_sh[0]) is True) + assert compare_bid_states(offerer_states, self.states_offerer_sh[0]) is True + assert compare_bid_states(bidder_states, self.states_bidder_sh[0]) is True js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 def test_03_ltc_part(self): - logging.info('---------- Test LTC to PART') + logging.info("---------- Test LTC to PART") swap_clients = self.swap_clients - offer_id = swap_clients[1].postOffer(Coins.LTC, Coins.PART, 10 * COIN, 9.0 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST) + offer_id = swap_clients[1].postOffer( + Coins.LTC, + Coins.PART, + 10 * COIN, + 9.0 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + ) wait_for_offer(test_delay_event, swap_clients[0], offer_id) offer = swap_clients[0].getOffer(offer_id) @@ -380,19 +598,39 @@ class Test(BaseTest): wait_for_in_progress(test_delay_event, swap_clients[0], bid_id, sent=True) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=80) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=30) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=80, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=30, + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 def test_04_ltc_btc(self): - logging.info('---------- Test LTC to BTC') + logging.info("---------- Test LTC to BTC") swap_clients = self.swap_clients - offer_id = swap_clients[0].postOffer(Coins.LTC, Coins.BTC, 10 * COIN, 0.1 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST) + offer_id = swap_clients[0].postOffer( + Coins.LTC, + Coins.BTC, + 10 * COIN, + 0.1 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -403,58 +641,99 @@ class Test(BaseTest): wait_for_in_progress(test_delay_event, swap_clients[1], bid_id, sent=True) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=80) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=30) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=80, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=30, + ) js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 def test_05_refund(self): # Seller submits initiate txn, buyer doesn't respond - logging.info('---------- Test refund, LTC to BTC') + logging.info("---------- Test refund, LTC to BTC") swap_clients = self.swap_clients - offer_id = swap_clients[0].postOffer(Coins.LTC, Coins.BTC, 10 * COIN, 0.1 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST, - TxLockTypes.SEQUENCE_LOCK_BLOCKS, 10) + offer_id = swap_clients[0].postOffer( + Coins.LTC, + Coins.BTC, + 10 * COIN, + 0.1 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + TxLockTypes.SEQUENCE_LOCK_BLOCKS, + 10, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) bid_id = swap_clients[1].postBid(offer_id, offer.amount_from) wait_for_bid(test_delay_event, swap_clients[0], bid_id) - read_json_api(1801, 'bids/{}'.format(bid_id.hex()), {'abandon': True}) + read_json_api(1801, "bids/{}".format(bid_id.hex()), {"abandon": True}) swap_clients[0].acceptBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=80) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.BID_ABANDONED, sent=True, wait_for=30) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=80, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.BID_ABANDONED, + sent=True, + wait_for=30, + ) - js_0_bid = read_json_api(1800, 'bids/{}'.format(bid_id.hex())) - js_1_bid = read_json_api(1801, 'bids/{}'.format(bid_id.hex())) - assert (js_0_bid['itx_state'] == 'Refunded') - assert (js_1_bid['ptx_state'] == 'Unknown') + js_0_bid = read_json_api(1800, "bids/{}".format(bid_id.hex())) + js_1_bid = read_json_api(1801, "bids/{}".format(bid_id.hex())) + assert js_0_bid["itx_state"] == "Refunded" + assert js_1_bid["ptx_state"] == "Unknown" js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 bid_id_hex = bid_id.hex() - path = f'bids/{bid_id_hex}/states' + path = f"bids/{bid_id_hex}/states" offerer_states = read_json_api(1800, path) bidder_states = read_json_api(1801, path) - assert (compare_bid_states(offerer_states, self.states_offerer_sh[1]) is True) - assert (bidder_states[-1][1] == 'Bid Abandoned') + assert compare_bid_states(offerer_states, self.states_offerer_sh[1]) is True + assert bidder_states[-1][1] == "Bid Abandoned" def test_06_self_bid(self): - logging.info('---------- Test same client, BTC to LTC') + logging.info("---------- Test same client, BTC to LTC") swap_clients = self.swap_clients js_0_before = read_json_api(1800) - offer_id = swap_clients[0].postOffer(Coins.BTC, Coins.LTC, 10 * COIN, 10 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST) + offer_id = swap_clients[0].postOffer( + Coins.BTC, + Coins.LTC, + 10 * COIN, + 10 * COIN, + 10 * COIN, + SwapTypes.SELLER_FIRST, + ) wait_for_offer(test_delay_event, swap_clients[0], offer_id) offer = swap_clients[0].getOffer(offer_id) @@ -463,20 +742,41 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[0], bid_id) swap_clients[0].acceptBid(bid_id) - wait_for_bid_tx_state(test_delay_event, swap_clients[0], bid_id, TxStates.TX_REDEEMED, TxStates.TX_REDEEMED, wait_for=80) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=30) + wait_for_bid_tx_state( + test_delay_event, + swap_clients[0], + bid_id, + TxStates.TX_REDEEMED, + TxStates.TX_REDEEMED, + wait_for=80, + ) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=30, + ) js_0 = read_json_api(1800) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_0['num_recv_bids'] == js_0_before['num_recv_bids'] + 1 and js_0['num_sent_bids'] == js_0_before['num_sent_bids'] + 1) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert ( + js_0["num_recv_bids"] == js_0_before["num_recv_bids"] + 1 + and js_0["num_sent_bids"] == js_0_before["num_sent_bids"] + 1 + ) def test_07_error(self): - logging.info('---------- Test error, BTC to LTC, set fee above bid value') + logging.info("---------- Test error, BTC to LTC, set fee above bid value") swap_clients = self.swap_clients - js_0_before = read_json_api(1800) - - offer_id = swap_clients[0].postOffer(Coins.BTC, Coins.LTC, 0.001 * COIN, 1.0 * COIN, 0.001 * COIN, SwapTypes.SELLER_FIRST) + offer_id = swap_clients[0].postOffer( + Coins.BTC, + Coins.LTC, + 0.001 * COIN, + 1.0 * COIN, + 0.001 * COIN, + SwapTypes.SELLER_FIRST, + ) wait_for_offer(test_delay_event, swap_clients[0], offer_id) offer = swap_clients[0].getOffer(offer_id) @@ -486,44 +786,86 @@ class Test(BaseTest): swap_clients[0].acceptBid(bid_id) try: - swap_clients[0].getChainClientSettings(Coins.BTC)['override_feerate'] = 10.0 - swap_clients[0].getChainClientSettings(Coins.LTC)['override_feerate'] = 10.0 - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_ERROR, wait_for=60) + swap_clients[0].getChainClientSettings(Coins.BTC)["override_feerate"] = 10.0 + swap_clients[0].getChainClientSettings(Coins.LTC)["override_feerate"] = 10.0 + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.BID_ERROR, + wait_for=60, + ) swap_clients[0].abandonBid(bid_id) finally: - del swap_clients[0].getChainClientSettings(Coins.BTC)['override_feerate'] - del swap_clients[0].getChainClientSettings(Coins.LTC)['override_feerate'] + del swap_clients[0].getChainClientSettings(Coins.BTC)["override_feerate"] + del swap_clients[0].getChainClientSettings(Coins.LTC)["override_feerate"] def test_08_part_ltc_buyer_first(self): - logging.info('---------- Test PART to LTC, buyer first') + logging.info("---------- Test PART to LTC, buyer first") swap_clients = self.swap_clients - offer_id = swap_clients[0].postOffer(Coins.PART, Coins.LTC, 100 * COIN, 0.1 * COIN, 100 * COIN, SwapTypes.BUYER_FIRST) + swap_clients[0].postOffer( + Coins.PART, + Coins.LTC, + 100 * COIN, + 0.1 * COIN, + 100 * COIN, + SwapTypes.BUYER_FIRST, + ) - logging.warning('TODO') + logging.warning("TODO") def test_09_part_ltc_auto_accept(self): - logging.info('---------- Test PART to LTC, auto accept bid') + logging.info("---------- Test PART to LTC, auto accept bid") swap_clients = self.swap_clients - offer_id = swap_clients[0].postOffer(Coins.PART, Coins.LTC, 100 * COIN, 0.1 * COIN, 100 * COIN, SwapTypes.SELLER_FIRST, auto_accept_bids=True) + offer_id = swap_clients[0].postOffer( + Coins.PART, + Coins.LTC, + 100 * COIN, + 0.1 * COIN, + 100 * COIN, + SwapTypes.SELLER_FIRST, + auto_accept_bids=True, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) bid_id = swap_clients[1].postBid(offer_id, offer.amount_from) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=80) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=30) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=80, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=30, + ) def test_10_bad_ptx(self): # Invalid PTX sent, swap should stall and ITx and PTx should be reclaimed by senders - logging.info('---------- Test bad PTx, LTC to BTC') + logging.info("---------- Test bad PTx, LTC to BTC") swap_clients = self.swap_clients swap_value = make_int(random.uniform(0.001, 10.0), scale=8, r=1) - logging.info('swap_value {}'.format(format_amount(swap_value, 8))) - offer_id = swap_clients[0].postOffer(Coins.LTC, Coins.BTC, swap_value, 0.1 * COIN, swap_value, SwapTypes.SELLER_FIRST, - TxLockTypes.SEQUENCE_LOCK_BLOCKS, 18) + logging.info("swap_value {}".format(format_amount(swap_value, 8))) + offer_id = swap_clients[0].postOffer( + Coins.LTC, + Coins.BTC, + swap_value, + 0.1 * COIN, + swap_value, + SwapTypes.SELLER_FIRST, + TxLockTypes.SEQUENCE_LOCK_BLOCKS, + 18, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -533,28 +875,41 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[0], bid_id) swap_clients[0].acceptBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=120) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=30) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=120, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=30, + ) - js_0_bid = read_json_api(1800, 'bids/{}'.format(bid_id.hex())) - js_1_bid = read_json_api(1801, 'bids/{}'.format(bid_id.hex())) - assert (js_0_bid['itx_state'] == 'Refunded') - assert (js_1_bid['ptx_state'] == 'Refunded') + js_0_bid = read_json_api(1800, "bids/{}".format(bid_id.hex())) + js_1_bid = read_json_api(1801, "bids/{}".format(bid_id.hex())) + assert js_0_bid["itx_state"] == "Refunded" + assert js_1_bid["ptx_state"] == "Refunded" js_0 = read_json_api(1800) js_1 = read_json_api(1801) - assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) - assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) + assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0 + assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0 bid_id_hex = bid_id.hex() - path = f'bids/{bid_id_hex}/states' + path = f"bids/{bid_id_hex}/states" offerer_states = read_json_api(1800, path) bidder_states = read_json_api(1801, path) - assert (compare_bid_states(offerer_states, self.states_offerer_sh[1]) is True) - assert (compare_bid_states(bidder_states, self.states_bidder_sh[1]) is True) + assert compare_bid_states(offerer_states, self.states_offerer_sh[1]) is True + assert compare_bid_states(bidder_states, self.states_bidder_sh[1]) is True - ''' + """ def test_11_refund(self): # Seller submits initiate txn, buyer doesn't respond, repeat of test 5 using debug_ind logging.info('---------- Test refund, LTC to BTC') @@ -585,36 +940,50 @@ class Test(BaseTest): js_1 = read_json_api(1801) assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0) assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0) - ''' + """ def test_12_withdrawal(self): - logging.info('---------- Test LTC withdrawals') + logging.info("---------- Test LTC withdrawals") - ltc_addr = callnoderpc(0, 'getnewaddress', ['Withdrawal test', 'legacy'], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat') - wallets0 = read_json_api(TEST_HTTP_PORT + 0, 'wallets') - assert (float(wallets0['LTC']['balance']) > 100) + ltc_addr = callnoderpc( + 0, + "getnewaddress", + ["Withdrawal test", "legacy"], + base_rpc_port=LTC_BASE_RPC_PORT, + wallet="wallet.dat", + ) + wallets0 = read_json_api(TEST_HTTP_PORT + 0, "wallets") + assert float(wallets0["LTC"]["balance"]) > 100 post_json = { - 'value': 100, - 'address': ltc_addr, - 'subfee': False, + "value": 100, + "address": ltc_addr, + "subfee": False, } - json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc/withdraw', post_json) - assert (len(json_rv['txid']) == 64) + json_rv = read_json_api(TEST_HTTP_PORT + 0, "wallets/ltc/withdraw", post_json) + assert len(json_rv["txid"]) == 64 def test_13_itx_refund(self): - logging.info('---------- Test ITX refunded') + logging.info("---------- Test ITX refunded") # Initiator claims PTX and refunds ITX after lock expires # Participant loses PTX value without gaining ITX value swap_clients = self.swap_clients - js_w0_before = read_json_api(1800, 'wallets') - js_w1_before = read_json_api(1801, 'wallets') + js_w0_before = read_json_api(1800, "wallets") + js_w1_before = read_json_api(1801, "wallets") swap_value = make_int(random.uniform(2.0, 20.0), scale=8, r=1) - logging.info('swap_value {}'.format(format_amount(swap_value, 8))) - offer_id = swap_clients[0].postOffer(Coins.LTC, Coins.BTC, swap_value, 0.5 * COIN, swap_value, SwapTypes.SELLER_FIRST, - TxLockTypes.SEQUENCE_LOCK_BLOCKS, 18) + logging.info("swap_value {}".format(format_amount(swap_value, 8))) + offer_id = swap_clients[0].postOffer( + Coins.LTC, + Coins.BTC, + swap_value, + 0.5 * COIN, + swap_value, + SwapTypes.SELLER_FIRST, + TxLockTypes.SEQUENCE_LOCK_BLOCKS, + 18, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -626,15 +995,28 @@ class Test(BaseTest): # For testing: Block refunding the ITX until PTX has been redeemed, else ITX refund can become spendable before PTX confirms swap_clients[0].setBidDebugInd(bid_id, DebugTypes.SKIP_LOCK_TX_REFUND) swap_clients[0].acceptBid(bid_id) - wait_for_bid_tx_state(test_delay_event, swap_clients[0], bid_id, TxStates.TX_CONFIRMED, TxStates.TX_REDEEMED, wait_for=60) + wait_for_bid_tx_state( + test_delay_event, + swap_clients[0], + bid_id, + TxStates.TX_CONFIRMED, + TxStates.TX_REDEEMED, + wait_for=60, + ) swap_clients[0].setBidDebugInd(bid_id, DebugTypes.NONE) - wait_for_bid_tx_state(test_delay_event, swap_clients[0], bid_id, TxStates.TX_REFUNDED, TxStates.TX_REDEEMED, wait_for=60) + wait_for_bid_tx_state( + test_delay_event, + swap_clients[0], + bid_id, + TxStates.TX_REFUNDED, + TxStates.TX_REDEEMED, + wait_for=60, + ) - js_w0_after = read_json_api(1800, 'wallets') - js_w1_after = read_json_api(1801, 'wallets') + js_w0_after = read_json_api(1800, "wallets") + js_w1_after = read_json_api(1801, "wallets") - ltc_swap_value = swap_value btc_swap_value = swap_value // 2 node0_btc_before = self.getBalance(js_w0_before, Coins.BTC) node0_btc_after = self.getBalance(js_w0_after, Coins.BTC) @@ -647,77 +1029,121 @@ class Test(BaseTest): node1_ltc_after = self.getBalance(js_w1_after, Coins.LTC) high_fee_value_btc = int(0.001 * COIN) - high_fee_value_ltc = int(0.01 * COIN) # TODO Set fees directly, see listtransactions + high_fee_value_ltc = int( + 0.01 * COIN + ) # TODO Set fees directly, see listtransactions - assert (node0_btc_after > node0_btc_before + btc_swap_value - high_fee_value_btc) - assert (node0_ltc_after > node0_ltc_before - high_fee_value_ltc) + assert node0_btc_after > node0_btc_before + btc_swap_value - high_fee_value_btc + assert node0_ltc_after > node0_ltc_before - high_fee_value_ltc - assert (node1_btc_after < node1_btc_before - btc_swap_value) - assert (node1_ltc_before == node1_ltc_after) + assert node1_btc_after < node1_btc_before - btc_swap_value + assert node1_ltc_before == node1_ltc_after - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=60, + ) bid_id_hex = bid_id.hex() - path = f'bids/{bid_id_hex}/states' + path = f"bids/{bid_id_hex}/states" offerer_states = read_json_api(1800, path) bidder_states = read_json_api(1801, path) - assert (compare_bid_states(offerer_states, self.states_offerer_sh[2]) is True) - assert (compare_bid_states(bidder_states, self.states_bidder_sh[2], exact_match=False) is True) + assert compare_bid_states(offerer_states, self.states_offerer_sh[2]) is True + assert ( + compare_bid_states( + bidder_states, self.states_bidder_sh[2], exact_match=False + ) + is True + ) def test_14_sweep_balance(self): - logging.info('---------- Test sweep balance offer') + logging.info("---------- Test sweep balance offer") swap_clients = self.swap_clients # Disable staking - walletsettings = callnoderpc(2, 'walletsettings', ['stakingoptions', ]) - walletsettings['enabled'] = False - walletsettings = callnoderpc(2, 'walletsettings', ['stakingoptions', walletsettings]) - walletsettings = callnoderpc(2, 'walletsettings', ['stakingoptions', ]) - assert (walletsettings['stakingoptions']['enabled'] is False) + walletsettings = callnoderpc( + 2, + "walletsettings", + [ + "stakingoptions", + ], + ) + walletsettings["enabled"] = False + walletsettings = callnoderpc( + 2, "walletsettings", ["stakingoptions", walletsettings] + ) + walletsettings = callnoderpc( + 2, + "walletsettings", + [ + "stakingoptions", + ], + ) + assert walletsettings["stakingoptions"]["enabled"] is False # Prepare balance - js_w2 = read_json_api(1802, 'wallets') - if float(js_w2['PART']['balance']) < 100.0: + js_w2 = read_json_api(1802, "wallets") + if float(js_w2["PART"]["balance"]) < 100.0: post_json = { - 'value': 100.0, - 'address': js_w2['PART']['deposit_address'], - 'subfee': False, + "value": 100.0, + "address": js_w2["PART"]["deposit_address"], + "subfee": False, } - json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/part/withdraw', post_json) - assert (len(json_rv['txid']) == 64) - wait_for_balance(test_delay_event, 'http://127.0.0.1:1802/json/wallets/part', 'balance', 100.0) + json_rv = read_json_api( + TEST_HTTP_PORT + 0, "wallets/part/withdraw", post_json + ) + assert len(json_rv["txid"]) == 64 + wait_for_balance( + test_delay_event, + "http://127.0.0.1:1802/json/wallets/part", + "balance", + 100.0, + ) - js_w2 = read_json_api(1802, 'wallets') - assert (float(js_w2['PART']['balance']) >= 100.0) + js_w2 = read_json_api(1802, "wallets") + assert float(js_w2["PART"]["balance"]) >= 100.0 - js_w2 = read_json_api(1802, 'wallets') + js_w2 = read_json_api(1802, "wallets") post_json = { - 'value': float(js_w2['PART']['balance']), - 'address': read_json_api(1802, 'wallets/part/nextdepositaddr'), - 'subfee': True, + "value": float(js_w2["PART"]["balance"]), + "address": read_json_api(1802, "wallets/part/nextdepositaddr"), + "subfee": True, } - json_rv = read_json_api(TEST_HTTP_PORT + 2, 'wallets/part/withdraw', post_json) - assert (len(json_rv['txid']) == 64) - wait_for_balance(test_delay_event, 'http://127.0.0.1:1802/json/wallets/part', 'balance', 10.0) + json_rv = read_json_api(TEST_HTTP_PORT + 2, "wallets/part/withdraw", post_json) + assert len(json_rv["txid"]) == 64 + wait_for_balance( + test_delay_event, "http://127.0.0.1:1802/json/wallets/part", "balance", 10.0 + ) # Create prefunded ITX ci = swap_clients[2].ci(Coins.PART) pi = swap_clients[2].pi(SwapTypes.SELLER_FIRST) - js_w2 = read_json_api(1802, 'wallets') - swap_value = ci.make_int(js_w2['PART']['balance']) + js_w2 = read_json_api(1802, "wallets") + swap_value = ci.make_int(js_w2["PART"]["balance"]) itx = pi.getFundedInitiateTxTemplate(ci, swap_value, True) itx_decoded = ci.describeTx(itx.hex()) n = pi.findMockVout(ci, itx_decoded) - value_after_subfee = ci.make_int(itx_decoded['vout'][n]['value']) - assert (value_after_subfee < swap_value) + value_after_subfee = ci.make_int(itx_decoded["vout"][n]["value"]) + assert value_after_subfee < swap_value swap_value = value_after_subfee wait_for_unspent(test_delay_event, ci, swap_value) # Create swap with prefunded ITX - extra_options = {'prefunded_itx': itx} - offer_id = swap_clients[2].postOffer(Coins.PART, Coins.BTC, swap_value, 2 * COIN, swap_value, SwapTypes.SELLER_FIRST, extra_options=extra_options) + extra_options = {"prefunded_itx": itx} + offer_id = swap_clients[2].postOffer( + Coins.PART, + Coins.BTC, + swap_value, + 2 * COIN, + swap_value, + SwapTypes.SELLER_FIRST, + extra_options=extra_options, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -726,56 +1152,110 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[2], bid_id) swap_clients[2].acceptBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[2], bid_id, BidStates.SWAP_COMPLETED, wait_for=80) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=30) + wait_for_bid( + test_delay_event, + swap_clients[2], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=80, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=30, + ) # Verify expected inputs were used bid, offer = swap_clients[2].getBidAndOffer(bid_id) - assert (bid.initiate_tx) - wtx = ci.rpc('gettransaction', [bid.initiate_tx.txid.hex(),]) - itx_after = ci.describeTx(wtx['hex']) - assert (len(itx_after['vin']) == len(itx_decoded['vin'])) - for i, txin in enumerate(itx_decoded['vin']): - assert (txin['txid'] == itx_after['vin'][i]['txid']) - assert (txin['vout'] == itx_after['vin'][i]['vout']) + assert bid.initiate_tx + wtx = ci.rpc( + "gettransaction", + [ + bid.initiate_tx.txid.hex(), + ], + ) + itx_after = ci.describeTx(wtx["hex"]) + assert len(itx_after["vin"]) == len(itx_decoded["vin"]) + for i, txin in enumerate(itx_decoded["vin"]): + assert txin["txid"] == itx_after["vin"][i]["txid"] + assert txin["vout"] == itx_after["vin"][i]["vout"] def test_15_variable_amount(self): - logging.info('---------- Test fixed rate variable amount offer') + logging.info("---------- Test fixed rate variable amount offer") swap_clients = self.swap_clients swap_value = 86474957 offer_rate = 996774992 - extra_options = {'amount_negotiable': True, 'rate_negotiable': False} - offer_id = swap_clients[1].postOffer(Coins.PART, Coins.BTC, swap_value, offer_rate, swap_value // 2, SwapTypes.SELLER_FIRST, extra_options=extra_options) + extra_options = {"amount_negotiable": True, "rate_negotiable": False} + offer_id = swap_clients[1].postOffer( + Coins.PART, + Coins.BTC, + swap_value, + offer_rate, + swap_value // 2, + SwapTypes.SELLER_FIRST, + extra_options=extra_options, + ) wait_for_offer(test_delay_event, swap_clients[0], offer_id) - offer = swap_clients[0].getOffer(offer_id) bid_amount = 86474842 - bid_id = swap_clients[0].postBid(offer_id, bid_amount, extra_options={'bid_rate': offer_rate}) + bid_id = swap_clients[0].postBid( + offer_id, bid_amount, extra_options={"bid_rate": offer_rate} + ) wait_for_bid(test_delay_event, swap_clients[1], bid_id) bid = swap_clients[1].getBid(bid_id) - assert (bid.amount == 86474828) + assert bid.amount == 86474828 swap_clients[1].acceptBid(bid_id) wait_for_in_progress(test_delay_event, swap_clients[0], bid_id, sent=True) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=80) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=30) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=80, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=30, + ) def pass_99_delay(self): - logging.info('Delay') + logging.info("Delay") for i in range(60 * 10): if test_delay_event.is_set(): break test_delay_event.wait(1) - print('delay', i) + print("delay", i) if i % 2 == 0: - offer_id = self.swap_clients[0].postOffer(Coins.BTC, Coins.LTC, 0.001 * (i + 1) * COIN, 1.0 * (i + 1) * COIN, 0.001 * (i + 1) * COIN, SwapTypes.SELLER_FIRST) + self.swap_clients[0].postOffer( + Coins.BTC, + Coins.LTC, + 0.001 * (i + 1) * COIN, + 1.0 * (i + 1) * COIN, + 0.001 * (i + 1) * COIN, + SwapTypes.SELLER_FIRST, + ) else: - offer_id = self.swap_clients[1].postOffer(Coins.LTC, Coins.BTC, 0.001 * (i + 1) * COIN, 1.0 * (i + 1) * COIN, 0.001 * COIN, SwapTypes.SELLER_FIRST) + self.swap_clients[1].postOffer( + Coins.LTC, + Coins.BTC, + 0.001 * (i + 1) * COIN, + 1.0 * (i + 1) * COIN, + 0.001 * COIN, + SwapTypes.SELLER_FIRST, + ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/test_xmr.py b/tests/basicswap/test_xmr.py index a237376..7f6a3d2 100644 --- a/tests/basicswap/test_xmr.py +++ b/tests/basicswap/test_xmr.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020-2024 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -31,12 +32,7 @@ from basicswap.basicswap_util import ( TxLockTypes, EventLogTypes, ) -from basicswap.util import ( - COIN, - format_amount, - make_int, - TemporaryError -) +from basicswap.util import COIN, format_amount, make_int, TemporaryError from basicswap.util.address import ( toWIF, ) @@ -109,130 +105,144 @@ XMR_BASE_WALLET_RPC_PORT = 23792 signal_event = threading.Event() # Set if test was cancelled test_delay_event = threading.Event() -RESET_TEST = make_boolean(os.getenv('RESET_TEST', 'true')) +RESET_TEST = make_boolean(os.getenv("RESET_TEST", "true")) def prepareXmrDataDir(datadir, node_id, conf_file): - node_dir = os.path.join(datadir, 'xmr_' + str(node_id)) + node_dir = os.path.join(datadir, "xmr_" + str(node_id)) if not os.path.exists(node_dir): os.makedirs(node_dir) cfg_file_path = os.path.join(node_dir, conf_file) if os.path.exists(cfg_file_path): return - with open(cfg_file_path, 'w+') as fp: - fp.write('regtest=1\n') - fp.write('keep-fakechain=1\n') - fp.write('data-dir={}\n'.format(node_dir)) - fp.write('fixed-difficulty=1\n') + with open(cfg_file_path, "w+") as fp: + fp.write("regtest=1\n") + fp.write("keep-fakechain=1\n") + fp.write("data-dir={}\n".format(node_dir)) + fp.write("fixed-difficulty=1\n") # fp.write('offline=1\n') - fp.write('p2p-bind-port={}\n'.format(XMR_BASE_P2P_PORT + node_id)) - fp.write('rpc-bind-port={}\n'.format(XMR_BASE_RPC_PORT + node_id)) - fp.write('p2p-bind-ip=127.0.0.1\n') - fp.write('rpc-bind-ip=127.0.0.1\n') - fp.write('prune-blockchain=1\n') - fp.write('zmq-rpc-bind-port={}\n'.format(XMR_BASE_ZMQ_PORT + node_id)) - fp.write('zmq-rpc-bind-ip=127.0.0.1\n') + fp.write("p2p-bind-port={}\n".format(XMR_BASE_P2P_PORT + node_id)) + fp.write("rpc-bind-port={}\n".format(XMR_BASE_RPC_PORT + node_id)) + fp.write("p2p-bind-ip=127.0.0.1\n") + fp.write("rpc-bind-ip=127.0.0.1\n") + fp.write("prune-blockchain=1\n") + fp.write("zmq-rpc-bind-port={}\n".format(XMR_BASE_ZMQ_PORT + node_id)) + fp.write("zmq-rpc-bind-ip=127.0.0.1\n") for i in range(0, NUM_XMR_NODES): if node_id == i: continue - fp.write('add-exclusive-node=127.0.0.1:{}\n'.format(XMR_BASE_P2P_PORT + i)) + fp.write("add-exclusive-node=127.0.0.1:{}\n".format(XMR_BASE_P2P_PORT + i)) -def prepare_swapclient_dir(datadir, node_id, network_key, network_pubkey, with_coins=set(), cls=None): - basicswap_dir = os.path.join(datadir, 'basicswap_' + str(node_id)) +def prepare_swapclient_dir( + datadir, node_id, network_key, network_pubkey, with_coins=set(), cls=None +): + basicswap_dir = os.path.join(datadir, "basicswap_" + str(node_id)) if not os.path.exists(basicswap_dir): os.makedirs(basicswap_dir) settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME) settings = { - 'debug': True, - 'zmqhost': 'tcp://127.0.0.1', - 'zmqport': BASE_ZMQ_PORT + node_id, - 'htmlhost': '127.0.0.1', - 'htmlport': TEST_HTTP_PORT + node_id, - 'network_key': network_key, - 'network_pubkey': network_pubkey, - 'chainclients': { - 'particl': { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': BASE_RPC_PORT + node_id, - 'rpcuser': 'test' + str(node_id), - 'rpcpassword': 'test_pass' + str(node_id), - 'datadir': os.path.join(datadir, 'part_' + str(node_id)), - 'bindir': cfg.PARTICL_BINDIR, - 'blocks_confirmed': 2, # Faster testing - 'anon_tx_ring_size': 5, # Faster testing + "debug": True, + "zmqhost": "tcp://127.0.0.1", + "zmqport": BASE_ZMQ_PORT + node_id, + "htmlhost": "127.0.0.1", + "htmlport": TEST_HTTP_PORT + node_id, + "network_key": network_key, + "network_pubkey": network_pubkey, + "chainclients": { + "particl": { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": BASE_RPC_PORT + node_id, + "rpcuser": "test" + str(node_id), + "rpcpassword": "test_pass" + str(node_id), + "datadir": os.path.join(datadir, "part_" + str(node_id)), + "bindir": cfg.PARTICL_BINDIR, + "blocks_confirmed": 2, # Faster testing + "anon_tx_ring_size": 5, # Faster testing + }, + "bitcoin": { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": BTC_BASE_RPC_PORT + node_id, + "rpcuser": "test" + str(node_id), + "rpcpassword": "test_pass" + str(node_id), + "datadir": os.path.join(datadir, "btc_" + str(node_id)), + "bindir": cfg.BITCOIN_BINDIR, + "use_segwit": True, }, - 'bitcoin': { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': BTC_BASE_RPC_PORT + node_id, - 'rpcuser': 'test' + str(node_id), - 'rpcpassword': 'test_pass' + str(node_id), - 'datadir': os.path.join(datadir, 'btc_' + str(node_id)), - 'bindir': cfg.BITCOIN_BINDIR, - 'use_segwit': True, - } }, - 'check_progress_seconds': 2, - 'check_watched_seconds': 4, - 'check_expired_seconds': 60, - 'check_events_seconds': 1, - 'check_xmr_swaps_seconds': 1, - 'min_delay_event': 1, - 'max_delay_event': 4, - 'min_delay_event_short': 1, - 'max_delay_event_short': 3, - 'min_delay_retry': 2, - 'max_delay_retry': 10, - 'debug_ui': True, - 'restrict_unknown_seed_wallets': False, + "check_progress_seconds": 2, + "check_watched_seconds": 4, + "check_expired_seconds": 60, + "check_events_seconds": 1, + "check_xmr_swaps_seconds": 1, + "min_delay_event": 1, + "max_delay_event": 4, + "min_delay_event_short": 1, + "max_delay_event_short": 3, + "min_delay_retry": 2, + "max_delay_retry": 10, + "debug_ui": True, + "restrict_unknown_seed_wallets": False, } if Coins.XMR in with_coins: - settings['chainclients']['monero'] = { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': XMR_BASE_RPC_PORT + node_id, - 'walletrpcport': XMR_BASE_WALLET_RPC_PORT + node_id, - 'walletrpcuser': 'test' + str(node_id), - 'walletrpcpassword': 'test_pass' + str(node_id), - 'walletfile': 'testwallet', - 'datadir': os.path.join(datadir, 'xmr_' + str(node_id)), - 'bindir': cfg.XMR_BINDIR, + settings["chainclients"]["monero"] = { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": XMR_BASE_RPC_PORT + node_id, + "walletrpcport": XMR_BASE_WALLET_RPC_PORT + node_id, + "walletrpcuser": "test" + str(node_id), + "walletrpcpassword": "test_pass" + str(node_id), + "walletfile": "testwallet", + "datadir": os.path.join(datadir, "xmr_" + str(node_id)), + "bindir": cfg.XMR_BINDIR, } if Coins.LTC in with_coins: - settings['chainclients']['litecoin'] = { - 'connection_type': 'rpc', - 'manage_daemon': False, - 'rpcport': LTC_BASE_RPC_PORT + node_id, - 'rpcuser': 'test' + str(node_id), - 'rpcpassword': 'test_pass' + str(node_id), - 'datadir': os.path.join(datadir, 'ltc_' + str(node_id)), - 'bindir': cfg.LITECOIN_BINDIR, - 'use_segwit': True, + settings["chainclients"]["litecoin"] = { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": LTC_BASE_RPC_PORT + node_id, + "rpcuser": "test" + str(node_id), + "rpcpassword": "test_pass" + str(node_id), + "datadir": os.path.join(datadir, "ltc_" + str(node_id)), + "bindir": cfg.LITECOIN_BINDIR, + "use_segwit": True, } if cls: cls.addCoinSettings(settings, datadir, node_id) - with open(settings_path, 'w') as fp: + with open(settings_path, "w") as fp: json.dump(settings, fp, indent=4) def btcCli(cmd, node_id=0): - return callrpc_cli(cfg.BITCOIN_BINDIR, os.path.join(TEST_DIR, 'btc_' + str(node_id)), 'regtest', cmd, cfg.BITCOIN_CLI) + return callrpc_cli( + cfg.BITCOIN_BINDIR, + os.path.join(TEST_DIR, "btc_" + str(node_id)), + "regtest", + cmd, + cfg.BITCOIN_CLI, + ) def ltcCli(cmd, node_id=0): - return callrpc_cli(cfg.LITECOIN_BINDIR, os.path.join(TEST_DIR, 'ltc_' + str(node_id)), 'regtest', cmd, cfg.LITECOIN_CLI) + return callrpc_cli( + cfg.LITECOIN_BINDIR, + os.path.join(TEST_DIR, "ltc_" + str(node_id)), + "regtest", + cmd, + cfg.LITECOIN_CLI, + ) def signal_handler(sig, frame): - logging.info('signal {} detected.'.format(sig)) + logging.info("signal {} detected.".format(sig)) signal_event.set() test_delay_event.set() @@ -240,29 +250,39 @@ def signal_handler(sig, frame): def waitForXMRNode(rpc_offset, max_tries=7): for i in range(max_tries + 1): try: - callrpc_xmr(XMR_BASE_RPC_PORT + rpc_offset, 'get_block_count') + callrpc_xmr(XMR_BASE_RPC_PORT + rpc_offset, "get_block_count") return except Exception as ex: if i < max_tries: - logging.warning('Can\'t connect to XMR RPC: %s. Retrying in %d second/s.', str(ex), (i + 1)) + logging.warning( + "Can't connect to XMR RPC: %s. Retrying in %d second/s.", + str(ex), + (i + 1), + ) time.sleep(i + 1) - raise ValueError('waitForXMRNode failed') + raise ValueError("waitForXMRNode failed") def waitForXMRWallet(rpc_offset, auth, max_tries=7): for i in range(max_tries + 1): try: - callrpc_xmr(XMR_BASE_WALLET_RPC_PORT + rpc_offset, 'get_languages', auth=auth) + callrpc_xmr( + XMR_BASE_WALLET_RPC_PORT + rpc_offset, "get_languages", auth=auth + ) return except Exception as ex: if i < max_tries: - logging.warning('Can\'t connect to XMR wallet RPC: %s. Retrying in %d second/s.', str(ex), (i + 1)) + logging.warning( + "Can't connect to XMR wallet RPC: %s. Retrying in %d second/s.", + str(ex), + (i + 1), + ) time.sleep(i + 1) - raise ValueError('waitForXMRWallet failed') + raise ValueError("waitForXMRWallet failed") def callnoderpc(node_id, method, params=[], wallet=None, base_rpc_port=BASE_RPC_PORT): - auth = 'test{0}:test_pass{0}'.format(node_id) + auth = "test{0}:test_pass{0}".format(node_id) return callrpc(base_rpc_port + node_id, auth, method, params, wallet) @@ -275,7 +295,7 @@ def run_coins_loop(cls): try: cls.coins_loop() except Exception as e: - logging.warning('run_coins_loop ' + str(e)) + logging.warning("run_coins_loop " + str(e)) test_delay_event.wait(1.0) @@ -316,32 +336,40 @@ class BaseTest(unittest.TestCase): @classmethod def setUpClass(cls): if signal_event.is_set(): - raise ValueError('Test has been cancelled.') + raise ValueError("Test has been cancelled.") test_delay_event.clear() random.seed(time.time()) logger.propagate = False logger.handlers = [] logger.setLevel(logging.INFO) # DEBUG shows many messages from requests.post - formatter = logging.Formatter('%(asctime)s %(levelname)s : %(message)s') + formatter = logging.Formatter("%(asctime)s %(levelname)s : %(message)s") stream_stdout = logging.StreamHandler() stream_stdout.setFormatter(formatter) logger.addHandler(stream_stdout) - logging.info('Setting up tests for class: ' + cls.__name__) + logging.info("Setting up tests for class: " + cls.__name__) - diagrams_dir = 'doc/protocols/sequence_diagrams' - cls.states_bidder = extract_states_from_xu_file(os.path.join(diagrams_dir, 'ads.bidder.alt.xu'), 'B') - cls.states_offerer = extract_states_from_xu_file(os.path.join(diagrams_dir, 'ads.offerer.alt.xu'), 'O') + diagrams_dir = "doc/protocols/sequence_diagrams" + cls.states_bidder = extract_states_from_xu_file( + os.path.join(diagrams_dir, "ads.bidder.alt.xu"), "B" + ) + cls.states_offerer = extract_states_from_xu_file( + os.path.join(diagrams_dir, "ads.offerer.alt.xu"), "O" + ) - cls.states_bidder_sh = extract_states_from_xu_file(os.path.join(diagrams_dir, 'bidder.alt.xu'), 'B') - cls.states_offerer_sh = extract_states_from_xu_file(os.path.join(diagrams_dir, 'offerer.alt.xu'), 'O') + cls.states_bidder_sh = extract_states_from_xu_file( + os.path.join(diagrams_dir, "bidder.alt.xu"), "B" + ) + cls.states_offerer_sh = extract_states_from_xu_file( + os.path.join(diagrams_dir, "offerer.alt.xu"), "O" + ) if os.path.isdir(TEST_DIR): if RESET_TEST: - logging.info('Removing ' + TEST_DIR) + logging.info("Removing " + TEST_DIR) for name in os.listdir(TEST_DIR): - if name == 'pivx-params': + if name == "pivx-params": continue fullpath = os.path.join(TEST_DIR, name) if os.path.isdir(fullpath): @@ -349,29 +377,53 @@ class BaseTest(unittest.TestCase): else: os.remove(fullpath) else: - logging.info('Restoring instance from ' + TEST_DIR) + logging.info("Restoring instance from " + TEST_DIR) cls.restore_instance = True if not os.path.exists(TEST_DIR): os.makedirs(TEST_DIR) - cls.stream_fp = logging.FileHandler(os.path.join(TEST_DIR, 'test.log')) + cls.stream_fp = logging.FileHandler(os.path.join(TEST_DIR, "test.log")) cls.stream_fp.setFormatter(formatter) logger.addHandler(cls.stream_fp) try: - logging.info('Preparing coin nodes.') + logging.info("Preparing coin nodes.") for i in range(NUM_NODES): if not cls.restore_instance: - data_dir = prepareDataDir(TEST_DIR, i, 'particl.conf', 'part_') - if os.path.exists(os.path.join(cfg.PARTICL_BINDIR, 'particl-wallet')): + data_dir = prepareDataDir(TEST_DIR, i, "particl.conf", "part_") + if os.path.exists( + os.path.join(cfg.PARTICL_BINDIR, "particl-wallet") + ): try: - callrpc_cli(cfg.PARTICL_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat -legacy create', 'particl-wallet') + callrpc_cli( + cfg.PARTICL_BINDIR, + data_dir, + "regtest", + "-wallet=wallet.dat -legacy create", + "particl-wallet", + ) except Exception as e: - logging.warning('particl-wallet create failed, retrying without -legacy') - callrpc_cli(cfg.PARTICL_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat create', 'particl-wallet') + logging.warning( + f"particl-wallet create failed {e}, retrying without -legacy" + ) + callrpc_cli( + cfg.PARTICL_BINDIR, + data_dir, + "regtest", + "-wallet=wallet.dat create", + "particl-wallet", + ) - cls.part_daemons.append(startDaemon(os.path.join(TEST_DIR, 'part_' + str(i)), cfg.PARTICL_BINDIR, cfg.PARTICLD)) - logging.info('Started %s %d', cfg.PARTICLD, cls.part_daemons[-1].handle.pid) + cls.part_daemons.append( + startDaemon( + os.path.join(TEST_DIR, "part_" + str(i)), + cfg.PARTICL_BINDIR, + cfg.PARTICLD, + ) + ) + logging.info( + "Started %s %d", cfg.PARTICLD, cls.part_daemons[-1].handle.pid + ) if not cls.restore_instance: for i in range(NUM_NODES): @@ -379,81 +431,177 @@ class BaseTest(unittest.TestCase): rpc = make_rpc_func(i) waitForRPC(rpc, test_delay_event) if i == 0: - rpc('extkeyimportmaster', ['abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb']) + rpc( + "extkeyimportmaster", + [ + "abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb" + ], + ) elif i == 1: - rpc('extkeyimportmaster', ['pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic', '', 'true']) - rpc('getnewextaddress', ['lblExtTest']) - rpc('rescanblockchain') + rpc( + "extkeyimportmaster", + [ + "pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic", + "", + "true", + ], + ) + rpc("getnewextaddress", ["lblExtTest"]) + rpc("rescanblockchain") else: - rpc('extkeyimportmaster', [rpc('mnemonic', ['new'])['master']]) + rpc("extkeyimportmaster", [rpc("mnemonic", ["new"])["master"]]) # Lower output split threshold for more stakeable outputs - rpc('walletsettings', ['stakingoptions', {'stakecombinethreshold': 100, 'stakesplitthreshold': 200}]) - rpc('reservebalance', [False]) + rpc( + "walletsettings", + [ + "stakingoptions", + {"stakecombinethreshold": 100, "stakesplitthreshold": 200}, + ], + ) + rpc("reservebalance", [False]) for i in range(NUM_BTC_NODES): if not cls.restore_instance: - data_dir = prepareDataDir(TEST_DIR, i, 'bitcoin.conf', 'btc_', base_p2p_port=BTC_BASE_PORT, base_rpc_port=BTC_BASE_RPC_PORT) - if os.path.exists(os.path.join(cfg.BITCOIN_BINDIR, 'bitcoin-wallet')): + data_dir = prepareDataDir( + TEST_DIR, + i, + "bitcoin.conf", + "btc_", + base_p2p_port=BTC_BASE_PORT, + base_rpc_port=BTC_BASE_RPC_PORT, + ) + if os.path.exists( + os.path.join(cfg.BITCOIN_BINDIR, "bitcoin-wallet") + ): try: - callrpc_cli(cfg.BITCOIN_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat -legacy create', 'bitcoin-wallet') + callrpc_cli( + cfg.BITCOIN_BINDIR, + data_dir, + "regtest", + "-wallet=wallet.dat -legacy create", + "bitcoin-wallet", + ) except Exception as e: - logging.warning('bitcoin-wallet create failed, retrying without -legacy') - callrpc_cli(cfg.BITCOIN_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat create', 'bitcoin-wallet') + logging.warning( + f"bitcoin-wallet create failed {e}, retrying without -legacy" + ) + callrpc_cli( + cfg.BITCOIN_BINDIR, + data_dir, + "regtest", + "-wallet=wallet.dat create", + "bitcoin-wallet", + ) - cls.btc_daemons.append(startDaemon(os.path.join(TEST_DIR, 'btc_' + str(i)), cfg.BITCOIN_BINDIR, cfg.BITCOIND)) - logging.info('Started %s %d', cfg.BITCOIND, cls.part_daemons[-1].handle.pid) + cls.btc_daemons.append( + startDaemon( + os.path.join(TEST_DIR, "btc_" + str(i)), + cfg.BITCOIN_BINDIR, + cfg.BITCOIND, + ) + ) + logging.info( + "Started %s %d", cfg.BITCOIND, cls.part_daemons[-1].handle.pid + ) - waitForRPC(make_rpc_func(i, base_rpc_port=BTC_BASE_RPC_PORT), test_delay_event) + waitForRPC( + make_rpc_func(i, base_rpc_port=BTC_BASE_RPC_PORT), test_delay_event + ) if cls.start_ltc_nodes: for i in range(NUM_LTC_NODES): if not cls.restore_instance: - data_dir = prepareDataDir(TEST_DIR, i, 'litecoin.conf', 'ltc_', base_p2p_port=LTC_BASE_PORT, base_rpc_port=LTC_BASE_RPC_PORT) - if os.path.exists(os.path.join(cfg.LITECOIN_BINDIR, 'litecoin-wallet')): - callrpc_cli(cfg.LITECOIN_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat create', 'litecoin-wallet') + data_dir = prepareDataDir( + TEST_DIR, + i, + "litecoin.conf", + "ltc_", + base_p2p_port=LTC_BASE_PORT, + base_rpc_port=LTC_BASE_RPC_PORT, + ) + if os.path.exists( + os.path.join(cfg.LITECOIN_BINDIR, "litecoin-wallet") + ): + callrpc_cli( + cfg.LITECOIN_BINDIR, + data_dir, + "regtest", + "-wallet=wallet.dat create", + "litecoin-wallet", + ) - cls.ltc_daemons.append(startDaemon(os.path.join(TEST_DIR, 'ltc_' + str(i)), cfg.LITECOIN_BINDIR, cfg.LITECOIND)) - logging.info('Started %s %d', cfg.LITECOIND, cls.part_daemons[-1].handle.pid) + cls.ltc_daemons.append( + startDaemon( + os.path.join(TEST_DIR, "ltc_" + str(i)), + cfg.LITECOIN_BINDIR, + cfg.LITECOIND, + ) + ) + logging.info( + "Started %s %d", cfg.LITECOIND, cls.part_daemons[-1].handle.pid + ) - waitForRPC(make_rpc_func(i, base_rpc_port=LTC_BASE_RPC_PORT), test_delay_event) + waitForRPC( + make_rpc_func(i, base_rpc_port=LTC_BASE_RPC_PORT), + test_delay_event, + ) if cls.start_xmr_nodes: for i in range(NUM_XMR_NODES): if not cls.restore_instance: - prepareXmrDataDir(TEST_DIR, i, 'monerod.conf') + prepareXmrDataDir(TEST_DIR, i, "monerod.conf") - node_dir = os.path.join(TEST_DIR, 'xmr_' + str(i)) - cls.xmr_daemons.append(startXmrDaemon(node_dir, cfg.XMR_BINDIR, cfg.XMRD)) - logging.info('Started %s %d', cfg.XMRD, cls.xmr_daemons[-1].handle.pid) + node_dir = os.path.join(TEST_DIR, "xmr_" + str(i)) + cls.xmr_daemons.append( + startXmrDaemon(node_dir, cfg.XMR_BINDIR, cfg.XMRD) + ) + logging.info( + "Started %s %d", cfg.XMRD, cls.xmr_daemons[-1].handle.pid + ) waitForXMRNode(i) opts = [ - '--daemon-address=127.0.0.1:{}'.format(XMR_BASE_RPC_PORT + i), - '--no-dns', - '--rpc-bind-port={}'.format(XMR_BASE_WALLET_RPC_PORT + i), - '--wallet-dir={}'.format(os.path.join(node_dir, 'wallets')), - '--log-file={}'.format(os.path.join(node_dir, 'wallet.log')), - '--rpc-login=test{0}:test_pass{0}'.format(i), - '--shared-ringdb-dir={}'.format(os.path.join(node_dir, 'shared-ringdb')), - '--allow-mismatched-daemon-version', + "--daemon-address=127.0.0.1:{}".format(XMR_BASE_RPC_PORT + i), + "--no-dns", + "--rpc-bind-port={}".format(XMR_BASE_WALLET_RPC_PORT + i), + "--wallet-dir={}".format(os.path.join(node_dir, "wallets")), + "--log-file={}".format(os.path.join(node_dir, "wallet.log")), + "--rpc-login=test{0}:test_pass{0}".format(i), + "--shared-ringdb-dir={}".format( + os.path.join(node_dir, "shared-ringdb") + ), + "--allow-mismatched-daemon-version", ] - cls.xmr_daemons.append(startXmrWalletDaemon(node_dir, cfg.XMR_BINDIR, cfg.XMR_WALLET_RPC, opts=opts)) + cls.xmr_daemons.append( + startXmrWalletDaemon( + node_dir, cfg.XMR_BINDIR, cfg.XMR_WALLET_RPC, opts=opts + ) + ) for i in range(NUM_XMR_NODES): - cls.xmr_wallet_auth.append(('test{0}'.format(i), 'test_pass{0}'.format(i))) - logging.info('Creating XMR wallet %i', i) + cls.xmr_wallet_auth.append( + ("test{0}".format(i), "test_pass{0}".format(i)) + ) + logging.info("Creating XMR wallet %i", i) waitForXMRWallet(i, cls.xmr_wallet_auth[i]) if not cls.restore_instance: - cls.callxmrnodewallet(cls, i, 'create_wallet', {'filename': 'testwallet', 'language': 'English'}) - cls.callxmrnodewallet(cls, i, 'open_wallet', {'filename': 'testwallet'}) + cls.callxmrnodewallet( + cls, + i, + "create_wallet", + {"filename": "testwallet", "language": "English"}, + ) + cls.callxmrnodewallet( + cls, i, "open_wallet", {"filename": "testwallet"} + ) for i in range(NUM_NODES): # Hook for descendant classes cls.prepareExtraDataDir(i) - logging.info('Preparing swap clients.') + logging.info("Preparing swap clients.") if not cls.restore_instance: eckey = ECKey() eckey.generate() @@ -467,16 +615,31 @@ class BaseTest(unittest.TestCase): if cls.start_xmr_nodes: start_nodes.add(Coins.XMR) if not cls.restore_instance: - prepare_swapclient_dir(TEST_DIR, i, cls.network_key, cls.network_pubkey, start_nodes, cls) - basicswap_dir = os.path.join(os.path.join(TEST_DIR, 'basicswap_' + str(i))) + prepare_swapclient_dir( + TEST_DIR, + i, + cls.network_key, + cls.network_pubkey, + start_nodes, + cls, + ) + basicswap_dir = os.path.join( + os.path.join(TEST_DIR, "basicswap_" + str(i)) + ) settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME) with open(settings_path) as fs: settings = json.load(fs) if cls.restore_instance and i == 1: - cls.network_key = settings['network_key'] - cls.network_pubkey = settings['network_pubkey'] - fp = open(os.path.join(basicswap_dir, 'basicswap.log'), 'w') - sc = BasicSwap(fp, basicswap_dir, settings, 'regtest', log_name='BasicSwap{}'.format(i)) + cls.network_key = settings["network_key"] + cls.network_pubkey = settings["network_pubkey"] + fp = open(os.path.join(basicswap_dir, "basicswap.log"), "w") + sc = BasicSwap( + fp, + basicswap_dir, + settings, + "regtest", + log_name="BasicSwap{}".format(i), + ) cls.swap_clients.append(sc) sc.setDaemonPID(Coins.BTC, cls.btc_daemons[i].handle.pid) sc.setDaemonPID(Coins.PART, cls.part_daemons[i].handle.pid) @@ -489,7 +652,10 @@ class BaseTest(unittest.TestCase): if cls.start_xmr_nodes: # Set XMR main wallet address xmr_ci = sc.ci(Coins.XMR) - sc.setStringKV('main_wallet_addr_' + xmr_ci.coin_name().lower(), xmr_ci.getMainWalletAddress()) + sc.setStringKV( + "main_wallet_addr_" + xmr_ci.coin_name().lower(), + xmr_ci.getMainWalletAddress(), + ) t = HttpThread(sc.fp, TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, sc) cls.http_threads.append(t) @@ -497,118 +663,268 @@ class BaseTest(unittest.TestCase): # Set future block rewards to nowhere (a random address), so wallet amounts stay constant void_block_rewards_pubkey = cls.getRandomPubkey() if cls.restore_instance: - cls.btc_addr = cls.swap_clients[0].ci(Coins.BTC).pubkey_to_segwit_address(void_block_rewards_pubkey) + cls.btc_addr = ( + cls.swap_clients[0] + .ci(Coins.BTC) + .pubkey_to_segwit_address(void_block_rewards_pubkey) + ) if cls.start_ltc_nodes: - cls.ltc_addr = cls.swap_clients[0].ci(Coins.LTC).pubkey_to_address(void_block_rewards_pubkey) + cls.ltc_addr = ( + cls.swap_clients[0] + .ci(Coins.LTC) + .pubkey_to_address(void_block_rewards_pubkey) + ) if cls.start_xmr_nodes: - cls.xmr_addr = cls.callxmrnodewallet(cls, 1, 'get_address')['address'] + cls.xmr_addr = cls.callxmrnodewallet(cls, 1, "get_address")[ + "address" + ] else: - cls.btc_addr = callnoderpc(0, 'getnewaddress', ['mining_addr', 'bech32'], base_rpc_port=BTC_BASE_RPC_PORT) + cls.btc_addr = callnoderpc( + 0, + "getnewaddress", + ["mining_addr", "bech32"], + base_rpc_port=BTC_BASE_RPC_PORT, + ) num_blocks = 400 # Mine enough to activate segwit - logging.info('Mining %d Bitcoin blocks to %s', num_blocks, cls.btc_addr) - callnoderpc(0, 'generatetoaddress', [num_blocks, cls.btc_addr], base_rpc_port=BTC_BASE_RPC_PORT) + logging.info("Mining %d Bitcoin blocks to %s", num_blocks, cls.btc_addr) + callnoderpc( + 0, + "generatetoaddress", + [num_blocks, cls.btc_addr], + base_rpc_port=BTC_BASE_RPC_PORT, + ) - btc_addr1 = callnoderpc(1, 'getnewaddress', ['initial addr'], base_rpc_port=BTC_BASE_RPC_PORT) + btc_addr1 = callnoderpc( + 1, + "getnewaddress", + ["initial addr"], + base_rpc_port=BTC_BASE_RPC_PORT, + ) for i in range(5): - callnoderpc(0, 'sendtoaddress', [btc_addr1, 100], base_rpc_port=BTC_BASE_RPC_PORT) + callnoderpc( + 0, + "sendtoaddress", + [btc_addr1, 100], + base_rpc_port=BTC_BASE_RPC_PORT, + ) # Switch addresses so wallet amounts stay constant num_blocks = 100 - cls.btc_addr = cls.swap_clients[0].ci(Coins.BTC).pubkey_to_segwit_address(void_block_rewards_pubkey) - logging.info('Mining %d Bitcoin blocks to %s', num_blocks, cls.btc_addr) - callnoderpc(0, 'generatetoaddress', [num_blocks, cls.btc_addr], base_rpc_port=BTC_BASE_RPC_PORT) + cls.btc_addr = ( + cls.swap_clients[0] + .ci(Coins.BTC) + .pubkey_to_segwit_address(void_block_rewards_pubkey) + ) + logging.info("Mining %d Bitcoin blocks to %s", num_blocks, cls.btc_addr) + callnoderpc( + 0, + "generatetoaddress", + [num_blocks, cls.btc_addr], + base_rpc_port=BTC_BASE_RPC_PORT, + ) - major_version = int(str(callnoderpc(0, 'getnetworkinfo', base_rpc_port=BTC_BASE_RPC_PORT)['version'])[:2]) + major_version = int( + str( + callnoderpc( + 0, "getnetworkinfo", base_rpc_port=BTC_BASE_RPC_PORT + )["version"] + )[:2] + ) if major_version >= 23: - checkForks(callnoderpc(0, 'getdeploymentinfo', base_rpc_port=BTC_BASE_RPC_PORT)) + checkForks( + callnoderpc( + 0, "getdeploymentinfo", base_rpc_port=BTC_BASE_RPC_PORT + ) + ) else: - checkForks(callnoderpc(0, 'getblockchaininfo', base_rpc_port=BTC_BASE_RPC_PORT)) + checkForks( + callnoderpc( + 0, "getblockchaininfo", base_rpc_port=BTC_BASE_RPC_PORT + ) + ) if cls.start_ltc_nodes: num_blocks = 400 - cls.ltc_addr = callnoderpc(0, 'getnewaddress', ['mining_addr', 'bech32'], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat') - logging.info('Mining %d Litecoin blocks to %s', num_blocks, cls.ltc_addr) - callnoderpc(0, 'generatetoaddress', [num_blocks, cls.ltc_addr], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat') + cls.ltc_addr = callnoderpc( + 0, + "getnewaddress", + ["mining_addr", "bech32"], + base_rpc_port=LTC_BASE_RPC_PORT, + wallet="wallet.dat", + ) + logging.info( + "Mining %d Litecoin blocks to %s", num_blocks, cls.ltc_addr + ) + callnoderpc( + 0, + "generatetoaddress", + [num_blocks, cls.ltc_addr], + base_rpc_port=LTC_BASE_RPC_PORT, + wallet="wallet.dat", + ) num_blocks = 31 - cls.ltc_addr = cls.swap_clients[0].ci(Coins.LTC).pubkey_to_address(void_block_rewards_pubkey) - logging.info('Mining %d Litecoin blocks to %s', num_blocks, cls.ltc_addr) - callnoderpc(0, 'generatetoaddress', [num_blocks, cls.ltc_addr], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat') + cls.ltc_addr = ( + cls.swap_clients[0] + .ci(Coins.LTC) + .pubkey_to_address(void_block_rewards_pubkey) + ) + logging.info( + "Mining %d Litecoin blocks to %s", num_blocks, cls.ltc_addr + ) + callnoderpc( + 0, + "generatetoaddress", + [num_blocks, cls.ltc_addr], + base_rpc_port=LTC_BASE_RPC_PORT, + wallet="wallet.dat", + ) # https://github.com/litecoin-project/litecoin/issues/807 # Block 432 is when MWEB activates. It requires a peg-in. You'll need to generate an mweb address and send some coins to it. Then it will allow you to mine the next block. - mweb_addr = callnoderpc(2, 'getnewaddress', ['mweb_addr', 'mweb'], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat') - callnoderpc(0, 'sendtoaddress', [mweb_addr, 1], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat') + mweb_addr = callnoderpc( + 2, + "getnewaddress", + ["mweb_addr", "mweb"], + base_rpc_port=LTC_BASE_RPC_PORT, + wallet="wallet.dat", + ) + callnoderpc( + 0, + "sendtoaddress", + [mweb_addr, 1], + base_rpc_port=LTC_BASE_RPC_PORT, + wallet="wallet.dat", + ) - ltc_addr1 = callnoderpc(1, 'getnewaddress', ['initial addr'], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat') + ltc_addr1 = callnoderpc( + 1, + "getnewaddress", + ["initial addr"], + base_rpc_port=LTC_BASE_RPC_PORT, + wallet="wallet.dat", + ) for i in range(5): - callnoderpc(0, 'sendtoaddress', [ltc_addr1, 100], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat') + callnoderpc( + 0, + "sendtoaddress", + [ltc_addr1, 100], + base_rpc_port=LTC_BASE_RPC_PORT, + wallet="wallet.dat", + ) num_blocks = 69 - cls.ltc_addr = cls.swap_clients[0].ci(Coins.LTC).pubkey_to_address(void_block_rewards_pubkey) - callnoderpc(0, 'generatetoaddress', [num_blocks, cls.ltc_addr], base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat') + cls.ltc_addr = ( + cls.swap_clients[0] + .ci(Coins.LTC) + .pubkey_to_address(void_block_rewards_pubkey) + ) + callnoderpc( + 0, + "generatetoaddress", + [num_blocks, cls.ltc_addr], + base_rpc_port=LTC_BASE_RPC_PORT, + wallet="wallet.dat", + ) - checkForks(callnoderpc(0, 'getblockchaininfo', base_rpc_port=LTC_BASE_RPC_PORT, wallet='wallet.dat')) + checkForks( + callnoderpc( + 0, + "getblockchaininfo", + base_rpc_port=LTC_BASE_RPC_PORT, + wallet="wallet.dat", + ) + ) num_blocks = 100 if cls.start_xmr_nodes: - cls.xmr_addr = cls.callxmrnodewallet(cls, 1, 'get_address')['address'] - if callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'get_block_count')['count'] < num_blocks: - logging.info('Mining %d Monero blocks to %s.', num_blocks, cls.xmr_addr) - callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'generateblocks', {'wallet_address': cls.xmr_addr, 'amount_of_blocks': num_blocks}) - logging.info('XMR blocks: %d', callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'get_block_count')['count']) + cls.xmr_addr = cls.callxmrnodewallet(cls, 1, "get_address")[ + "address" + ] + if ( + callrpc_xmr(XMR_BASE_RPC_PORT + 1, "get_block_count")["count"] + < num_blocks + ): + logging.info( + "Mining %d Monero blocks to %s.", num_blocks, cls.xmr_addr + ) + callrpc_xmr( + XMR_BASE_RPC_PORT + 1, + "generateblocks", + { + "wallet_address": cls.xmr_addr, + "amount_of_blocks": num_blocks, + }, + ) + logging.info( + "XMR blocks: %d", + callrpc_xmr(XMR_BASE_RPC_PORT + 1, "get_block_count")["count"], + ) - logging.info('Adding anon outputs') + logging.info("Adding anon outputs") outputs = [] for i in range(8): - sx_addr = callnoderpc(1, 'getnewstealthaddress') - outputs.append({'address': sx_addr, 'amount': 0.5}) + sx_addr = callnoderpc(1, "getnewstealthaddress") + outputs.append({"address": sx_addr, "amount": 0.5}) for i in range(7): - callnoderpc(0, 'sendtypeto', ['part', 'anon', outputs]) + callnoderpc(0, "sendtypeto", ["part", "anon", outputs]) - part_addr1 = callnoderpc(1, 'getnewaddress', ['initial addr']) - part_addr2 = callnoderpc(1, 'getnewaddress', ['initial addr 2']) - callnoderpc(0, 'sendtypeto', ['part', 'part', [{'address': part_addr1, 'amount': 100}, {'address': part_addr2, 'amount': 100}]]) + part_addr1 = callnoderpc(1, "getnewaddress", ["initial addr"]) + part_addr2 = callnoderpc(1, "getnewaddress", ["initial addr 2"]) + callnoderpc( + 0, + "sendtypeto", + [ + "part", + "part", + [ + {"address": part_addr1, "amount": 100}, + {"address": part_addr2, "amount": 100}, + ], + ], + ) cls.prepareExtraCoins() - logging.info('Starting update thread.') + logging.info("Starting update thread.") signal.signal(signal.SIGINT, signal_handler) cls.update_thread = threading.Thread(target=run_loop, args=(cls,)) cls.update_thread.start() pause_event.set() - cls.coins_update_thread = threading.Thread(target=run_coins_loop, args=(cls,)) + cls.coins_update_thread = threading.Thread( + target=run_coins_loop, args=(cls,) + ) cls.coins_update_thread.start() except Exception: traceback.print_exc() cls.tearDownClass() - raise ValueError('setUpClass() failed.') + raise ValueError("setUpClass() failed.") @classmethod def tearDownClass(cls): - logging.info('Finalising') + logging.info("Finalising") test_delay_event.set() if cls.update_thread is not None: try: cls.update_thread.join() except Exception: - logging.info('Failed to join update_thread') + logging.info("Failed to join update_thread") if cls.coins_update_thread is not None: try: cls.coins_update_thread.join() except Exception: - logging.info('Failed to join coins_update_thread') + logging.info("Failed to join coins_update_thread") for t in cls.http_threads: t.stop() t.join() - logging.info('Stopping swap clients') + logging.info("Stopping swap clients") for c in cls.swap_clients: c.finalise() c.fp.close() - logging.info('Stopping coin nodes') + logging.info("Stopping coin nodes") stopDaemons(cls.xmr_daemons) stopDaemons(cls.part_daemons) stopDaemons(cls.btc_daemons) @@ -642,69 +958,102 @@ class BaseTest(unittest.TestCase): @classmethod def coins_loop(cls): if cls.btc_addr is not None: - btcCli('generatetoaddress 1 {}'.format(cls.btc_addr)) + btcCli("generatetoaddress 1 {}".format(cls.btc_addr)) if cls.ltc_addr is not None: - ltcCli('generatetoaddress 1 {}'.format(cls.ltc_addr)) + ltcCli("generatetoaddress 1 {}".format(cls.ltc_addr)) if cls.xmr_addr is not None: - callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'generateblocks', {'wallet_address': cls.xmr_addr, 'amount_of_blocks': 1}) + callrpc_xmr( + XMR_BASE_RPC_PORT + 1, + "generateblocks", + {"wallet_address": cls.xmr_addr, "amount_of_blocks": 1}, + ) @classmethod def waitForParticlHeight(cls, num_blocks, node_id=0): - logging.info(f'Waiting for Particl chain height {num_blocks}', ) + logging.info( + f"Waiting for Particl chain height {num_blocks}", + ) for i in range(60): if test_delay_event.is_set(): - raise ValueError('Test stopped.') - particl_blocks = callnoderpc(0, 'getblockcount') - print('particl_blocks', particl_blocks) + raise ValueError("Test stopped.") + particl_blocks = callnoderpc(0, "getblockcount") + print("particl_blocks", particl_blocks) if particl_blocks >= num_blocks: break test_delay_event.wait(1) - logging.info('PART blocks: %d', callnoderpc(0, 'getblockcount')) + logging.info("PART blocks: %d", callnoderpc(0, "getblockcount")) assert particl_blocks >= num_blocks def callxmrnodewallet(self, node_id, method, params=None): - return callrpc_xmr(XMR_BASE_WALLET_RPC_PORT + node_id, method, params, auth=self.xmr_wallet_auth[node_id]) + return callrpc_xmr( + XMR_BASE_WALLET_RPC_PORT + node_id, + method, + params, + auth=self.xmr_wallet_auth[node_id], + ) def getXmrBalance(self, js_wallets): - return float(js_wallets[Coins.XMR.name]['unconfirmed']) + float(js_wallets[Coins.XMR.name]['balance']) + return float(js_wallets[Coins.XMR.name]["unconfirmed"]) + float( + js_wallets[Coins.XMR.name]["balance"] + ) - def prepare_balance(self, coin, amount: float, port_target_node: int, port_take_from_node: int, test_balance: bool = True) -> None: + def prepare_balance( + self, + coin, + amount: float, + port_target_node: int, + port_take_from_node: int, + test_balance: bool = True, + ) -> None: delay_iterations = 100 if coin == Coins.NAV else 20 delay_time = 5 if coin == Coins.NAV else 3 if coin == Coins.PART_BLIND: - coin_ticker: str = 'PART' - balance_type: str = 'blind_balance' - address_type: str = 'stealth_address' - type_to: str = 'blind' + coin_ticker: str = "PART" + balance_type: str = "blind_balance" + address_type: str = "stealth_address" + type_to: str = "blind" elif coin == Coins.PART_ANON: - coin_ticker: str = 'PART' - balance_type: str = 'anon_balance' - address_type: str = 'stealth_address' - type_to: str = 'anon' + coin_ticker: str = "PART" + balance_type: str = "anon_balance" + address_type: str = "stealth_address" + type_to: str = "anon" else: coin_ticker: str = coin.name - balance_type: str = 'balance' - address_type: str = 'deposit_address' - js_w = read_json_api(port_target_node, 'wallets') + balance_type: str = "balance" + address_type: str = "deposit_address" + js_w = read_json_api(port_target_node, "wallets") current_balance: float = float(js_w[coin_ticker][balance_type]) if test_balance and current_balance >= amount: return post_json = { - 'value': amount, - 'address': js_w[coin_ticker][address_type], - 'subfee': False, + "value": amount, + "address": js_w[coin_ticker][address_type], + "subfee": False, } if coin in (Coins.XMR, Coins.WOW): - post_json['sweepall'] = False + post_json["sweepall"] = False if coin in (Coins.PART_BLIND, Coins.PART_ANON): - post_json['type_to'] = type_to - json_rv = read_json_api(port_take_from_node, 'wallets/{}/withdraw'.format(coin_ticker.lower()), post_json) - assert (len(json_rv['txid']) == 64) + post_json["type_to"] = type_to + json_rv = read_json_api( + port_take_from_node, + "wallets/{}/withdraw".format(coin_ticker.lower()), + post_json, + ) + assert len(json_rv["txid"]) == 64 wait_for_amount: float = amount if not test_balance: wait_for_amount += current_balance - wait_for_balance(test_delay_event, 'http://127.0.0.1:{}/json/wallets/{}'.format(port_target_node, coin_ticker.lower()), balance_type, wait_for_amount, iterations=delay_iterations, delay_time=delay_time) + wait_for_balance( + test_delay_event, + "http://127.0.0.1:{}/json/wallets/{}".format( + port_target_node, coin_ticker.lower() + ), + balance_type, + wait_for_amount, + iterations=delay_iterations, + delay_time=delay_time, + ) class Test(BaseTest): @@ -714,7 +1063,7 @@ class Test(BaseTest): test_delay_event.wait(100000) def test_010_txn_size(self): - logging.info('---------- Test {} txn_size'.format(Coins.PART)) + logging.info("---------- Test {} txn_size".format(Coins.PART)) swap_clients = self.swap_clients ci = swap_clients[0].ci(Coins.PART) @@ -723,7 +1072,7 @@ class Test(BaseTest): amount: int = ci.make_int(random.uniform(0.1, 2.0), r=1) # Record unspents before createSCLockTx as the used ones will be locked - unspents = ci.rpc('listunspent') + unspents = ci.rpc("listunspent") # fee_rate is in sats/kvB fee_rate: int = 1000 @@ -739,62 +1088,63 @@ class Test(BaseTest): lock_tx = ci.fundSCLockTx(lock_tx, fee_rate) lock_tx = ci.signTxWithWallet(lock_tx) - unspents_after = ci.rpc('listunspent') - assert (len(unspents) > len(unspents_after)) + unspents_after = ci.rpc("listunspent") + assert len(unspents) > len(unspents_after) - tx_decoded = ci.rpc('decoderawtransaction', [lock_tx.hex()]) - txid = tx_decoded['txid'] + tx_decoded = ci.rpc("decoderawtransaction", [lock_tx.hex()]) + txid = tx_decoded["txid"] - vsize = tx_decoded['vsize'] + vsize = tx_decoded["vsize"] expect_fee_int = round(fee_rate * vsize / 1000) - expect_fee = ci.format_amount(expect_fee_int) out_value: int = 0 - for txo in tx_decoded['vout']: - if 'value' in txo: - out_value += ci.make_int(txo['value']) + for txo in tx_decoded["vout"]: + if "value" in txo: + out_value += ci.make_int(txo["value"]) in_value: int = 0 - for txi in tx_decoded['vin']: + for txi in tx_decoded["vin"]: for utxo in unspents: - if 'vout' not in utxo: + if "vout" not in utxo: continue - if utxo['txid'] == txi['txid'] and utxo['vout'] == txi['vout']: - in_value += ci.make_int(utxo['amount']) + if utxo["txid"] == txi["txid"] and utxo["vout"] == txi["vout"]: + in_value += ci.make_int(utxo["amount"]) break fee_value = in_value - out_value - ci.rpc('sendrawtransaction', [lock_tx.hex()]) - rv = ci.rpc('gettransaction', [txid]) - wallet_tx_fee = -ci.make_int(rv['fee']) + ci.rpc("sendrawtransaction", [lock_tx.hex()]) + rv = ci.rpc("gettransaction", [txid]) + wallet_tx_fee = -ci.make_int(rv["fee"]) - assert (wallet_tx_fee == fee_value) - assert (wallet_tx_fee == expect_fee_int) + assert wallet_tx_fee == fee_value + assert wallet_tx_fee == expect_fee_int addr_out = ci.getNewAddress(True) pkh_out = ci.decodeAddress(addr_out) fee_info = {} - lock_spend_tx = ci.createSCLockSpendTx(lock_tx, lock_tx_script, pkh_out, fee_rate, fee_info=fee_info) - vsize_estimated: int = fee_info['vsize'] + lock_spend_tx = ci.createSCLockSpendTx( + lock_tx, lock_tx_script, pkh_out, fee_rate, fee_info=fee_info + ) + vsize_estimated: int = fee_info["vsize"] - tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()]) - txid = tx_decoded['txid'] + tx_decoded = ci.rpc("decoderawtransaction", [lock_spend_tx.hex()]) + txid = tx_decoded["txid"] witness_stack = [ - b'', + b"", ci.signTx(a, lock_spend_tx, 0, lock_tx_script, amount), ci.signTx(b, lock_spend_tx, 0, lock_tx_script, amount), lock_tx_script, ] lock_spend_tx = ci.setTxSignature(lock_spend_tx, witness_stack) - tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()]) - vsize_actual: int = tx_decoded['vsize'] + tx_decoded = ci.rpc("decoderawtransaction", [lock_spend_tx.hex()]) + vsize_actual: int = tx_decoded["vsize"] - assert (vsize_actual <= vsize_estimated and vsize_estimated - vsize_actual < 4) - assert (ci.rpc('sendrawtransaction', [lock_spend_tx.hex()]) == txid) + assert vsize_actual <= vsize_estimated and vsize_estimated - vsize_actual < 4 + assert ci.rpc("sendrawtransaction", [lock_spend_tx.hex()]) == txid expect_vsize: int = ci.xmr_swap_a_lock_spend_tx_vsize() - assert (expect_vsize >= vsize_actual) - assert (expect_vsize - vsize_actual < 10) + assert expect_vsize >= vsize_actual + assert expect_vsize - vsize_actual < 10 # Test chain b (no-script) lock tx size v = ci.getNewSecretKey() @@ -803,22 +1153,25 @@ class Test(BaseTest): lock_tx_b_txid = ci.publishBLockTx(v, S, amount, fee_rate) addr_out = ci.getNewAddress(True) - lock_tx_b_spend_txid = ci.spendBLockTx(lock_tx_b_txid, addr_out, v, s, amount, fee_rate, 0) + lock_tx_b_spend_txid = ci.spendBLockTx( + lock_tx_b_txid, addr_out, v, s, amount, fee_rate, 0 + ) lock_tx_b_spend = ci.getTransaction(lock_tx_b_spend_txid) if lock_tx_b_spend is None: lock_tx_b_spend = ci.getWalletTransaction(lock_tx_b_spend_txid) - lock_tx_b_spend_decoded = ci.rpc('decoderawtransaction', [lock_tx_b_spend.hex()]) + lock_tx_b_spend_decoded = ci.rpc( + "decoderawtransaction", [lock_tx_b_spend.hex()] + ) expect_vsize: int = ci.xmr_swap_b_lock_spend_tx_vsize() - assert (expect_vsize >= lock_tx_b_spend_decoded['vsize']) - assert (expect_vsize - lock_tx_b_spend_decoded['vsize'] < 10) + assert expect_vsize >= lock_tx_b_spend_decoded["vsize"] + assert expect_vsize - lock_tx_b_spend_decoded["vsize"] < 10 def test_010_xmr_txn_size(self): - logging.info('---------- Test {} txn_size'.format(Coins.XMR)) + logging.info("---------- Test {} txn_size".format(Coins.XMR)) swap_clients = self.swap_clients ci = swap_clients[1].ci(Coins.XMR) - pi = swap_clients[1].pi(SwapTypes.XMR_SWAP) amount: int = ci.make_int(random.uniform(0.1, 2.0), r=1) fee_rate: int = 1000 # TODO: How to set feerate for rpc functions? @@ -831,7 +1184,9 @@ class Test(BaseTest): addr_out = ci.getNewAddress(True) for i in range(20): try: - lock_tx_b_spend_txid = ci.spendBLockTx(lock_tx_b_txid, addr_out, v, s, amount, fee_rate, 0) + lock_tx_b_spend_txid = ci.spendBLockTx( + lock_tx_b_txid, addr_out, v, s, amount, fee_rate, 0 + ) break except Exception as e: if isinstance(e, TemporaryError): @@ -842,129 +1197,137 @@ class Test(BaseTest): lock_tx_b_spend = ci.getTransaction(lock_tx_b_spend_txid) - actual_size: int = len(lock_tx_b_spend['txs_as_hex'][0]) // 2 + actual_size: int = len(lock_tx_b_spend["txs_as_hex"][0]) // 2 expect_size: int = ci.xmr_swap_b_lock_spend_tx_vsize() - assert (expect_size >= actual_size) - assert (expect_size - actual_size < 100) # TODO + assert expect_size >= actual_size + assert expect_size - actual_size < 100 # TODO def test_011_smsgaddresses(self): - logging.info('---------- Test address management and private offers') + logging.info("---------- Test address management and private offers") swap_clients = self.swap_clients - js_1 = read_json_api(1801, 'smsgaddresses') + js_1 = read_json_api(1801, "smsgaddresses") post_json = { - 'addressnote': 'testing', + "addressnote": "testing", } - json_rv = read_json_api(1801, 'smsgaddresses/new', post_json) - new_address = json_rv['new_address'] - new_address_pk = json_rv['pubkey'] + json_rv = read_json_api(1801, "smsgaddresses/new", post_json) + new_address = json_rv["new_address"] + new_address_pk = json_rv["pubkey"] - js_2 = read_json_api(1801, 'smsgaddresses') - assert (len(js_2) == len(js_1) + 1) + js_2 = read_json_api(1801, "smsgaddresses") + assert len(js_2) == len(js_1) + 1 found = False for addr in js_2: - if addr['addr'] == new_address: - assert (addr['note'] == 'testing') + if addr["addr"] == new_address: + assert addr["note"] == "testing" found = True - assert (found is True) + assert found is True found = False - lks = callnoderpc(1, 'smsglocalkeys') - for key in lks['wallet_keys']: - if key['address'] == new_address: - assert (key['receive'] == '1') + lks = callnoderpc(1, "smsglocalkeys") + for key in lks["wallet_keys"]: + if key["address"] == new_address: + assert key["receive"] == "1" found = True - assert (found is True) + assert found is True # Disable post_json = { - 'address': new_address, - 'addressnote': 'testing2', - 'active_ind': '0', + "address": new_address, + "addressnote": "testing2", + "active_ind": "0", } - json_rv = read_json_api(1801, 'smsgaddresses/edit', post_json) - assert (json_rv['edited_address'] == new_address) + json_rv = read_json_api(1801, "smsgaddresses/edit", post_json) + assert json_rv["edited_address"] == new_address - js_3 = read_json_api(1801, 'smsgaddresses') - assert (len(js_3) == 0) + js_3 = read_json_api(1801, "smsgaddresses") + assert len(js_3) == 0 post_json = { - 'exclude_inactive': False, + "exclude_inactive": False, } - js_3 = read_json_api(1801, 'smsgaddresses', post_json) + js_3 = read_json_api(1801, "smsgaddresses", post_json) found = False for addr in js_3: - if addr['addr'] == new_address: - assert (addr['note'] == 'testing2') - assert (addr['active_ind'] == 0) + if addr["addr"] == new_address: + assert addr["note"] == "testing2" + assert addr["active_ind"] == 0 found = True - assert (found is True) + assert found is True found = False - lks = callnoderpc(1, 'smsglocalkeys') - for key in lks['wallet_keys']: - if key['address'] == new_address: + lks = callnoderpc(1, "smsglocalkeys") + for key in lks["wallet_keys"]: + if key["address"] == new_address: found = True - assert (found is False) + assert found is False # Re-enable post_json = { - 'address': new_address, - 'active_ind': '1', + "address": new_address, + "active_ind": "1", } - json_rv = read_json_api(1801, 'smsgaddresses/edit', post_json) - assert (json_rv['edited_address'] == new_address) + json_rv = read_json_api(1801, "smsgaddresses/edit", post_json) + assert json_rv["edited_address"] == new_address found = False - lks = callnoderpc(1, 'smsglocalkeys') - for key in lks['wallet_keys']: - if key['address'] == new_address: - assert (key['receive'] == '1') + lks = callnoderpc(1, "smsglocalkeys") + for key in lks["wallet_keys"]: + if key["address"] == new_address: + assert key["receive"] == "1" found = True - assert (found is True) + assert found is True post_json = { - 'addresspubkey': new_address_pk, - 'addressnote': 'testing_add_addr', + "addresspubkey": new_address_pk, + "addressnote": "testing_add_addr", } - json_rv = read_json_api(1800, 'smsgaddresses/add', post_json) - assert (json_rv['added_address'] == new_address) + json_rv = read_json_api(1800, "smsgaddresses/add", post_json) + assert json_rv["added_address"] == new_address post_json = { - 'addr_to': new_address, - 'addr_from': -1, - 'coin_from': 1, - 'coin_to': 6, - 'amt_from': 1, - 'amt_to': 1, - 'lockhrs': 24} - rv = read_json_api(1800, 'offers/new', post_json) - offer_id_hex = rv['offer_id'] + "addr_to": new_address, + "addr_from": -1, + "coin_from": 1, + "coin_to": 6, + "amt_from": 1, + "amt_to": 1, + "lockhrs": 24, + } + rv = read_json_api(1800, "offers/new", post_json) + offer_id_hex = rv["offer_id"] wait_for_offer(test_delay_event, swap_clients[1], bytes.fromhex(offer_id_hex)) - rv = read_json_api(1801, f'offers/{offer_id_hex}') - assert (rv[0]['addr_to'] == new_address) + rv = read_json_api(1801, f"offers/{offer_id_hex}") + assert rv[0]["addr_to"] == new_address - rv = read_json_api(1800, f'offers/{offer_id_hex}') - assert (rv[0]['addr_to'] == new_address) + rv = read_json_api(1800, f"offers/{offer_id_hex}") + assert rv[0]["addr_to"] == new_address # Disable all - json_rv = read_json_api(1800, 'smsgaddresses/disableall') - assert (json_rv['num_disabled'] >= 1) + json_rv = read_json_api(1800, "smsgaddresses/disableall") + assert json_rv["num_disabled"] >= 1 def test_01_part_xmr(self): - logging.info('---------- Test PART to XMR') + logging.info("---------- Test PART to XMR") swap_clients = self.swap_clients - start_xmr_amount = self.getXmrBalance(read_json_api(1800, 'wallets')) - js_1 = read_json_api(1801, 'wallets') - assert (self.getXmrBalance(js_1) > 0.0) + start_xmr_amount = self.getXmrBalance(read_json_api(1800, "wallets")) + js_1 = read_json_api(1801, "wallets") + assert self.getXmrBalance(js_1) > 0.0 - offer_id = swap_clients[0].postOffer(Coins.PART, Coins.XMR, 100 * COIN, 0.11 * XMR_COIN, 100 * COIN, SwapTypes.XMR_SWAP) + offer_id = swap_clients[0].postOffer( + Coins.PART, + Coins.XMR, + 100 * COIN, + 0.11 * XMR_COIN, + 100 * COIN, + SwapTypes.XMR_SWAP, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) - offers = swap_clients[1].listOffers(filters={'offer_id': offer_id}) - assert (len(offers) == 1) + offers = swap_clients[1].listOffers(filters={"offer_id": offer_id}) + assert len(offers) == 1 offer = offers[0] bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from) @@ -972,38 +1335,59 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) bid, xmr_swap = swap_clients[0].getXmrBid(bid_id) - assert (xmr_swap) + assert xmr_swap swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=180, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + ) - js_0_end = read_json_api(1800, 'wallets') + js_0_end = read_json_api(1800, "wallets") end_xmr_amount = self.getXmrBalance(js_0_end) xmr_amount_diff = end_xmr_amount - start_xmr_amount - assert (xmr_amount_diff > 10.9 and xmr_amount_diff < 11.0) + assert xmr_amount_diff > 10.9 and xmr_amount_diff < 11.0 bid_id_hex = bid_id.hex() - path = f'bids/{bid_id_hex}/states' + path = f"bids/{bid_id_hex}/states" offerer_states = read_json_api(1800, path) bidder_states = read_json_api(1801, path) - assert (compare_bid_states(offerer_states, self.states_offerer[0]) is True) - assert (compare_bid_states(bidder_states, self.states_bidder[0]) is True) + assert compare_bid_states(offerer_states, self.states_offerer[0]) is True + assert compare_bid_states(bidder_states, self.states_bidder[0]) is True # Test remove_expired_data - remove_expired_data(swap_clients[0], -swap_clients[0]._expire_db_records_after * 2) - offers = swap_clients[0].listOffers(filters={'offer_id': offer_id}) - assert (len(offers) == 0) + remove_expired_data( + swap_clients[0], -swap_clients[0]._expire_db_records_after * 2 + ) + offers = swap_clients[0].listOffers(filters={"offer_id": offer_id}) + assert len(offers) == 0 def test_02_leader_recover_a_lock_tx(self): - logging.info('---------- Test PART to XMR leader recovers coin a lock tx') + logging.info("---------- Test PART to XMR leader recovers coin a lock tx") swap_clients = self.swap_clients offer_id = swap_clients[0].postOffer( - Coins.PART, Coins.XMR, 101 * COIN, 0.12 * XMR_COIN, 101 * COIN, SwapTypes.XMR_SWAP, - lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=12) + Coins.PART, + Coins.XMR, + 101 * COIN, + 0.12 * XMR_COIN, + 101 * COIN, + SwapTypes.XMR_SWAP, + lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, + lock_value=12, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -1012,30 +1396,49 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) bid, xmr_swap = swap_clients[0].getXmrBid(bid_id) - assert (xmr_swap) + assert xmr_swap swap_clients[1].setBidDebugInd(bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK) swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=180) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, [BidStates.BID_STALLED_FOR_TEST, BidStates.XMR_SWAP_FAILED], sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + wait_for=180, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + [BidStates.BID_STALLED_FOR_TEST, BidStates.XMR_SWAP_FAILED], + sent=True, + ) bid_id_hex = bid_id.hex() - path = f'bids/{bid_id_hex}/states' + path = f"bids/{bid_id_hex}/states" offerer_states = read_json_api(1800, path) - assert (compare_bid_states(offerer_states, self.states_offerer[1]) is True) + assert compare_bid_states(offerer_states, self.states_offerer[1]) is True def test_03_follower_recover_a_lock_tx(self): - logging.info('---------- Test PART to XMR follower recovers coin a lock tx') + logging.info("---------- Test PART to XMR follower recovers coin a lock tx") swap_clients = self.swap_clients swap_clients[1].ci(Coins.PART)._altruistic = False offer_id = swap_clients[0].postOffer( - Coins.PART, Coins.XMR, 101 * COIN, 0.13 * XMR_COIN, 101 * COIN, SwapTypes.XMR_SWAP, - lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=16) + Coins.PART, + Coins.XMR, + 101 * COIN, + 0.13 * XMR_COIN, + 101 * COIN, + SwapTypes.XMR_SWAP, + lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, + lock_value=16, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -1044,35 +1447,59 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) bid, xmr_swap = swap_clients[0].getXmrBid(bid_id) - assert (xmr_swap) + assert xmr_swap swap_clients[1].setBidDebugInd(bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK) - swap_clients[0].setBidDebugInd(bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND) + swap_clients[0].setBidDebugInd( + bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND + ) swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_STALLED_FOR_TEST, wait_for=220) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_SWIPED, wait_for=80, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.BID_STALLED_FOR_TEST, + wait_for=220, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.XMR_SWAP_FAILED_SWIPED, + wait_for=80, + sent=True, + ) wait_for_none_active(test_delay_event, 1800) wait_for_none_active(test_delay_event, 1801) bid_id_hex = bid_id.hex() - path = f'bids/{bid_id_hex}/states' + path = f"bids/{bid_id_hex}/states" bidder_states = read_json_api(1801, path) - bidder_states = [s for s in bidder_states if s[1] != 'Bid Stalled (debug)'] - assert (compare_bid_states(bidder_states, self.states_bidder[2]) is True) + bidder_states = [s for s in bidder_states if s[1] != "Bid Stalled (debug)"] + assert compare_bid_states(bidder_states, self.states_bidder[2]) is True def test_03b_follower_recover_a_lock_tx_with_mercy(self): - logging.info('---------- Test PART to XMR follower recovers coin a lock tx with mercy output') + logging.info( + "---------- Test PART to XMR follower recovers coin a lock tx with mercy output" + ) swap_clients = self.swap_clients swap_clients[1].ci(Coins.PART)._altruistic = True offer_id = swap_clients[0].postOffer( - Coins.PART, Coins.XMR, 101 * COIN, 0.13 * XMR_COIN, 101 * COIN, SwapTypes.XMR_SWAP, - lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=16) + Coins.PART, + Coins.XMR, + 101 * COIN, + 0.13 * XMR_COIN, + 101 * COIN, + SwapTypes.XMR_SWAP, + lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, + lock_value=16, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -1081,30 +1508,56 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) bid, xmr_swap = swap_clients[0].getXmrBid(bid_id) - assert (xmr_swap) + assert xmr_swap swap_clients[1].setBidDebugInd(bid_id, DebugTypes.BID_DONT_SPEND_COIN_B_LOCK) - swap_clients[0].setBidDebugInd(bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND2) + swap_clients[0].setBidDebugInd( + bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND2 + ) - swap_clients[0].setBidDebugInd(bid_id, DebugTypes.WAIT_FOR_COIN_B_LOCK_BEFORE_REFUND, False) - swap_clients[1].setBidDebugInd(bid_id, DebugTypes.WAIT_FOR_COIN_B_LOCK_BEFORE_REFUND, False) + swap_clients[0].setBidDebugInd( + bid_id, DebugTypes.WAIT_FOR_COIN_B_LOCK_BEFORE_REFUND, False + ) + swap_clients[1].setBidDebugInd( + bid_id, DebugTypes.WAIT_FOR_COIN_B_LOCK_BEFORE_REFUND, False + ) swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, (BidStates.XMR_SWAP_NOSCRIPT_TX_REDEEMED, BidStates.SWAP_COMPLETED), wait_for=220) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_SWIPED, wait_for=120, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + (BidStates.XMR_SWAP_NOSCRIPT_TX_REDEEMED, BidStates.SWAP_COMPLETED), + wait_for=220, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.XMR_SWAP_FAILED_SWIPED, + wait_for=120, + sent=True, + ) wait_for_none_active(test_delay_event, 1800) wait_for_none_active(test_delay_event, 1801) def test_04_follower_recover_b_lock_tx(self): - logging.info('---------- Test PART to XMR follower recovers coin b lock tx') + logging.info("---------- Test PART to XMR follower recovers coin b lock tx") swap_clients = self.swap_clients offer_id = swap_clients[0].postOffer( - Coins.PART, Coins.XMR, 101 * COIN, 0.14 * XMR_COIN, 101 * COIN, SwapTypes.XMR_SWAP, - lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=28) + Coins.PART, + Coins.XMR, + 101 * COIN, + 0.14 * XMR_COIN, + 101 * COIN, + SwapTypes.XMR_SWAP, + lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, + lock_value=28, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -1112,29 +1565,48 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) bid, xmr_swap = swap_clients[0].getXmrBid(bid_id) - assert (xmr_swap) + assert xmr_swap swap_clients[1].setBidDebugInd(bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK) swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=180) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + wait_for=180, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + sent=True, + ) bid_id_hex = bid_id.hex() - path = f'bids/{bid_id_hex}/states' + path = f"bids/{bid_id_hex}/states" offerer_states = read_json_api(1800, path) bidder_states = read_json_api(1801, path) - assert (compare_bid_states(offerer_states, self.states_offerer[1]) is True) - assert (compare_bid_states(bidder_states, self.states_bidder[1]) is True) + assert compare_bid_states(offerer_states, self.states_offerer[1]) is True + assert compare_bid_states(bidder_states, self.states_bidder[1]) is True def test_05_btc_xmr(self): - logging.info('---------- Test BTC to XMR') + logging.info("---------- Test BTC to XMR") swap_clients = self.swap_clients - offer_id = swap_clients[0].postOffer(Coins.BTC, Coins.XMR, 10 * COIN, 100 * XMR_COIN, 10 * COIN, SwapTypes.XMR_SWAP) + offer_id = swap_clients[0].postOffer( + Coins.BTC, + Coins.XMR, + 10 * COIN, + 100 * XMR_COIN, + 10 * COIN, + SwapTypes.XMR_SWAP, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) - offers = swap_clients[1].listOffers(filters={'offer_id': offer_id}) + offers = swap_clients[1].listOffers(filters={"offer_id": offer_id}) offer = offers[0] swap_clients[1].ci(Coins.XMR).setFeePriority(3) @@ -1144,21 +1616,33 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) bid, xmr_swap = swap_clients[0].getXmrBid(bid_id) - assert (xmr_swap) + assert xmr_swap swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=180, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + ) swap_clients[1].ci(Coins.XMR).setFeePriority(0) def test_06_multiple_swaps(self): - logging.info('---------- Test Multiple concurrent swaps') + logging.info("---------- Test Multiple concurrent swaps") swap_clients = self.swap_clients - js_w0_before = read_json_api(1800, 'wallets') - js_w1_before = read_json_api(1801, 'wallets') + js_w0_before = read_json_api(1800, "wallets") + js_w1_before = read_json_api(1801, "wallets") amt_1 = make_int(random.uniform(0.001, 19.0), scale=8, r=1) amt_2 = make_int(random.uniform(0.001, 49.0), scale=8, r=1) @@ -1166,10 +1650,14 @@ class Test(BaseTest): rate_1 = make_int(random.uniform(80.0, 110.0), scale=12, r=1) rate_2 = make_int(random.uniform(0.01, 0.5), scale=12, r=1) - logging.info('amt_1 {}, rate_1 {}'.format(amt_1, rate_1)) - logging.info('amt_2 {}, rate_2 {}'.format(amt_2, rate_2)) - offer1_id = swap_clients[0].postOffer(Coins.BTC, Coins.XMR, amt_1, rate_1, amt_1, SwapTypes.XMR_SWAP) - offer2_id = swap_clients[0].postOffer(Coins.PART, Coins.XMR, amt_2, rate_2, amt_2, SwapTypes.XMR_SWAP) + logging.info("amt_1 {}, rate_1 {}".format(amt_1, rate_1)) + logging.info("amt_2 {}, rate_2 {}".format(amt_2, rate_2)) + offer1_id = swap_clients[0].postOffer( + Coins.BTC, Coins.XMR, amt_1, rate_1, amt_1, SwapTypes.XMR_SWAP + ) + offer2_id = swap_clients[0].postOffer( + Coins.PART, Coins.XMR, amt_2, rate_2, amt_2, SwapTypes.XMR_SWAP + ) wait_for_offer(test_delay_event, swap_clients[1], offer1_id) offer1 = swap_clients[1].getOffer(offer1_id) @@ -1179,7 +1667,14 @@ class Test(BaseTest): bid1_id = swap_clients[1].postXmrBid(offer1_id, offer1.amount_from) bid2_id = swap_clients[1].postXmrBid(offer2_id, offer2.amount_from) - offer3_id = swap_clients[0].postOffer(Coins.PART, Coins.XMR, 11 * COIN, 0.15 * XMR_COIN, 11 * COIN, SwapTypes.XMR_SWAP) + offer3_id = swap_clients[0].postOffer( + Coins.PART, + Coins.XMR, + 11 * COIN, + 0.15 * XMR_COIN, + 11 * COIN, + SwapTypes.XMR_SWAP, + ) wait_for_bid(test_delay_event, swap_clients[0], bid1_id, BidStates.BID_RECEIVED) swap_clients[0].acceptXmrBid(bid1_id) @@ -1194,26 +1689,79 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[0], bid3_id, BidStates.BID_RECEIVED) swap_clients[0].acceptXmrBid(bid3_id) - wait_for_bid(test_delay_event, swap_clients[0], bid1_id, BidStates.SWAP_COMPLETED, wait_for=180) - wait_for_bid(test_delay_event, swap_clients[1], bid1_id, BidStates.SWAP_COMPLETED, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid1_id, + BidStates.SWAP_COMPLETED, + wait_for=180, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid1_id, + BidStates.SWAP_COMPLETED, + sent=True, + ) - wait_for_bid(test_delay_event, swap_clients[0], bid2_id, BidStates.SWAP_COMPLETED, wait_for=120) - wait_for_bid(test_delay_event, swap_clients[1], bid2_id, BidStates.SWAP_COMPLETED, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid2_id, + BidStates.SWAP_COMPLETED, + wait_for=120, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid2_id, + BidStates.SWAP_COMPLETED, + sent=True, + ) - wait_for_bid(test_delay_event, swap_clients[0], bid3_id, BidStates.SWAP_COMPLETED, wait_for=120) - wait_for_bid(test_delay_event, swap_clients[1], bid3_id, BidStates.SWAP_COMPLETED, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid3_id, + BidStates.SWAP_COMPLETED, + wait_for=120, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid3_id, + BidStates.SWAP_COMPLETED, + sent=True, + ) wait_for_none_active(test_delay_event, 1800) wait_for_none_active(test_delay_event, 1801) - js_w0_after = read_json_api(1800, 'wallets') - js_w1_after = read_json_api(1801, 'wallets') - assert (make_int(js_w1_after['BTC']['balance'], scale=8, r=1) - (make_int(js_w1_before['BTC']['balance'], scale=8, r=1) + amt_1) < 1000) + js_w0_after = read_json_api(1800, "wallets") + js_w1_after = read_json_api(1801, "wallets") + assert ( + make_int(js_w1_after["BTC"]["balance"], scale=8, r=1) + - (make_int(js_w1_before["BTC"]["balance"], scale=8, r=1) + amt_1) + < 1000 + ) + logging.debug( + "node0 PART difference: {}".format( + make_int(js_w0_after["PART"]["balance"], scale=8, r=1) + - (make_int(js_w0_before["PART"]["balance"], scale=8, r=1) + amt_1) + ) + ) # TODO: exclude staking def test_07_revoke_offer(self): - logging.info('---------- Test offer revocaction') + logging.info("---------- Test offer revocaction") swap_clients = self.swap_clients - offer_id = swap_clients[0].postOffer(Coins.BTC, Coins.XMR, 10 * COIN, 100 * XMR_COIN, 10 * COIN, SwapTypes.XMR_SWAP) + offer_id = swap_clients[0].postOffer( + Coins.BTC, + Coins.XMR, + 10 * COIN, + 100 * XMR_COIN, + 10 * COIN, + SwapTypes.XMR_SWAP, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) swap_clients[0].revokeOffer(offer_id) @@ -1221,49 +1769,76 @@ class Test(BaseTest): wait_for_no_offer(test_delay_event, swap_clients[1], offer_id) def test_08_withdraw(self): - logging.info('---------- Test XMR withdrawals') - swap_clients = self.swap_clients - js_0 = read_json_api(1800, 'wallets') - address_to = js_0[Coins.XMR.name]['deposit_address'] + logging.info("---------- Test XMR withdrawals") - js_1 = read_json_api(1801, 'wallets') - assert (float(js_1[Coins.XMR.name]['balance']) > 0.0) + js_0 = read_json_api(1800, "wallets") + address_to = js_0[Coins.XMR.name]["deposit_address"] + + js_1 = read_json_api(1801, "wallets") + assert float(js_1[Coins.XMR.name]["balance"]) > 0.0 post_json = { - 'value': 1.1, - 'address': address_to, - 'sweepall': False, + "value": 1.1, + "address": address_to, + "sweepall": False, } - rv = read_json_api(1801, 'wallets/xmr/withdraw', post_json) - assert (len(rv['txid']) == 64) + rv = read_json_api(1801, "wallets/xmr/withdraw", post_json) + assert len(rv["txid"]) == 64 def test_09_auto_accept(self): - logging.info('---------- Test BTC to XMR auto accept') + logging.info("---------- Test BTC to XMR auto accept") swap_clients = self.swap_clients amt_swap = make_int(random.uniform(0.01, 11.0), scale=8, r=1) rate_swap = make_int(random.uniform(10.0, 101.0), scale=12, r=1) - offer_id = swap_clients[0].postOffer(Coins.BTC, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, auto_accept_bids=True) + offer_id = swap_clients[0].postOffer( + Coins.BTC, + Coins.XMR, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + auto_accept_bids=True, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) - offer = swap_clients[1].listOffers(filters={'offer_id': offer_id})[0] + offer = swap_clients[1].listOffers(filters={"offer_id": offer_id})[0] bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=180, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + ) def test_09_1_auto_accept_multiple(self): - logging.info('---------- Test BTC to XMR auto accept multiple bids') + logging.info("---------- Test BTC to XMR auto accept multiple bids") swap_clients = self.swap_clients amt_swap = make_int(10, scale=8, r=1) rate_swap = make_int(100, scale=12, r=1) min_bid = make_int(1, scale=8, r=1) extra_options = { - 'amount_negotiable': True, - 'automation_id': 1, + "amount_negotiable": True, + "automation_id": 1, } - offer_id = swap_clients[0].postOffer(Coins.BTC, Coins.XMR, amt_swap, rate_swap, min_bid, SwapTypes.XMR_SWAP, extra_options=extra_options) + offer_id = swap_clients[0].postOffer( + Coins.BTC, + Coins.XMR, + amt_swap, + rate_swap, + min_bid, + SwapTypes.XMR_SWAP, + extra_options=extra_options, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) - offer = swap_clients[1].listOffers(filters={'offer_id': offer_id})[0] below_min_bid = min_bid - 1 @@ -1271,14 +1846,18 @@ class Test(BaseTest): try: bid_id = swap_clients[1].postBid(offer_id, below_min_bid) except Exception as e: - assert ('Bid amount below minimum' in str(e)) + assert "Bid amount below minimum" in str(e) extra_bid_options = { - 'debug_skip_validation': True, + "debug_skip_validation": True, } - bid_id = swap_clients[1].postBid(offer_id, below_min_bid, extra_options=extra_bid_options) + bid_id = swap_clients[1].postBid( + offer_id, below_min_bid, extra_options=extra_bid_options + ) - event = wait_for_event(test_delay_event, swap_clients[0], Concepts.NETWORK_MESSAGE, bid_id) - assert ('Bid amount below minimum' in event.event_msg) + event = wait_for_event( + test_delay_event, swap_clients[0], Concepts.NETWORK_MESSAGE, bid_id + ) + assert "Bid amount below minimum" in event.event_msg bid_ids = [] for i in range(5): @@ -1287,34 +1866,77 @@ class Test(BaseTest): # Should fail > max concurrent test_delay_event.wait(1.0) bid_id = swap_clients[1].postBid(offer_id, min_bid) - logging.info('Waiting for bid {} to fail.'.format(bid_id.hex())) - event = wait_for_event(test_delay_event, swap_clients[0], Concepts.BID, bid_id, event_type=EventLogTypes.AUTOMATION_CONSTRAINT) - assert ('Already have 5 bids to complete' in event.event_msg) + logging.info("Waiting for bid {} to fail.".format(bid_id.hex())) + event = wait_for_event( + test_delay_event, + swap_clients[0], + Concepts.BID, + bid_id, + event_type=EventLogTypes.AUTOMATION_CONSTRAINT, + ) + assert "Already have 5 bids to complete" in event.event_msg for bid_id in bid_ids: - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=240) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=240, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + ) amt_bid = make_int(5, scale=8, r=1) # Should fail > total value amt_bid += 1 bid_id = swap_clients[1].postBid(offer_id, amt_bid) - event = wait_for_event(test_delay_event, swap_clients[0], Concepts.BID, bid_id, event_type=EventLogTypes.AUTOMATION_CONSTRAINT) - assert ('Over remaining offer value' in event.event_msg) + event = wait_for_event( + test_delay_event, + swap_clients[0], + Concepts.BID, + bid_id, + event_type=EventLogTypes.AUTOMATION_CONSTRAINT, + ) + assert "Over remaining offer value" in event.event_msg # Should pass amt_bid -= 1 bid_id = swap_clients[1].postBid(offer_id, amt_bid) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=180, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + ) def test_10_locked_refundtx(self): - logging.info('---------- Test Refund tx is locked') + logging.info("---------- Test Refund tx is locked") swap_clients = self.swap_clients - offer_id = swap_clients[0].postOffer(Coins.BTC, Coins.XMR, 10 * COIN, 100 * XMR_COIN, 10 * COIN, SwapTypes.XMR_SWAP) + offer_id = swap_clients[0].postOffer( + Coins.BTC, + Coins.XMR, + 10 * COIN, + 100 * XMR_COIN, + 10 * COIN, + SwapTypes.XMR_SWAP, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) - offers = swap_clients[1].listOffers(filters={'offer_id': offer_id}) + offers = swap_clients[1].listOffers(filters={"offer_id": offer_id}) offer = offers[0] bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from) @@ -1322,72 +1944,106 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) bid, xmr_swap = swap_clients[0].getXmrBid(bid_id) - assert (xmr_swap) + assert xmr_swap swap_clients[1].setBidDebugInd(bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK) swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_SCRIPT_COIN_LOCKED, wait_for=180) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.XMR_SWAP_SCRIPT_COIN_LOCKED, + wait_for=180, + ) bid, xmr_swap = swap_clients[0].getXmrBid(bid_id) - assert (xmr_swap) + assert xmr_swap try: swap_clients[0].ci(Coins.BTC).publishTx(xmr_swap.a_lock_refund_tx) - assert (False), 'Lock refund tx should be locked' + assert False, "Lock refund tx should be locked" except Exception as e: - assert ('non-BIP68-final' in str(e)) + assert "non-BIP68-final" in str(e) def test_11_particl_anon(self): - logging.info('---------- Test Particl anon transactions') + logging.info("---------- Test Particl anon transactions") swap_clients = self.swap_clients - js_0 = read_json_api(1800, 'wallets/part') - assert (float(js_0['anon_balance']) == 0.0) - node0_anon_before = js_0['anon_balance'] + js_0['anon_pending'] + js_0 = read_json_api(1800, "wallets/part") + assert float(js_0["anon_balance"]) == 0.0 + node0_anon_before = js_0["anon_balance"] + js_0["anon_pending"] - wait_for_balance(test_delay_event, 'http://127.0.0.1:1801/json/wallets/part', 'balance', 200.0) - js_1 = read_json_api(1801, 'wallets/part') - assert (float(js_1['balance']) > 200.0) - node1_anon_before = js_1['anon_balance'] + js_1['anon_pending'] + wait_for_balance( + test_delay_event, + "http://127.0.0.1:1801/json/wallets/part", + "balance", + 200.0, + ) + js_1 = read_json_api(1801, "wallets/part") + assert float(js_1["balance"]) > 200.0 + node1_anon_before = js_1["anon_balance"] + js_1["anon_pending"] - callnoderpc(1, 'reservebalance', [True, 1000000]) # Stop staking to avoid conflicts (input used by tx->anon staked before tx gets in the chain) + callnoderpc( + 1, "reservebalance", [True, 1000000] + ) # Stop staking to avoid conflicts (input used by tx->anon staked before tx gets in the chain) post_json = { - 'value': 100, - 'address': js_1['stealth_address'], - 'subfee': False, - 'type_to': 'anon', + "value": 100, + "address": js_1["stealth_address"], + "subfee": False, + "type_to": "anon", } - json_rv = json.loads(post_json_req('http://127.0.0.1:1801/json/wallets/part/withdraw', post_json)) - assert (len(json_rv['txid']) == 64) + json_rv = json.loads( + post_json_req("http://127.0.0.1:1801/json/wallets/part/withdraw", post_json) + ) + assert len(json_rv["txid"]) == 64 - logging.info('Waiting for anon balance') - wait_for_balance(test_delay_event, 'http://127.0.0.1:1801/json/wallets/part', 'anon_balance', 100.0 + node1_anon_before) - js_1 = read_json_api(1801, 'wallets/part') - node1_anon_before = js_1['anon_balance'] + js_1['anon_pending'] + logging.info("Waiting for anon balance") + wait_for_balance( + test_delay_event, + "http://127.0.0.1:1801/json/wallets/part", + "anon_balance", + 100.0 + node1_anon_before, + ) + js_1 = read_json_api(1801, "wallets/part") + node1_anon_before = js_1["anon_balance"] + js_1["anon_pending"] - callnoderpc(1, 'reservebalance', [False]) + callnoderpc(1, "reservebalance", [False]) post_json = { - 'value': 10, - 'address': js_0['stealth_address'], - 'subfee': True, - 'type_from': 'anon', - 'type_to': 'blind', + "value": 10, + "address": js_0["stealth_address"], + "subfee": True, + "type_from": "anon", + "type_to": "blind", } - json_rv = json.loads(post_json_req('http://127.0.0.1:1801/json/wallets/part/withdraw', post_json)) - assert (len(json_rv['txid']) == 64) + json_rv = json.loads( + post_json_req("http://127.0.0.1:1801/json/wallets/part/withdraw", post_json) + ) + assert len(json_rv["txid"]) == 64 - logging.info('Waiting for blind balance') - wait_for_balance(test_delay_event, 'http://127.0.0.1:1800/json/wallets/part', 'blind_balance', 9.8) - if float(js_0['blind_balance']) >= 10.0: - raise ValueError('Expect blind balance < 10') + logging.info("Waiting for blind balance") + wait_for_balance( + test_delay_event, + "http://127.0.0.1:1800/json/wallets/part", + "blind_balance", + 9.8, + ) + if float(js_0["blind_balance"]) >= 10.0: + raise ValueError("Expect blind balance < 10") amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1) rate_swap = make_int(random.uniform(2.0, 20.0), scale=8, r=1) - offer_id = swap_clients[0].postOffer(Coins.BTC, Coins.PART_ANON, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP) + offer_id = swap_clients[0].postOffer( + Coins.BTC, + Coins.PART_ANON, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) - offers = swap_clients[0].listOffers(filters={'offer_id': offer_id}) + offers = swap_clients[0].listOffers(filters={"offer_id": offer_id}) offer = offers[0] bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from) @@ -1395,23 +2051,36 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) bid, xmr_swap = swap_clients[0].getXmrBid(bid_id) - assert (xmr_swap) + assert xmr_swap amount_to = float(format_amount(bid.amount_to, 8)) swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=180, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + ) - js_1 = read_json_api(1801, 'wallets/part') - assert (js_1['anon_balance'] < node1_anon_before - amount_to) + js_1 = read_json_api(1801, "wallets/part") + assert js_1["anon_balance"] < node1_anon_before - amount_to - js_0 = read_json_api(1800, 'wallets/part') - assert (js_0['anon_balance'] + js_0['anon_pending'] > node0_anon_before + (amount_to - 0.05)) + js_0 = read_json_api(1800, "wallets/part") + assert js_0["anon_balance"] + js_0["anon_pending"] > node0_anon_before + ( + amount_to - 0.05 + ) # Test chain b (no-script) lock tx size ci = swap_clients[1].ci(Coins.PART_ANON) - pi = swap_clients[1].pi(SwapTypes.XMR_SWAP) amount: int = ci.make_int(random.uniform(0.1, 2.0), r=1) fee_rate: int = 1000 v = ci.getNewSecretKey() @@ -1423,47 +2092,63 @@ class Test(BaseTest): lock_tx_b_spend_txid = None for i in range(20): try: - lock_tx_b_spend_txid = ci.spendBLockTx(lock_tx_b_txid, addr_out, v, s, amount, fee_rate, 0) + lock_tx_b_spend_txid = ci.spendBLockTx( + lock_tx_b_txid, addr_out, v, s, amount, fee_rate, 0 + ) break except Exception as e: - print('spendBLockTx failed', str(e)) + print("spendBLockTx failed", str(e)) test_delay_event.wait(2) - assert (lock_tx_b_spend_txid is not None) + assert lock_tx_b_spend_txid is not None lock_tx_b_spend = ci.getTransaction(lock_tx_b_spend_txid) if lock_tx_b_spend is None: lock_tx_b_spend = ci.getWalletTransaction(lock_tx_b_spend_txid) - lock_tx_b_spend_decoded = ci.rpc('decoderawtransaction', [lock_tx_b_spend.hex()]) + lock_tx_b_spend_decoded = ci.rpc( + "decoderawtransaction", [lock_tx_b_spend.hex()] + ) expect_vsize: int = ci.xmr_swap_b_lock_spend_tx_vsize() - assert (expect_vsize >= lock_tx_b_spend_decoded['vsize']) - assert (expect_vsize - lock_tx_b_spend_decoded['vsize'] < 10) + assert expect_vsize >= lock_tx_b_spend_decoded["vsize"] + assert expect_vsize - lock_tx_b_spend_decoded["vsize"] < 10 def test_12_particl_blind(self): - logging.info('---------- Test Particl blind transactions') + logging.info("---------- Test Particl blind transactions") swap_clients = self.swap_clients - js_0 = read_json_api(1800, 'wallets/part') - node0_blind_before = js_0['blind_balance'] + js_0['blind_unconfirmed'] + js_0 = read_json_api(1800, "wallets/part") + node0_blind_before = js_0["blind_balance"] + js_0["blind_unconfirmed"] - wait_for_balance(test_delay_event, 'http://127.0.0.1:1801/json/wallets/part', 'balance', 200.0) - js_1 = read_json_api(1801, 'wallets/part') - assert (float(js_1['balance']) > 200.0) - node1_blind_before = js_1['blind_balance'] + js_1['blind_unconfirmed'] + wait_for_balance( + test_delay_event, + "http://127.0.0.1:1801/json/wallets/part", + "balance", + 200.0, + ) + js_1 = read_json_api(1801, "wallets/part") + assert float(js_1["balance"]) > 200.0 + node1_blind_before = js_1["blind_balance"] + js_1["blind_unconfirmed"] post_json = { - 'value': 100, - 'address': js_0['stealth_address'], - 'subfee': False, - 'type_to': 'blind', + "value": 100, + "address": js_0["stealth_address"], + "subfee": False, + "type_to": "blind", } - json_rv = json.loads(post_json_req('http://127.0.0.1:1800/json/wallets/part/withdraw', post_json)) - assert (len(json_rv['txid']) == 64) + json_rv = json.loads( + post_json_req("http://127.0.0.1:1800/json/wallets/part/withdraw", post_json) + ) + assert len(json_rv["txid"]) == 64 - logging.info('Waiting for blind balance') - wait_for_balance(test_delay_event, 'http://127.0.0.1:1800/json/wallets/part', 'blind_balance', 100.0 + node0_blind_before) - js_0 = read_json_api(1800, 'wallets/part') - node0_blind_before = js_0['blind_balance'] + js_0['blind_unconfirmed'] + logging.info("Waiting for blind balance") + wait_for_balance( + test_delay_event, + "http://127.0.0.1:1800/json/wallets/part", + "blind_balance", + 100.0 + node0_blind_before, + ) + js_0 = read_json_api(1800, "wallets/part") + node0_blind_before = js_0["blind_balance"] + js_0["blind_unconfirmed"] coin_from = Coins.PART_BLIND coin_to = Coins.XMR @@ -1471,9 +2156,11 @@ class Test(BaseTest): ci_to = swap_clients[0].ci(coin_to) amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1) rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1) - offer_id = swap_clients[0].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP) + offer_id = swap_clients[0].postOffer( + coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) - offers = swap_clients[0].listOffers(filters={'offer_id': offer_id}) + offers = swap_clients[0].listOffers(filters={"offer_id": offer_id}) offer = offers[0] bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from) @@ -1482,25 +2169,39 @@ class Test(BaseTest): swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=180, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + ) amount_from = float(format_amount(amt_swap, 8)) - js_1 = read_json_api(1801, 'wallets/part') - node1_blind_after = js_1['blind_balance'] + js_1['blind_unconfirmed'] - assert (node1_blind_after > node1_blind_before + (amount_from - 0.05)) + js_1 = read_json_api(1801, "wallets/part") + node1_blind_after = js_1["blind_balance"] + js_1["blind_unconfirmed"] + assert node1_blind_after > node1_blind_before + (amount_from - 0.05) - js_0 = read_json_api(1800, 'wallets/part') - node0_blind_after = js_0['blind_balance'] + js_0['blind_unconfirmed'] - assert (node0_blind_after < node0_blind_before - amount_from) + js_0 = read_json_api(1800, "wallets/part") + node0_blind_after = js_0["blind_balance"] + js_0["blind_unconfirmed"] + assert node0_blind_after < node0_blind_before - amount_from def test_13_locked_xmr(self): - logging.info('---------- Test PART to XMR leader recovers coin a lock tx') + logging.info("---------- Test PART to XMR leader recovers coin a lock tx") swap_clients = self.swap_clients amt_swap = make_int(random.uniform(0.1, 10.0), scale=8, r=1) rate_swap = make_int(random.uniform(2.0, 20.0), scale=12, r=1) - offer_id = swap_clients[0].postOffer(Coins.PART, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP) + offer_id = swap_clients[0].postOffer( + Coins.PART, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -1510,66 +2211,116 @@ class Test(BaseTest): swap_clients[1].setBidDebugInd(bid_id, DebugTypes.SEND_LOCKED_XMR) swap_clients[0].acceptXmrBid(bid_id) - wait_for_event(test_delay_event, swap_clients[0], Concepts.BID, bid_id, event_type=EventLogTypes.LOCK_TX_B_INVALID, wait_for=180) + wait_for_event( + test_delay_event, + swap_clients[0], + Concepts.BID, + bid_id, + event_type=EventLogTypes.LOCK_TX_B_INVALID, + wait_for=180, + ) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_SCRIPT_COIN_LOCKED, wait_for=180) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_SCRIPT_COIN_LOCKED, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.XMR_SWAP_SCRIPT_COIN_LOCKED, + wait_for=180, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.XMR_SWAP_SCRIPT_COIN_LOCKED, + sent=True, + ) swap_clients[0].abandonBid(bid_id) swap_clients[1].abandonBid(bid_id) def test_14_sweep_balance(self): - logging.info('---------- Test sweep balance offer') + logging.info("---------- Test sweep balance offer") swap_clients = self.swap_clients # Disable staking - walletsettings = callnoderpc(2, 'walletsettings', ['stakingoptions', ]) - walletsettings['enabled'] = False - walletsettings = callnoderpc(2, 'walletsettings', ['stakingoptions', walletsettings]) - walletsettings = callnoderpc(2, 'walletsettings', ['stakingoptions', ]) - assert (walletsettings['stakingoptions']['enabled'] is False) + walletsettings = callnoderpc( + 2, + "walletsettings", + [ + "stakingoptions", + ], + ) + walletsettings["enabled"] = False + walletsettings = callnoderpc( + 2, "walletsettings", ["stakingoptions", walletsettings] + ) + walletsettings = callnoderpc( + 2, + "walletsettings", + [ + "stakingoptions", + ], + ) + assert walletsettings["stakingoptions"]["enabled"] is False # Prepare balance - js_w2 = read_json_api(1802, 'wallets') - if float(js_w2['PART']['balance']) < 100.0: + js_w2 = read_json_api(1802, "wallets") + if float(js_w2["PART"]["balance"]) < 100.0: post_json = { - 'value': 100, - 'address': js_w2['PART']['deposit_address'], - 'subfee': False, + "value": 100, + "address": js_w2["PART"]["deposit_address"], + "subfee": False, } - json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/part/withdraw', post_json) - assert (len(json_rv['txid']) == 64) - wait_for_balance(test_delay_event, 'http://127.0.0.1:1802/json/wallets/part', 'balance', 100.0) + json_rv = read_json_api( + TEST_HTTP_PORT + 0, "wallets/part/withdraw", post_json + ) + assert len(json_rv["txid"]) == 64 + wait_for_balance( + test_delay_event, + "http://127.0.0.1:1802/json/wallets/part", + "balance", + 100.0, + ) - js_w2 = read_json_api(1802, 'wallets') - assert (float(js_w2['PART']['balance']) >= 100.0) + js_w2 = read_json_api(1802, "wallets") + assert float(js_w2["PART"]["balance"]) >= 100.0 - js_w2 = read_json_api(1802, 'wallets') + js_w2 = read_json_api(1802, "wallets") post_json = { - 'value': float(js_w2['PART']['balance']), - 'address': read_json_api(1802, 'wallets/part/nextdepositaddr'), - 'subfee': True, + "value": float(js_w2["PART"]["balance"]), + "address": read_json_api(1802, "wallets/part/nextdepositaddr"), + "subfee": True, } - json_rv = read_json_api(TEST_HTTP_PORT + 2, 'wallets/part/withdraw', post_json) - wait_for_balance(test_delay_event, 'http://127.0.0.1:1802/json/wallets/part', 'balance', 10.0) - assert (len(json_rv['txid']) == 64) + json_rv = read_json_api(TEST_HTTP_PORT + 2, "wallets/part/withdraw", post_json) + wait_for_balance( + test_delay_event, "http://127.0.0.1:1802/json/wallets/part", "balance", 10.0 + ) + assert len(json_rv["txid"]) == 64 # Create prefunded ITX ci = swap_clients[2].ci(Coins.PART) pi = swap_clients[2].pi(SwapTypes.XMR_SWAP) - js_w2 = read_json_api(1802, 'wallets') - swap_value = ci.make_int(js_w2['PART']['balance']) + js_w2 = read_json_api(1802, "wallets") + swap_value = ci.make_int(js_w2["PART"]["balance"]) itx = pi.getFundedInitiateTxTemplate(ci, swap_value, True) itx_decoded = ci.describeTx(itx.hex()) n = pi.findMockVout(ci, itx_decoded) - value_after_subfee = ci.make_int(itx_decoded['vout'][n]['value']) - assert (value_after_subfee < swap_value) + value_after_subfee = ci.make_int(itx_decoded["vout"][n]["value"]) + assert value_after_subfee < swap_value swap_value = value_after_subfee wait_for_unspent(test_delay_event, ci, swap_value) - extra_options = {'prefunded_itx': itx} - offer_id = swap_clients[2].postOffer(Coins.PART, Coins.XMR, swap_value, 2 * COIN, swap_value, SwapTypes.XMR_SWAP, extra_options=extra_options) + extra_options = {"prefunded_itx": itx} + offer_id = swap_clients[2].postOffer( + Coins.PART, + Coins.XMR, + swap_value, + 2 * COIN, + swap_value, + SwapTypes.XMR_SWAP, + extra_options=extra_options, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -1578,27 +2329,53 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[2], bid_id, BidStates.BID_RECEIVED) swap_clients[2].acceptBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[2], bid_id, BidStates.SWAP_COMPLETED, wait_for=120) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=120) + wait_for_bid( + test_delay_event, + swap_clients[2], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=120, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + wait_for=120, + ) # Verify expected inputs were used bid, _, _, _, _ = swap_clients[2].getXmrBidAndOffer(bid_id) - assert (bid.xmr_a_lock_tx) - wtx = ci.rpc('gettransaction', [bid.xmr_a_lock_tx.txid.hex(),]) - itx_after = ci.describeTx(wtx['hex']) - assert (len(itx_after['vin']) == len(itx_decoded['vin'])) - for i, txin in enumerate(itx_decoded['vin']): - assert (txin['txid'] == itx_after['vin'][i]['txid']) - assert (txin['vout'] == itx_after['vin'][i]['vout']) + assert bid.xmr_a_lock_tx + wtx = ci.rpc( + "gettransaction", + [ + bid.xmr_a_lock_tx.txid.hex(), + ], + ) + itx_after = ci.describeTx(wtx["hex"]) + assert len(itx_after["vin"]) == len(itx_decoded["vin"]) + for i, txin in enumerate(itx_decoded["vin"]): + assert txin["txid"] == itx_after["vin"][i]["txid"] + assert txin["vout"] == itx_after["vin"][i]["vout"] def test_15_missed_xmr_send(self): - logging.info('---------- Test PART to XMR B lock tx is lost') + logging.info("---------- Test PART to XMR B lock tx is lost") swap_clients = self.swap_clients amt_swap = make_int(random.uniform(0.1, 10.0), scale=8, r=1) rate_swap = make_int(random.uniform(2.0, 20.0), scale=12, r=1) - offer_id = swap_clients[0].postOffer(Coins.PART, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, - lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=28) + offer_id = swap_clients[0].postOffer( + Coins.PART, + Coins.XMR, + amt_swap, + rate_swap, + amt_swap, + SwapTypes.XMR_SWAP, + lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, + lock_value=28, + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) offer = swap_clients[1].getOffer(offer_id) @@ -1608,27 +2385,42 @@ class Test(BaseTest): swap_clients[1].setBidDebugInd(bid_id, DebugTypes.B_LOCK_TX_MISSED_SEND) swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=1800) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=30, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + wait_for=1800, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.XMR_SWAP_FAILED_REFUNDED, + wait_for=30, + sent=True, + ) def test_16_new_subaddress(self): - logging.info('---------- Test that new subaddresses are created') + logging.info("---------- Test that new subaddresses are created") - current_subaddress = read_json_api(1800, 'wallets/xmr')['deposit_address'] - first_subaddress = read_json_api(1800, 'wallets/xmr/nextdepositaddr') - second_subaddress = read_json_api(1800, 'wallets/xmr/nextdepositaddr') - assert (first_subaddress != second_subaddress) - assert (first_subaddress != current_subaddress) - assert (second_subaddress != current_subaddress) + current_subaddress = read_json_api(1800, "wallets/xmr")["deposit_address"] + first_subaddress = read_json_api(1800, "wallets/xmr/nextdepositaddr") + second_subaddress = read_json_api(1800, "wallets/xmr/nextdepositaddr") + assert first_subaddress != second_subaddress + assert first_subaddress != current_subaddress + assert second_subaddress != current_subaddress def test_17_edit_bid_state(self): - logging.info('---------- Test manually changing the state of a bid') + logging.info("---------- Test manually changing the state of a bid") # Stall the bid by setting a debug token. Once it's stalled, clear the debug token and fix the bid state. swap_clients = self.swap_clients amt_swap = make_int(random.uniform(0.1, 10.0), scale=8, r=1) rate_swap = make_int(random.uniform(2.0, 20.0), scale=12, r=1) - offer_id = swap_clients[0].postOffer(Coins.PART, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP) + offer_id = swap_clients[0].postOffer( + Coins.PART, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP + ) wait_for_offer(test_delay_event, swap_clients[1], offer_id) bid_id = swap_clients[1].postXmrBid(offer_id, amt_swap) @@ -1637,60 +2429,113 @@ class Test(BaseTest): wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED) swap_clients[0].acceptXmrBid(bid_id) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.BID_STALLED_FOR_TEST, sent=True, wait_for=90) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.BID_STALLED_FOR_TEST, + sent=True, + wait_for=90, + ) data = { - 'debug_ind': int(DebugTypes.NONE), - 'bid_state': int(BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX), + "debug_ind": int(DebugTypes.NONE), + "bid_state": int(BidStates.XMR_SWAP_MSG_SCRIPT_LOCK_SPEND_TX), } swap_clients[1].manualBidUpdate(bid_id, data) - wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180) - wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True) + wait_for_bid( + test_delay_event, + swap_clients[0], + bid_id, + BidStates.SWAP_COMPLETED, + wait_for=180, + ) + wait_for_bid( + test_delay_event, + swap_clients[1], + bid_id, + BidStates.SWAP_COMPLETED, + sent=True, + ) def test_97_withdraw_all(self): - logging.info('---------- Test XMR withdrawal all') + logging.info("---------- Test XMR withdrawal all") - wait_for_balance(test_delay_event, 'http://127.0.0.1:1800/json/wallets/xmr', 'unconfirmed', 0.0) - wallets0 = read_json_api(TEST_HTTP_PORT + 0, 'wallets') - xmr_total = float(wallets0[Coins.XMR.name]['balance']) + wait_for_balance( + test_delay_event, + "http://127.0.0.1:1800/json/wallets/xmr", + "unconfirmed", + 0.0, + ) + wallets0 = read_json_api(TEST_HTTP_PORT + 0, "wallets") + xmr_total = float(wallets0[Coins.XMR.name]["balance"]) if xmr_total < 10.0: - address_to = read_json_api(1800, 'wallets')[Coins.XMR.name]['deposit_address'] + address_to = read_json_api(1800, "wallets")[Coins.XMR.name][ + "deposit_address" + ] post_json = { - 'value': 10.0, - 'address': address_to, - 'sweepall': False, + "value": 10.0, + "address": address_to, + "sweepall": False, } - json_rv = read_json_api(TEST_HTTP_PORT + 1, 'wallets/xmr/withdraw', post_json) - wait_for_balance(test_delay_event, 'http://127.0.0.1:1800/json/wallets/xmr', 'balance', 10.0) + json_rv = read_json_api( + TEST_HTTP_PORT + 1, "wallets/xmr/withdraw", post_json + ) + wait_for_balance( + test_delay_event, + "http://127.0.0.1:1800/json/wallets/xmr", + "balance", + 10.0, + ) post_json = { - 'address': read_json_api(1801, 'wallets')[Coins.XMR.name]['deposit_address'], - 'sweepall': True, + "address": read_json_api(1801, "wallets")[Coins.XMR.name][ + "deposit_address" + ], + "sweepall": True, } - json_rv = json.loads(post_json_req('http://127.0.0.1:{}/json/wallets/xmr/withdraw'.format(TEST_HTTP_PORT + 0), post_json)) - assert (len(json_rv['txid']) == 64) + json_rv = json.loads( + post_json_req( + "http://127.0.0.1:{}/json/wallets/xmr/withdraw".format( + TEST_HTTP_PORT + 0 + ), + post_json, + ) + ) + assert len(json_rv["txid"]) == 64 try: - logging.info('Disabling XMR mining') + logging.info("Disabling XMR mining") pause_event.clear() - address_to = read_json_api(1800, 'wallets')[Coins.XMR.name]['deposit_address'] + address_to = read_json_api(1800, "wallets")[Coins.XMR.name][ + "deposit_address" + ] - wallets1 = read_json_api(TEST_HTTP_PORT + 1, 'wallets') - xmr_total = float(wallets1[Coins.XMR.name]['balance']) - assert (xmr_total > 10) + wallets1 = read_json_api(TEST_HTTP_PORT + 1, "wallets") + xmr_total = float(wallets1[Coins.XMR.name]["balance"]) + assert xmr_total > 10 post_json = { - 'address': address_to, - 'sweepall': True, + "address": address_to, + "sweepall": True, } - json_rv = json.loads(post_json_req('http://127.0.0.1:{}/json/wallets/xmr/withdraw'.format(TEST_HTTP_PORT + 1), post_json)) - assert ('Balance must be fully confirmed to use sweep all' in json_rv['error']) + json_rv = json.loads( + post_json_req( + "http://127.0.0.1:{}/json/wallets/xmr/withdraw".format( + TEST_HTTP_PORT + 1 + ), + post_json, + ) + ) + assert ( + "Balance must be fully confirmed to use sweep all" in json_rv["error"] + ) finally: - logging.info('Restoring XMR mining') + logging.info("Restoring XMR mining") pause_event.set() -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/test_xmr_bids_offline.py b/tests/basicswap/test_xmr_bids_offline.py index e52b4df..a1323a5 100644 --- a/tests/basicswap/test_xmr_bids_offline.py +++ b/tests/basicswap/test_xmr_bids_offline.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2021-2022 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -51,105 +52,140 @@ class Test(XmrTestBase): waitForServer(self.delay_event, 12700) waitForServer(self.delay_event, 12701) - wallets1 = read_json_api(12701, 'wallets') - assert (float(wallets1['XMR']['balance']) > 0.0) + wallets1 = read_json_api(12701, "wallets") + assert float(wallets1["XMR"]["balance"]) > 0.0 offer_data = { - 'addr_from': -1, - 'coin_from': 'PART', - 'coin_to': 'XMR', - 'amt_from': 1, - 'amt_to': 1, - 'lockhrs': 24, - 'automation_strat_id': 1} - rv = json.loads(urlopen('http://127.0.0.1:12700/json/offers/new', data=parse.urlencode(offer_data).encode()).read()) - offer0_id = rv['offer_id'] + "addr_from": -1, + "coin_from": "PART", + "coin_to": "XMR", + "amt_from": 1, + "amt_to": 1, + "lockhrs": 24, + "automation_strat_id": 1, + } + rv = json.loads( + urlopen( + "http://127.0.0.1:12700/json/offers/new", + data=parse.urlencode(offer_data).encode(), + ).read() + ) + offer0_id = rv["offer_id"] - offer_data['amt_from'] = '2' - rv = json.loads(urlopen('http://127.0.0.1:12700/json/offers/new', data=parse.urlencode(offer_data).encode()).read()) - offer1_id = rv['offer_id'] + offer_data["amt_from"] = "2" + rv = json.loads( + urlopen( + "http://127.0.0.1:12700/json/offers/new", + data=parse.urlencode(offer_data).encode(), + ).read() + ) + offer1_id = rv["offer_id"] summary = read_json_api(12700) - assert (summary['num_sent_offers'] > 1) + assert summary["num_sent_offers"] > 1 - logger.info('Waiting for offer') + logger.info("Waiting for offer") waitForNumOffers(self.delay_event, 12701, 2) - logger.info('Stopping node 0') + logger.info("Stopping node 0") c0 = self.processes[0] c0.terminate() c0.join() - offers = json.loads(urlopen('http://127.0.0.1:12701/json/offers/{}'.format(offer0_id)).read()) - assert (len(offers) == 1) + offers = json.loads( + urlopen("http://127.0.0.1:12701/json/offers/{}".format(offer0_id)).read() + ) + assert len(offers) == 1 offer0 = offers[0] - post_data = { - 'coin_from': 'PART' - } - test_post_offers = json.loads(urlopen('http://127.0.0.1:12701/json/offers', data=parse.urlencode(post_data).encode()).read()) - assert (len(test_post_offers) == 2) - post_data['coin_from'] = '2' - test_post_offers = json.loads(urlopen('http://127.0.0.1:12701/json/offers', data=parse.urlencode(post_data).encode()).read()) - assert (len(test_post_offers) == 0) + post_data = {"coin_from": "PART"} + test_post_offers = json.loads( + urlopen( + "http://127.0.0.1:12701/json/offers", + data=parse.urlencode(post_data).encode(), + ).read() + ) + assert len(test_post_offers) == 2 + post_data["coin_from"] = "2" + test_post_offers = json.loads( + urlopen( + "http://127.0.0.1:12701/json/offers", + data=parse.urlencode(post_data).encode(), + ).read() + ) + assert len(test_post_offers) == 0 - bid_data = { - 'offer_id': offer0_id, - 'amount_from': offer0['amount_from']} + bid_data = {"offer_id": offer0_id, "amount_from": offer0["amount_from"]} - bid0_id = json.loads(urlopen('http://127.0.0.1:12701/json/bids/new', data=parse.urlencode(bid_data).encode()).read())['bid_id'] + bid0_id = json.loads( + urlopen( + "http://127.0.0.1:12701/json/bids/new", + data=parse.urlencode(bid_data).encode(), + ).read() + )["bid_id"] - offers = json.loads(urlopen('http://127.0.0.1:12701/json/offers/{}'.format(offer1_id)).read()) - assert (len(offers) == 1) + offers = json.loads( + urlopen("http://127.0.0.1:12701/json/offers/{}".format(offer1_id)).read() + ) + assert len(offers) == 1 offer1 = offers[0] - bid_data = { - 'offer_id': offer1_id, - 'amount_from': offer1['amount_from']} + bid_data = {"offer_id": offer1_id, "amount_from": offer1["amount_from"]} - bid1_id = json.loads(urlopen('http://127.0.0.1:12701/json/bids/new', data=parse.urlencode(bid_data).encode()).read())['bid_id'] + bid1_id = json.loads( + urlopen( + "http://127.0.0.1:12701/json/bids/new", + data=parse.urlencode(bid_data).encode(), + ).read() + )["bid_id"] - logger.info('Delaying for 5 seconds.') + logger.info("Delaying for 5 seconds.") self.delay_event.wait(5) - logger.info('Starting node 0') + logger.info("Starting node 0") self.processes[0] = multiprocessing.Process(target=self.run_thread, args=(0,)) self.processes[0].start() waitForServer(self.delay_event, 12700) waitForNumBids(self.delay_event, 12700, 2) - waitForBidState(self.delay_event, 12700, bid0_id, 'Received') - waitForBidState(self.delay_event, 12700, bid1_id, 'Received') + waitForBidState(self.delay_event, 12700, bid0_id, "Received") + waitForBidState(self.delay_event, 12700, bid1_id, "Received") # Manually accept on top of auto-accept for extra chaos - data = parse.urlencode({ - 'accept': True - }).encode() + data = parse.urlencode({"accept": True}).encode() try: - rv = json.loads(urlopen('http://127.0.0.1:12700/json/bids/{}'.format(bid0_id), data=data).read()) - assert rv['bid_state'] == 'Accepted' + rv = json.loads( + urlopen( + "http://127.0.0.1:12700/json/bids/{}".format(bid0_id), data=data + ).read() + ) + assert rv["bid_state"] == "Accepted" except Exception as e: - print('Accept bid failed', str(e), rv) + print("Accept bid failed", str(e), rv) try: - rv = json.loads(urlopen('http://127.0.0.1:12700/json/bids/{}'.format(bid1_id), data=data).read()) - assert (rv['bid_state'] == 'Accepted') + rv = json.loads( + urlopen( + "http://127.0.0.1:12700/json/bids/{}".format(bid1_id), data=data + ).read() + ) + assert rv["bid_state"] == "Accepted" except Exception as e: - print('Accept bid failed', str(e), rv) + print("Accept bid failed", str(e), rv) - logger.info('Completing swap') + logger.info("Completing swap") for i in range(240): if self.delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") self.delay_event.wait(4) - rv0 = read_json_api(12700, 'bids/{}'.format(bid0_id)) - rv1 = read_json_api(12700, 'bids/{}'.format(bid1_id)) - if rv0['bid_state'] == 'Completed' and rv1['bid_state'] == 'Completed': + rv0 = read_json_api(12700, "bids/{}".format(bid0_id)) + rv1 = read_json_api(12700, "bids/{}".format(bid1_id)) + if rv0["bid_state"] == "Completed" and rv1["bid_state"] == "Completed": break - assert rv0['bid_state'] == 'Completed' - assert rv1['bid_state'] == 'Completed' + assert rv0["bid_state"] == "Completed" + assert rv1["bid_state"] == "Completed" -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/test_xmr_reload.py b/tests/basicswap/test_xmr_reload.py index f68ee18..c3b18e8 100644 --- a/tests/basicswap/test_xmr_reload.py +++ b/tests/basicswap/test_xmr_reload.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020-2022 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -47,70 +48,67 @@ class Test(XmrTestBase): waitForServer(self.delay_event, 12700) waitForServer(self.delay_event, 12701) - wallets1 = read_json_api(12701, 'wallets') - assert (float(wallets1['XMR']['balance']) > 0.0) + wallets1 = read_json_api(12701, "wallets") + assert float(wallets1["XMR"]["balance"]) > 0.0 data = { - 'addr_from': '-1', - 'coin_from': 'part', - 'coin_to': 'xmr', - 'amt_from': '1', - 'amt_to': '1', - 'lockhrs': '24'} + "addr_from": "-1", + "coin_from": "part", + "coin_to": "xmr", + "amt_from": "1", + "amt_to": "1", + "lockhrs": "24", + } - offer_id = post_json_api(12700, 'offers/new', data)['offer_id'] + offer_id = post_json_api(12700, "offers/new", data)["offer_id"] summary = read_json_api(12700) - assert (summary['num_sent_offers'] == 1) + assert summary["num_sent_offers"] == 1 - logger.info('Waiting for offer') + logger.info("Waiting for offer") waitForNumOffers(self.delay_event, 12701, 1) - offers = read_json_api(12701, 'offers') + offers = read_json_api(12701, "offers") offer = offers[0] - data = { - 'offer_id': offer['offer_id'], - 'amount_from': offer['amount_from']} + data = {"offer_id": offer["offer_id"], "amount_from": offer["amount_from"]} - data['valid_for_seconds'] = 24 * 60 * 60 + 1 - bid = post_json_api(12701, 'bids/new', data) - assert (bid['error'] == 'Bid TTL too high') - del data['valid_for_seconds'] - data['validmins'] = 24 * 60 + 1 - bid = post_json_api(12701, 'bids/new', data) - assert (bid['error'] == 'Bid TTL too high') + data["valid_for_seconds"] = 24 * 60 * 60 + 1 + bid = post_json_api(12701, "bids/new", data) + assert bid["error"] == "Bid TTL too high" + del data["valid_for_seconds"] + data["validmins"] = 24 * 60 + 1 + bid = post_json_api(12701, "bids/new", data) + assert bid["error"] == "Bid TTL too high" - del data['validmins'] - data['valid_for_seconds'] = 10 - bid = post_json_api(12701, 'bids/new', data) - assert (bid['error'] == 'Bid TTL too low') - del data['valid_for_seconds'] - data['validmins'] = 1 - bid = post_json_api(12701, 'bids/new', data) - assert (bid['error'] == 'Bid TTL too low') + del data["validmins"] + data["valid_for_seconds"] = 10 + bid = post_json_api(12701, "bids/new", data) + assert bid["error"] == "Bid TTL too low" + del data["valid_for_seconds"] + data["validmins"] = 1 + bid = post_json_api(12701, "bids/new", data) + assert bid["error"] == "Bid TTL too low" - data['validmins'] = 60 - bid_id = post_json_api(12701, 'bids/new', data) + data["validmins"] = 60 + post_json_api(12701, "bids/new", data) waitForNumBids(self.delay_event, 12700, 1) for i in range(10): - bids = read_json_api(12700, 'bids') + bids = read_json_api(12700, "bids") bid = bids[0] - if bid['bid_state'] == 'Received': + if bid["bid_state"] == "Received": break self.delay_event.wait(1) - assert (bid['expire_at'] == bid['created_at'] + data['validmins'] * 60) + assert bid["expire_at"] == bid["created_at"] + data["validmins"] * 60 - data = { - 'accept': True - } - rv = post_json_api(12700, 'bids/{}'.format(bid['bid_id']), data) - assert (rv['bid_state'] == 'Accepted') + data = {"accept": True} + rv = post_json_api(12700, "bids/{}".format(bid["bid_id"]), data) + assert rv["bid_state"] == "Accepted" waitForNumSwapping(self.delay_event, 12701, 1) - logger.info('Restarting client') + logger.info("Restarting client") c1 = self.processes[1] c1.terminate() c1.join() @@ -119,29 +117,29 @@ class Test(XmrTestBase): waitForServer(self.delay_event, 12701) rv = read_json_api(12701) - assert (rv['num_swapping'] == 1) + assert rv["num_swapping"] == 1 - rv = read_json_api(12700, 'revokeoffer/{}'.format(offer_id)) - assert (rv['revoked_offer'] == offer_id) + rv = read_json_api(12700, "revokeoffer/{}".format(offer_id)) + assert rv["revoked_offer"] == offer_id - logger.info('Completing swap') + logger.info("Completing swap") for i in range(240): if self.delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") self.delay_event.wait(4) - rv = read_json_api(12700, 'bids/{}'.format(bid['bid_id'])) - if rv['bid_state'] == 'Completed': + rv = read_json_api(12700, "bids/{}".format(bid["bid_id"])) + if rv["bid_state"] == "Completed": break - assert (rv['bid_state'] == 'Completed') + assert rv["bid_state"] == "Completed" # Ensure offer was revoked summary = read_json_api(12700) - assert (summary['num_network_offers'] == 0) + assert summary["num_network_offers"] == 0 # Wait for bid to be removed from in-progress waitForNumBids(self.delay_event, 12700, 0) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/basicswap/util.py b/tests/basicswap/util.py index 1985516..81a11c3 100644 --- a/tests/basicswap/util.py +++ b/tests/basicswap/util.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2022-2024 tecnovert +# Copyright (c) 2024 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE.txt or http://www.opensource.org/licenses/mit-license.php. @@ -10,32 +11,37 @@ import urllib from urllib.request import urlopen -REQUIRED_SETTINGS = {'blocks_confirmed': 1, 'conf_target': 1, 'use_segwit': True, 'connection_type': 'rpc'} +REQUIRED_SETTINGS = { + "blocks_confirmed": 1, + "conf_target": 1, + "use_segwit": True, + "connection_type": "rpc", +} def make_boolean(s): - return s.lower() in ['1', 'true'] + return s.lower() in ["1", "true"] def post_json_req(url, json_data): req = urllib.request.Request(url) - req.add_header('Content-Type', 'application/json; charset=utf-8') - post_bytes = json.dumps(json_data).encode('utf-8') - req.add_header('Content-Length', len(post_bytes)) + req.add_header("Content-Type", "application/json; charset=utf-8") + post_bytes = json.dumps(json_data).encode("utf-8") + req.add_header("Content-Length", len(post_bytes)) return urlopen(req, post_bytes, timeout=300).read() def read_text_api(port, path=None): - url = f'http://127.0.0.1:{port}/json' + url = f"http://127.0.0.1:{port}/json" if path is not None: - url += '/' + path - return urlopen(url, timeout=300).read().decode('utf-8') + url += "/" + path + return urlopen(url, timeout=300).read().decode("utf-8") def read_json_api(port, path=None, json_data=None): - url = f'http://127.0.0.1:{port}/json' + url = f"http://127.0.0.1:{port}/json" if path is not None: - url += '/' + path + url += "/" + path if json_data is not None: return json.loads(post_json_req(url, json_data)) @@ -43,20 +49,20 @@ def read_json_api(port, path=None, json_data=None): def post_json_api(port, path, json_data): - url = f'http://127.0.0.1:{port}/json' + url = f"http://127.0.0.1:{port}/json" if path is not None: - url += '/' + path + url += "/" + path return json.loads(post_json_req(url, json_data)) def waitForServer(delay_event, port, wait_for=20): for i in range(wait_for): if delay_event.is_set(): - raise ValueError('Test stopped.') + raise ValueError("Test stopped.") try: delay_event.wait(1) - summary = read_json_api(port) + _ = read_json_api(port) return except Exception as e: - print('waitForServer, error:', str(e)) - raise ValueError('waitForServer failed') + print("waitForServer, error:", str(e)) + raise ValueError("waitForServer failed")