diff --git a/basicswap/bin/prepare.py b/basicswap/bin/prepare.py index 98a4e18..233e30f 100755 --- a/basicswap/bin/prepare.py +++ b/basicswap/bin/prepare.py @@ -52,11 +52,17 @@ PARTICL_VERSION = os.getenv("PARTICL_VERSION", "23.2.7.0") PARTICL_VERSION_TAG = os.getenv("PARTICL_VERSION_TAG", "") PARTICL_LINUX_EXTRA = os.getenv("PARTICL_LINUX_EXTRA", "nousb") +BITCOIN_VERSION = os.getenv("BITCOIN_VERSION", "28.0") +BITCOIN_VERSION_TAG = os.getenv("BITCOIN_VERSION_TAG", "") + LITECOIN_VERSION = os.getenv("LITECOIN_VERSION", "0.21.4") LITECOIN_VERSION_TAG = os.getenv("LITECOIN_VERSION_TAG", "") -BITCOIN_VERSION = os.getenv("BITCOIN_VERSION", "28.0") -BITCOIN_VERSION_TAG = os.getenv("BITCOIN_VERSION_TAG", "") +DCR_VERSION = os.getenv("DCR_VERSION", "1.8.1") +DCR_VERSION_TAG = os.getenv("DCR_VERSION_TAG", "") + +NMC_VERSION = os.getenv("NMC_VERSION", "28.0") +NMC_VERSION_TAG = os.getenv("NMC_VERSION_TAG", "") MONERO_VERSION = os.getenv("MONERO_VERSION", "0.18.3.4") MONERO_VERSION_TAG = os.getenv("MONERO_VERSION_TAG", "") @@ -82,12 +88,6 @@ FIRO_VERSION_TAG = os.getenv("FIRO_VERSION_TAG", "") NAV_VERSION = os.getenv("NAV_VERSION", "7.0.3") NAV_VERSION_TAG = os.getenv("NAV_VERSION_TAG", "") -NMC_VERSION = os.getenv("NAV_VERSION", "28.0") -NMC_VERSION_TAG = os.getenv("NAV_VERSION_TAG", "") - -DCR_VERSION = os.getenv("DCR_VERSION", "1.8.1") -DCR_VERSION_TAG = os.getenv("DCR_VERSION_TAG", "") - BITCOINCASH_VERSION = os.getenv("BITCOINCASH_VERSION", "28.0.1") BITCOINCASH_VERSION_TAG = os.getenv("BITCOINCASH_VERSION_TAG", "") @@ -117,9 +117,7 @@ known_coins = { "dogecoin": (DOGECOIN_VERSION, DOGECOIN_VERSION_TAG, ("tecnovert",)), } -disabled_coins = [ - "navcoin" -] +disabled_coins = ["navcoin"] expected_key_ids = { "tecnovert": ("13F13651C9CF0D6B",), @@ -184,6 +182,35 @@ PART_ONION_PORT = int(os.getenv("PART_ONION_PORT", 51734)) PART_RPC_USER = os.getenv("PART_RPC_USER", "") PART_RPC_PWD = os.getenv("PART_RPC_PWD", "") +BTC_RPC_HOST = os.getenv("BTC_RPC_HOST", "127.0.0.1") +BTC_RPC_PORT = int(os.getenv("BTC_RPC_PORT", 19996)) +BTC_PORT = int(os.getenv("BTC_PORT", 8333)) +BTC_ONION_PORT = int(os.getenv("BTC_ONION_PORT", 8334)) +BTC_RPC_USER = os.getenv("BTC_RPC_USER", "") +BTC_RPC_PWD = os.getenv("BTC_RPC_PWD", "") + +LTC_RPC_HOST = os.getenv("LTC_RPC_HOST", "127.0.0.1") +LTC_RPC_PORT = int(os.getenv("LTC_RPC_PORT", 19895)) +LTC_ONION_PORT = int(os.getenv("LTC_ONION_PORT", 9333)) +LTC_RPC_USER = os.getenv("LTC_RPC_USER", "") +LTC_RPC_PWD = os.getenv("LTC_RPC_PWD", "") + +DCR_RPC_HOST = os.getenv("DCR_RPC_HOST", "127.0.0.1") +DCR_RPC_PORT = int(os.getenv("DCR_RPC_PORT", 9109)) +DCR_WALLET_RPC_HOST = os.getenv("DCR_WALLET_RPC_HOST", "127.0.0.1") +DCR_WALLET_RPC_PORT = int(os.getenv("DCR_WALLET_RPC_PORT", 9209)) +DCR_WALLET_PWD = os.getenv( + "DCR_WALLET_PWD", random.randbytes(random.randint(14, 18)).hex() +) +DCR_RPC_USER = os.getenv("DCR_RPC_USER", "user") +DCR_RPC_PWD = os.getenv("DCR_RPC_PWD", random.randbytes(random.randint(14, 18)).hex()) + +NMC_RPC_HOST = os.getenv("NMC_RPC_HOST", "127.0.0.1") +NMC_RPC_PORT = int(os.getenv("NMC_RPC_PORT", 19698)) +NMC_ONION_PORT = int(os.getenv("NMC_ONION_PORT", 9698)) +NMC_RPC_USER = os.getenv("NMC_RPC_USER", "") +NMC_RPC_PWD = os.getenv("NMC_RPC_PWD", "") + XMR_RPC_HOST = os.getenv("XMR_RPC_HOST", "127.0.0.1") XMR_RPC_PORT = int(os.getenv("XMR_RPC_PORT", 29798)) XMR_ZMQ_PORT = int(os.getenv("XMR_ZMQ_PORT", 30898)) @@ -206,35 +233,6 @@ WOW_RPC_USER = os.getenv("WOW_RPC_USER", "") WOW_RPC_PWD = os.getenv("WOW_RPC_PWD", "") DEFAULT_WOW_RESTORE_HEIGHT = int(os.getenv("DEFAULT_WOW_RESTORE_HEIGHT", 450000)) -LTC_RPC_HOST = os.getenv("LTC_RPC_HOST", "127.0.0.1") -LTC_RPC_PORT = int(os.getenv("LTC_RPC_PORT", 19895)) -LTC_ONION_PORT = int(os.getenv("LTC_ONION_PORT", 9333)) -LTC_RPC_USER = os.getenv("LTC_RPC_USER", "") -LTC_RPC_PWD = os.getenv("LTC_RPC_PWD", "") - -BTC_RPC_HOST = os.getenv("BTC_RPC_HOST", "127.0.0.1") -BTC_RPC_PORT = int(os.getenv("BTC_RPC_PORT", 19996)) -BTC_PORT = int(os.getenv("BTC_PORT", 8333)) -BTC_ONION_PORT = int(os.getenv("BTC_ONION_PORT", 8334)) -BTC_RPC_USER = os.getenv("BTC_RPC_USER", "") -BTC_RPC_PWD = os.getenv("BTC_RPC_PWD", "") - -DCR_RPC_HOST = os.getenv("DCR_RPC_HOST", "127.0.0.1") -DCR_RPC_PORT = int(os.getenv("DCR_RPC_PORT", 9109)) -DCR_WALLET_RPC_HOST = os.getenv("DCR_WALLET_RPC_HOST", "127.0.0.1") -DCR_WALLET_RPC_PORT = int(os.getenv("DCR_WALLET_RPC_PORT", 9209)) -DCR_WALLET_PWD = os.getenv( - "DCR_WALLET_PWD", random.randbytes(random.randint(14, 18)).hex() -) -DCR_RPC_USER = os.getenv("DCR_RPC_USER", "user") -DCR_RPC_PWD = os.getenv("DCR_RPC_PWD", random.randbytes(random.randint(14, 18)).hex()) - -NMC_RPC_HOST = os.getenv("NMC_RPC_HOST", "127.0.0.1") -NMC_RPC_PORT = int(os.getenv("NMC_RPC_PORT", 19698)) -NMC_ONION_PORT = int(os.getenv("NMC_ONION_PORT", 9698)) -NMC_RPC_USER = os.getenv("NMC_RPC_USER", "") -NMC_RPC_PWD = os.getenv("NMC_RPC_PWD", "") - PIVX_RPC_HOST = os.getenv("PIVX_RPC_HOST", "127.0.0.1") PIVX_RPC_PORT = int(os.getenv("PIVX_RPC_PORT", 51473)) PIVX_ONION_PORT = int(os.getenv("PIVX_ONION_PORT", 51472)) # nDefaultPort @@ -1400,8 +1398,10 @@ def prepareDataDir(coin, settings, chain, particl_mnemonic, extra_opts={}): ) ) elif coin == "namecoin": - fp.write("deprecatedrpc=create_bdb\n") fp.write("prune=2000\n") + fp.write("deprecatedrpc=create_bdb\n") + fp.write("addresstype=bech32\n") + fp.write("changetype=bech32\n") elif coin == "pivx": params_dir = os.path.join(data_dir, "pivx-params") downloadPIVXParams(params_dir) diff --git a/basicswap/chainparams.py b/basicswap/chainparams.py index 82d7ad4..f4e36d5 100644 --- a/basicswap/chainparams.py +++ b/basicswap/chainparams.py @@ -256,6 +256,8 @@ chainparams = { "bip44": 7, "min_amount": 100000, "max_amount": 10000000 * COIN, + "ext_public_key_prefix": 0x0488B21E, # base58Prefixes[EXT_PUBLIC_KEY] + "ext_secret_key_prefix": 0x0488ADE4, }, "testnet": { "rpcport": 18336, @@ -267,6 +269,8 @@ chainparams = { "min_amount": 100000, "max_amount": 10000000 * COIN, "name": "testnet3", + "ext_public_key_prefix": 0x043587CF, + "ext_secret_key_prefix": 0x04358394, }, "regtest": { "rpcport": 18443, @@ -277,6 +281,8 @@ chainparams = { "bip44": 1, "min_amount": 100000, "max_amount": 10000000 * COIN, + "ext_public_key_prefix": 0x043587CF, + "ext_secret_key_prefix": 0x04358394, }, }, Coins.XMR: { diff --git a/basicswap/interface/nmc.py b/basicswap/interface/nmc.py index cf9bae7..19aa48e 100644 --- a/basicswap/interface/nmc.py +++ b/basicswap/interface/nmc.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright (c) 2020-2022 tecnovert +# Copyright (c) 2025 The Basicswap developers # Distributed under the MIT software license, see the accompanying # file LICENSE or http://www.opensource.org/licenses/mit-license.php. @@ -14,38 +15,56 @@ class NMCInterface(BTCInterface): def coin_type(): return Coins.NMC - def getLockTxHeight( - self, - txid, - dest_address, - bid_amount, - rescan_from, - find_index: bool = False, - vout: int = -1, - ): - self._log.debug("[rm] scantxoutset start") # scantxoutset is slow - ro = self.rpc( - "scantxoutset", ["start", ["addr({})".format(dest_address)]] - ) # TODO: Use combo(address) where possible - self._log.debug("[rm] scantxoutset end") - return_txid = True if txid is None else False - for o in ro["unspents"]: - if txid and o["txid"] != txid.hex(): - continue - # Verify amount - if self.make_int(o["amount"]) != int(bid_amount): - self._log.warning( - "Found output to lock tx address of incorrect value: %s, %s", - str(o["amount"]), - o["txid"], - ) - continue + def lockNonSegwitPrevouts(self) -> None: + # For tests + # NMC Seems to ignore utxo locks + unspent = self.rpc_wallet("listunspent") - rv = {"depth": 0, "height": o["height"]} - if o["height"] > 0: - rv["depth"] = ro["height"] - o["height"] - if find_index: - rv["index"] = o["vout"] - if return_txid: - rv["txid"] = o["txid"] - return rv + to_lock = [] + for u in unspent: + if u.get("spendable", False) is False: + continue + if "desc" in u: + desc = u["desc"] + if self.use_p2shp2wsh(): + if not desc.startswith("sh(wpkh"): + to_lock.append( + { + "txid": u["txid"], + "vout": u["vout"], + "amount": u["amount"], + } + ) + else: + if not desc.startswith("wpkh"): + to_lock.append( + { + "txid": u["txid"], + "vout": u["vout"], + "amount": u["amount"], + } + ) + + if len(to_lock) > 0: + self._log.debug(f"Spending {len(to_lock)} non segwit prevouts") + addr_out = self.rpc_wallet( + "getnewaddress", ["convert non segwit", "bech32"] + ) + prevouts = [] + sum_amount: int = 0 + for utxo in to_lock: + prevouts.append( + { + "txid": utxo["txid"], + "vout": utxo["vout"], + } + ) + sum_amount += self.make_int(utxo["amount"]) + + fee = 100000 * len(prevouts) + funded_tx = self.rpc( + "createrawtransaction", + [prevouts, {addr_out: self.format_amount(sum_amount - fee)}], + ) + signed_tx = self.rpc_wallet("signrawtransactionwithwallet", [funded_tx]) + self.rpc("sendrawtransaction", [signed_tx["hex"]]) diff --git a/tests/basicswap/extended/test_dcr.py b/tests/basicswap/extended/test_dcr.py index d063160..e3c7bfe 100644 --- a/tests/basicswap/extended/test_dcr.py +++ b/tests/basicswap/extended/test_dcr.py @@ -138,7 +138,6 @@ def run_test_success_path(self, coin_from: Coins, coin_to: Coins): # 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( @@ -147,7 +146,9 @@ def run_test_success_path(self, coin_from: Coins, coin_to: Coins): itx_spend, ], ) - assert amt_swap - node_to_ci_from.make_int(wtx["details"][0]["amount"]) < max_fee + assert ( + amt_swap - node_to_ci_from.make_int(wtx["details"][0]["amount"]) < self.max_fee + ) node_from_ci_to = swap_clients[node_from].ci(coin_to) ptx_spend = bid.participate_tx.spend_txid.hex() @@ -158,7 +159,8 @@ def run_test_success_path(self, coin_from: Coins, coin_to: Coins): ], ) assert ( - bid.amount_to - node_from_ci_to.make_int(wtx["details"][0]["amount"]) < max_fee + bid.amount_to - node_from_ci_to.make_int(wtx["details"][0]["amount"]) + < self.max_fee ) js_0 = read_json_api(1800 + node_from) @@ -235,7 +237,6 @@ def run_test_bad_ptx(self, coin_from: Coins, coin_to: Coins): # 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( @@ -244,7 +245,10 @@ def run_test_bad_ptx(self, coin_from: Coins, coin_to: Coins): itx_spend, ], ) - assert amt_swap - node_from_ci_from.make_int(wtx["details"][0]["amount"]) < max_fee + assert ( + amt_swap - node_from_ci_from.make_int(wtx["details"][0]["amount"]) + < self.max_fee + ) node_to_ci_to = swap_clients[node_to].ci(coin_to) bid, offer = swap_clients[node_to].getBidAndOffer(bid_id) @@ -255,7 +259,10 @@ def run_test_bad_ptx(self, coin_from: Coins, coin_to: Coins): ptx_spend, ], ) - assert bid.amount_to - node_to_ci_to.make_int(wtx["details"][0]["amount"]) < max_fee + assert ( + bid.amount_to - node_to_ci_to.make_int(wtx["details"][0]["amount"]) + < self.max_fee + ) bid_id_hex = bid_id.hex() path = f"bids/{bid_id_hex}/states" @@ -338,7 +345,6 @@ def run_test_itx_refund(self, coin_from: Coins, coin_to: Coins): # 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( @@ -348,7 +354,8 @@ def run_test_itx_refund(self, coin_from: Coins, coin_to: Coins): ], ) assert ( - swap_value - node_from_ci_from.make_int(wtx["details"][0]["amount"]) < max_fee + swap_value - node_from_ci_from.make_int(wtx["details"][0]["amount"]) + < self.max_fee ) node_from_ci_to = swap_clients[node_from].ci(coin_to) @@ -360,7 +367,8 @@ def run_test_itx_refund(self, coin_from: Coins, coin_to: Coins): ], ) assert ( - bid.amount_to - node_from_ci_to.make_int(wtx["details"][0]["amount"]) < max_fee + bid.amount_to - node_from_ci_to.make_int(wtx["details"][0]["amount"]) + < self.max_fee ) @@ -425,7 +433,6 @@ def run_test_ads_success_path(self, coin_from: Coins, coin_to: Coins): bid, xmr_swap = swap_clients[id_offerer].getXmrBid(bid_id) node_from_ci_to = swap_clients[0].ci(coin_to) - max_fee: int = 10000 if node_from_ci_to.coin_type() in (Coins.XMR, Coins.WOW): pass else: @@ -437,7 +444,7 @@ def run_test_ads_success_path(self, coin_from: Coins, coin_to: Coins): ) assert ( bid.amount_to - node_from_ci_to.make_int(wtx["details"][0]["amount"]) - < max_fee + < self.max_fee ) node_to_ci_from = swap_clients[1].ci(coin_from) @@ -451,7 +458,8 @@ def run_test_ads_success_path(self, coin_from: Coins, coin_to: Coins): ], ) assert ( - bid.amount - node_to_ci_from.make_int(wtx["details"][0]["amount"]) < max_fee + bid.amount - node_to_ci_from.make_int(wtx["details"][0]["amount"]) + < self.max_fee ) bid_id_hex = bid_id.hex() @@ -550,7 +558,6 @@ def run_test_ads_both_refund( bid, xmr_swap = swap_clients[id_bidder].getXmrBid(bid_id) node_from_ci_from = swap_clients[0].ci(coin_from) - max_fee: int = 10000 if node_from_ci_from.coin_type() in (Coins.XMR, Coins.WOW): pass else: @@ -562,7 +569,7 @@ def run_test_ads_both_refund( ) assert ( bid.amount - node_from_ci_from.make_int(wtx["details"][0]["amount"]) - < max_fee + < self.max_fee ) node_to_ci_to = swap_clients[1].ci(coin_to) @@ -577,7 +584,7 @@ def run_test_ads_both_refund( ) assert ( bid.amount_to - node_to_ci_to.make_int(wtx["details"][0]["amount"]) - < max_fee + < self.max_fee ) bid_id_hex = bid_id.hex() @@ -720,6 +727,7 @@ class Test(BaseTest): start_xmr_nodes = True dcr_mining_addr = "SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH" extra_wait_time = 0 + max_fee: int = 10000 hex_seeds = [ "e8574b2a94404ee62d8acc0258cab4c0defcfab8a5dfc2f4954c1f9d7e09d72a", diff --git a/tests/basicswap/extended/test_nmc.py b/tests/basicswap/extended/test_nmc.py index 1bee5a1..ac839e9 100644 --- a/tests/basicswap/extended/test_nmc.py +++ b/tests/basicswap/extended/test_nmc.py @@ -11,67 +11,38 @@ basicswap]$ python tests/basicswap/extended/test_nmc.py """ -import json import logging import os -import shutil -import signal +import random import sys -import threading -import time import unittest import basicswap.config as cfg from basicswap.basicswap import ( - BasicSwap, Coins, - SwapTypes, - BidStates, - TxStates, ) from basicswap.util import ( - COIN, -) -from basicswap.basicswap_util import ( - TxLockTypes, -) -from basicswap.util.address import ( - toWIF, -) -from basicswap.rpc import ( - callrpc_cli, -) -from basicswap.contrib.key import ( - ECKey, + toBool, ) +from basicswap.bin.run import startDaemon from basicswap.contrib.rpcauth import generate_salt, password_to_hmac -from basicswap.http_server import ( - HttpThread, -) -from tests.basicswap.util import ( - read_json_api, -) from tests.basicswap.common import ( - checkForks, stopDaemons, - wait_for_offer, - wait_for_bid, - wait_for_bid_tx_state, - wait_for_in_progress, - TEST_HTTP_HOST, - TEST_HTTP_PORT, - BASE_PORT, - BASE_RPC_PORT, - BASE_ZMQ_PORT, - PREFIX_SECRET_KEY_REGTEST, waitForRPC, make_rpc_func, ) -from basicswap.bin.run import startDaemon + +from tests.basicswap.test_btc_xmr import BasicSwapTest, test_delay_event +from tests.basicswap.test_xmr import NUM_NODES +from tests.basicswap.extended.test_dcr import ( + run_test_success_path, + run_test_bad_ptx, + run_test_itx_refund, +) -logger = logging.getLogger() -logger.level = logging.DEBUG +logger = logging.getLogger("BSX Tests") + if not len(logger.handlers): logger.addHandler(logging.StreamHandler(sys.stdout)) @@ -83,19 +54,14 @@ NAMECOIND = os.getenv("NAMECOIND", "namecoind" + cfg.bin_suffix) NAMECOIN_CLI = os.getenv("NAMECOIN_CLI", "namecoin-cli" + cfg.bin_suffix) NAMECOIN_TX = os.getenv("NAMECOIN_TX", "namecoin-tx" + cfg.bin_suffix) +USE_DESCRIPTOR_WALLETS = toBool(os.getenv("USE_DESCRIPTOR_WALLETS", False)) + NMC_BASE_PORT = 8136 -NMC_BASE_RPC_PORT= 8146 - -NUM_NODES = 3 -NMC_NODE = 3 -BTC_NODE = 4 - -delay_event = threading.Event() -stop_test = False +NMC_BASE_RPC_PORT = 8146 -def prepareOtherDir(datadir, nodeId, conf_file="namecoin.conf"): - node_dir = os.path.join(datadir, str(nodeId)) +def prepareNMCDataDir(datadir, nodeId, conf_file="namecoin.conf"): + node_dir = os.path.join(datadir, "nmc_" + str(nodeId)) if not os.path.exists(node_dir): os.makedirs(node_dir) filePath = os.path.join(node_dir, conf_file) @@ -104,20 +70,16 @@ def prepareOtherDir(datadir, nodeId, conf_file="namecoin.conf"): fp.write("regtest=1\n") fp.write("[regtest]\n") - if conf_file == "bitcoin.conf": - fp.write("port=" + str(BASE_PORT + nodeId) + "\n") - fp.write("rpcport=" + str(BASE_RPC_PORT + nodeId) + "\n") - else: - fp.write("port=" + str(NMC_BASE_PORT + nodeId) + "\n") - fp.write("rpcport=" + str(NMC_BASE_RPC_PORT + nodeId) + "\n") - salt = generate_salt(16) - fp.write( - "rpcauth={}:{}${}\n".format( - "test" + str(nodeId), - salt, - password_to_hmac(salt, "test_pass" + str(nodeId)), - ) + fp.write("port=" + str(NMC_BASE_PORT + nodeId) + "\n") + fp.write("rpcport=" + str(NMC_BASE_RPC_PORT + nodeId) + "\n") + salt = generate_salt(16) + fp.write( + "rpcauth={}:{}${}\n".format( + "test" + str(nodeId), + salt, + password_to_hmac(salt, "test_pass" + str(nodeId)), ) + ) fp.write("daemon=0\n") fp.write("printtoconsole=0\n") @@ -125,592 +87,171 @@ def prepareOtherDir(datadir, nodeId, conf_file="namecoin.conf"): 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("deprecatedrpc=create_bdb\n") - 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") - - 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("acceptnonstdtxn=0\n") - fp.write("minstakeinterval=5\n") - fp.write("smsgsregtestadjust=0\n") + fp.write("addresstype=bech32\n") + fp.write("changetype=bech32\n") for i in range(0, NUM_NODES): if nodeId == i: continue - 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") - - basicswap_dir = os.path.join(datadir, str(nodeId), "basicswap") - if not os.path.exists(basicswap_dir): - os.makedirs(basicswap_dir) - - nmcdatadir = os.path.join(datadir, str(NMC_NODE)) - 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 - }, - "namecoin": { - "connection_type": "rpc", - "manage_daemon": False, - "rpcport": NMC_BASE_RPC_PORT + NMC_NODE, - "datadir": nmcdatadir, - "bindir": NAMECOIN_BINDIR, - "use_csv": True, - "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, - } - with open(settings_path, "w") as fp: - json.dump(settings, fp, indent=4) + fp.write("addnode=127.0.0.1:{}\n".format(NMC_BASE_PORT + i)) -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, - ) +class TestNMC(BasicSwapTest): + __test__ = True + test_coin = Coins.NMC + test_coin_from = Coins.NMC + nmc_daemons = [] + start_ltc_nodes = False + start_xmr_nodes = True + base_rpc_port = NMC_BASE_RPC_PORT + nmc_addr = None + max_fee: int = 200000 + test_fee_rate: int = 10000 # sats/kvB - -def btcRpc(cmd): - 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( - NAMECOIN_BINDIR, - os.path.join(cfg.TEST_DATADIRS, str(NMC_NODE)), - "regtest", - cmd, - NAMECOIN_CLI, - ) - - -def signal_handler(sig, frame): - global stop_test - os.write(sys.stdout.fileno(), f"Signal {sig} detected.\n".encode("utf-8")) - stop_test = True - delay_event.set() - - -def run_coins_loop(cls): - while not stop_test: - try: - 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)) - time.sleep(1.0) - - -def run_loop(self): - while not stop_test: - for c in self.swap_clients: - c.update() - time.sleep(1) - - -def make_part_cli_rpc_func(node_id): - node_id = node_id - - def rpc_func(method, params=None, wallet=None): - cmd = method - if params: - for p in params: - cmd += ' "' + p + '"' - return partRpc(cmd, node_id) - - return rpc_func - - -class Test(unittest.TestCase): + def mineBlock(self, num_blocks: int = 1) -> None: + self.callnoderpc("generatetoaddress", [num_blocks, self.nmc_addr]) @classmethod - def setUpClass(cls): - super(Test, cls).setUpClass() + def tearDownClass(cls): + logging.info("Finalising Namecoin Test") + stopDaemons(cls.nmc_daemons) + cls.nmc_daemons.clear() - eckey = ECKey() - eckey.generate() - cls.network_key = toWIF(PREFIX_SECRET_KEY_REGTEST, eckey.get_bytes()) - cls.network_pubkey = eckey.get_pubkey().get_bytes().hex() + super(TestNMC, cls).tearDownClass() - if os.path.isdir(cfg.TEST_DATADIRS): - logging.info("Removing " + cfg.TEST_DATADIRS) - shutil.rmtree(cfg.TEST_DATADIRS) + @classmethod + def coins_loop(cls): + super(TestNMC, cls).coins_loop() + ci0 = cls.swap_clients[0].ci(cls.test_coin) + try: + if cls.nmc_addr is not None: + ci0.rpc_wallet("generatetoaddress", [1, cls.nmc_addr]) + except Exception as e: + logging.warning(f"coins_loop generate {e}") - for i in range(NUM_NODES): - prepareDir(cfg.TEST_DATADIRS, i, cls.network_key, cls.network_pubkey) + @classmethod + def prepareExtraDataDir(cls, i: int) -> None: + if not cls.restore_instance: + prepareNMCDataDir(cfg.TEST_DATADIRS, i) - prepareOtherDir(cfg.TEST_DATADIRS, NMC_NODE) - 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", - ) - 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( + cls.nmc_daemons.append( startDaemon( - os.path.join(cfg.TEST_DATADIRS, str(NMC_NODE)), + os.path.join(cfg.TEST_DATADIRS, "nmc_" + str(i)), NAMECOIN_BINDIR, NAMECOIND, ) ) - logging.info("Started %s %d", NAMECOIND, cls.daemons[-1].handle.pid) - nmcRpc2 = make_rpc_func(NMC_NODE, base_rpc_port=NMC_BASE_RPC_PORT) - waitForRPC(nmcRpc2, delay_event, rpc_command="getblockchaininfo") - if len(nmcRpc2("listwallets")) < 1: - nmcRpc2("createwallet", ["wallet.dat", False, False, "", False, False]) + logging.info("Started {} {}".format(NAMECOIND, cls.nmc_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", - ) - cls.daemons.append(startDaemon(data_dir, cfg.PARTICL_BINDIR, cfg.PARTICLD)) - 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" - ], - ) - 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") - else: - rpc("extkeyimportmaster", [rpc("mnemonic", ["new"])["master"]]) - rpc( - "walletsettings", - [ - "stakingoptions", - json.dumps( - {"stakecombinethreshold": 100, "stakesplitthreshold": 200} - ).replace('"', '\\"'), - ], + nmc_rpc = make_rpc_func(i, base_rpc_port=NMC_BASE_RPC_PORT) + waitForRPC( + nmc_rpc, + test_delay_event, + rpc_command="getnetworkinfo", + max_tries=12, + ) + waitForRPC(nmc_rpc, test_delay_event, rpc_command="getblockchaininfo") + if len(nmc_rpc("listwallets")) < 1: + nmc_rpc( + "createwallet", + ["wallet.dat", False, False, "", False, USE_DESCRIPTOR_WALLETS], ) - rpc("reservebalance", ["false"]) - - 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) - sc = BasicSwap( - 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.NMC, cls.daemons[1].handle.pid) - sc.setDaemonPID(Coins.PART, cls.daemons[2 + i].handle.pid) - sc.start() - - t = HttpThread(TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, sc) - cls.http_threads.append(t) - t.start() - - num_blocks = 500 - logging.info("Mining %d namecoin blocks", num_blocks) - cls.nmc_addr = nmcRpc("getnewaddress mining_addr bech32") - nmcRpc("generatetoaddress {} {}".format(num_blocks, cls.nmc_addr)) - - ro = nmcRpc("getblockchaininfo") - try: - assert ro["bip9_softforks"]["csv"]["status"] == "active" - except Exception: - logging.info("nmc: csv is not active") - try: - assert ro["bip9_softforks"]["segwit"]["status"] == "active" - except Exception: - 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)) - - ro = btcRpc("getblockchaininfo") - checkForks(ro) - - ro = nmcRpc("getwalletinfo") - print("nmcRpc", ro) - - 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.start() - - # Wait for height, or sequencelock is thrown off by genesis blocktime - num_blocks = 3 - 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) - if particl_blocks >= num_blocks: - break - delay_event.wait(1) - assert particl_blocks >= num_blocks @classmethod - def tearDownClass(cls): - global stop_test - logging.info("Finalising") - stop_test = True - cls.update_thread.join() - cls.coins_update_thread.join() - for t in cls.http_threads: - t.stop() - t.join() - for c in cls.swap_clients: - c.finalise() + def addPIDInfo(cls, sc, i): + sc.setDaemonPID(Coins.DCR, cls.nmc_daemons[i].handle.pid) - stopDaemons(cls.daemons) - cls.http_threads.clear() - cls.swap_clients.clear() - cls.daemons.clear() + @classmethod + def addCoinSettings(cls, settings, datadir, node_id): + settings["chainclients"]["namecoin"] = { + "connection_type": "rpc", + "manage_daemon": False, + "rpcport": NMC_BASE_RPC_PORT + node_id, + "rpcuser": "test" + str(node_id), + "rpcpassword": "test_pass" + str(node_id), + "datadir": os.path.join(datadir, "nmc_" + str(node_id)), + "bindir": NAMECOIN_BINDIR, + "use_csv": True, + "use_segwit": True, + "blocks_confirmed": 1, + } - super(Test, cls).tearDownClass() - - def test_02_part_nmc(self): - 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 - ) - - wait_for_offer(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(delay_event, swap_clients[0], bid_id) - - swap_clients[0].acceptBid(bid_id) - - 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_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 - - def test_03_nmc_part(self): - 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 - ) - - wait_for_offer(delay_event, swap_clients[0], offer_id) - offer = swap_clients[0].getOffer(offer_id) - bid_id = swap_clients[0].postBid(offer_id, offer.amount_from) - - wait_for_bid(delay_event, swap_clients[1], bid_id) - swap_clients[1].acceptBid(bid_id) - - 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 - ) - - 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 - - def test_04_nmc_btc(self): - 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 - ) - - wait_for_offer(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(delay_event, swap_clients[0], bid_id) - swap_clients[0].acceptBid(bid_id) - - 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_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 - - def test_05_refund(self): - # Seller submits initiate txn, buyer doesn't respond - 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.SEQUENCE_LOCK_BLOCKS, - 10, - ) - - wait_for_offer(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(delay_event, swap_clients[0], bid_id) - 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, - ) - - 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 - - def test_06_self_bid(self): - 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 - ) - - wait_for_offer(delay_event, swap_clients[0], offer_id) - offer = swap_clients[0].getOffer(offer_id) - bid_id = swap_clients[0].postBid(offer_id, offer.amount_from) - - 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 - ) - - 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 - ) - - def test_07_error(self): - logging.info("---------- Test error, BTC to NMC, set fee above bid value") - swap_clients = self.swap_clients - - offer_id = swap_clients[0].postOffer( - Coins.NMC, - Coins.BTC, - 0.01 * COIN, - 1.0 * COIN, - 0.01 * COIN, - SwapTypes.SELLER_FIRST - ) - - wait_for_offer(delay_event, swap_clients[0], offer_id) - offer = swap_clients[0].getOffer(offer_id) - bid_id = swap_clients[0].postBid(offer_id, offer.amount_from) - - 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"] = 100.0 - swap_clients[0].getChainClientSettings(Coins.NMC)["override_feerate"] = 100.0 - wait_for_bid( - delay_event, swap_clients[0], bid_id, BidStates.BID_ERROR, wait_for=60 + @classmethod + def prepareExtraCoins(cls): + ci0 = cls.swap_clients[0].ci(cls.test_coin) + if not cls.restore_instance: + cls.nmc_addr = ci0.rpc_wallet("getnewaddress", ["mining_addr", "bech32"]) + else: + addrs = ci0.rpc_wallet( + "getaddressesbylabel", + [ + "mining_addr", + ], ) - 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"] + cls.nmc_addr = addrs.keys()[0] - def pass_99_delay(self): - global stop_test - logging.info("Delay") - for i in range(60 * 5): - if stop_test: - break - time.sleep(1) - print("delay", i) - stop_test = True + num_blocks: int = 500 + if ci0.rpc("getblockcount") < num_blocks: + logging.info(f"Mining {num_blocks} Namecoin blocks to {cls.nmc_addr}") + ci0.rpc("generatetoaddress", [num_blocks, cls.nmc_addr]) + logging.info("NMC blocks: {}".format(ci0.rpc("getblockcount"))) + + def test_007_hdwallet(self): + 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)) + ) + new_wallet_name = random.randbytes(10).hex() + self.callnoderpc( + "createwallet", + [new_wallet_name, False, False, "", False, USE_DESCRIPTOR_WALLETS], + ) + self.callnoderpc("sethdseed", [True, test_wif], wallet=new_wallet_name) + addr = self.callnoderpc( + "getnewaddress", ["add test", "bech32"], wallet=new_wallet_name + ) + self.callnoderpc("unloadwallet", [new_wallet_name]) + assert addr == "ncrt1qps7hnjd866e9ynxadgseprkc2l56m00dxkl7pk" + + def test_012_p2sh_p2wsh(self): + # Fee rate + pass + + def test_02_sh_part_coin(self): + self.prepare_balance(self.test_coin, 200.0, 1801, 1800) + run_test_success_path(self, Coins.PART, self.test_coin) + + def test_03_sh_coin_part(self): + run_test_success_path(self, self.test_coin, Coins.PART) + + def test_04_sh_part_coin_bad_ptx(self): + self.prepare_balance(self.test_coin, 200.0, 1801, 1800) + run_test_bad_ptx(self, Coins.PART, self.test_coin) + + def test_05_sh_coin_part_bad_ptx(self): + self.prepare_balance(self.test_coin, 200.0, 1801, 1800) + run_test_bad_ptx(self, self.test_coin, Coins.PART) + + def test_06_sh_part_coin_itx_refund(self): + run_test_itx_refund(self, Coins.PART, self.test_coin) + + def test_07_sh_coin_part_itx_refund(self): + self.prepare_balance(self.test_coin, 200.0, 1801, 1800) + run_test_itx_refund(self, self.test_coin, Coins.PART) + + def test_01_b_full_swap_reverse(self): + self.prepare_balance(self.test_coin, 100.0, 1801, 1800) + self.do_test_01_full_swap(Coins.XMR, self.test_coin_from) if __name__ == "__main__": diff --git a/tests/basicswap/test_btc_xmr.py b/tests/basicswap/test_btc_xmr.py index 866fbed..32d2082 100644 --- a/tests/basicswap/test_btc_xmr.py +++ b/tests/basicswap/test_btc_xmr.py @@ -59,7 +59,6 @@ from basicswap.contrib.test_framework.script import ( from .test_xmr import BaseTest, test_delay_event, callnoderpc logger = logging.getLogger() - test_seed = "8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b" @@ -666,7 +665,7 @@ class TestFunctions(BaseTest): balance_from_before: float = self.getBalance(jsw, coin_from) self.prepare_balance( coin_to, - balance_from_before + 1, + balance_from_before * 3, 1800 + id_bidder, 1801 if coin_to in (Coins.XMR,) else 1800, ) @@ -718,6 +717,7 @@ class TestFunctions(BaseTest): assert False, "Should fail" amt_swap -= ci_from.make_int(1) + rate_swap = ci_to.make_int(1.0, r=1) offer_id = swap_clients[id_offerer].postOffer( coin_from, coin_to, @@ -770,6 +770,8 @@ class TestFunctions(BaseTest): class BasicSwapTest(TestFunctions): + test_fee_rate: int = 1000 # sats/kvB + @classmethod def setUpClass(cls): super(BasicSwapTest, cls).setUpClass() @@ -1236,12 +1238,7 @@ class BasicSwapTest(TestFunctions): swap_client = self.swap_clients[0] ci = swap_client.ci(self.test_coin_from) - addr_1 = ci.rpc_wallet( - "getnewaddress", - [ - "gettxout test 1", - ], - ) + addr_1 = ci.getNewAddress(True, "gettxout test 1") txid = ci.rpc_wallet("sendtoaddress", [addr_1, 1.0]) assert len(txid) == 64 @@ -1266,12 +1263,7 @@ class BasicSwapTest(TestFunctions): else: assert addr_1 in txout["scriptPubKey"]["addresses"] # Spend - addr_2 = ci.rpc_wallet( - "getnewaddress", - [ - "gettxout test 2", - ], - ) + addr_2 = ci.getNewAddress(True, "gettxout test 2") tx_funded = ci.rpc( "createrawtransaction", [[{"txid": utxo["txid"], "vout": utxo["vout"]}], {addr_2: 0.99}], @@ -1297,12 +1289,7 @@ class BasicSwapTest(TestFunctions): 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", - ], - ) + addr_1 = ci.getNewAddress(True, "scantxoutset test") txid = ci.rpc_wallet("sendtoaddress", [addr_1, 1.0]) assert len(txid) == 64 @@ -1324,9 +1311,6 @@ class BasicSwapTest(TestFunctions): # Record unspents before createSCLockTx as the used ones will be locked unspents = ci.rpc_wallet("listunspent") - # fee_rate is in sats/kvB - fee_rate: int = 1000 - a = ci.getNewRandomKey() b = ci.getNewRandomKey() @@ -1335,7 +1319,7 @@ class BasicSwapTest(TestFunctions): lock_tx_script = pi.genScriptLockTxScript(ci, A, B) lock_tx = ci.createSCLockTx(amount, lock_tx_script) - lock_tx = ci.fundSCLockTx(lock_tx, fee_rate) + lock_tx = ci.fundSCLockTx(lock_tx, self.test_fee_rate) lock_tx = ci.signTxWithWallet(lock_tx) unspents_after = ci.rpc_wallet("listunspent") @@ -1345,7 +1329,7 @@ class BasicSwapTest(TestFunctions): txid = tx_decoded["txid"] vsize = tx_decoded["vsize"] - expect_fee_int = round(fee_rate * vsize / 1000) + expect_fee_int = round(self.test_fee_rate * vsize / 1000) out_value: int = 0 for txo in tx_decoded["vout"]: @@ -1372,7 +1356,7 @@ class BasicSwapTest(TestFunctions): 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 + lock_tx, lock_tx_script, pkh_out, self.test_fee_rate, fee_info=fee_info ) vsize_estimated: int = fee_info["vsize"] @@ -1400,11 +1384,11 @@ class BasicSwapTest(TestFunctions): v = ci.getNewRandomKey() s = ci.getNewRandomKey() S = ci.getPubkey(s) - lock_tx_b_txid = ci.publishBLockTx(v, S, amount, fee_rate) + lock_tx_b_txid = ci.publishBLockTx(v, S, amount, self.test_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_txid, addr_out, v, s, amount, self.test_fee_rate, 0 ) lock_tx_b_spend = ci.getTransaction(lock_tx_b_spend_txid) if lock_tx_b_spend is None: @@ -1635,7 +1619,9 @@ class BasicSwapTest(TestFunctions): wallet=new_wallet_name, ) - addr = self.callnoderpc("getnewaddress", wallet=new_wallet_name) + addr = self.callnoderpc( + "getnewaddress", ["test descriptors"], wallet=new_wallet_name + ) addr_info = self.callnoderpc( "getaddressinfo", [ @@ -1645,7 +1631,8 @@ class BasicSwapTest(TestFunctions): ) assert addr_info["hdmasterfingerprint"] == "a55b7ea9" assert addr_info["hdkeypath"] == "m/0h/0h/0h" - assert addr == "bcrt1qps7hnjd866e9ynxadgseprkc2l56m00dvwargr" + if self.test_coin_from == Coins.BTC: + assert addr == "bcrt1qps7hnjd866e9ynxadgseprkc2l56m00dvwargr" addr_change = self.callnoderpc("getrawchangeaddress", wallet=new_wallet_name) addr_info = self.callnoderpc( @@ -1657,7 +1644,8 @@ class BasicSwapTest(TestFunctions): ) assert addr_info["hdmasterfingerprint"] == "a55b7ea9" assert addr_info["hdkeypath"] == "m/0h/1h/0h" - assert addr_change == "bcrt1qdl9ryxkqjltv42lhfnqgdjf9tagxsjpp2xak9a" + if self.test_coin_from == Coins.BTC: + assert addr_change == "bcrt1qdl9ryxkqjltv42lhfnqgdjf9tagxsjpp2xak9a" desc_watch = descsum_create(f"addr({addr})") self.callnoderpc( @@ -1683,7 +1671,13 @@ class BasicSwapTest(TestFunctions): # Test that addresses can be generated beyond range in listdescriptors for i in range(2000): - self.callnoderpc("getnewaddress", wallet=new_wallet_name) + self.callnoderpc( + "getnewaddress", + [ + f"t{i}", + ], + wallet=new_wallet_name, + ) self.callnoderpc("unloadwallet", [new_wallet_name]) self.callnoderpc("unloadwallet", [new_watch_wallet_name])