mirror of
https://github.com/basicswap/basicswap.git
synced 2025-04-24 23:18:22 +00:00
nmc: Update test.
This commit is contained in:
parent
8967f677c3
commit
f263bb53c3
6 changed files with 309 additions and 741 deletions
basicswap
tests/basicswap
|
@ -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)
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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"]])
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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__":
|
||||
|
|
|
@ -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])
|
||||
|
|
Loading…
Reference in a new issue