Reformat tests with black.

This commit is contained in:
tecnovert 2024-11-15 17:21:20 +02:00
parent b484827c15
commit 7b03ce4769
No known key found for this signature in database
GPG key ID: 8ED6D8750C4E3F93
38 changed files with 10345 additions and 5226 deletions

View file

@ -6,7 +6,7 @@ lint_task:
- pip install flake8 codespell
script:
- flake8 --version
- PYTHONWARNINGS="ignore" flake8 --ignore=E501,F841,W503,E702,E131 --exclude=basicswap/contrib,basicswap/interface/contrib,messages_pb2.py,.eggs,.tox,bin/install_certifi.py
- PYTHONWARNINGS="ignore" flake8 --ignore=E203,E501,F841,W503,E702,E131 --exclude=basicswap/contrib,basicswap/interface/contrib,messages_pb2.py,.eggs,.tox,bin/install_certifi.py
- codespell --check-filenames --disable-colors --quiet-level=7 --ignore-words=tests/lint/spelling.ignore-words.txt -S .git,.eggs,.tox,pgp,*.pyc,*basicswap/contrib,*basicswap/interface/contrib,*mnemonics.py,bin/install_certifi.py,*basicswap/static
test_task:

View file

@ -20,7 +20,7 @@ jobs:
pip install flake8 codespell
- name: Running flake8
run: |
flake8 --ignore=E501,F841,W503 --per-file-ignores="basicswap/interface/bch.py:E131,E702" --exclude=basicswap/contrib,basicswap/interface/contrib,messages_pb2.py,.eggs,.tox,bin/install_certifi.py
flake8 --ignore=E203,E501,F841,W503 --per-file-ignores="basicswap/interface/bch.py:E131,E702" --exclude=basicswap/contrib,basicswap/interface/contrib,messages_pb2.py,.eggs,.tox,bin/install_certifi.py
- name: Running codespell
run: |
codespell --check-filenames --disable-colors --quiet-level=7 --ignore-words=tests/lint/spelling.ignore-words.txt -S .git,.eggs,.tox,pgp,*.pyc,*basicswap/contrib,*basicswap/interface/contrib,*mnemonics.py,bin/install_certifi.py,*basicswap/static

View file

@ -34,6 +34,8 @@ dev = [
"flake8",
"pip-tools",
"pytest",
"ruff",
"black",
"selenium",
]
@ -42,3 +44,6 @@ path = "basicswap/__init__.py"
[tool.hatch.metadata]
allow-direct-references = true
[tool.ruff]
exclude = ["basicswap/contrib","basicswap/interface/contrib"]

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE.txt or http://www.opensource.org/licenses/mit-license.php.
@ -17,7 +18,9 @@ from basicswap.contrib.rpcauth import generate_salt, password_to_hmac
from basicswap.bin.prepare import downloadPIVXParams
TEST_HTTP_HOST = os.getenv('TEST_HTTP_HOST', '127.0.0.1') # Set to 0.0.0.0 when used in docker
TEST_HTTP_HOST = os.getenv(
"TEST_HTTP_HOST", "127.0.0.1"
) # Set to 0.0.0.0 when used in docker
TEST_HTTP_PORT = 1800
BASE_P2P_PORT = 12792
@ -39,84 +42,99 @@ PIVX_BASE_PORT = 34892
PIVX_BASE_RPC_PORT = 35892
PIVX_BASE_ZMQ_PORT = 36892
PREFIX_SECRET_KEY_REGTEST = 0x2e
PREFIX_SECRET_KEY_REGTEST = 0x2E
def prepareDataDir(datadir, node_id, conf_file, dir_prefix, base_p2p_port=BASE_PORT, base_rpc_port=BASE_RPC_PORT, num_nodes=3, extra_opts=[]):
def prepareDataDir(
datadir,
node_id,
conf_file,
dir_prefix,
base_p2p_port=BASE_PORT,
base_rpc_port=BASE_RPC_PORT,
num_nodes=3,
extra_opts=[],
):
node_dir = os.path.join(datadir, dir_prefix + str(node_id))
if not os.path.exists(node_dir):
os.makedirs(node_dir)
cfg_file_path = os.path.join(node_dir, conf_file)
if os.path.exists(cfg_file_path):
return
with open(cfg_file_path, 'w+') as fp:
fp.write('regtest=1\n')
fp.write('[regtest]\n')
fp.write('port=' + str(base_p2p_port + node_id) + '\n')
fp.write('rpcport=' + str(base_rpc_port + node_id) + '\n')
with open(cfg_file_path, "w+") as fp:
fp.write("regtest=1\n")
fp.write("[regtest]\n")
fp.write("port=" + str(base_p2p_port + node_id) + "\n")
fp.write("rpcport=" + str(base_rpc_port + node_id) + "\n")
salt = generate_salt(16)
fp.write('rpcauth={}:{}${}\n'.format('test' + str(node_id), salt, password_to_hmac(salt, 'test_pass' + str(node_id))))
fp.write(
"rpcauth={}:{}${}\n".format(
"test" + str(node_id),
salt,
password_to_hmac(salt, "test_pass" + str(node_id)),
)
)
fp.write('daemon=0\n')
fp.write('printtoconsole=0\n')
fp.write('server=1\n')
fp.write('discover=0\n')
fp.write('listenonion=0\n')
fp.write('bind=127.0.0.1\n')
fp.write('debug=1\n')
fp.write('debugexclude=libevent\n')
fp.write("daemon=0\n")
fp.write("printtoconsole=0\n")
fp.write("server=1\n")
fp.write("discover=0\n")
fp.write("listenonion=0\n")
fp.write("bind=127.0.0.1\n")
fp.write("debug=1\n")
fp.write("debugexclude=libevent\n")
fp.write('fallbackfee=0.01\n')
fp.write('acceptnonstdtxn=0\n')
fp.write('txindex=1\n')
fp.write('wallet=wallet.dat\n')
fp.write("fallbackfee=0.01\n")
fp.write("acceptnonstdtxn=0\n")
fp.write("txindex=1\n")
fp.write("wallet=wallet.dat\n")
fp.write('findpeers=0\n')
fp.write("findpeers=0\n")
for opt in extra_opts:
fp.write(opt + '\n')
fp.write(opt + "\n")
if base_p2p_port == BTC_BASE_PORT:
fp.write('deprecatedrpc=create_bdb\n')
fp.write("deprecatedrpc=create_bdb\n")
elif base_p2p_port == BASE_PORT: # Particl
fp.write('zmqpubsmsg=tcp://127.0.0.1:{}\n'.format(BASE_ZMQ_PORT + node_id))
fp.write("zmqpubsmsg=tcp://127.0.0.1:{}\n".format(BASE_ZMQ_PORT + node_id))
# minstakeinterval=5 # Using walletsettings stakelimit instead
fp.write('stakethreadconddelayms=1000\n')
fp.write('smsgsregtestadjust=0\n')
fp.write("stakethreadconddelayms=1000\n")
fp.write("smsgsregtestadjust=0\n")
if conf_file == 'pivx.conf':
params_dir = os.path.join(datadir, 'pivx-params')
if conf_file == "pivx.conf":
params_dir = os.path.join(datadir, "pivx-params")
downloadPIVXParams(params_dir)
fp.write(f'paramsdir={params_dir}\n')
fp.write(f"paramsdir={params_dir}\n")
for i in range(0, num_nodes):
if node_id == i:
continue
fp.write('addnode=127.0.0.1:{}\n'.format(base_p2p_port + i))
fp.write("addnode=127.0.0.1:{}\n".format(base_p2p_port + i))
return node_dir
def checkForks(ro):
try:
if 'bip9_softforks' in ro:
assert (ro['bip9_softforks']['csv']['status'] == 'active')
assert (ro['bip9_softforks']['segwit']['status'] == 'active')
if "bip9_softforks" in ro:
assert ro["bip9_softforks"]["csv"]["status"] == "active"
assert ro["bip9_softforks"]["segwit"]["status"] == "active"
else:
assert (ro['softforks']['csv']['active'])
assert (ro['softforks']['segwit']['active'])
assert ro["softforks"]["csv"]["active"]
assert ro["softforks"]["segwit"]["active"]
except Exception as e:
logging.warning('Could not parse deployment info')
logging.warning("Could not parse deployment info")
def stopDaemons(daemons):
for d in daemons:
logging.info('Interrupting %d', d.handle.pid)
logging.info("Interrupting %d", d.handle.pid)
try:
d.handle.send_signal(signal.SIGINT)
except Exception as e:
logging.info('Interrupting %d, error %s', d.handle.pid, str(e))
logging.info("Interrupting %d, error %s", d.handle.pid, str(e))
for d in daemons:
try:
d.handle.wait(timeout=20)
@ -124,21 +142,23 @@ def stopDaemons(daemons):
if fp:
fp.close()
except Exception as e:
logging.info('Closing %d, error %s', d.handle.pid, str(e))
logging.info("Closing %d, error %s", d.handle.pid, str(e))
def wait_for_bid(delay_event, swap_client, bid_id, state=None, sent: bool = False, wait_for: int = 20) -> None:
logging.info('wait_for_bid %s', bid_id.hex())
def wait_for_bid(
delay_event, swap_client, bid_id, state=None, sent: bool = False, wait_for: int = 20
) -> None:
logging.info("wait_for_bid %s", bid_id.hex())
for i in range(wait_for):
if delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
delay_event.wait(1)
filters = {
'bid_id': bid_id,
"bid_id": bid_id,
}
bids = swap_client.listBids(sent=sent, filters=filters)
assert (len(bids) < 2)
assert len(bids) < 2
for bid in bids:
if bid[2] == bid_id:
if isinstance(state, (list, tuple)):
@ -149,55 +169,65 @@ def wait_for_bid(delay_event, swap_client, bid_id, state=None, sent: bool = Fals
elif state is not None and state != bid[5]:
continue
return
raise ValueError('wait_for_bid timed out.')
raise ValueError("wait_for_bid timed out.")
def wait_for_bid_tx_state(delay_event, swap_client, bid_id, initiate_state, participate_state, wait_for=30):
logging.info('wait_for_bid_tx_state %s %s %s', bid_id.hex(), str(initiate_state), str(participate_state))
def wait_for_bid_tx_state(
delay_event, swap_client, bid_id, initiate_state, participate_state, wait_for=30
):
logging.info(
"wait_for_bid_tx_state %s %s %s",
bid_id.hex(),
str(initiate_state),
str(participate_state),
)
for i in range(wait_for):
if delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
delay_event.wait(1)
bid = swap_client.getBid(bid_id)
if (initiate_state is None or bid.getITxState() == initiate_state) \
and (participate_state is None or bid.getPTxState() == participate_state):
if (initiate_state is None or bid.getITxState() == initiate_state) and (
participate_state is None or bid.getPTxState() == participate_state
):
return
raise ValueError('wait_for_bid_tx_state timed out.')
raise ValueError("wait_for_bid_tx_state timed out.")
def wait_for_event(delay_event, swap_client, linked_type, linked_id, event_type=None, wait_for=20):
logging.info('wait_for_event')
def wait_for_event(
delay_event, swap_client, linked_type, linked_id, event_type=None, wait_for=20
):
logging.info("wait_for_event")
for i in range(wait_for):
if delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
delay_event.wait(1)
rv = swap_client.getEvents(linked_type, linked_id)
for event in rv:
if event_type is None or event.event_type == event_type:
return event
raise ValueError('wait_for_event timed out.')
raise ValueError("wait_for_event timed out.")
def wait_for_offer(delay_event, swap_client, offer_id, wait_for=20):
logging.info('wait_for_offer %s', offer_id.hex())
logging.info("wait_for_offer %s", offer_id.hex())
for i in range(wait_for):
if delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
delay_event.wait(1)
offers = swap_client.listOffers()
for offer in offers:
if offer.offer_id == offer_id:
return
raise ValueError('wait_for_offer timed out.')
raise ValueError("wait_for_offer timed out.")
def wait_for_no_offer(delay_event, swap_client, offer_id, wait_for=20):
logging.info('wait_for_no_offer %s', offer_id.hex())
logging.info("wait_for_no_offer %s", offer_id.hex())
for i in range(wait_for):
if delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
delay_event.wait(1)
offers = swap_client.listOffers()
found_offer = False
@ -207,35 +237,35 @@ def wait_for_no_offer(delay_event, swap_client, offer_id, wait_for=20):
break
if not found_offer:
return True
raise ValueError('wait_for_offer timed out.')
raise ValueError("wait_for_offer timed out.")
def wait_for_in_progress(delay_event, swap_client, bid_id, sent=False):
logging.info('wait_for_in_progress %s', bid_id.hex())
logging.info("wait_for_in_progress %s", bid_id.hex())
for i in range(20):
if delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
delay_event.wait(1)
swaps = swap_client.listSwapsInProgress()
for b in swaps:
if b[0] == bid_id:
return
raise ValueError('wait_for_in_progress timed out.')
raise ValueError("wait_for_in_progress timed out.")
def wait_for_none_active(delay_event, port, wait_for=30):
for i in range(wait_for):
if delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
delay_event.wait(1)
js = read_json_api(port)
if js['num_swapping'] == 0 and js['num_watched_outputs'] == 0:
if js["num_swapping"] == 0 and js["num_watched_outputs"] == 0:
return
raise ValueError('wait_for_none_active timed out.')
raise ValueError("wait_for_none_active timed out.")
def abandon_all_swaps(delay_event, swap_client) -> None:
logging.info('abandon_all_swaps')
logging.info("abandon_all_swaps")
for bid in swap_client.listBids(sent=True):
swap_client.abandonBid(bid[2])
for bid in swap_client.listBids(sent=False):
@ -245,37 +275,39 @@ def abandon_all_swaps(delay_event, swap_client) -> None:
def waitForNumOffers(delay_event, port, offers, wait_for=20):
for i in range(wait_for):
if delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
summary = read_json_api(port)
if summary['num_network_offers'] >= offers:
if summary["num_network_offers"] >= offers:
return
delay_event.wait(1)
raise ValueError('waitForNumOffers failed')
raise ValueError("waitForNumOffers failed")
def waitForNumBids(delay_event, port, bids, wait_for=20):
for i in range(wait_for):
if delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
summary = read_json_api(port)
if summary['num_recv_bids'] >= bids:
if summary["num_recv_bids"] >= bids:
return
delay_event.wait(1)
raise ValueError('waitForNumBids failed')
raise ValueError("waitForNumBids failed")
def waitForNumSwapping(delay_event, port, bids, wait_for=60):
for i in range(wait_for):
if delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
summary = read_json_api(port)
if summary['num_swapping'] >= bids:
if summary["num_swapping"] >= bids:
return
delay_event.wait(1)
raise ValueError('waitForNumSwapping failed')
raise ValueError("waitForNumSwapping failed")
def wait_for_balance(delay_event, url, balance_key, expect_amount, iterations=20, delay_time=3) -> None:
def wait_for_balance(
delay_event, url, balance_key, expect_amount, iterations=20, delay_time=3
) -> None:
i = 0
while not delay_event.is_set():
rv_js = json.loads(urlopen(url).read())
@ -284,11 +316,13 @@ def wait_for_balance(delay_event, url, balance_key, expect_amount, iterations=20
delay_event.wait(delay_time)
i += 1
if i > iterations:
raise ValueError('Expect {} {}'.format(balance_key, expect_amount))
raise ValueError("Expect {} {}".format(balance_key, expect_amount))
def wait_for_unspent(delay_event, ci, expect_amount, iterations=20, delay_time=1) -> None:
logging.info(f'Waiting for unspent balance: {expect_amount}')
def wait_for_unspent(
delay_event, ci, expect_amount, iterations=20, delay_time=1
) -> None:
logging.info(f"Waiting for unspent balance: {expect_amount}")
i = 0
while not delay_event.is_set():
unspent_addr = ci.getUnspentsByAddr()
@ -298,36 +332,41 @@ def wait_for_unspent(delay_event, ci, expect_amount, iterations=20, delay_time=1
delay_event.wait(delay_time)
i += 1
if i > iterations:
raise ValueError('wait_for_unspent {}'.format(expect_amount))
raise ValueError("wait_for_unspent {}".format(expect_amount))
def delay_for(delay_event, delay_for=60):
logging.info('Delaying for {} seconds.'.format(delay_for))
logging.info("Delaying for {} seconds.".format(delay_for))
delay_event.wait(delay_for)
def make_rpc_func(node_id, base_rpc_port=BASE_RPC_PORT):
node_id = node_id
auth = 'test{0}:test_pass{0}'.format(node_id)
auth = "test{0}:test_pass{0}".format(node_id)
def rpc_func(method, params=None, wallet=None):
nonlocal node_id, auth
return callrpc(base_rpc_port + node_id, auth, method, params, wallet)
return rpc_func
def waitForRPC(rpc_func, delay_event, rpc_command='getwalletinfo', max_tries=7):
def waitForRPC(rpc_func, delay_event, rpc_command="getwalletinfo", max_tries=7):
for i in range(max_tries + 1):
if delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
try:
rpc_func(rpc_command)
return
except Exception as ex:
if i < max_tries:
logging.warning('Can\'t connect to RPC: %s. Retrying in %d second/s.', str(ex), (i + 1))
logging.warning(
"Can't connect to RPC: %s. Retrying in %d second/s.",
str(ex),
(i + 1),
)
delay_event.wait(i + 1)
raise ValueError('waitForRPC failed')
raise ValueError("waitForRPC failed")
def extract_states_from_xu_file(file_path, prefix):
@ -336,39 +375,41 @@ def extract_states_from_xu_file(file_path, prefix):
alt_counter = 0
active_path = 0
states[active_path] = []
path_stack = [active_path, ]
path_stack = [
active_path,
]
with open(file_path) as fp:
for line in fp:
line = line.strip()
if line.startswith('#'):
if line.startswith("#"):
continue
if line == '};':
if line == "};":
if len(path_stack) > 1:
path_stack.pop()
active_path = path_stack[-1]
continue
split_line = line.split('[')
split_line = line.split("[")
if len(split_line) < 2:
continue
definitions = split_line[0].split(' ')
definitions = split_line[0].split(" ")
if len(definitions) < 2:
continue
if definitions[1] == 'alt':
if definitions[1] == "alt":
alt_counter += 1
path_stack.append(alt_counter)
states[alt_counter] = [s for s in states[active_path]]
continue
if definitions[0] == '---':
if definitions[0] == "---":
active_path = path_stack[-1]
continue
if definitions[1] != 'abox':
if definitions[1] != "abox":
continue
if definitions[0] != prefix:
continue
@ -384,7 +425,7 @@ def extract_states_from_xu_file(file_path, prefix):
continue
label = split_line[1][pos_start:pos_end]
if line.find('textbgcolor') > 0:
if line.find("textbgcolor") > 0:
# transaction status
pass
@ -396,35 +437,39 @@ def extract_states_from_xu_file(file_path, prefix):
def compare_bid_states(states, expect_states, exact_match: bool = True) -> bool:
for i in range(len(states) - 1, -1, -1):
if states[i][1] == 'Bid Delaying':
if states[i][1] == "Bid Delaying":
del states[i]
try:
if exact_match:
assert (len(states) == len(expect_states))
assert len(states) == len(expect_states)
else:
assert (len(states) >= len(expect_states))
assert len(states) >= len(expect_states)
for i in range(len(expect_states)):
s = states[i]
if s[1] != expect_states[i]:
if 'Bid ' + expect_states[i] == s[1]:
logging.warning(f'Expected state {expect_states[i]} not an exact match to {s[1]}.')
if "Bid " + expect_states[i] == s[1]:
logging.warning(
f"Expected state {expect_states[i]} not an exact match to {s[1]}."
)
continue
if [s[0], expect_states[i]] in states:
logging.warning(f'Expected state {expect_states[i]} found out of order at the same time as {s[1]}.')
logging.warning(
f"Expected state {expect_states[i]} found out of order at the same time as {s[1]}."
)
continue
raise ValueError(f'Expected state {expect_states[i]}, found {s[1]}')
assert (s[1] == expect_states[i])
raise ValueError(f"Expected state {expect_states[i]}, found {s[1]}")
assert s[1] == expect_states[i]
except Exception as e:
logging.info('Expecting states: {}'.format(json.dumps(expect_states, indent=4)))
logging.info('Have states: {}'.format(json.dumps(states, indent=4)))
logging.info("Expecting states: {}".format(json.dumps(expect_states, indent=4)))
logging.info("Have states: {}".format(json.dumps(states, indent=4)))
raise e
return True
def compare_bid_states_unordered(states, expect_states, ignore_states=[]) -> bool:
ignore_states.append('Bid Delaying')
ignore_states.append("Bid Delaying")
for i in range(len(states) - 1, -1, -1):
if states[i][1] in ignore_states:
del states[i]
@ -432,9 +477,9 @@ def compare_bid_states_unordered(states, expect_states, ignore_states=[]) -> boo
try:
assert len(states) == len(expect_states)
for state in expect_states:
assert (any(state in s[1] for s in states))
assert any(state in s[1] for s in states)
except Exception as e:
logging.info('Expecting states: {}'.format(json.dumps(expect_states, indent=4)))
logging.info('Have states: {}'.format(json.dumps(states, indent=4)))
logging.info("Expecting states: {}".format(json.dumps(expect_states, indent=4)))
logging.info("Have states: {}".format(json.dumps(states, indent=4)))
raise e
return True

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -26,16 +27,22 @@ from tests.basicswap.util import (
waitForServer,
)
from tests.basicswap.common import (
BASE_PORT, BASE_RPC_PORT,
BTC_BASE_PORT, BTC_BASE_RPC_PORT, BTC_BASE_TOR_PORT,
LTC_BASE_PORT, LTC_BASE_RPC_PORT,
BASE_PORT,
BASE_RPC_PORT,
BTC_BASE_PORT,
BTC_BASE_RPC_PORT,
BTC_BASE_TOR_PORT,
LTC_BASE_PORT,
LTC_BASE_RPC_PORT,
PIVX_BASE_PORT,
)
from tests.basicswap.extended.test_dcr import (
DCR_BASE_PORT, DCR_BASE_RPC_PORT,
DCR_BASE_PORT,
DCR_BASE_RPC_PORT,
)
from tests.basicswap.test_bch_xmr import (
BCH_BASE_PORT, BCH_BASE_RPC_PORT,
BCH_BASE_PORT,
BCH_BASE_RPC_PORT,
)
from basicswap.contrib.rpcauth import generate_salt, password_to_hmac
@ -43,49 +50,58 @@ from basicswap.contrib.rpcauth import generate_salt, password_to_hmac
import basicswap.config as cfg
import basicswap.bin.run as runSystem
TEST_PATH = os.path.expanduser(os.getenv('TEST_PATH', '~/test_basicswap1'))
TEST_PATH = os.path.expanduser(os.getenv("TEST_PATH", "~/test_basicswap1"))
PARTICL_PORT_BASE = int(os.getenv('PARTICL_PORT_BASE', BASE_PORT))
PARTICL_RPC_PORT_BASE = int(os.getenv('PARTICL_RPC_PORT_BASE', BASE_RPC_PORT))
PARTICL_PORT_BASE = int(os.getenv("PARTICL_PORT_BASE", BASE_PORT))
PARTICL_RPC_PORT_BASE = int(os.getenv("PARTICL_RPC_PORT_BASE", BASE_RPC_PORT))
BITCOIN_PORT_BASE = int(os.getenv('BITCOIN_PORT_BASE', BTC_BASE_PORT))
BITCOIN_RPC_PORT_BASE = int(os.getenv('BITCOIN_RPC_PORT_BASE', BTC_BASE_RPC_PORT))
BITCOIN_TOR_PORT_BASE = int(os.getenv('BITCOIN_TOR_PORT_BASE', BTC_BASE_TOR_PORT))
BITCOIN_PORT_BASE = int(os.getenv("BITCOIN_PORT_BASE", BTC_BASE_PORT))
BITCOIN_RPC_PORT_BASE = int(os.getenv("BITCOIN_RPC_PORT_BASE", BTC_BASE_RPC_PORT))
BITCOIN_TOR_PORT_BASE = int(os.getenv("BITCOIN_TOR_PORT_BASE", BTC_BASE_TOR_PORT))
LITECOIN_RPC_PORT_BASE = int(os.getenv('LITECOIN_RPC_PORT_BASE', LTC_BASE_RPC_PORT))
DECRED_RPC_PORT_BASE = int(os.getenv('DECRED_RPC_PORT_BASE', DCR_BASE_RPC_PORT))
BITCOINCASH_RPC_PORT_BASE = int(os.getenv('BITCOINCASH_RPC_PORT_BASE', BCH_BASE_RPC_PORT))
LITECOIN_RPC_PORT_BASE = int(os.getenv("LITECOIN_RPC_PORT_BASE", LTC_BASE_RPC_PORT))
DECRED_RPC_PORT_BASE = int(os.getenv("DECRED_RPC_PORT_BASE", DCR_BASE_RPC_PORT))
BITCOINCASH_RPC_PORT_BASE = int(
os.getenv("BITCOINCASH_RPC_PORT_BASE", BCH_BASE_RPC_PORT)
)
FIRO_BASE_PORT = 34832
FIRO_BASE_RPC_PORT = 35832
FIRO_RPC_PORT_BASE = int(os.getenv('FIRO_RPC_PORT_BASE', FIRO_BASE_RPC_PORT))
FIRO_RPC_PORT_BASE = int(os.getenv("FIRO_RPC_PORT_BASE", FIRO_BASE_RPC_PORT))
XMR_BASE_P2P_PORT = 17792
XMR_BASE_RPC_PORT = 29798
XMR_BASE_WALLET_RPC_PORT = 29998
EXTRA_CONFIG_JSON = json.loads(os.getenv('EXTRA_CONFIG_JSON', '{}'))
EXTRA_CONFIG_JSON = json.loads(os.getenv("EXTRA_CONFIG_JSON", "{}"))
def waitForBidState(delay_event, port, bid_id, state_str, wait_for=60):
for i in range(wait_for):
if delay_event.is_set():
raise ValueError('Test stopped.')
bid = json.loads(urlopen('http://127.0.0.1:12700/json/bids/{}'.format(bid_id)).read())
if bid['bid_state'] == state_str:
raise ValueError("Test stopped.")
bid = json.loads(
urlopen("http://127.0.0.1:12700/json/bids/{}".format(bid_id)).read()
)
if bid["bid_state"] == state_str:
return
delay_event.wait(1)
raise ValueError('waitForBidState failed')
raise ValueError("waitForBidState failed")
def updateThread(xmr_addr, delay_event, xmr_auth):
while not delay_event.is_set():
try:
callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'generateblocks', {'wallet_address': xmr_addr, 'amount_of_blocks': 1}, auth=xmr_auth)
callrpc_xmr(
XMR_BASE_RPC_PORT + 1,
"generateblocks",
{"wallet_address": xmr_addr, "amount_of_blocks": 1},
auth=xmr_auth,
)
except Exception as e:
print('updateThread error', str(e))
print("updateThread error", str(e))
delay_event.wait(2)
@ -97,47 +113,63 @@ def recursive_update_dict(base, new_vals):
base[key] = value
def run_prepare(node_id, datadir_path, bins_path, with_coins, mnemonic_in=None, num_nodes=3, use_rpcauth=False, extra_settings={}, port_ofs=0):
def run_prepare(
node_id,
datadir_path,
bins_path,
with_coins,
mnemonic_in=None,
num_nodes=3,
use_rpcauth=False,
extra_settings={},
port_ofs=0,
):
config_path = os.path.join(datadir_path, cfg.CONFIG_FILENAME)
os.environ['BSX_TEST_MODE'] = 'true'
os.environ['PART_RPC_PORT'] = str(PARTICL_RPC_PORT_BASE)
os.environ['BTC_RPC_PORT'] = str(BITCOIN_RPC_PORT_BASE)
os.environ['LTC_RPC_PORT'] = str(LITECOIN_RPC_PORT_BASE)
os.environ['DCR_RPC_PORT'] = str(DECRED_RPC_PORT_BASE)
os.environ['BCH_PORT'] = str(BCH_BASE_PORT)
os.environ['BCH_RPC_PORT'] = str(BITCOINCASH_RPC_PORT_BASE)
os.environ['FIRO_RPC_PORT'] = str(FIRO_RPC_PORT_BASE)
os.environ["BSX_TEST_MODE"] = "true"
os.environ["PART_RPC_PORT"] = str(PARTICL_RPC_PORT_BASE)
os.environ["BTC_RPC_PORT"] = str(BITCOIN_RPC_PORT_BASE)
os.environ["LTC_RPC_PORT"] = str(LITECOIN_RPC_PORT_BASE)
os.environ["DCR_RPC_PORT"] = str(DECRED_RPC_PORT_BASE)
os.environ["BCH_PORT"] = str(BCH_BASE_PORT)
os.environ["BCH_RPC_PORT"] = str(BITCOINCASH_RPC_PORT_BASE)
os.environ["FIRO_RPC_PORT"] = str(FIRO_RPC_PORT_BASE)
os.environ['XMR_RPC_USER'] = 'xmr_user'
os.environ['XMR_RPC_PWD'] = 'xmr_pwd'
os.environ["XMR_RPC_USER"] = "xmr_user"
os.environ["XMR_RPC_PWD"] = "xmr_pwd"
os.environ['DCR_RPC_PWD'] = 'dcr_pwd'
os.environ["DCR_RPC_PWD"] = "dcr_pwd"
import basicswap.bin.prepare as prepareSystem
# Hack: Reload module to set env vars as the basicswap_prepare module is initialised if imported from elsewhere earlier
from importlib import reload
prepareSystem = reload(prepareSystem)
testargs = [
'basicswap-prepare',
"basicswap-prepare",
f'-datadir="{datadir_path}"',
f'-bindir="{bins_path}"',
f'-portoffset={(node_id + port_ofs)}',
'-regtest',
f'-withcoins={with_coins}',
'-noextractover',
'-noreleasesizecheck',
'-xmrrestoreheight=0']
f"-portoffset={(node_id + port_ofs)}",
"-regtest",
f"-withcoins={with_coins}",
"-noextractover",
"-noreleasesizecheck",
"-xmrrestoreheight=0",
]
if mnemonic_in:
testargs.append(f'-particl_mnemonic="{mnemonic_in}"')
keysdirpath = os.getenv('PGP_KEYS_DIR_PATH', None)
keysdirpath = os.getenv("PGP_KEYS_DIR_PATH", None)
if keysdirpath is not None:
testargs.append('-keysdirpath="' + os.path.expanduser(keysdirpath) + '"')
with patch.object(sys, 'argv', testargs), patch('sys.stdout', new=StringIO()) as mocked_stdout:
with (
patch.object(sys, "argv", testargs),
patch("sys.stdout", new=StringIO()) as mocked_stdout,
):
prepareSystem.main()
lines = mocked_stdout.getvalue().split('\n')
lines = mocked_stdout.getvalue().split("\n")
if mnemonic_in is None:
mnemonic_out = lines[-4]
else:
@ -146,248 +178,311 @@ def run_prepare(node_id, datadir_path, bins_path, with_coins, mnemonic_in=None,
with open(config_path) as fs:
settings = json.load(fs)
config_filename = os.path.join(datadir_path, 'particl', 'particl.conf')
with open(config_filename, 'r') as fp:
config_filename = os.path.join(datadir_path, "particl", "particl.conf")
with open(config_filename, "r") as fp:
lines = fp.readlines()
with open(config_filename, 'w') as fp:
with open(config_filename, "w") as fp:
for line in lines:
if not line.startswith('staking'):
if not line.startswith("staking"):
fp.write(line)
fp.write('port={}\n'.format(PARTICL_PORT_BASE + node_id + port_ofs))
fp.write('bind=127.0.0.1\n')
fp.write('dnsseed=0\n')
fp.write('discover=0\n')
fp.write('listenonion=0\n')
fp.write('upnp=0\n')
fp.write('minstakeinterval=5\n')
fp.write('stakethreadconddelayms=2000\n')
fp.write('smsgsregtestadjust=0\n')
fp.write("port={}\n".format(PARTICL_PORT_BASE + node_id + port_ofs))
fp.write("bind=127.0.0.1\n")
fp.write("dnsseed=0\n")
fp.write("discover=0\n")
fp.write("listenonion=0\n")
fp.write("upnp=0\n")
fp.write("minstakeinterval=5\n")
fp.write("stakethreadconddelayms=2000\n")
fp.write("smsgsregtestadjust=0\n")
if use_rpcauth:
salt = generate_salt(16)
rpc_user = 'test_part_' + str(node_id)
rpc_pass = 'test_part_pwd_' + str(node_id)
fp.write('rpcauth={}:{}${}\n'.format(rpc_user, salt, password_to_hmac(salt, rpc_pass)))
settings['chainclients']['particl']['rpcuser'] = rpc_user
settings['chainclients']['particl']['rpcpassword'] = rpc_pass
rpc_user = "test_part_" + str(node_id)
rpc_pass = "test_part_pwd_" + str(node_id)
fp.write(
"rpcauth={}:{}${}\n".format(
rpc_user, salt, password_to_hmac(salt, rpc_pass)
)
)
settings["chainclients"]["particl"]["rpcuser"] = rpc_user
settings["chainclients"]["particl"]["rpcpassword"] = rpc_pass
for ip in range(num_nodes):
if ip != node_id:
fp.write('connect=127.0.0.1:{}\n'.format(PARTICL_PORT_BASE + ip + port_ofs))
for opt in EXTRA_CONFIG_JSON.get('part{}'.format(node_id), []):
fp.write(opt + '\n')
fp.write(
"connect=127.0.0.1:{}\n".format(PARTICL_PORT_BASE + ip + port_ofs)
)
for opt in EXTRA_CONFIG_JSON.get("part{}".format(node_id), []):
fp.write(opt + "\n")
coins_array = with_coins.split(',')
coins_array = with_coins.split(",")
if 'bitcoin' in coins_array:
if "bitcoin" in coins_array:
# Pruned nodes don't provide blocks
config_filename = os.path.join(datadir_path, 'bitcoin', 'bitcoin.conf')
with open(config_filename, 'r') as fp:
config_filename = os.path.join(datadir_path, "bitcoin", "bitcoin.conf")
with open(config_filename, "r") as fp:
lines = fp.readlines()
with open(config_filename, 'w') as fp:
with open(config_filename, "w") as fp:
for line in lines:
if not line.startswith('prune'):
if not line.startswith("prune"):
fp.write(line)
fp.write('port={}\n'.format(BITCOIN_PORT_BASE + node_id + port_ofs))
fp.write('bind=127.0.0.1\n')
fp.write("port={}\n".format(BITCOIN_PORT_BASE + node_id + port_ofs))
fp.write("bind=127.0.0.1\n")
# listenonion=0 does not stop the node from trying to bind to the tor port
# https://github.com/bitcoin/bitcoin/issues/22726
fp.write('bind=127.0.0.1:{}=onion\n'.format(BITCOIN_TOR_PORT_BASE + node_id + port_ofs))
fp.write('dnsseed=0\n')
fp.write('discover=0\n')
fp.write('listenonion=0\n')
fp.write('upnp=0\n')
fp.write(
"bind=127.0.0.1:{}=onion\n".format(
BITCOIN_TOR_PORT_BASE + node_id + port_ofs
)
)
fp.write("dnsseed=0\n")
fp.write("discover=0\n")
fp.write("listenonion=0\n")
fp.write("upnp=0\n")
if use_rpcauth:
salt = generate_salt(16)
rpc_user = 'test_btc_' + str(node_id)
rpc_pass = 'test_btc_pwd_' + str(node_id)
fp.write('rpcauth={}:{}${}\n'.format(rpc_user, salt, password_to_hmac(salt, rpc_pass)))
settings['chainclients']['bitcoin']['rpcuser'] = rpc_user
settings['chainclients']['bitcoin']['rpcpassword'] = rpc_pass
rpc_user = "test_btc_" + str(node_id)
rpc_pass = "test_btc_pwd_" + str(node_id)
fp.write(
"rpcauth={}:{}${}\n".format(
rpc_user, salt, password_to_hmac(salt, rpc_pass)
)
)
settings["chainclients"]["bitcoin"]["rpcuser"] = rpc_user
settings["chainclients"]["bitcoin"]["rpcpassword"] = rpc_pass
for ip in range(num_nodes):
if ip != node_id:
fp.write('connect=127.0.0.1:{}\n'.format(BITCOIN_PORT_BASE + ip + port_ofs))
for opt in EXTRA_CONFIG_JSON.get('btc{}'.format(node_id), []):
fp.write(opt + '\n')
fp.write(
"connect=127.0.0.1:{}\n".format(
BITCOIN_PORT_BASE + ip + port_ofs
)
)
for opt in EXTRA_CONFIG_JSON.get("btc{}".format(node_id), []):
fp.write(opt + "\n")
if 'litecoin' in coins_array:
if "litecoin" in coins_array:
# Pruned nodes don't provide blocks
config_filename = os.path.join(datadir_path, 'litecoin', 'litecoin.conf')
with open(config_filename, 'r') as fp:
config_filename = os.path.join(datadir_path, "litecoin", "litecoin.conf")
with open(config_filename, "r") as fp:
lines = fp.readlines()
with open(config_filename, 'w') as fp:
with open(config_filename, "w") as fp:
for line in lines:
if not line.startswith('prune'):
if not line.startswith("prune"):
fp.write(line)
fp.write('port={}\n'.format(LTC_BASE_PORT + node_id + port_ofs))
fp.write('bind=127.0.0.1\n')
fp.write('dnsseed=0\n')
fp.write('discover=0\n')
fp.write('listenonion=0\n')
fp.write('upnp=0\n')
fp.write("port={}\n".format(LTC_BASE_PORT + node_id + port_ofs))
fp.write("bind=127.0.0.1\n")
fp.write("dnsseed=0\n")
fp.write("discover=0\n")
fp.write("listenonion=0\n")
fp.write("upnp=0\n")
if use_rpcauth:
salt = generate_salt(16)
rpc_user = 'test_ltc_' + str(node_id)
rpc_pass = 'test_ltc_pwd_' + str(node_id)
fp.write('rpcauth={}:{}${}\n'.format(rpc_user, salt, password_to_hmac(salt, rpc_pass)))
settings['chainclients']['litecoin']['rpcuser'] = rpc_user
settings['chainclients']['litecoin']['rpcpassword'] = rpc_pass
rpc_user = "test_ltc_" + str(node_id)
rpc_pass = "test_ltc_pwd_" + str(node_id)
fp.write(
"rpcauth={}:{}${}\n".format(
rpc_user, salt, password_to_hmac(salt, rpc_pass)
)
)
settings["chainclients"]["litecoin"]["rpcuser"] = rpc_user
settings["chainclients"]["litecoin"]["rpcpassword"] = rpc_pass
for ip in range(num_nodes):
if ip != node_id:
fp.write('connect=127.0.0.1:{}\n'.format(LTC_BASE_PORT + ip + port_ofs))
for opt in EXTRA_CONFIG_JSON.get('ltc{}'.format(node_id), []):
fp.write(opt + '\n')
fp.write(
"connect=127.0.0.1:{}\n".format(LTC_BASE_PORT + ip + port_ofs)
)
for opt in EXTRA_CONFIG_JSON.get("ltc{}".format(node_id), []):
fp.write(opt + "\n")
if 'decred' in coins_array:
if "decred" in coins_array:
# Pruned nodes don't provide blocks
config_filename = os.path.join(datadir_path, 'decred', 'dcrd.conf')
with open(config_filename, 'r') as fp:
config_filename = os.path.join(datadir_path, "decred", "dcrd.conf")
with open(config_filename, "r") as fp:
lines = fp.readlines()
with open(config_filename, 'w') as fp:
with open(config_filename, "w") as fp:
for line in lines:
if not line.startswith('prune'):
if not line.startswith("prune"):
fp.write(line)
fp.write('listen=127.0.0.1:{}\n'.format(DCR_BASE_PORT + node_id + port_ofs))
fp.write('noseeders=1\n')
fp.write('nodnsseed=1\n')
fp.write('nodiscoverip=1\n')
fp.write("listen=127.0.0.1:{}\n".format(DCR_BASE_PORT + node_id + port_ofs))
fp.write("noseeders=1\n")
fp.write("nodnsseed=1\n")
fp.write("nodiscoverip=1\n")
if node_id == 0:
fp.write('miningaddr=SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH\n')
fp.write("miningaddr=SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH\n")
for ip in range(num_nodes):
if ip != node_id:
fp.write('addpeer=127.0.0.1:{}\n'.format(DCR_BASE_PORT + ip + port_ofs))
config_filename = os.path.join(datadir_path, 'decred', 'dcrwallet.conf')
with open(config_filename, 'a') as fp:
fp.write('enablevoting=1\n')
fp.write(
"addpeer=127.0.0.1:{}\n".format(
DCR_BASE_PORT + ip + port_ofs
)
)
config_filename = os.path.join(datadir_path, "decred", "dcrwallet.conf")
with open(config_filename, "a") as fp:
fp.write("enablevoting=1\n")
if 'pivx' in coins_array:
if "pivx" in coins_array:
# Pruned nodes don't provide blocks
config_filename = os.path.join(datadir_path, 'pivx', 'pivx.conf')
with open(config_filename, 'r') as fp:
config_filename = os.path.join(datadir_path, "pivx", "pivx.conf")
with open(config_filename, "r") as fp:
lines = fp.readlines()
with open(config_filename, 'w') as fp:
with open(config_filename, "w") as fp:
for line in lines:
if not line.startswith('prune'):
if not line.startswith("prune"):
fp.write(line)
fp.write('port={}\n'.format(PIVX_BASE_PORT + node_id + port_ofs))
fp.write('bind=127.0.0.1\n')
fp.write('dnsseed=0\n')
fp.write('discover=0\n')
fp.write('listenonion=0\n')
fp.write('upnp=0\n')
fp.write("port={}\n".format(PIVX_BASE_PORT + node_id + port_ofs))
fp.write("bind=127.0.0.1\n")
fp.write("dnsseed=0\n")
fp.write("discover=0\n")
fp.write("listenonion=0\n")
fp.write("upnp=0\n")
if use_rpcauth:
salt = generate_salt(16)
rpc_user = 'test_pivx_' + str(node_id)
rpc_pass = 'test_pivx_pwd_' + str(node_id)
fp.write('rpcauth={}:{}${}\n'.format(rpc_user, salt, password_to_hmac(salt, rpc_pass)))
settings['chainclients']['pivx']['rpcuser'] = rpc_user
settings['chainclients']['pivx']['rpcpassword'] = rpc_pass
rpc_user = "test_pivx_" + str(node_id)
rpc_pass = "test_pivx_pwd_" + str(node_id)
fp.write(
"rpcauth={}:{}${}\n".format(
rpc_user, salt, password_to_hmac(salt, rpc_pass)
)
)
settings["chainclients"]["pivx"]["rpcuser"] = rpc_user
settings["chainclients"]["pivx"]["rpcpassword"] = rpc_pass
for ip in range(num_nodes):
if ip != node_id:
fp.write('connect=127.0.0.1:{}\n'.format(PIVX_BASE_PORT + ip + port_ofs))
for opt in EXTRA_CONFIG_JSON.get('pivx{}'.format(node_id), []):
fp.write(opt + '\n')
fp.write(
"connect=127.0.0.1:{}\n".format(PIVX_BASE_PORT + ip + port_ofs)
)
for opt in EXTRA_CONFIG_JSON.get("pivx{}".format(node_id), []):
fp.write(opt + "\n")
if 'firo' in coins_array:
if "firo" in coins_array:
# Pruned nodes don't provide blocks
config_filename = os.path.join(datadir_path, 'firo', 'firo.conf')
with open(config_filename, 'r') as fp:
config_filename = os.path.join(datadir_path, "firo", "firo.conf")
with open(config_filename, "r") as fp:
lines = fp.readlines()
with open(config_filename, 'w') as fp:
with open(config_filename, "w") as fp:
for line in lines:
if not line.startswith('prune'):
if not line.startswith("prune"):
fp.write(line)
fp.write('port={}\n'.format(FIRO_BASE_PORT + node_id + port_ofs))
fp.write('bind=127.0.0.1\n')
fp.write('dnsseed=0\n')
fp.write('discover=0\n')
fp.write('listenonion=0\n')
fp.write('upnp=0\n')
fp.write("port={}\n".format(FIRO_BASE_PORT + node_id + port_ofs))
fp.write("bind=127.0.0.1\n")
fp.write("dnsseed=0\n")
fp.write("discover=0\n")
fp.write("listenonion=0\n")
fp.write("upnp=0\n")
if use_rpcauth:
salt = generate_salt(16)
rpc_user = 'test_firo_' + str(node_id)
rpc_pass = 'test_firo_pwd_' + str(node_id)
fp.write('rpcauth={}:{}${}\n'.format(rpc_user, salt, password_to_hmac(salt, rpc_pass)))
settings['chainclients']['firo']['rpcuser'] = rpc_user
settings['chainclients']['firo']['rpcpassword'] = rpc_pass
rpc_user = "test_firo_" + str(node_id)
rpc_pass = "test_firo_pwd_" + str(node_id)
fp.write(
"rpcauth={}:{}${}\n".format(
rpc_user, salt, password_to_hmac(salt, rpc_pass)
)
)
settings["chainclients"]["firo"]["rpcuser"] = rpc_user
settings["chainclients"]["firo"]["rpcpassword"] = rpc_pass
for ip in range(num_nodes):
if ip != node_id:
fp.write('connect=127.0.0.1:{}\n'.format(FIRO_BASE_PORT + ip + port_ofs))
for opt in EXTRA_CONFIG_JSON.get('firo{}'.format(node_id), []):
fp.write(opt + '\n')
fp.write(
"connect=127.0.0.1:{}\n".format(FIRO_BASE_PORT + ip + port_ofs)
)
for opt in EXTRA_CONFIG_JSON.get("firo{}".format(node_id), []):
fp.write(opt + "\n")
if 'monero' in coins_array:
with open(os.path.join(datadir_path, 'monero', 'monerod.conf'), 'a') as fp:
fp.write('p2p-bind-ip=127.0.0.1\n')
fp.write('p2p-bind-port={}\n'.format(XMR_BASE_P2P_PORT + node_id + port_ofs))
if "monero" in coins_array:
with open(os.path.join(datadir_path, "monero", "monerod.conf"), "a") as fp:
fp.write("p2p-bind-ip=127.0.0.1\n")
fp.write(
"p2p-bind-port={}\n".format(XMR_BASE_P2P_PORT + node_id + port_ofs)
)
for ip in range(num_nodes):
if ip != node_id:
fp.write('add-exclusive-node=127.0.0.1:{}\n'.format(XMR_BASE_P2P_PORT + ip + port_ofs))
fp.write(
"add-exclusive-node=127.0.0.1:{}\n".format(
XMR_BASE_P2P_PORT + ip + port_ofs
)
)
if 'bitcoincash' in coins_array:
config_filename = os.path.join(datadir_path, 'bitcoincash', 'bitcoin.conf')
with open(config_filename, 'r') as fp:
if "bitcoincash" in coins_array:
config_filename = os.path.join(datadir_path, "bitcoincash", "bitcoin.conf")
with open(config_filename, "r") as fp:
lines = fp.readlines()
with open(config_filename, 'w') as fp:
with open(config_filename, "w") as fp:
for line in lines:
if not line.startswith('prune'):
if not line.startswith("prune"):
fp.write(line)
# NOTE: port is set (when starting daemon) from basicswap.json
fp.write('bind=127.0.0.1\n')
fp.write('dnsseed=0\n')
fp.write('discover=0\n')
fp.write('listenonion=0\n')
fp.write('upnp=0\n')
fp.write("bind=127.0.0.1\n")
fp.write("dnsseed=0\n")
fp.write("discover=0\n")
fp.write("listenonion=0\n")
fp.write("upnp=0\n")
if use_rpcauth:
salt = generate_salt(16)
rpc_user = 'test_bch_' + str(node_id)
rpc_pass = 'test_bch_pwd_' + str(node_id)
fp.write('rpcauth={}:{}${}\n'.format(rpc_user, salt, password_to_hmac(salt, rpc_pass)))
settings['chainclients']['bitcoincash']['rpcuser'] = rpc_user
settings['chainclients']['bitcoincash']['rpcpassword'] = rpc_pass
rpc_user = "test_bch_" + str(node_id)
rpc_pass = "test_bch_pwd_" + str(node_id)
fp.write(
"rpcauth={}:{}${}\n".format(
rpc_user, salt, password_to_hmac(salt, rpc_pass)
)
)
settings["chainclients"]["bitcoincash"]["rpcuser"] = rpc_user
settings["chainclients"]["bitcoincash"]["rpcpassword"] = rpc_pass
for ip in range(num_nodes):
if ip != node_id:
fp.write('connect=127.0.0.1:{}\n'.format(BCH_BASE_PORT + ip + port_ofs))
for opt in EXTRA_CONFIG_JSON.get('bch{}'.format(node_id), []):
fp.write(opt + '\n')
fp.write(
"connect=127.0.0.1:{}\n".format(BCH_BASE_PORT + ip + port_ofs)
)
for opt in EXTRA_CONFIG_JSON.get("bch{}".format(node_id), []):
fp.write(opt + "\n")
with open(config_path) as fs:
settings = json.load(fs)
settings['min_delay_event'] = 1
settings['max_delay_event'] = 4
settings['min_delay_event_short'] = 1
settings['max_delay_event_short'] = 4
settings['min_delay_retry'] = 10
settings['max_delay_retry'] = 20
settings["min_delay_event"] = 1
settings["max_delay_event"] = 4
settings["min_delay_event_short"] = 1
settings["max_delay_event_short"] = 4
settings["min_delay_retry"] = 10
settings["max_delay_retry"] = 20
settings['check_progress_seconds'] = 5
settings['check_watched_seconds'] = 5
settings['check_expired_seconds'] = 60
settings['check_events_seconds'] = 5
settings['check_xmr_swaps_seconds'] = 5
settings["check_progress_seconds"] = 5
settings["check_watched_seconds"] = 5
settings["check_expired_seconds"] = 60
settings["check_events_seconds"] = 5
settings["check_xmr_swaps_seconds"] = 5
recursive_update_dict(settings, extra_settings)
extra_config = EXTRA_CONFIG_JSON.get('sc{}'.format(node_id), {})
extra_config = EXTRA_CONFIG_JSON.get("sc{}".format(node_id), {})
recursive_update_dict(settings, extra_config)
with open(config_path, 'w') as fp:
with open(config_path, "w") as fp:
json.dump(settings, fp, indent=4)
return mnemonic_out
def prepare_nodes(num_nodes, extra_coins, use_rpcauth=False, extra_settings={}, port_ofs=0):
bins_path = os.path.join(TEST_PATH, 'bin')
def prepare_nodes(
num_nodes, extra_coins, use_rpcauth=False, extra_settings={}, port_ofs=0
):
bins_path = os.path.join(TEST_PATH, "bin")
for i in range(num_nodes):
logging.info('Preparing node: %d.', i)
client_path = os.path.join(TEST_PATH, 'client{}'.format(i))
logging.info("Preparing node: %d.", i)
client_path = os.path.join(TEST_PATH, "client{}".format(i))
try:
shutil.rmtree(client_path)
except Exception as ex:
logging.warning('setUpClass %s', str(ex))
logging.warning("setUpClass %s", str(ex))
run_prepare(i, client_path, bins_path, extra_coins, mnemonics[i] if i < len(mnemonics) else None,
num_nodes=num_nodes, use_rpcauth=use_rpcauth, extra_settings=extra_settings, port_ofs=port_ofs)
run_prepare(
i,
client_path,
bins_path,
extra_coins,
mnemonics[i] if i < len(mnemonics) else None,
num_nodes=num_nodes,
use_rpcauth=use_rpcauth,
extra_settings=extra_settings,
port_ofs=port_ofs,
)
class TestBase(unittest.TestCase):
@ -395,34 +490,38 @@ class TestBase(unittest.TestCase):
super(TestBase, cls).setUpClass()
cls.delay_event = threading.Event()
signal.signal(signal.SIGINT, lambda signal, frame: cls.signal_handler(cls, signal, frame))
signal.signal(
signal.SIGINT, lambda signal, frame: cls.signal_handler(cls, signal, frame)
)
def signal_handler(self, sig, frame):
logging.info('signal {} detected.'.format(sig))
logging.info("signal {} detected.".format(sig))
self.delay_event.set()
def wait_seconds(self, seconds):
self.delay_event.wait(seconds)
if self.delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
def wait_for_particl_height(self, http_port, num_blocks=3):
# Wait for height, or sequencelock is thrown off by genesis blocktime
logging.info('Waiting for Particl chain height %d', num_blocks)
logging.info("Waiting for Particl chain height %d", num_blocks)
for i in range(60):
if self.delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
try:
wallets = json.loads(urlopen(f'http://127.0.0.1:{http_port}/json/wallets').read())
particl_blocks = wallets['PART']['blocks']
print('particl_blocks', particl_blocks)
wallets = json.loads(
urlopen(f"http://127.0.0.1:{http_port}/json/wallets").read()
)
particl_blocks = wallets["PART"]["blocks"]
print("particl_blocks", particl_blocks)
if particl_blocks >= num_blocks:
return
except Exception as e:
print('Error reading wallets', str(e))
print("Error reading wallets", str(e))
self.delay_event.wait(1)
raise ValueError(f'wait_for_particl_height failed http_port: {http_port}')
raise ValueError(f"wait_for_particl_height failed http_port: {http_port}")
class XmrTestBase(TestBase):
@ -433,19 +532,21 @@ class XmrTestBase(TestBase):
cls.update_thread = None
cls.processes = []
prepare_nodes(3, 'monero')
prepare_nodes(3, "monero")
def run_thread(self, client_id):
client_path = os.path.join(TEST_PATH, 'client{}'.format(client_id))
testargs = ['basicswap-run', '-datadir=' + client_path, '-regtest']
with patch.object(sys, 'argv', testargs):
client_path = os.path.join(TEST_PATH, "client{}".format(client_id))
testargs = ["basicswap-run", "-datadir=" + client_path, "-regtest"]
with patch.object(sys, "argv", testargs):
runSystem.main()
def start_processes(self):
self.delay_event.clear()
for i in range(3):
self.processes.append(multiprocessing.Process(target=self.run_thread, args=(i,)))
self.processes.append(
multiprocessing.Process(target=self.run_thread, args=(i,))
)
self.processes[-1].start()
waitForServer(self.delay_event, 12701)
@ -453,35 +554,55 @@ class XmrTestBase(TestBase):
def waitForMainAddress():
for i in range(20):
if self.delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
try:
wallets = json.loads(urlopen('http://127.0.0.1:12701/json/wallets').read())
return wallets['XMR']['main_address']
wallets = json.loads(
urlopen("http://127.0.0.1:12701/json/wallets").read()
)
return wallets["XMR"]["main_address"]
except Exception as e:
print('Waiting for main address {}'.format(str(e)))
print("Waiting for main address {}".format(str(e)))
self.delay_event.wait(1)
raise ValueError('waitForMainAddress timedout')
raise ValueError("waitForMainAddress timedout")
xmr_addr1 = waitForMainAddress()
num_blocks = 100
xmr_auth = None
if os.getenv('XMR_RPC_USER', '') != '':
xmr_auth = (os.getenv('XMR_RPC_USER', ''), os.getenv('XMR_RPC_PWD', ''))
if os.getenv("XMR_RPC_USER", "") != "":
xmr_auth = (os.getenv("XMR_RPC_USER", ""), os.getenv("XMR_RPC_PWD", ""))
if callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'get_block_count', auth=xmr_auth)['count'] < num_blocks:
logging.info('Mining {} Monero blocks to {}.'.format(num_blocks, xmr_addr1))
callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'generateblocks', {'wallet_address': xmr_addr1, 'amount_of_blocks': num_blocks}, auth=xmr_auth)
logging.info('XMR blocks: %d', callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'get_block_count', auth=xmr_auth)['count'])
if (
callrpc_xmr(XMR_BASE_RPC_PORT + 1, "get_block_count", auth=xmr_auth)[
"count"
]
< num_blocks
):
logging.info("Mining {} Monero blocks to {}.".format(num_blocks, xmr_addr1))
callrpc_xmr(
XMR_BASE_RPC_PORT + 1,
"generateblocks",
{"wallet_address": xmr_addr1, "amount_of_blocks": num_blocks},
auth=xmr_auth,
)
logging.info(
"XMR blocks: %d",
callrpc_xmr(XMR_BASE_RPC_PORT + 1, "get_block_count", auth=xmr_auth)[
"count"
],
)
self.update_thread = threading.Thread(target=updateThread, args=(xmr_addr1, self.delay_event, xmr_auth))
self.update_thread = threading.Thread(
target=updateThread, args=(xmr_addr1, self.delay_event, xmr_auth)
)
self.update_thread.start()
self.wait_for_particl_height(12701, num_blocks=3)
@classmethod
def tearDownClass(cls):
logging.info('Stopping test')
logging.info("Stopping test")
cls.delay_event.set()
if cls.update_thread:
cls.update_thread.join()

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2023 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -47,77 +48,76 @@ class Test(XmrTestBase):
waitForServer(self.delay_event, 12700)
waitForServer(self.delay_event, 12701)
wallets1 = read_json_api(12701, 'wallets')
assert (float(wallets1['XMR']['balance']) > 0.0)
wallets1 = read_json_api(12701, "wallets")
assert float(wallets1["XMR"]["balance"]) > 0.0
node1_password: str = 'notapassword123'
logger.info('Encrypting node 1 wallets')
rv = read_json_api(12701, 'setpassword', {'oldpassword': '', 'newpassword': node1_password})
assert ('success' in rv)
rv = read_json_api(12701, 'unlock', {'password': node1_password})
assert ('success' in rv)
node1_password: str = "notapassword123"
logger.info("Encrypting node 1 wallets")
rv = read_json_api(
12701, "setpassword", {"oldpassword": "", "newpassword": node1_password}
)
assert "success" in rv
rv = read_json_api(12701, "unlock", {"password": node1_password})
assert "success" in rv
data = {
'addr_from': '-1',
'coin_from': 'part',
'coin_to': 'xmr',
'amt_from': '1',
'amt_to': '1',
'lockhrs': '24'}
"addr_from": "-1",
"coin_from": "part",
"coin_to": "xmr",
"amt_from": "1",
"amt_to": "1",
"lockhrs": "24",
}
offer_id = post_json_api(12700, 'offers/new', data)['offer_id']
offer_id = post_json_api(12700, "offers/new", data)["offer_id"]
summary = read_json_api(12700)
assert (summary['num_sent_offers'] == 1)
assert summary["num_sent_offers"] == 1
logger.info('Waiting for offer')
logger.info("Waiting for offer")
waitForNumOffers(self.delay_event, 12701, 1)
offers = read_json_api(12701, 'offers')
offers = read_json_api(12701, "offers")
offer = offers[0]
data = {
'offer_id': offer['offer_id'],
'amount_from': offer['amount_from']}
data = {"offer_id": offer["offer_id"], "amount_from": offer["amount_from"]}
data['valid_for_seconds'] = 24 * 60 * 60 + 1
bid = post_json_api(12701, 'bids/new', data)
assert (bid['error'] == 'Bid TTL too high')
del data['valid_for_seconds']
data['validmins'] = 24 * 60 + 1
bid = post_json_api(12701, 'bids/new', data)
assert (bid['error'] == 'Bid TTL too high')
data["valid_for_seconds"] = 24 * 60 * 60 + 1
bid = post_json_api(12701, "bids/new", data)
assert bid["error"] == "Bid TTL too high"
del data["valid_for_seconds"]
data["validmins"] = 24 * 60 + 1
bid = post_json_api(12701, "bids/new", data)
assert bid["error"] == "Bid TTL too high"
del data['validmins']
data['valid_for_seconds'] = 10
bid = post_json_api(12701, 'bids/new', data)
assert (bid['error'] == 'Bid TTL too low')
del data['valid_for_seconds']
data['validmins'] = 1
bid = post_json_api(12701, 'bids/new', data)
assert (bid['error'] == 'Bid TTL too low')
del data["validmins"]
data["valid_for_seconds"] = 10
bid = post_json_api(12701, "bids/new", data)
assert bid["error"] == "Bid TTL too low"
del data["valid_for_seconds"]
data["validmins"] = 1
bid = post_json_api(12701, "bids/new", data)
assert bid["error"] == "Bid TTL too low"
data['validmins'] = 60
bid_id = post_json_api(12701, 'bids/new', data)
data["validmins"] = 60
post_json_api(12701, "bids/new", data)
waitForNumBids(self.delay_event, 12700, 1)
for i in range(10):
bids = read_json_api(12700, 'bids')
bids = read_json_api(12700, "bids")
bid = bids[0]
if bid['bid_state'] == 'Received':
if bid["bid_state"] == "Received":
break
self.delay_event.wait(1)
assert (bid['expire_at'] == bid['created_at'] + data['validmins'] * 60)
assert bid["expire_at"] == bid["created_at"] + data["validmins"] * 60
data = {
'accept': True
}
rv = post_json_api(12700, 'bids/{}'.format(bid['bid_id']), data)
assert (rv['bid_state'] == 'Accepted')
data = {"accept": True}
rv = post_json_api(12700, "bids/{}".format(bid["bid_id"]), data)
assert rv["bid_state"] == "Accepted"
waitForNumSwapping(self.delay_event, 12701, 1)
logger.info('Restarting node 1')
logger.info("Restarting node 1")
c1 = self.processes[1]
c1.terminate()
c1.join()
@ -126,35 +126,35 @@ class Test(XmrTestBase):
waitForServer(self.delay_event, 12701)
rv = read_json_api(12701)
assert ('error' in rv)
assert "error" in rv
logger.info('Unlocking node 1')
rv = read_json_api(12701, 'unlock', {'password': node1_password})
assert ('success' in rv)
logger.info("Unlocking node 1")
rv = read_json_api(12701, "unlock", {"password": node1_password})
assert "success" in rv
rv = read_json_api(12701)
assert (rv['num_swapping'] == 1)
assert rv["num_swapping"] == 1
rv = read_json_api(12700, 'revokeoffer/{}'.format(offer_id))
assert (rv['revoked_offer'] == offer_id)
rv = read_json_api(12700, "revokeoffer/{}".format(offer_id))
assert rv["revoked_offer"] == offer_id
logger.info('Completing swap')
logger.info("Completing swap")
for i in range(240):
if self.delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
self.delay_event.wait(4)
rv = read_json_api(12700, 'bids/{}'.format(bid['bid_id']))
if rv['bid_state'] == 'Completed':
rv = read_json_api(12700, "bids/{}".format(bid["bid_id"]))
if rv["bid_state"] == "Completed":
break
assert (rv['bid_state'] == 'Completed')
assert rv["bid_state"] == "Completed"
# Ensure offer was revoked
summary = read_json_api(12700)
assert (summary['num_network_offers'] == 0)
assert summary["num_network_offers"] == 0
# Wait for bid to be removed from in-progress
waitForNumBids(self.delay_event, 12700, 0)
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022-2023 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -49,10 +50,12 @@ from tests.basicswap.test_xmr import BaseTest, test_delay_event, callnoderpc
logger = logging.getLogger()
FIRO_BINDIR = os.path.expanduser(os.getenv('FIRO_BINDIR', os.path.join(cfg.DEFAULT_TEST_BINDIR, 'firo')))
FIROD = os.getenv('FIROD', 'firod' + cfg.bin_suffix)
FIRO_CLI = os.getenv('FIRO_CLI', 'firo-cli' + cfg.bin_suffix)
FIRO_TX = os.getenv('FIRO_TX', 'firo-tx' + cfg.bin_suffix)
FIRO_BINDIR = os.path.expanduser(
os.getenv("FIRO_BINDIR", os.path.join(cfg.DEFAULT_TEST_BINDIR, "firo"))
)
FIROD = os.getenv("FIROD", "firod" + cfg.bin_suffix)
FIRO_CLI = os.getenv("FIRO_CLI", "firo-cli" + cfg.bin_suffix)
FIRO_TX = os.getenv("FIRO_TX", "firo-tx" + cfg.bin_suffix)
FIRO_BASE_PORT = 34832
FIRO_BASE_RPC_PORT = 35832
@ -60,50 +63,64 @@ FIRO_BASE_ZMQ_PORT = 36832
def firoCli(cmd, node_id=0):
return callrpc_cli(FIRO_BINDIR, os.path.join(cfg.TEST_DATADIRS, 'firo_' + str(node_id)), 'regtest', cmd, FIRO_CLI)
return callrpc_cli(
FIRO_BINDIR,
os.path.join(cfg.TEST_DATADIRS, "firo_" + str(node_id)),
"regtest",
cmd,
FIRO_CLI,
)
def prepareDataDir(datadir, node_id, conf_file, dir_prefix, base_p2p_port, base_rpc_port, num_nodes=3):
def prepareDataDir(
datadir, node_id, conf_file, dir_prefix, base_p2p_port, base_rpc_port, num_nodes=3
):
node_dir = os.path.join(datadir, dir_prefix + str(node_id))
if not os.path.exists(node_dir):
os.makedirs(node_dir)
cfg_file_path = os.path.join(node_dir, conf_file)
if os.path.exists(cfg_file_path):
return
with open(cfg_file_path, 'w+') as fp:
fp.write('regtest=1\n')
fp.write('port=' + str(base_p2p_port + node_id) + '\n')
fp.write('rpcport=' + str(base_rpc_port + node_id) + '\n')
with open(cfg_file_path, "w+") as fp:
fp.write("regtest=1\n")
fp.write("port=" + str(base_p2p_port + node_id) + "\n")
fp.write("rpcport=" + str(base_rpc_port + node_id) + "\n")
salt = generate_salt(16)
fp.write('rpcauth={}:{}${}\n'.format('test' + str(node_id), salt, password_to_hmac(salt, 'test_pass' + str(node_id))))
fp.write(
"rpcauth={}:{}${}\n".format(
"test" + str(node_id),
salt,
password_to_hmac(salt, "test_pass" + str(node_id)),
)
)
fp.write('daemon=0\n')
fp.write('dandelion=0\n')
fp.write('printtoconsole=0\n')
fp.write('server=1\n')
fp.write('discover=0\n')
fp.write('listenonion=0\n')
fp.write('bind=127.0.0.1\n')
fp.write('findpeers=0\n')
fp.write('debug=1\n')
fp.write('debugexclude=libevent\n')
fp.write("daemon=0\n")
fp.write("dandelion=0\n")
fp.write("printtoconsole=0\n")
fp.write("server=1\n")
fp.write("discover=0\n")
fp.write("listenonion=0\n")
fp.write("bind=127.0.0.1\n")
fp.write("findpeers=0\n")
fp.write("debug=1\n")
fp.write("debugexclude=libevent\n")
fp.write('fallbackfee=0.01\n')
fp.write('acceptnonstdtxn=0\n')
fp.write("fallbackfee=0.01\n")
fp.write("acceptnonstdtxn=0\n")
'''
"""
# qa/rpc-tests/segwit.py
fp.write('prematurewitness=1\n')
fp.write('walletprematurewitness=1\n')
fp.write('blockversion=4\n')
fp.write('promiscuousmempoolflags=517\n')
'''
"""
for i in range(0, num_nodes):
if node_id == i:
continue
fp.write('addnode=127.0.0.1:{}\n'.format(base_p2p_port + i))
fp.write("addnode=127.0.0.1:{}\n".format(base_p2p_port + i))
return node_dir
@ -121,9 +138,9 @@ class Test(BaseTest):
# Particl node mnemonics are test_xmr.py, node 2 is set randomly
firo_seeds = [
'd90b7ed1be614e1c172653aee1f3b6230f43b7fa99cf07fa984a17966ad81de7',
'6c81d6d74ba33a0db9e41518c2b6789fbe938e98018a4597dac661cfc5f2dfc1',
'c5de2be44834e7e47ad7dc8e35c6b77c79f17c6bb40d5509a00fc3dff384a865',
"d90b7ed1be614e1c172653aee1f3b6230f43b7fa99cf07fa984a17966ad81de7",
"6c81d6d74ba33a0db9e41518c2b6789fbe938e98018a4597dac661cfc5f2dfc1",
"c5de2be44834e7e47ad7dc8e35c6b77c79f17c6bb40d5509a00fc3dff384a865",
]
@classmethod
@ -131,13 +148,33 @@ class Test(BaseTest):
extra_opts = []
if not cls.restore_instance:
seed_hex = cls.firo_seeds[i]
extra_opts.append(f'-hdseed={seed_hex}')
data_dir = prepareDataDir(cfg.TEST_DATADIRS, i, 'firo.conf', 'firo_', base_p2p_port=FIRO_BASE_PORT, base_rpc_port=FIRO_BASE_RPC_PORT)
if os.path.exists(os.path.join(FIRO_BINDIR, 'firo-wallet')):
callrpc_cli(FIRO_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat create', 'firo-wallet')
extra_opts.append(f"-hdseed={seed_hex}")
data_dir = prepareDataDir(
cfg.TEST_DATADIRS,
i,
"firo.conf",
"firo_",
base_p2p_port=FIRO_BASE_PORT,
base_rpc_port=FIRO_BASE_RPC_PORT,
)
if os.path.exists(os.path.join(FIRO_BINDIR, "firo-wallet")):
callrpc_cli(
FIRO_BINDIR,
data_dir,
"regtest",
"-wallet=wallet.dat create",
"firo-wallet",
)
cls.firo_daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, 'firo_' + str(i)), FIRO_BINDIR, FIROD, opts=extra_opts))
logging.info('Started %s %d', FIROD, cls.firo_daemons[-1].handle.pid)
cls.firo_daemons.append(
startDaemon(
os.path.join(cfg.TEST_DATADIRS, "firo_" + str(i)),
FIRO_BINDIR,
FIROD,
opts=extra_opts,
)
)
logging.info("Started %s %d", FIROD, cls.firo_daemons[-1].handle.pid)
waitForRPC(make_rpc_func(i, base_rpc_port=FIRO_BASE_RPC_PORT), test_delay_event)
@ -153,30 +190,59 @@ class Test(BaseTest):
if cls.restore_instance:
void_block_rewards_pubkey = cls.getRandomPubkey()
cls.firo_addr = cls.swap_clients[0].ci(Coins.FIRO).pubkey_to_address(void_block_rewards_pubkey)
cls.firo_addr = (
cls.swap_clients[0]
.ci(Coins.FIRO)
.pubkey_to_address(void_block_rewards_pubkey)
)
else:
num_blocks = 400
cls.firo_addr = callnoderpc(0, 'getnewaddress', ['mining_addr'], base_rpc_port=FIRO_BASE_RPC_PORT)
cls.firo_addr = callnoderpc(
0, "getnewaddress", ["mining_addr"], base_rpc_port=FIRO_BASE_RPC_PORT
)
# cls.firo_addr = callnoderpc(0, 'addwitnessaddress', [cls.firo_addr], base_rpc_port=FIRO_BASE_RPC_PORT)
logging.info('Mining %d Firo blocks to %s', num_blocks, cls.firo_addr)
callnoderpc(0, 'generatetoaddress', [num_blocks, cls.firo_addr], base_rpc_port=FIRO_BASE_RPC_PORT)
logging.info("Mining %d Firo blocks to %s", num_blocks, cls.firo_addr)
callnoderpc(
0,
"generatetoaddress",
[num_blocks, cls.firo_addr],
base_rpc_port=FIRO_BASE_RPC_PORT,
)
firo_addr1 = callnoderpc(1, 'getnewaddress', ['initial addr'], base_rpc_port=FIRO_BASE_RPC_PORT)
firo_addr1 = callnoderpc(
1, "getnewaddress", ["initial addr"], base_rpc_port=FIRO_BASE_RPC_PORT
)
# firo_addr1 = callnoderpc(1, 'addwitnessaddress', [firo_addr1], base_rpc_port=FIRO_BASE_RPC_PORT)
for i in range(5):
callnoderpc(0, 'sendtoaddress', [firo_addr1, 1000], base_rpc_port=FIRO_BASE_RPC_PORT)
callnoderpc(
0,
"sendtoaddress",
[firo_addr1, 1000],
base_rpc_port=FIRO_BASE_RPC_PORT,
)
# Set future block rewards to nowhere (a random address), so wallet amounts stay constant
void_block_rewards_pubkey = cls.getRandomPubkey()
cls.firo_addr = cls.swap_clients[0].ci(Coins.FIRO).pubkey_to_address(void_block_rewards_pubkey)
chain_height = callnoderpc(0, 'getblockcount', base_rpc_port=FIRO_BASE_RPC_PORT)
cls.firo_addr = (
cls.swap_clients[0]
.ci(Coins.FIRO)
.pubkey_to_address(void_block_rewards_pubkey)
)
chain_height = callnoderpc(
0, "getblockcount", base_rpc_port=FIRO_BASE_RPC_PORT
)
num_blocks = 1352 - chain_height # Activate CTLV (bip65)
logging.info('Mining %d Firo blocks to %s', num_blocks, cls.firo_addr)
callnoderpc(0, 'generatetoaddress', [num_blocks, cls.firo_addr], base_rpc_port=FIRO_BASE_RPC_PORT)
logging.info("Mining %d Firo blocks to %s", num_blocks, cls.firo_addr)
callnoderpc(
0,
"generatetoaddress",
[num_blocks, cls.firo_addr],
base_rpc_port=FIRO_BASE_RPC_PORT,
)
@classmethod
def tearDownClass(cls):
logging.info('Finalising FIRO Test')
logging.info("Finalising FIRO Test")
super(Test, cls).tearDownClass()
stopDaemons(cls.firo_daemons)
@ -184,163 +250,223 @@ class Test(BaseTest):
@classmethod
def addCoinSettings(cls, settings, datadir, node_id):
settings['chainclients']['firo'] = {
'connection_type': 'rpc',
'manage_daemon': False,
'rpcport': FIRO_BASE_RPC_PORT + node_id,
'rpcuser': 'test' + str(node_id),
'rpcpassword': 'test_pass' + str(node_id),
'datadir': os.path.join(datadir, 'firo_' + str(node_id)),
'bindir': FIRO_BINDIR,
'use_csv': False,
'use_segwit': False,
settings["chainclients"]["firo"] = {
"connection_type": "rpc",
"manage_daemon": False,
"rpcport": FIRO_BASE_RPC_PORT + node_id,
"rpcuser": "test" + str(node_id),
"rpcpassword": "test_pass" + str(node_id),
"datadir": os.path.join(datadir, "firo_" + str(node_id)),
"bindir": FIRO_BINDIR,
"use_csv": False,
"use_segwit": False,
}
@classmethod
def coins_loop(cls):
super(Test, cls).coins_loop()
callnoderpc(0, 'generatetoaddress', [1, cls.firo_addr], base_rpc_port=FIRO_BASE_RPC_PORT)
callnoderpc(
0, "generatetoaddress", [1, cls.firo_addr], base_rpc_port=FIRO_BASE_RPC_PORT
)
def getBalance(self, js_wallets):
return float(js_wallets[self.test_coin_from.name]['balance']) + float(js_wallets[self.test_coin_from.name]['unconfirmed'])
return float(js_wallets[self.test_coin_from.name]["balance"]) + float(
js_wallets[self.test_coin_from.name]["unconfirmed"]
)
def getXmrBalance(self, js_wallets):
return float(js_wallets[Coins.XMR.name]['unconfirmed']) + float(js_wallets[Coins.XMR.name]['balance'])
return float(js_wallets[Coins.XMR.name]["unconfirmed"]) + float(
js_wallets[Coins.XMR.name]["balance"]
)
def callnoderpc(self, method, params=[], wallet=None, node_id=0):
return callnoderpc(node_id, method, params, wallet, base_rpc_port=FIRO_BASE_RPC_PORT)
return callnoderpc(
node_id, method, params, wallet, base_rpc_port=FIRO_BASE_RPC_PORT
)
def mineBlock(self, num_blocks: int = 1):
self.callnoderpc('generatetoaddress', [num_blocks, self.firo_addr])
self.callnoderpc("generatetoaddress", [num_blocks, self.firo_addr])
def test_001_firo(self):
logging.info('---------- Test {} segwit'.format(self.test_coin_from.name))
logging.info("---------- Test {} segwit".format(self.test_coin_from.name))
'''
"""
Segwit is not currently enabled:
https://github.com/firoorg/firo/blob/master/src/validation.cpp#L4425
Txns spending segwit utxos don't get mined.
'''
"""
return
swap_clients = self.swap_clients
addr_plain = firoCli('getnewaddress \"segwit test\"')
addr_witness = firoCli(f'addwitnessaddress {addr_plain}')
addr_witness_info = firoCli(f'validateaddress {addr_witness}')
txid = firoCli(f'sendtoaddress {addr_witness} 1.0')
addr_plain = firoCli('getnewaddress "segwit test"')
addr_witness = firoCli(f"addwitnessaddress {addr_plain}")
addr_witness_info = firoCli(f"validateaddress {addr_witness}")
txid = firoCli(f"sendtoaddress {addr_witness} 1.0")
assert len(txid) == 64
self.callnoderpc('generatetoaddress', [1, self.firo_addr])
'''
self.callnoderpc("generatetoaddress", [1, self.firo_addr])
"""
TODO: Add back when segwit is active
ro = self.callnoderpc('scantxoutset', ['start', ['addr({})'.format(addr_witness)]])
assert (len(ro['unspents']) == 1)
assert (ro['unspents'][0]['txid'] == txid)
'''
"""
tx_wallet = firoCli(f'gettransaction {txid}')
tx_hex = tx_wallet['hex']
tx = firoCli(f'decoderawtransaction {tx_hex}')
tx_wallet = firoCli(f"gettransaction {txid}")
tx_hex = tx_wallet["hex"]
tx = firoCli(f"decoderawtransaction {tx_hex}")
prevout_n = -1
for txo in tx['vout']:
if addr_witness in txo['scriptPubKey']['addresses']:
prevout_n = txo['n']
for txo in tx["vout"]:
if addr_witness in txo["scriptPubKey"]["addresses"]:
prevout_n = txo["n"]
break
assert prevout_n > -1
tx_funded = firoCli(f'createrawtransaction [{{\\"txid\\":\\"{txid}\\",\\"vout\\":{prevout_n}}}] {{\\"{addr_plain}\\":0.99}}')
tx_signed = firoCli(f'signrawtransaction {tx_funded}')['hex']
tx_funded = firoCli(
f'createrawtransaction [{{\\"txid\\":\\"{txid}\\",\\"vout\\":{prevout_n}}}] {{\\"{addr_plain}\\":0.99}}'
)
tx_signed = firoCli(f"signrawtransaction {tx_funded}")["hex"]
# Add scriptsig for txids to match
decoded_tx = CTransaction()
decoded_tx = FromHex(decoded_tx, tx_funded)
decoded_tx.vin[0].scriptSig = bytes.fromhex('16' + addr_witness_info['hex'])
decoded_tx.vin[0].scriptSig = bytes.fromhex("16" + addr_witness_info["hex"])
decoded_tx.rehash()
txid_with_scriptsig = decoded_tx.hash
tx_funded_decoded = firoCli(f'decoderawtransaction {tx_funded}')
tx_signed_decoded = firoCli(f'decoderawtransaction {tx_signed}')
assert tx_funded_decoded['txid'] != tx_signed_decoded['txid']
assert txid_with_scriptsig == tx_signed_decoded['txid']
tx_funded_decoded = firoCli(f"decoderawtransaction {tx_funded}")
tx_signed_decoded = firoCli(f"decoderawtransaction {tx_signed}")
assert tx_funded_decoded["txid"] != tx_signed_decoded["txid"]
assert txid_with_scriptsig == tx_signed_decoded["txid"]
def test_007_hdwallet(self):
logging.info('---------- Test {} hdwallet'.format(self.test_coin_from.name))
logging.info("---------- Test {} hdwallet".format(self.test_coin_from.name))
swap_client = self.swap_clients[0]
# Run initialiseWallet to set 'main_wallet_seedid_'
swap_client.initialiseWallet(self.test_coin_from)
ci = swap_client.ci(self.test_coin_from)
assert ('490ba1e2c3894d5534c467141ee3cdf77292c362' == ci.getWalletSeedID())
assert "490ba1e2c3894d5534c467141ee3cdf77292c362" == ci.getWalletSeedID()
assert swap_client.checkWalletSeed(self.test_coin_from) is True
def test_008_gettxout(self):
logging.info('---------- Test {} gettxout'.format(self.test_coin_from.name))
logging.info("---------- Test {} gettxout".format(self.test_coin_from.name))
swap_client = self.swap_clients[0]
# First address sometimes has a balance already
addr_plain = self.callnoderpc('getnewaddress', ['gettxout test',])
_ = self.callnoderpc(
"getnewaddress",
[
"gettxout test",
],
)
addr_plain1 = self.callnoderpc('getnewaddress', ['gettxout test 1',])
addr_plain = self.callnoderpc(
"getnewaddress",
[
"gettxout test 1",
],
)
txid = self.callnoderpc('sendtoaddress', [addr_plain1, 1.0])
txid = self.callnoderpc("sendtoaddress", [addr_plain, 1.0])
assert len(txid) == 64
self.mineBlock()
unspents = self.callnoderpc('listunspent', [0, 999999999, [addr_plain1,]])
assert (len(unspents) == 1)
unspents = self.callnoderpc(
"listunspent",
[
0,
999999999,
[
addr_plain,
],
],
)
assert len(unspents) == 1
utxo = unspents[0]
txout = self.callnoderpc('gettxout', [utxo['txid'], utxo['vout']])
assert (addr_plain1 in txout['scriptPubKey']['addresses'])
txout = self.callnoderpc("gettxout", [utxo["txid"], utxo["vout"]])
assert addr_plain in txout["scriptPubKey"]["addresses"]
# Spend
addr_plain2 = self.callnoderpc('getnewaddress', ['gettxout test 2',])
tx_funded = self.callnoderpc('createrawtransaction', [[{'txid': utxo['txid'], 'vout': utxo['vout']}], {addr_plain2: 0.99}])
tx_signed = self.callnoderpc('signrawtransaction', [tx_funded,])['hex']
self.callnoderpc('sendrawtransaction', [tx_signed,])
addr_plain2 = self.callnoderpc(
"getnewaddress",
[
"gettxout test 2",
],
)
tx_funded = self.callnoderpc(
"createrawtransaction",
[[{"txid": utxo["txid"], "vout": utxo["vout"]}], {addr_plain2: 0.99}],
)
tx_signed = self.callnoderpc(
"signrawtransaction",
[
tx_funded,
],
)["hex"]
self.callnoderpc(
"sendrawtransaction",
[
tx_signed,
],
)
# utxo should be unavailable when spent in the mempool
txout = self.callnoderpc('gettxout', [utxo['txid'], utxo['vout']])
assert (txout is None)
txout = self.callnoderpc("gettxout", [utxo["txid"], utxo["vout"]])
assert txout is None
self.mineBlock()
ci = swap_client.ci(Coins.FIRO)
require_amount: int = ci.make_int(1)
funds_proof = ci.getProofOfFunds(require_amount, 'test'.encode('utf-8'))
funds_proof = ci.getProofOfFunds(require_amount, "test".encode("utf-8"))
amount_proved = ci.verifyProofOfFunds(funds_proof[0], funds_proof[1], funds_proof[2], 'test'.encode('utf-8'))
assert (amount_proved >= require_amount)
amount_proved = ci.verifyProofOfFunds(
funds_proof[0], funds_proof[1], funds_proof[2], "test".encode("utf-8")
)
assert amount_proved >= require_amount
def test_08_wallet(self):
logging.info('---------- Test {} wallet'.format(self.test_coin_from.name))
logging.info("---------- Test {} wallet".format(self.test_coin_from.name))
logging.info('Test withdrawal')
addr = self.callnoderpc('getnewaddress', ['Withdrawal test', ])
wallets = read_json_api(TEST_HTTP_PORT + 0, 'wallets')
assert (float(wallets[self.test_coin_from.name]['balance']) > 100)
logging.info("Test withdrawal")
addr = self.callnoderpc(
"getnewaddress",
[
"Withdrawal test",
],
)
wallets = read_json_api(TEST_HTTP_PORT + 0, "wallets")
assert float(wallets[self.test_coin_from.name]["balance"]) > 100
post_json = {
'value': 100,
'address': addr,
'subfee': False,
"value": 100,
"address": addr,
"subfee": False,
}
json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/{}/withdraw'.format(self.test_coin_from.name.lower()), post_json)
assert (len(json_rv['txid']) == 64)
json_rv = read_json_api(
TEST_HTTP_PORT + 0,
"wallets/{}/withdraw".format(self.test_coin_from.name.lower()),
post_json,
)
assert len(json_rv["txid"]) == 64
logging.info('Test createutxo')
logging.info("Test createutxo")
post_json = {
'value': 10,
"value": 10,
}
json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/{}/createutxo'.format(self.test_coin_from.name.lower()), post_json)
assert (len(json_rv['txid']) == 64)
json_rv = read_json_api(
TEST_HTTP_PORT + 0,
"wallets/{}/createutxo".format(self.test_coin_from.name.lower()),
post_json,
)
assert len(json_rv["txid"]) == 64
def test_11_xmrswap_to(self):
logging.info('---------- Test xmr swap protocol to')
logging.info("---------- Test xmr swap protocol to")
swap_clients = self.swap_clients
coin_from = Coins.BTC
@ -351,7 +477,9 @@ class Test(BaseTest):
swap_value = ci_from.make_int(random.uniform(0.2, 20.0), r=1)
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
offer_id = swap_clients[0].postOffer(coin_from, coin_to, swap_value, rate_swap, swap_value, swap_type)
offer_id = swap_clients[0].postOffer(
coin_from, coin_to, swap_value, rate_swap, swap_value, swap_type
)
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
offer = swap_clients[1].getOffer(offer_id)
@ -360,13 +488,30 @@ class Test(BaseTest):
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED)
swap_clients[0].acceptBid(bid_id)
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=120)
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=120)
wait_for_bid(
test_delay_event,
swap_clients[0],
bid_id,
BidStates.SWAP_COMPLETED,
wait_for=120,
)
wait_for_bid(
test_delay_event,
swap_clients[1],
bid_id,
BidStates.SWAP_COMPLETED,
sent=True,
wait_for=120,
)
def test_12_xmrswap_to_recover_b_lock_tx(self):
coin_from = Coins.BTC
coin_to = Coins.FIRO
logging.info('---------- Test {} to {} follower recovers coin b lock tx'.format(coin_from.name, coin_to.name))
logging.info(
"---------- Test {} to {} follower recovers coin b lock tx".format(
coin_from.name, coin_to.name
)
)
swap_clients = self.swap_clients
ci_from = swap_clients[0].ci(coin_from)
@ -375,8 +520,15 @@ class Test(BaseTest):
amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
offer_id = swap_clients[0].postOffer(
coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=32)
coin_from,
coin_to,
amt_swap,
rate_swap,
amt_swap,
SwapTypes.XMR_SWAP,
lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS,
lock_value=32,
)
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
offer = swap_clients[1].getOffer(offer_id)
@ -387,11 +539,23 @@ class Test(BaseTest):
swap_clients[1].setBidDebugInd(bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK)
swap_clients[0].acceptXmrBid(bid_id)
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=180)
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=True)
wait_for_bid(
test_delay_event,
swap_clients[0],
bid_id,
BidStates.XMR_SWAP_FAILED_REFUNDED,
wait_for=180,
)
wait_for_bid(
test_delay_event,
swap_clients[1],
bid_id,
BidStates.XMR_SWAP_FAILED_REFUNDED,
sent=True,
)
def test_13_adsswap_reverse(self):
logging.info('---------- Test ads swap protocol reverse')
logging.info("---------- Test ads swap protocol reverse")
swap_clients = self.swap_clients
coin_from = Coins.FIRO
@ -402,7 +566,9 @@ class Test(BaseTest):
swap_value = ci_from.make_int(random.uniform(0.2, 20.0), r=1)
rate_swap = ci_to.make_int(random.uniform(0.2, 10.0), r=1)
offer_id = swap_clients[0].postOffer(coin_from, coin_to, swap_value, rate_swap, swap_value, swap_type)
offer_id = swap_clients[0].postOffer(
coin_from, coin_to, swap_value, rate_swap, swap_value, swap_type
)
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
offer = swap_clients[1].getOffer(offer_id)
@ -411,28 +577,44 @@ class Test(BaseTest):
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED)
swap_clients[0].acceptBid(bid_id)
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=120)
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=120)
wait_for_bid(
test_delay_event,
swap_clients[0],
bid_id,
BidStates.SWAP_COMPLETED,
wait_for=120,
)
wait_for_bid(
test_delay_event,
swap_clients[1],
bid_id,
BidStates.SWAP_COMPLETED,
sent=True,
wait_for=120,
)
def test_101_full_swap(self):
logging.info('---------- Test {} to XMR'.format(self.test_coin_from.name))
logging.info("---------- Test {} to XMR".format(self.test_coin_from.name))
if not self.test_xmr:
logging.warning('Skipping test')
logging.warning("Skipping test")
return
swap_clients = self.swap_clients
js_0 = read_json_api(1800, 'wallets')
node0_from_before = self.getBalance(js_0)
js_1 = read_json_api(1801, 'wallets')
js_1 = read_json_api(1801, "wallets")
node1_from_before = self.getBalance(js_1)
js_0_xmr = read_json_api(1800, 'wallets/xmr')
js_1_xmr = read_json_api(1801, 'wallets/xmr')
js_1_xmr = read_json_api(1801, "wallets/xmr")
amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1)
rate_swap = make_int(random.uniform(0.2, 20.0), scale=12, r=1)
offer_id = swap_clients[0].postOffer(self.test_coin_from, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP)
offer_id = swap_clients[0].postOffer(
self.test_coin_from,
Coins.XMR,
amt_swap,
rate_swap,
amt_swap,
SwapTypes.XMR_SWAP,
)
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
offer = swap_clients[0].getOffer(offer_id)
@ -440,29 +622,42 @@ class Test(BaseTest):
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED)
swap_clients[0].acceptXmrBid(bid_id)
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180)
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True)
wait_for_bid(
test_delay_event,
swap_clients[0],
bid_id,
BidStates.SWAP_COMPLETED,
wait_for=180,
)
wait_for_bid(
test_delay_event,
swap_clients[1],
bid_id,
BidStates.SWAP_COMPLETED,
sent=True,
)
amount_from = float(format_amount(amt_swap, 8))
js_1 = read_json_api(1801, 'wallets')
js_1 = read_json_api(1801, "wallets")
node1_from_after = self.getBalance(js_1)
assert (node1_from_after > node1_from_before + (amount_from - 0.05))
assert node1_from_after > node1_from_before + (amount_from - 0.05)
js_0 = read_json_api(1800, 'wallets')
node0_from_after = self.getBalance(js_0)
# TODO: Discard block rewards
# js_0 = read_json_api(1800, 'wallets')
# node0_from_after = self.getBalance(js_0)
# assert (node0_from_after < node0_from_before - amount_from)
js_0_xmr_after = read_json_api(1800, 'wallets/xmr')
js_1_xmr_after = read_json_api(1801, 'wallets/xmr')
js_1_xmr_after = read_json_api(1801, "wallets/xmr")
scale_from = 8
amount_to = int((amt_swap * rate_swap) // (10 ** scale_from))
amount_to = int((amt_swap * rate_swap) // (10**scale_from))
amount_to_float = float(format_amount(amount_to, 12))
node1_xmr_after = float(js_1_xmr_after['unconfirmed']) + float(js_1_xmr_after['balance'])
node1_xmr_before = float(js_1_xmr['unconfirmed']) + float(js_1_xmr['balance'])
assert (node1_xmr_after > node1_xmr_before + (amount_to_float - 0.02))
node1_xmr_after = float(js_1_xmr_after["unconfirmed"]) + float(
js_1_xmr_after["balance"]
)
node1_xmr_before = float(js_1_xmr["unconfirmed"]) + float(js_1_xmr["balance"])
assert node1_xmr_after > node1_xmr_before + (amount_to_float - 0.02)
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

View file

@ -1,68 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# https://chromedriver.chromium.org/downloads
# 7z x chromedriver_linux64.zip
# sudo mv chromedriver /opt/chromedriver88
# Run test_xmr_persistent.py
# python tests/basicswap/extended/test_http_ui.py
import time
import logging
from urllib.parse import urljoin
from selenium import webdriver
from selenium.webdriver.support.ui import Select, WebDriverWait
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def run_test():
base_url = 'http://localhost:12701'
driver = webdriver.Chrome('/opt/chromedriver88')
driver.get(base_url)
link = driver.find_element_by_xpath('//a[@href="/offers"]')
num_offers_start = int(link.text.split(':')[1].strip())
logging.info('Offers: %d', num_offers_start)
logging.info('Creating offer')
driver.get(urljoin(base_url, 'newoffer'))
select_coin_from = Select(driver.find_element_by_name('coin_from'))
select_coin_from.select_by_visible_text('Particl')
select_coin_to = Select(driver.find_element_by_name('coin_to'))
select_coin_to.select_by_visible_text('Monero')
from_value = driver.find_element_by_name('amt_from')
from_value.send_keys('1')
to_value = driver.find_element_by_name('amt_to')
to_value.send_keys('2')
submit_button = driver.find_element_by_name('continue')
submit_button.click()
time.sleep(0.1)
submit_button = driver.find_element_by_name('check_offer')
submit_button.click()
time.sleep(0.1)
submit_button = driver.find_element_by_name('submit_offer')
submit_button.click()
time.sleep(0.1)
link = WebDriverWait(driver, 5).until(lambda d: d.find_element_by_xpath("//a[contains(@href, '/offer')]"))
offer_id = link.text.rsplit(' ', 1)[1]
logging.info('Offer ID: %s', offer_id)
driver.get(base_url)
link = driver.find_element_by_xpath('//a[@href="/offers"]')
num_offers_end = int(link.text.split(':')[1].strip())
assert num_offers_end == num_offers_start + 1
driver.quit()
if __name__ == '__main__':
run_test()

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2021 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -72,79 +73,90 @@ stop_test = False
def prepare_swapclient_dir(datadir, node_id, network_key, network_pubkey):
basicswap_dir = os.path.join(datadir, 'basicswap_' + str(node_id))
basicswap_dir = os.path.join(datadir, "basicswap_" + str(node_id))
if not os.path.exists(basicswap_dir):
os.makedirs(basicswap_dir)
settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
settings = {
'debug': True,
'p2p_host': '127.0.0.1',
'p2p_port': BASE_P2P_PORT + node_id,
'zmqhost': 'tcp://127.0.0.1',
'zmqport': BASE_ZMQ_PORT + node_id,
'htmlhost': '127.0.0.1',
'htmlport': TEST_HTTP_PORT + node_id,
'network_key': network_key,
'network_pubkey': network_pubkey,
'chainclients': {
'particl': {
'connection_type': 'rpc',
'manage_daemon': False,
'rpcport': BASE_RPC_PORT + node_id,
'rpcuser': 'test' + str(node_id),
'rpcpassword': 'test_pass' + str(node_id),
'datadir': os.path.join(datadir, 'part_' + str(node_id)),
'bindir': cfg.PARTICL_BINDIR,
'blocks_confirmed': 2, # Faster testing
"debug": True,
"p2p_host": "127.0.0.1",
"p2p_port": BASE_P2P_PORT + node_id,
"zmqhost": "tcp://127.0.0.1",
"zmqport": BASE_ZMQ_PORT + node_id,
"htmlhost": "127.0.0.1",
"htmlport": TEST_HTTP_PORT + node_id,
"network_key": network_key,
"network_pubkey": network_pubkey,
"chainclients": {
"particl": {
"connection_type": "rpc",
"manage_daemon": False,
"rpcport": BASE_RPC_PORT + node_id,
"rpcuser": "test" + str(node_id),
"rpcpassword": "test_pass" + str(node_id),
"datadir": os.path.join(datadir, "part_" + str(node_id)),
"bindir": cfg.PARTICL_BINDIR,
"blocks_confirmed": 2, # Faster testing
},
"bitcoin": {
"connection_type": "rpc",
"manage_daemon": False,
"rpcport": BTC_BASE_RPC_PORT + node_id,
"rpcuser": "test" + str(node_id),
"rpcpassword": "test_pass" + str(node_id),
"datadir": os.path.join(datadir, "btc_" + str(node_id)),
"bindir": cfg.BITCOIN_BINDIR,
"use_segwit": True,
},
'bitcoin': {
'connection_type': 'rpc',
'manage_daemon': False,
'rpcport': BTC_BASE_RPC_PORT + node_id,
'rpcuser': 'test' + str(node_id),
'rpcpassword': 'test_pass' + str(node_id),
'datadir': os.path.join(datadir, 'btc_' + str(node_id)),
'bindir': cfg.BITCOIN_BINDIR,
'use_segwit': True,
}
},
'check_progress_seconds': 2,
'check_watched_seconds': 4,
'check_expired_seconds': 60,
'check_events_seconds': 1,
'check_xmr_swaps_seconds': 1,
'min_delay_event': 1,
'max_delay_event': 5,
'min_delay_event_short': 1,
'max_delay_event_short': 5,
'min_delay_retry': 2,
'max_delay_retry': 10,
'restrict_unknown_seed_wallets': False
"check_progress_seconds": 2,
"check_watched_seconds": 4,
"check_expired_seconds": 60,
"check_events_seconds": 1,
"check_xmr_swaps_seconds": 1,
"min_delay_event": 1,
"max_delay_event": 5,
"min_delay_event_short": 1,
"max_delay_event_short": 5,
"min_delay_retry": 2,
"max_delay_retry": 10,
"restrict_unknown_seed_wallets": False,
}
with open(settings_path, 'w') as fp:
with open(settings_path, "w") as fp:
json.dump(settings, fp, indent=4)
def partRpc(cmd, node_id=0):
return callrpc_cli(cfg.PARTICL_BINDIR, os.path.join(TEST_DIR, 'part_' + str(node_id)), 'regtest', cmd, cfg.PARTICL_CLI)
return callrpc_cli(
cfg.PARTICL_BINDIR,
os.path.join(TEST_DIR, "part_" + str(node_id)),
"regtest",
cmd,
cfg.PARTICL_CLI,
)
def btcRpc(cmd, node_id=0):
return callrpc_cli(cfg.BITCOIN_BINDIR, os.path.join(TEST_DIR, 'btc_' + str(node_id)), 'regtest', cmd, cfg.BITCOIN_CLI)
return callrpc_cli(
cfg.BITCOIN_BINDIR,
os.path.join(TEST_DIR, "btc_" + str(node_id)),
"regtest",
cmd,
cfg.BITCOIN_CLI,
)
def signal_handler(sig, frame):
global stop_test
logging.info('signal {} detected.'.format(sig))
logging.info("signal {} detected.".format(sig))
stop_test = True
delay_event.set()
def callnoderpc(node_id, method, params=[], wallet=None, base_rpc_port=BASE_RPC_PORT):
auth = 'test{0}:test_pass{0}'.format(node_id)
auth = "test{0}:test_pass{0}".format(node_id)
return callrpc(base_rpc_port + node_id, auth, method, params, wallet)
@ -152,9 +164,9 @@ def run_coins_loop(cls):
while not stop_test:
try:
if cls.btc_addr is not None:
btcRpc('generatetoaddress 1 {}'.format(cls.btc_addr))
btcRpc("generatetoaddress 1 {}".format(cls.btc_addr))
except Exception as e:
logging.warning('run_coins_loop ' + str(e))
logging.warning("run_coins_loop " + str(e))
time.sleep(1.0)
@ -183,58 +195,122 @@ class Test(unittest.TestCase):
logger.propagate = False
logger.handlers = []
logger.setLevel(logging.INFO) # DEBUG shows many messages from requests.post
formatter = logging.Formatter('%(asctime)s %(levelname)s : %(message)s')
formatter = logging.Formatter("%(asctime)s %(levelname)s : %(message)s")
stream_stdout = logging.StreamHandler()
stream_stdout.setFormatter(formatter)
logger.addHandler(stream_stdout)
if os.path.isdir(TEST_DIR):
logging.info('Removing ' + TEST_DIR)
logging.info("Removing " + TEST_DIR)
shutil.rmtree(TEST_DIR)
if not os.path.exists(TEST_DIR):
os.makedirs(TEST_DIR)
cls.stream_fp = logging.FileHandler(os.path.join(TEST_DIR, 'test.log'))
cls.stream_fp = logging.FileHandler(os.path.join(TEST_DIR, "test.log"))
cls.stream_fp.setFormatter(formatter)
logger.addHandler(cls.stream_fp)
try:
logging.info('Preparing coin nodes.')
logging.info("Preparing coin nodes.")
for i in range(NUM_NODES):
data_dir = prepareDataDir(TEST_DIR, i, 'particl.conf', 'part_')
if os.path.exists(os.path.join(cfg.PARTICL_BINDIR, 'particl-wallet')):
callrpc_cli(cfg.PARTICL_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat -legacy create', 'particl-wallet')
data_dir = prepareDataDir(TEST_DIR, i, "particl.conf", "part_")
if os.path.exists(os.path.join(cfg.PARTICL_BINDIR, "particl-wallet")):
callrpc_cli(
cfg.PARTICL_BINDIR,
data_dir,
"regtest",
"-wallet=wallet.dat -legacy create",
"particl-wallet",
)
cls.part_daemons.append(startDaemon(os.path.join(TEST_DIR, 'part_' + str(i)), cfg.PARTICL_BINDIR, cfg.PARTICLD))
logging.info('Started %s %d', cfg.PARTICLD, cls.handle.part_daemons[-1].handle.pid)
cls.part_daemons.append(
startDaemon(
os.path.join(TEST_DIR, "part_" + str(i)),
cfg.PARTICL_BINDIR,
cfg.PARTICLD,
)
)
logging.info(
"Started %s %d",
cfg.PARTICLD,
cls.handle.part_daemons[-1].handle.pid,
)
for i in range(NUM_NODES):
# Load mnemonics after all nodes have started to avoid staking getting stuck in TryToSync
rpc = make_rpc_func(i)
waitForRPC(rpc, delay_event)
if i == 0:
rpc('extkeyimportmaster', ['abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb'])
rpc(
"extkeyimportmaster",
[
"abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb"
],
)
elif i == 1:
rpc('extkeyimportmaster', ['pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic', '', 'true'])
rpc('getnewextaddress', ['lblExtTest'])
rpc('rescanblockchain')
rpc(
"extkeyimportmaster",
[
"pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic",
"",
"true",
],
)
rpc("getnewextaddress", ["lblExtTest"])
rpc("rescanblockchain")
else:
rpc('extkeyimportmaster', [rpc('mnemonic', ['new'])['master']])
rpc("extkeyimportmaster", [rpc("mnemonic", ["new"])["master"]])
# Lower output split threshold for more stakeable outputs
rpc('walletsettings', ['stakingoptions', {'stakecombinethreshold': 100, 'stakesplitthreshold': 200}])
rpc('reservebalance', [False,])
rpc(
"walletsettings",
[
"stakingoptions",
{"stakecombinethreshold": 100, "stakesplitthreshold": 200},
],
)
rpc(
"reservebalance",
[
False,
],
)
for i in range(NUM_BTC_NODES):
data_dir = prepareDataDir(TEST_DIR, i, 'bitcoin.conf', 'btc_', base_p2p_port=BTC_BASE_PORT, base_rpc_port=BTC_BASE_RPC_PORT)
if os.path.exists(os.path.join(cfg.BITCOIN_BINDIR, 'bitcoin-wallet')):
callrpc_cli(cfg.BITCOIN_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat -legacy create', 'bitcoin-wallet')
data_dir = prepareDataDir(
TEST_DIR,
i,
"bitcoin.conf",
"btc_",
base_p2p_port=BTC_BASE_PORT,
base_rpc_port=BTC_BASE_RPC_PORT,
)
if os.path.exists(os.path.join(cfg.BITCOIN_BINDIR, "bitcoin-wallet")):
callrpc_cli(
cfg.BITCOIN_BINDIR,
data_dir,
"regtest",
"-wallet=wallet.dat -legacy create",
"bitcoin-wallet",
)
cls.btc_daemons.append(startDaemon(os.path.join(TEST_DIR, 'btc_' + str(i)), cfg.BITCOIN_BINDIR, cfg.BITCOIND))
logging.info('Started %s %d', cfg.BITCOIND, cls.handle.part_daemons[-1].handle.pid)
cls.btc_daemons.append(
startDaemon(
os.path.join(TEST_DIR, "btc_" + str(i)),
cfg.BITCOIN_BINDIR,
cfg.BITCOIND,
)
)
logging.info(
"Started %s %d",
cfg.BITCOIND,
cls.handle.part_daemons[-1].handle.pid,
)
waitForRPC(make_rpc_func(i, base_rpc_port=BTC_BASE_RPC_PORT), delay_event)
waitForRPC(
make_rpc_func(i, base_rpc_port=BTC_BASE_RPC_PORT), delay_event
)
logging.info('Preparing swap clients.')
logging.info("Preparing swap clients.")
eckey = ECKey()
eckey.generate()
cls.network_key = toWIF(PREFIX_SECRET_KEY_REGTEST, eckey.get_bytes())
@ -242,12 +318,20 @@ class Test(unittest.TestCase):
for i in range(NUM_NODES):
prepare_swapclient_dir(TEST_DIR, i, cls.network_key, cls.network_pubkey)
basicswap_dir = os.path.join(os.path.join(TEST_DIR, 'basicswap_' + str(i)))
basicswap_dir = os.path.join(
os.path.join(TEST_DIR, "basicswap_" + str(i))
)
settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
with open(settings_path) as fs:
settings = json.load(fs)
fp = open(os.path.join(basicswap_dir, 'basicswap.log'), 'w')
sc = BasicSwap(fp, basicswap_dir, settings, 'regtest', log_name='BasicSwap{}'.format(i))
fp = open(os.path.join(basicswap_dir, "basicswap.log"), "w")
sc = BasicSwap(
fp,
basicswap_dir,
settings,
"regtest",
log_name="BasicSwap{}".format(i),
)
cls.swap_clients.append(sc)
sc.setDaemonPID(Coins.BTC, cls.btc_daemons[i].handle.pid)
sc.setDaemonPID(Coins.PART, cls.part_daemons[i].handle.pid)
@ -257,41 +341,55 @@ class Test(unittest.TestCase):
cls.http_threads.append(t)
t.start()
cls.btc_addr = callnoderpc(0, 'getnewaddress', ['mining_addr', 'bech32'], base_rpc_port=BTC_BASE_RPC_PORT)
cls.btc_addr = callnoderpc(
0,
"getnewaddress",
["mining_addr", "bech32"],
base_rpc_port=BTC_BASE_RPC_PORT,
)
num_blocks = 500
logging.info('Mining %d Bitcoin blocks to %s', num_blocks, cls.btc_addr)
callnoderpc(0, 'generatetoaddress', [num_blocks, cls.btc_addr], base_rpc_port=BTC_BASE_RPC_PORT)
logging.info("Mining %d Bitcoin blocks to %s", num_blocks, cls.btc_addr)
callnoderpc(
0,
"generatetoaddress",
[num_blocks, cls.btc_addr],
base_rpc_port=BTC_BASE_RPC_PORT,
)
checkForks(callnoderpc(0, 'getblockchaininfo', base_rpc_port=BTC_BASE_RPC_PORT))
checkForks(
callnoderpc(0, "getblockchaininfo", base_rpc_port=BTC_BASE_RPC_PORT)
)
logging.info('Starting update thread.')
logging.info("Starting update thread.")
signal.signal(signal.SIGINT, signal_handler)
cls.update_thread = threading.Thread(target=run_loop, args=(cls,))
cls.update_thread.start()
cls.coins_update_thread = threading.Thread(target=run_coins_loop, args=(cls,))
cls.coins_update_thread = threading.Thread(
target=run_coins_loop, args=(cls,)
)
cls.coins_update_thread.start()
except Exception:
traceback.print_exc()
cls.tearDownClass()
raise ValueError('setUpClass() failed.')
raise ValueError("setUpClass() failed.")
@classmethod
def tearDownClass(cls):
global stop_test
logging.info('Finalising')
logging.info("Finalising")
stop_test = True
if cls.update_thread is not None:
try:
cls.update_thread.join()
except Exception:
logging.info('Failed to join update_thread')
logging.info("Failed to join update_thread")
if cls.coins_update_thread is not None:
try:
cls.coins_update_thread.join()
except Exception:
logging.info('Failed to join coins_update_thread')
logging.info("Failed to join coins_update_thread")
for t in cls.http_threads:
t.stop()
@ -313,39 +411,51 @@ class Test(unittest.TestCase):
def wait_for_num_nodes(self, port, expect_nodes, wait_for=20):
for i in range(wait_for):
if delay_event.is_set():
raise ValueError('Test stopped.')
js = read_json_api(port, 'network')
raise ValueError("Test stopped.")
js = read_json_api(port, "network")
num_nodes = 0
for p in js['peers']:
if p['ready'] is True:
for p in js["peers"]:
if p["ready"] is True:
num_nodes += 1
if num_nodes >= expect_nodes:
return True
delay_event.wait(1)
raise ValueError('wait_for_num_nodes timed out.')
raise ValueError("wait_for_num_nodes timed out.")
def test_01_network(self):
logging.info('---------- Test Network')
logging.info("---------- Test Network")
swap_clients = self.swap_clients
js_1 = read_json_api(1801, 'wallets')
swap_clients[0].postOffer(
Coins.PART,
Coins.BTC,
100 * COIN,
0.1 * COIN,
100 * COIN,
SwapTypes.SELLER_FIRST,
)
offer_id = swap_clients[0].postOffer(Coins.PART, Coins.BTC, 100 * COIN, 0.1 * COIN, 100 * COIN, SwapTypes.SELLER_FIRST)
swap_clients[1].add_connection('127.0.0.1', BASE_P2P_PORT + 0, swap_clients[0]._network._network_pubkey)
swap_clients[2].add_connection('127.0.0.1', BASE_P2P_PORT + 0, swap_clients[0]._network._network_pubkey)
swap_clients[1].add_connection(
"127.0.0.1", BASE_P2P_PORT + 0, swap_clients[0]._network._network_pubkey
)
swap_clients[2].add_connection(
"127.0.0.1", BASE_P2P_PORT + 0, swap_clients[0]._network._network_pubkey
)
self.wait_for_num_nodes(1800, 2)
js_n0 = read_json_api(1800, 'network')
js_n0 = read_json_api(1800, "network")
print(dumpj(js_n0))
path = [swap_clients[0]._network._network_pubkey, swap_clients[2]._network._network_pubkey]
path = [
swap_clients[0]._network._network_pubkey,
swap_clients[2]._network._network_pubkey,
]
swap_clients[1]._network.test_onion(path)
delay_for(delay_event, 1000)
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-2021 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -80,74 +81,74 @@ delay_event = threading.Event()
stop_test = False
def prepareOtherDir(datadir, nodeId, conf_file='namecoin.conf'):
def prepareOtherDir(datadir, nodeId, conf_file="namecoin.conf"):
node_dir = os.path.join(datadir, str(nodeId))
if not os.path.exists(node_dir):
os.makedirs(node_dir)
filePath = os.path.join(node_dir, conf_file)
with open(filePath, 'w+') as fp:
fp.write('regtest=1\n')
fp.write('[regtest]\n')
fp.write('port=' + str(BASE_PORT + nodeId) + '\n')
fp.write('rpcport=' + str(BASE_RPC_PORT + nodeId) + '\n')
with open(filePath, "w+") as fp:
fp.write("regtest=1\n")
fp.write("[regtest]\n")
fp.write("port=" + str(BASE_PORT + nodeId) + "\n")
fp.write("rpcport=" + str(BASE_RPC_PORT + nodeId) + "\n")
fp.write('daemon=0\n')
fp.write('printtoconsole=0\n')
fp.write('server=1\n')
fp.write('discover=0\n')
fp.write('listenonion=0\n')
fp.write('bind=127.0.0.1\n')
fp.write('findpeers=0\n')
fp.write('debug=1\n')
fp.write('debugexclude=libevent\n')
fp.write("daemon=0\n")
fp.write("printtoconsole=0\n")
fp.write("server=1\n")
fp.write("discover=0\n")
fp.write("listenonion=0\n")
fp.write("bind=127.0.0.1\n")
fp.write("findpeers=0\n")
fp.write("debug=1\n")
fp.write("debugexclude=libevent\n")
fp.write('fallbackfee=0.01\n')
fp.write('acceptnonstdtxn=0\n')
fp.write("fallbackfee=0.01\n")
fp.write("acceptnonstdtxn=0\n")
if conf_file == 'bitcoin.conf':
fp.write('wallet=wallet.dat\n')
if conf_file == "bitcoin.conf":
fp.write("wallet=wallet.dat\n")
def prepareDir(datadir, nodeId, network_key, network_pubkey):
node_dir = os.path.join(datadir, str(nodeId))
if not os.path.exists(node_dir):
os.makedirs(node_dir)
filePath = os.path.join(node_dir, 'particl.conf')
filePath = os.path.join(node_dir, "particl.conf")
with open(filePath, 'w+') as fp:
fp.write('regtest=1\n')
fp.write('[regtest]\n')
fp.write('port=' + str(BASE_PORT + nodeId) + '\n')
fp.write('rpcport=' + str(BASE_RPC_PORT + nodeId) + '\n')
with open(filePath, "w+") as fp:
fp.write("regtest=1\n")
fp.write("[regtest]\n")
fp.write("port=" + str(BASE_PORT + nodeId) + "\n")
fp.write("rpcport=" + str(BASE_RPC_PORT + nodeId) + "\n")
fp.write('daemon=0\n')
fp.write('printtoconsole=0\n')
fp.write('server=1\n')
fp.write('discover=0\n')
fp.write('listenonion=0\n')
fp.write('bind=127.0.0.1\n')
fp.write('findpeers=0\n')
fp.write('debug=1\n')
fp.write('debugexclude=libevent\n')
fp.write('zmqpubsmsg=tcp://127.0.0.1:' + str(BASE_ZMQ_PORT + nodeId) + '\n')
fp.write('wallet=wallet.dat\n')
fp.write('fallbackfee=0.01\n')
fp.write("daemon=0\n")
fp.write("printtoconsole=0\n")
fp.write("server=1\n")
fp.write("discover=0\n")
fp.write("listenonion=0\n")
fp.write("bind=127.0.0.1\n")
fp.write("findpeers=0\n")
fp.write("debug=1\n")
fp.write("debugexclude=libevent\n")
fp.write("zmqpubsmsg=tcp://127.0.0.1:" + str(BASE_ZMQ_PORT + nodeId) + "\n")
fp.write("wallet=wallet.dat\n")
fp.write("fallbackfee=0.01\n")
fp.write('acceptnonstdtxn=0\n')
fp.write('minstakeinterval=5\n')
fp.write('smsgsregtestadjust=0\n')
fp.write("acceptnonstdtxn=0\n")
fp.write("minstakeinterval=5\n")
fp.write("smsgsregtestadjust=0\n")
for i in range(0, NUM_NODES):
if nodeId == i:
continue
fp.write('addnode=127.0.0.1:%d\n' % (BASE_PORT + i))
fp.write("addnode=127.0.0.1:%d\n" % (BASE_PORT + i))
if nodeId < 2:
fp.write('spentindex=1\n')
fp.write('txindex=1\n')
fp.write("spentindex=1\n")
fp.write("txindex=1\n")
basicswap_dir = os.path.join(datadir, str(nodeId), 'basicswap')
basicswap_dir = os.path.join(datadir, str(nodeId), "basicswap")
if not os.path.exists(basicswap_dir):
os.makedirs(basicswap_dir)
@ -155,64 +156,82 @@ def prepareDir(datadir, nodeId, network_key, network_pubkey):
btcdatadir = os.path.join(datadir, str(BTC_NODE))
settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
settings = {
'debug': True,
'zmqhost': 'tcp://127.0.0.1',
'zmqport': BASE_ZMQ_PORT + nodeId,
'htmlhost': '127.0.0.1',
'htmlport': 12700 + nodeId,
'network_key': network_key,
'network_pubkey': network_pubkey,
'chainclients': {
'particl': {
'connection_type': 'rpc',
'manage_daemon': False,
'rpcport': BASE_RPC_PORT + nodeId,
'datadir': node_dir,
'bindir': cfg.PARTICL_BINDIR,
'blocks_confirmed': 2, # Faster testing
"debug": True,
"zmqhost": "tcp://127.0.0.1",
"zmqport": BASE_ZMQ_PORT + nodeId,
"htmlhost": "127.0.0.1",
"htmlport": 12700 + nodeId,
"network_key": network_key,
"network_pubkey": network_pubkey,
"chainclients": {
"particl": {
"connection_type": "rpc",
"manage_daemon": False,
"rpcport": BASE_RPC_PORT + nodeId,
"datadir": node_dir,
"bindir": cfg.PARTICL_BINDIR,
"blocks_confirmed": 2, # Faster testing
},
'namecoin': {
'connection_type': 'rpc',
'manage_daemon': False,
'rpcport': BASE_RPC_PORT + NMC_NODE,
'datadir': nmcdatadir,
'bindir': cfg.NAMECOIN_BINDIR,
'use_csv': False,
"namecoin": {
"connection_type": "rpc",
"manage_daemon": False,
"rpcport": BASE_RPC_PORT + NMC_NODE,
"datadir": nmcdatadir,
"bindir": cfg.NAMECOIN_BINDIR,
"use_csv": False,
# 'use_segwit': True,
},
'bitcoin': {
'connection_type': 'rpc',
'manage_daemon': False,
'rpcport': BASE_RPC_PORT + BTC_NODE,
'datadir': btcdatadir,
'bindir': cfg.BITCOIN_BINDIR,
'use_segwit': True,
}
"bitcoin": {
"connection_type": "rpc",
"manage_daemon": False,
"rpcport": BASE_RPC_PORT + BTC_NODE,
"datadir": btcdatadir,
"bindir": cfg.BITCOIN_BINDIR,
"use_segwit": True,
},
},
'check_progress_seconds': 2,
'check_watched_seconds': 4,
'check_expired_seconds': 60,
'restrict_unknown_seed_wallets': False,
"check_progress_seconds": 2,
"check_watched_seconds": 4,
"check_expired_seconds": 60,
"restrict_unknown_seed_wallets": False,
}
with open(settings_path, 'w') as fp:
with open(settings_path, "w") as fp:
json.dump(settings, fp, indent=4)
def partRpc(cmd, node_id=0):
return callrpc_cli(cfg.PARTICL_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(node_id)), 'regtest', cmd, cfg.PARTICL_CLI)
return callrpc_cli(
cfg.PARTICL_BINDIR,
os.path.join(cfg.TEST_DATADIRS, str(node_id)),
"regtest",
cmd,
cfg.PARTICL_CLI,
)
def btcRpc(cmd):
return callrpc_cli(cfg.BITCOIN_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)), 'regtest', cmd, cfg.BITCOIN_CLI)
return callrpc_cli(
cfg.BITCOIN_BINDIR,
os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)),
"regtest",
cmd,
cfg.BITCOIN_CLI,
)
def nmcRpc(cmd):
return callrpc_cli(cfg.NAMECOIN_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(NMC_NODE)), 'regtest', cmd, cfg.NAMECOIN_CLI)
return callrpc_cli(
cfg.NAMECOIN_BINDIR,
os.path.join(cfg.TEST_DATADIRS, str(NMC_NODE)),
"regtest",
cmd,
cfg.NAMECOIN_CLI,
)
def signal_handler(sig, frame):
global stop_test
print('signal {} detected.'.format(sig))
print("signal {} detected.".format(sig))
stop_test = True
delay_event.set()
@ -220,10 +239,10 @@ def signal_handler(sig, frame):
def run_coins_loop(cls):
while not stop_test:
try:
nmcRpc('generatetoaddress 1 {}'.format(cls.nmc_addr))
btcRpc('generatetoaddress 1 {}'.format(cls.btc_addr))
nmcRpc("generatetoaddress 1 {}".format(cls.nmc_addr))
btcRpc("generatetoaddress 1 {}".format(cls.btc_addr))
except Exception as e:
logging.warning('run_coins_loop ' + str(e))
logging.warning("run_coins_loop " + str(e))
time.sleep(1.0)
@ -244,6 +263,7 @@ def make_part_cli_rpc_func(node_id):
for p in params:
cmd += ' "' + p + '"'
return partRpc(cmd, node_id)
return rpc_func
@ -259,54 +279,96 @@ class Test(unittest.TestCase):
cls.network_pubkey = eckey.get_pubkey().get_bytes().hex()
if os.path.isdir(cfg.TEST_DATADIRS):
logging.info('Removing ' + cfg.TEST_DATADIRS)
logging.info("Removing " + cfg.TEST_DATADIRS)
shutil.rmtree(cfg.TEST_DATADIRS)
for i in range(NUM_NODES):
prepareDir(cfg.TEST_DATADIRS, i, cls.network_key, cls.network_pubkey)
prepareOtherDir(cfg.TEST_DATADIRS, NMC_NODE)
prepareOtherDir(cfg.TEST_DATADIRS, BTC_NODE, 'bitcoin.conf')
prepareOtherDir(cfg.TEST_DATADIRS, BTC_NODE, "bitcoin.conf")
cls.daemons = []
cls.swap_clients = []
cls.http_threads = []
btc_data_dir = os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE))
if os.path.exists(os.path.join(cfg.BITCOIN_BINDIR, 'bitcoin-wallet')):
callrpc_cli(cfg.BITCOIN_BINDIR, btc_data_dir, 'regtest', '-wallet=wallet.dat -legacy create', 'bitcoin-wallet')
if os.path.exists(os.path.join(cfg.BITCOIN_BINDIR, "bitcoin-wallet")):
callrpc_cli(
cfg.BITCOIN_BINDIR,
btc_data_dir,
"regtest",
"-wallet=wallet.dat -legacy create",
"bitcoin-wallet",
)
cls.daemons.append(startDaemon(btc_data_dir, cfg.BITCOIN_BINDIR, cfg.BITCOIND))
logging.info('Started %s %d', cfg.BITCOIND, cls.daemons[-1].handle.pid)
cls.daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, str(NMC_NODE)), cfg.NAMECOIN_BINDIR, cfg.NAMECOIND))
logging.info('Started %s %d', cfg.NAMECOIND, cls.daemons[-1].handle.pid)
logging.info("Started %s %d", cfg.BITCOIND, cls.daemons[-1].handle.pid)
cls.daemons.append(
startDaemon(
os.path.join(cfg.TEST_DATADIRS, str(NMC_NODE)),
cfg.NAMECOIN_BINDIR,
cfg.NAMECOIND,
)
)
logging.info("Started %s %d", cfg.NAMECOIND, cls.daemons[-1].handle.pid)
for i in range(NUM_NODES):
data_dir = os.path.join(cfg.TEST_DATADIRS, str(i))
if os.path.exists(os.path.join(cfg.PARTICL_BINDIR, 'particl-wallet')):
callrpc_cli(cfg.PARTICL_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat -legacy create', 'particl-wallet')
if os.path.exists(os.path.join(cfg.PARTICL_BINDIR, "particl-wallet")):
callrpc_cli(
cfg.PARTICL_BINDIR,
data_dir,
"regtest",
"-wallet=wallet.dat -legacy create",
"particl-wallet",
)
cls.daemons.append(startDaemon(data_dir, cfg.PARTICL_BINDIR, cfg.PARTICLD))
logging.info('Started %s %d', cfg.PARTICLD, cls.daemons[-1].handle.pid)
logging.info("Started %s %d", cfg.PARTICLD, cls.daemons[-1].handle.pid)
for i in range(NUM_NODES):
rpc = make_part_cli_rpc_func(i)
waitForRPC(rpc, delay_event)
if i == 0:
rpc('extkeyimportmaster', ['abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb'])
rpc(
"extkeyimportmaster",
[
"abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb"
],
)
elif i == 1:
rpc('extkeyimportmaster', ['pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic', '', 'true'])
rpc('getnewextaddress', ['lblExtTest'])
rpc('rescanblockchain')
rpc(
"extkeyimportmaster",
[
"pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic",
"",
"true",
],
)
rpc("getnewextaddress", ["lblExtTest"])
rpc("rescanblockchain")
else:
rpc('extkeyimportmaster', [rpc('mnemonic', ['new'])['master']])
rpc('walletsettings', ['stakingoptions', json.dumps({'stakecombinethreshold': 100, 'stakesplitthreshold': 200}).replace('"', '\\"')])
rpc('reservebalance', ['false'])
rpc("extkeyimportmaster", [rpc("mnemonic", ["new"])["master"]])
rpc(
"walletsettings",
[
"stakingoptions",
json.dumps(
{"stakecombinethreshold": 100, "stakesplitthreshold": 200}
).replace('"', '\\"'),
],
)
rpc("reservebalance", ["false"])
basicswap_dir = os.path.join(os.path.join(cfg.TEST_DATADIRS, str(i)), 'basicswap')
basicswap_dir = os.path.join(
os.path.join(cfg.TEST_DATADIRS, str(i)), "basicswap"
)
settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
with open(settings_path) as fs:
settings = json.load(fs)
fp = open(os.path.join(basicswap_dir, 'basicswap.log'), 'w')
sc = BasicSwap(fp, basicswap_dir, settings, 'regtest', log_name='BasicSwap{}'.format(i))
fp = open(os.path.join(basicswap_dir, "basicswap.log"), "w")
sc = BasicSwap(
fp, basicswap_dir, settings, "regtest", log_name="BasicSwap{}".format(i)
)
cls.swap_clients.append(sc)
sc.setDaemonPID(Coins.BTC, cls.daemons[0].handle.pid)
@ -320,30 +382,30 @@ class Test(unittest.TestCase):
waitForRPC(nmcRpc, delay_event)
num_blocks = 500
logging.info('Mining %d namecoin blocks', num_blocks)
cls.nmc_addr = nmcRpc('getnewaddress mining_addr legacy')
nmcRpc('generatetoaddress {} {}'.format(num_blocks, cls.nmc_addr))
logging.info("Mining %d namecoin blocks", num_blocks)
cls.nmc_addr = nmcRpc("getnewaddress mining_addr legacy")
nmcRpc("generatetoaddress {} {}".format(num_blocks, cls.nmc_addr))
ro = nmcRpc('getblockchaininfo')
ro = nmcRpc("getblockchaininfo")
try:
assert (ro['bip9_softforks']['csv']['status'] == 'active')
assert ro["bip9_softforks"]["csv"]["status"] == "active"
except Exception:
logging.info('nmc: csv is not active')
logging.info("nmc: csv is not active")
try:
assert (ro['bip9_softforks']['segwit']['status'] == 'active')
assert ro["bip9_softforks"]["segwit"]["status"] == "active"
except Exception:
logging.info('nmc: segwit is not active')
logging.info("nmc: segwit is not active")
waitForRPC(btcRpc, delay_event)
cls.btc_addr = btcRpc('getnewaddress mining_addr bech32')
logging.info('Mining %d Bitcoin blocks to %s', num_blocks, cls.btc_addr)
btcRpc('generatetoaddress {} {}'.format(num_blocks, cls.btc_addr))
cls.btc_addr = btcRpc("getnewaddress mining_addr bech32")
logging.info("Mining %d Bitcoin blocks to %s", num_blocks, cls.btc_addr)
btcRpc("generatetoaddress {} {}".format(num_blocks, cls.btc_addr))
ro = btcRpc('getblockchaininfo')
ro = btcRpc("getblockchaininfo")
checkForks(ro)
ro = nmcRpc('getwalletinfo')
print('nmcRpc', ro)
ro = nmcRpc("getwalletinfo")
print("nmcRpc", ro)
signal.signal(signal.SIGINT, signal_handler)
cls.update_thread = threading.Thread(target=run_loop, args=(cls,))
@ -354,19 +416,19 @@ class Test(unittest.TestCase):
# Wait for height, or sequencelock is thrown off by genesis blocktime
num_blocks = 3
logging.info('Waiting for Particl chain height %d', num_blocks)
logging.info("Waiting for Particl chain height %d", num_blocks)
for i in range(60):
particl_blocks = cls.swap_clients[0].callrpc('getblockcount')
print('particl_blocks', particl_blocks)
particl_blocks = cls.swap_clients[0].callrpc("getblockcount")
print("particl_blocks", particl_blocks)
if particl_blocks >= num_blocks:
break
delay_event.wait(1)
assert (particl_blocks >= num_blocks)
assert particl_blocks >= num_blocks
@classmethod
def tearDownClass(cls):
global stop_test
logging.info('Finalising')
logging.info("Finalising")
stop_test = True
cls.update_thread.join()
cls.coins_update_thread.join()
@ -385,10 +447,18 @@ class Test(unittest.TestCase):
super(Test, cls).tearDownClass()
def test_02_part_nmc(self):
logging.info('---------- Test PART to NMC')
logging.info("---------- Test PART to NMC")
swap_clients = self.swap_clients
offer_id = swap_clients[0].postOffer(Coins.PART, Coins.NMC, 100 * COIN, 0.1 * COIN, 100 * COIN, SwapTypes.SELLER_FIRST, TxLockTypes.ABS_LOCK_TIME)
offer_id = swap_clients[0].postOffer(
Coins.PART,
Coins.NMC,
100 * COIN,
0.1 * COIN,
100 * COIN,
SwapTypes.SELLER_FIRST,
TxLockTypes.ABS_LOCK_TIME,
)
wait_for_offer(delay_event, swap_clients[1], offer_id)
offer = swap_clients[1].getOffer(offer_id)
@ -400,19 +470,36 @@ class Test(unittest.TestCase):
wait_for_in_progress(delay_event, swap_clients[1], bid_id, sent=True)
wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60)
wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60)
wait_for_bid(
delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60
)
wait_for_bid(
delay_event,
swap_clients[1],
bid_id,
BidStates.SWAP_COMPLETED,
sent=True,
wait_for=60,
)
js_0 = read_json_api(1800)
js_1 = read_json_api(1801)
assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0)
assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0)
assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0
assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0
def test_03_nmc_part(self):
logging.info('---------- Test NMC to PART')
logging.info("---------- Test NMC to PART")
swap_clients = self.swap_clients
offer_id = swap_clients[1].postOffer(Coins.NMC, Coins.PART, 10 * COIN, 9.0 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST, TxLockTypes.ABS_LOCK_TIME)
offer_id = swap_clients[1].postOffer(
Coins.NMC,
Coins.PART,
10 * COIN,
9.0 * COIN,
10 * COIN,
SwapTypes.SELLER_FIRST,
TxLockTypes.ABS_LOCK_TIME,
)
wait_for_offer(delay_event, swap_clients[0], offer_id)
offer = swap_clients[0].getOffer(offer_id)
@ -423,19 +510,36 @@ class Test(unittest.TestCase):
wait_for_in_progress(delay_event, swap_clients[0], bid_id, sent=True)
wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60)
wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=60)
wait_for_bid(
delay_event,
swap_clients[0],
bid_id,
BidStates.SWAP_COMPLETED,
sent=True,
wait_for=60,
)
wait_for_bid(
delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=60
)
js_0 = read_json_api(1800)
js_1 = read_json_api(1801)
assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0)
assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0)
assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0
assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0
def test_04_nmc_btc(self):
logging.info('---------- Test NMC to BTC')
logging.info("---------- Test NMC to BTC")
swap_clients = self.swap_clients
offer_id = swap_clients[0].postOffer(Coins.NMC, Coins.BTC, 10 * COIN, 0.1 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST, TxLockTypes.ABS_LOCK_TIME)
offer_id = swap_clients[0].postOffer(
Coins.NMC,
Coins.BTC,
10 * COIN,
0.1 * COIN,
10 * COIN,
SwapTypes.SELLER_FIRST,
TxLockTypes.ABS_LOCK_TIME,
)
wait_for_offer(delay_event, swap_clients[1], offer_id)
offer = swap_clients[1].getOffer(offer_id)
@ -446,24 +550,39 @@ class Test(unittest.TestCase):
wait_for_in_progress(delay_event, swap_clients[1], bid_id, sent=True)
wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60)
wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60)
js_0bid = read_json_api(1800, 'bids/{}'.format(bid_id.hex()))
wait_for_bid(
delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60
)
wait_for_bid(
delay_event,
swap_clients[1],
bid_id,
BidStates.SWAP_COMPLETED,
sent=True,
wait_for=60,
)
js_0 = read_json_api(1800)
js_1 = read_json_api(1801)
assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0)
assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0)
assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0
assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0
def test_05_refund(self):
# Seller submits initiate txn, buyer doesn't respond
logging.info('---------- Test refund, NMC to BTC')
logging.info("---------- Test refund, NMC to BTC")
swap_clients = self.swap_clients
offer_id = swap_clients[0].postOffer(Coins.NMC, Coins.BTC, 10 * COIN, 0.1 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST,
TxLockTypes.ABS_LOCK_BLOCKS, 10)
offer_id = swap_clients[0].postOffer(
Coins.NMC,
Coins.BTC,
10 * COIN,
0.1 * COIN,
10 * COIN,
SwapTypes.SELLER_FIRST,
TxLockTypes.ABS_LOCK_BLOCKS,
10,
)
wait_for_offer(delay_event, swap_clients[1], offer_id)
offer = swap_clients[1].getOffer(offer_id)
@ -473,21 +592,38 @@ class Test(unittest.TestCase):
swap_clients[1].abandonBid(bid_id)
swap_clients[0].acceptBid(bid_id)
wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60)
wait_for_bid(delay_event, swap_clients[1], bid_id, BidStates.BID_ABANDONED, sent=True, wait_for=60)
wait_for_bid(
delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60
)
wait_for_bid(
delay_event,
swap_clients[1],
bid_id,
BidStates.BID_ABANDONED,
sent=True,
wait_for=60,
)
js_0 = read_json_api(1800)
js_1 = read_json_api(1801)
assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0)
assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0)
assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0
assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0
def test_06_self_bid(self):
logging.info('---------- Test same client, BTC to NMC')
logging.info("---------- Test same client, BTC to NMC")
swap_clients = self.swap_clients
js_0_before = read_json_api(1800)
offer_id = swap_clients[0].postOffer(Coins.NMC, Coins.BTC, 10 * COIN, 10 * COIN, 10 * COIN, SwapTypes.SELLER_FIRST, TxLockTypes.ABS_LOCK_TIME)
offer_id = swap_clients[0].postOffer(
Coins.NMC,
Coins.BTC,
10 * COIN,
10 * COIN,
10 * COIN,
SwapTypes.SELLER_FIRST,
TxLockTypes.ABS_LOCK_TIME,
)
wait_for_offer(delay_event, swap_clients[0], offer_id)
offer = swap_clients[0].getOffer(offer_id)
@ -496,20 +632,38 @@ class Test(unittest.TestCase):
wait_for_bid(delay_event, swap_clients[0], bid_id)
swap_clients[0].acceptBid(bid_id)
wait_for_bid_tx_state(delay_event, swap_clients[0], bid_id, TxStates.TX_REDEEMED, TxStates.TX_REDEEMED, wait_for=60)
wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60)
wait_for_bid_tx_state(
delay_event,
swap_clients[0],
bid_id,
TxStates.TX_REDEEMED,
TxStates.TX_REDEEMED,
wait_for=60,
)
wait_for_bid(
delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60
)
js_0 = read_json_api(1800)
assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0)
assert (js_0['num_recv_bids'] == js_0_before['num_recv_bids'] + 1 and js_0['num_sent_bids'] == js_0_before['num_sent_bids'] + 1)
assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0
assert (
js_0["num_recv_bids"] == js_0_before["num_recv_bids"] + 1
and js_0["num_sent_bids"] == js_0_before["num_sent_bids"] + 1
)
def test_07_error(self):
logging.info('---------- Test error, BTC to NMC, set fee above bid value')
logging.info("---------- Test error, BTC to NMC, set fee above bid value")
swap_clients = self.swap_clients
js_0_before = read_json_api(1800)
offer_id = swap_clients[0].postOffer(Coins.NMC, Coins.BTC, 0.001 * COIN, 1.0 * COIN, 0.001 * COIN, SwapTypes.SELLER_FIRST, TxLockTypes.ABS_LOCK_TIME)
offer_id = swap_clients[0].postOffer(
Coins.NMC,
Coins.BTC,
0.001 * COIN,
1.0 * COIN,
0.001 * COIN,
SwapTypes.SELLER_FIRST,
TxLockTypes.ABS_LOCK_TIME,
)
wait_for_offer(delay_event, swap_clients[0], offer_id)
offer = swap_clients[0].getOffer(offer_id)
@ -518,24 +672,26 @@ class Test(unittest.TestCase):
wait_for_bid(delay_event, swap_clients[0], bid_id)
swap_clients[0].acceptBid(bid_id)
try:
swap_clients[0].getChainClientSettings(Coins.BTC)['override_feerate'] = 10.0
swap_clients[0].getChainClientSettings(Coins.NMC)['override_feerate'] = 10.0
wait_for_bid(delay_event, swap_clients[0], bid_id, BidStates.BID_ERROR, wait_for=60)
swap_clients[0].getChainClientSettings(Coins.BTC)["override_feerate"] = 10.0
swap_clients[0].getChainClientSettings(Coins.NMC)["override_feerate"] = 10.0
wait_for_bid(
delay_event, swap_clients[0], bid_id, BidStates.BID_ERROR, wait_for=60
)
swap_clients[0].abandonBid(bid_id)
finally:
del swap_clients[0].getChainClientSettings(Coins.BTC)['override_feerate']
del swap_clients[0].getChainClientSettings(Coins.NMC)['override_feerate']
del swap_clients[0].getChainClientSettings(Coins.BTC)["override_feerate"]
del swap_clients[0].getChainClientSettings(Coins.NMC)["override_feerate"]
def pass_99_delay(self):
global stop_test
logging.info('Delay')
logging.info("Delay")
for i in range(60 * 5):
if stop_test:
break
time.sleep(1)
print('delay', i)
print("delay", i)
stop_test = True
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -23,11 +24,11 @@ from tests.basicswap.util import (
waitForServer,
)
bin_path = os.path.expanduser(os.getenv('TEST_BIN_PATH', ''))
test_base_path = os.path.expanduser(os.getenv('TEST_PREPARE_PATH', '~/test_basicswap'))
test_path_plain = os.path.join(test_base_path, 'plain')
test_path_encrypted = os.path.join(test_base_path, 'encrypted')
test_path_encrypt = os.path.join(test_base_path, 'encrypt')
bin_path = os.path.expanduser(os.getenv("TEST_BIN_PATH", ""))
test_base_path = os.path.expanduser(os.getenv("TEST_PREPARE_PATH", "~/test_basicswap"))
test_path_plain = os.path.join(test_base_path, "plain")
test_path_encrypted = os.path.join(test_base_path, "encrypted")
test_path_encrypt = os.path.join(test_base_path, "encrypt")
delay_event = threading.Event()
logger = logging.getLogger()
@ -40,7 +41,8 @@ def start_prepare(args, env_pairs=[]):
os.environ[pair[0]] = pair[1]
print(pair[0], os.environ[pair[0]])
import basicswap.bin.prepare as prepareSystemThread
with patch.object(sys, 'argv', args):
with patch.object(sys, "argv", args):
prepareSystemThread.main()
del prepareSystemThread
@ -50,7 +52,8 @@ def start_run(args, env_pairs=[]):
os.environ[pair[0]] = pair[1]
print(pair[0], os.environ[pair[0]])
import basicswap.bin.run as runSystemThread
with patch.object(sys, 'argv', args):
with patch.object(sys, "argv", args):
runSystemThread.main()
del runSystemThread
@ -63,17 +66,21 @@ class Test(unittest.TestCase):
if os.path.exists(test_dir):
shutil.rmtree(test_dir)
except Exception as ex:
logger.warning('tearDownClass %s', str(ex))
logger.warning("tearDownClass %s", str(ex))
super(Test, self).tearDownClass()
def test_plain(self):
if os.path.exists(test_path_plain):
shutil.rmtree(test_path_plain)
if bin_path != '':
if bin_path != "":
os.makedirs(test_path_plain)
os.symlink(bin_path, os.path.join(test_path_plain, 'bin'))
os.symlink(bin_path, os.path.join(test_path_plain, "bin"))
testargs = ('basicswap-prepare', '-datadir=' + test_path_plain, '-withcoin=litecoin')
testargs = (
"basicswap-prepare",
"-datadir=" + test_path_plain,
"-withcoin=litecoin",
)
process = multiprocessing.Process(target=start_prepare, args=(testargs,))
process.start()
process.join()
@ -82,50 +89,81 @@ class Test(unittest.TestCase):
self.assertTrue(os.path.exists(config_path))
import basicswap.bin.prepare as prepareSystem
try:
logging.info('Test no overwrite')
testargs = ['basicswap-prepare', '-datadir=' + test_path_plain, '-withcoin=litecoin']
with patch('sys.stderr', new=StringIO()) as fake_stderr:
with patch.object(sys, 'argv', testargs):
logging.info("Test no overwrite")
testargs = [
"basicswap-prepare",
"-datadir=" + test_path_plain,
"-withcoin=litecoin",
]
with patch("sys.stderr", new=StringIO()) as fake_stderr:
with patch.object(sys, "argv", testargs):
with self.assertRaises(SystemExit) as cm:
prepareSystem.main()
self.assertEqual(cm.exception.code, 1)
self.assertTrue('exists, exiting' in fake_stderr.getvalue())
self.assertTrue("exists, exiting" in fake_stderr.getvalue())
logger.info('Test addcoin new')
testargs = ['basicswap-prepare', '-datadir=' + test_path_plain, '-addcoin=namecoin']
with patch.object(sys, 'argv', testargs):
logger.info("Test addcoin new")
testargs = [
"basicswap-prepare",
"-datadir=" + test_path_plain,
"-addcoin=namecoin",
]
with patch.object(sys, "argv", testargs):
prepareSystem.main()
with open(config_path) as fs:
settings = json.load(fs)
self.assertTrue(settings['chainclients']['namecoin']['connection_type'] == 'rpc')
self.assertTrue(
settings["chainclients"]["namecoin"]["connection_type"] == "rpc"
)
logger.info('Test disablecoin')
testargs = ['basicswap-prepare', '-datadir=' + test_path_plain, '-disablecoin=namecoin']
with patch.object(sys, 'argv', testargs):
logger.info("Test disablecoin")
testargs = [
"basicswap-prepare",
"-datadir=" + test_path_plain,
"-disablecoin=namecoin",
]
with patch.object(sys, "argv", testargs):
prepareSystem.main()
with open(config_path) as fs:
settings = json.load(fs)
self.assertTrue(settings['chainclients']['namecoin']['connection_type'] == 'none')
self.assertTrue(
settings["chainclients"]["namecoin"]["connection_type"] == "none"
)
logger.info('Test addcoin existing')
testargs = ['basicswap-prepare', '-datadir=' + test_path_plain, '-addcoin=namecoin']
with patch.object(sys, 'argv', testargs):
logger.info("Test addcoin existing")
testargs = [
"basicswap-prepare",
"-datadir=" + test_path_plain,
"-addcoin=namecoin",
]
with patch.object(sys, "argv", testargs):
prepareSystem.main()
with open(config_path) as fs:
settings = json.load(fs)
self.assertTrue(settings['chainclients']['namecoin']['connection_type'] == 'rpc')
self.assertTrue(
settings["chainclients"]["namecoin"]["connection_type"] == "rpc"
)
logging.info('notorproxy')
testargs = ['basicswap-prepare', '-datadir=' + test_path_plain, '-addcoin=firo', '--usetorproxy', '--notorproxy']
with patch('sys.stderr', new=StringIO()) as fake_stderr:
with patch.object(sys, 'argv', testargs):
logging.info("notorproxy")
testargs = [
"basicswap-prepare",
"-datadir=" + test_path_plain,
"-addcoin=firo",
"--usetorproxy",
"--notorproxy",
]
with patch("sys.stderr", new=StringIO()) as fake_stderr:
with patch.object(sys, "argv", testargs):
with self.assertRaises(SystemExit) as cm:
prepareSystem.main()
self.assertEqual(cm.exception.code, 1)
self.assertTrue('--usetorproxy and --notorproxy together' in fake_stderr.getvalue())
self.assertTrue(
"--usetorproxy and --notorproxy together" in fake_stderr.getvalue()
)
finally:
del prepareSystem
@ -133,81 +171,114 @@ class Test(unittest.TestCase):
def test_encrypted(self):
if os.path.exists(test_path_encrypted):
shutil.rmtree(test_path_encrypted)
if bin_path != '':
if bin_path != "":
os.makedirs(test_path_encrypted)
os.symlink(bin_path, os.path.join(test_path_encrypted, 'bin'))
os.symlink(bin_path, os.path.join(test_path_encrypted, "bin"))
env_vars = [('WALLET_ENCRYPTION_PWD', 'test123'), ]
testargs = ('basicswap-prepare', '-datadir=' + test_path_encrypted, '-withcoin=litecoin,monero')
process = multiprocessing.Process(target=start_prepare, args=(testargs, env_vars))
env_vars = [
("WALLET_ENCRYPTION_PWD", "test123"),
]
testargs = (
"basicswap-prepare",
"-datadir=" + test_path_encrypted,
"-withcoin=litecoin,monero",
)
process = multiprocessing.Process(
target=start_prepare, args=(testargs, env_vars)
)
process.start()
process.join()
assert (process.exitcode == 0)
assert process.exitcode == 0
logger.info('Should not be able to add a coin without setting WALLET_ENCRYPTION_PWD')
testargs = ('basicswap-prepare', '-datadir=' + test_path_encrypted, '-addcoin=bitcoin')
logger.info(
"Should not be able to add a coin without setting WALLET_ENCRYPTION_PWD"
)
testargs = (
"basicswap-prepare",
"-datadir=" + test_path_encrypted,
"-addcoin=bitcoin",
)
process = multiprocessing.Process(target=start_prepare, args=(testargs, []))
process.start()
process.join()
assert (process.exitcode == 1)
assert process.exitcode == 1
testargs = ('basicswap-prepare', '-datadir=' + test_path_encrypted, '-addcoin=bitcoin')
process = multiprocessing.Process(target=start_prepare, args=(testargs, env_vars))
testargs = (
"basicswap-prepare",
"-datadir=" + test_path_encrypted,
"-addcoin=bitcoin",
)
process = multiprocessing.Process(
target=start_prepare, args=(testargs, env_vars)
)
process.start()
process.join()
assert (process.exitcode == 0)
assert process.exitcode == 0
def test_encrypt(self):
if os.path.exists(test_path_encrypt):
shutil.rmtree(test_path_encrypt)
if bin_path != '':
if bin_path != "":
os.makedirs(test_path_encrypt)
os.symlink(bin_path, os.path.join(test_path_encrypt, 'bin'))
os.symlink(bin_path, os.path.join(test_path_encrypt, "bin"))
testargs = ('basicswap-prepare', '-regtest=1', '-datadir=' + test_path_encrypt, '-withcoin=litecoin,monero')
process = multiprocessing.Process(target=start_prepare, args=(testargs, ))
testargs = (
"basicswap-prepare",
"-regtest=1",
"-datadir=" + test_path_encrypt,
"-withcoin=litecoin,monero",
)
process = multiprocessing.Process(target=start_prepare, args=(testargs,))
process.start()
process.join()
assert (process.exitcode == 0)
assert process.exitcode == 0
logger.info('basicswap-run should fail if WALLET_ENCRYPTION_PWD is set')
env_vars = [('WALLET_ENCRYPTION_PWD', 'test123'), ]
testargs = ('basicswap-run', '-regtest=1', '-datadir=' + test_path_encrypt)
logger.info("basicswap-run should fail if WALLET_ENCRYPTION_PWD is set")
env_vars = [
("WALLET_ENCRYPTION_PWD", "test123"),
]
testargs = ("basicswap-run", "-regtest=1", "-datadir=" + test_path_encrypt)
process = multiprocessing.Process(target=start_run, args=(testargs, env_vars))
process.start()
process.join()
assert (process.exitcode == 1)
assert process.exitcode == 1
testargs = ('basicswap-run', '-regtest=1', '-datadir=' + test_path_encrypt)
process = multiprocessing.Process(target=start_run, args=(testargs, ))
testargs = ("basicswap-run", "-regtest=1", "-datadir=" + test_path_encrypt)
process = multiprocessing.Process(target=start_run, args=(testargs,))
process.start()
waitForServer(delay_event, 12700)
rv = read_json_api(12700, 'setpassword', {'oldpassword': 'wrongpass', 'newpassword': 'test123'})
assert ('error' in rv)
rv = read_json_api(
12700, "setpassword", {"oldpassword": "wrongpass", "newpassword": "test123"}
)
assert "error" in rv
rv = read_json_api(12700, 'setpassword', {'oldpassword': '', 'newpassword': 'test123'})
assert ('success' in rv)
rv = read_json_api(
12700, "setpassword", {"oldpassword": "", "newpassword": "test123"}
)
assert "success" in rv
rv = read_json_api(12700, 'setpassword', {'oldpassword': 'test123', 'newpassword': 'next123'})
assert ('success' in rv)
rv = read_json_api(
12700, "setpassword", {"oldpassword": "test123", "newpassword": "next123"}
)
assert "success" in rv
rv = read_json_api(12700, 'lock')
assert ('success' in rv)
rv = read_json_api(12700, "lock")
assert "success" in rv
rv = read_json_api(12700, 'wallets')
assert ('error' in rv)
rv = read_json_api(12700, "wallets")
assert "error" in rv
rv = read_json_api(12700, 'unlock', {'password': 'next123'})
assert ('success' in rv)
rv = read_json_api(12700, "unlock", {"password": "next123"})
assert "success" in rv
rv = read_json_api(12700, 'wallets')
assert ('PART' in rv)
rv = read_json_api(12700, "wallets")
assert "PART" in rv
process.terminate()
process.join()
assert (process.exitcode == 0)
assert process.exitcode == 0
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2022 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -36,7 +37,7 @@ from tests.basicswap.common_xmr import (
)
import basicswap.bin.run as runSystem
TEST_PATH = os.path.expanduser(os.getenv('TEST_PATH', '~/test_basicswap1'))
TEST_PATH = os.path.expanduser(os.getenv("TEST_PATH", "~/test_basicswap1"))
logger = logging.getLogger()
logger.level = logging.DEBUG
@ -52,21 +53,21 @@ class Test(unittest.TestCase):
cls.delay_event = threading.Event()
# Load both wallets from the same mnemonic
bins_path = os.path.join(TEST_PATH, 'bin')
bins_path = os.path.join(TEST_PATH, "bin")
for i in range(2):
logging.info('Preparing node: %d.', i)
client_path = os.path.join(TEST_PATH, 'client{}'.format(i))
logging.info("Preparing node: %d.", i)
client_path = os.path.join(TEST_PATH, "client{}".format(i))
try:
shutil.rmtree(client_path)
except Exception as ex:
logging.warning('setUpClass %s', str(ex))
logging.warning("setUpClass %s", str(ex))
run_prepare(i, client_path, bins_path, 'monero,bitcoin', mnemonics[0])
run_prepare(i, client_path, bins_path, "monero,bitcoin", mnemonics[0])
def run_thread(self, client_id):
client_path = os.path.join(TEST_PATH, 'client{}'.format(client_id))
testargs = ['basicswap-run', '-datadir=' + client_path, '-regtest']
with patch.object(sys, 'argv', testargs):
client_path = os.path.join(TEST_PATH, "client{}".format(client_id))
testargs = ["basicswap-run", "-datadir=" + client_path, "-regtest"]
with patch.object(sys, "argv", testargs):
runSystem.main()
def test_wallet(self):
@ -81,20 +82,25 @@ class Test(unittest.TestCase):
try:
waitForServer(self.delay_event, 12700)
wallets_0 = read_json_api(12700, 'wallets')
assert (wallets_0['PART']['expected_seed'] is True)
assert (wallets_0['XMR']['expected_seed'] is True)
wallets_0 = read_json_api(12700, "wallets")
assert wallets_0["PART"]["expected_seed"] is True
assert wallets_0["XMR"]["expected_seed"] is True
waitForServer(self.delay_event, 12701)
wallets_1 = read_json_api(12701, 'wallets')
wallets_1 = read_json_api(12701, "wallets")
assert (wallets_0['PART']['expected_seed'] is True)
assert (wallets_1['XMR']['expected_seed'] is True)
assert wallets_0["PART"]["expected_seed"] is True
assert wallets_1["XMR"]["expected_seed"] is True
# TODO: Check other coins
assert (wallets_0['PART']['deposit_address'] == wallets_1['1']['deposit_address'])
assert (wallets_0['XMR']['deposit_address'] == wallets_1['6']['deposit_address'])
assert (
wallets_0["PART"]["deposit_address"]
== wallets_1["1"]["deposit_address"]
)
assert (
wallets_0["XMR"]["deposit_address"] == wallets_1["6"]["deposit_address"]
)
except Exception:
traceback.print_exc()
@ -106,5 +112,5 @@ class Test(unittest.TestCase):
p.join()
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -50,10 +51,10 @@ from tests.basicswap.common import (
LTC_BASE_RPC_PORT,
)
PORT_OFS = int(os.getenv('PORT_OFS', 1))
TEST_PATH = os.path.expanduser(os.getenv('TEST_PATH', '~/test_basicswap1'))
LITECOIN_RPC_PORT_BASE = int(os.getenv('LITECOIN_RPC_PORT_BASE', LTC_BASE_RPC_PORT))
BITCOIN_RPC_PORT_BASE = int(os.getenv('BITCOIN_RPC_PORT_BASE', BTC_BASE_RPC_PORT))
PORT_OFS = int(os.getenv("PORT_OFS", 1))
TEST_PATH = os.path.expanduser(os.getenv("TEST_PATH", "~/test_basicswap1"))
LITECOIN_RPC_PORT_BASE = int(os.getenv("LITECOIN_RPC_PORT_BASE", LTC_BASE_RPC_PORT))
BITCOIN_RPC_PORT_BASE = int(os.getenv("BITCOIN_RPC_PORT_BASE", BTC_BASE_RPC_PORT))
logger = logging.getLogger()
logger.level = logging.DEBUG
@ -61,32 +62,44 @@ if not len(logger.handlers):
logger.addHandler(logging.StreamHandler(sys.stdout))
def callbtcnoderpc(node_id, method, params=[], wallet=None, base_rpc_port=BITCOIN_RPC_PORT_BASE):
auth = 'test_btc_{0}:test_btc_pwd_{0}'.format(node_id)
def callbtcnoderpc(
node_id, method, params=[], wallet=None, base_rpc_port=BITCOIN_RPC_PORT_BASE
):
auth = "test_btc_{0}:test_btc_pwd_{0}".format(node_id)
return callrpc(base_rpc_port + node_id, auth, method, params, wallet)
def callltcnoderpc(node_id, method, params=[], wallet=None, base_rpc_port=LITECOIN_RPC_PORT_BASE):
auth = 'test_ltc_{0}:test_ltc_pwd_{0}'.format(node_id)
def callltcnoderpc(
node_id, method, params=[], wallet=None, base_rpc_port=LITECOIN_RPC_PORT_BASE
):
auth = "test_ltc_{0}:test_ltc_pwd_{0}".format(node_id)
return callrpc(base_rpc_port + node_id, auth, method, params, wallet)
def updateThread(self):
while not self.delay_event.is_set():
callbtcnoderpc(2, 'generatetoaddress', [1, self.btc_addr])
callltcnoderpc(1, 'generatetoaddress', [1, self.ltc_addr])
callbtcnoderpc(2, "generatetoaddress", [1, self.btc_addr])
callltcnoderpc(1, "generatetoaddress", [1, self.ltc_addr])
self.delay_event.wait(2)
def prepare_node(node_id, mnemonic):
logging.info('Preparing node: %d.', node_id)
bins_path = os.path.join(TEST_PATH, 'bin')
client_path = os.path.join(TEST_PATH, 'client{}'.format(node_id))
logging.info("Preparing node: %d.", node_id)
bins_path = os.path.join(TEST_PATH, "bin")
client_path = os.path.join(TEST_PATH, "client{}".format(node_id))
try:
shutil.rmtree(client_path)
except Exception as ex:
logging.warning('setUpClass %s', str(ex))
return run_prepare(node_id, client_path, bins_path, 'monero,bitcoin,litecoin', mnemonic, 3, use_rpcauth=True)
logging.warning("setUpClass %s", str(ex))
return run_prepare(
node_id,
client_path,
bins_path,
"monero,bitcoin,litecoin",
mnemonic,
3,
use_rpcauth=True,
)
class Test(TestBase):
@ -100,9 +113,9 @@ class Test(TestBase):
cls.used_mnemonics.append(prepare_node(i, mnemonics[0] if i == 0 else None))
def run_thread(self, client_id):
client_path = os.path.join(TEST_PATH, 'client{}'.format(client_id))
testargs = ['basicswap-run', '-datadir=' + client_path, '-regtest']
with patch.object(sys, 'argv', testargs):
client_path = os.path.join(TEST_PATH, "client{}".format(client_id))
testargs = ["basicswap-run", "-datadir=" + client_path, "-regtest"]
with patch.object(sys, "argv", testargs):
runSystem.main()
def finalise(self, processes):
@ -127,19 +140,25 @@ class Test(TestBase):
waitForServer(self.delay_event, 12702)
num_blocks = 500 # Mine enough to activate segwit
self.btc_addr = callbtcnoderpc(2, 'getnewaddress', ['mining_addr', 'bech32'])
logging.info('Mining %d Bitcoin blocks to %s', num_blocks, self.btc_addr)
callbtcnoderpc(2, 'generatetoaddress', [num_blocks, self.btc_addr])
self.btc_addr = callbtcnoderpc(
2, "getnewaddress", ["mining_addr", "bech32"]
)
logging.info("Mining %d Bitcoin blocks to %s", num_blocks, self.btc_addr)
callbtcnoderpc(2, "generatetoaddress", [num_blocks, self.btc_addr])
num_blocks = 431
self.ltc_addr = callltcnoderpc(1, 'getnewaddress', ['mining_addr', 'bech32'], wallet='wallet.dat')
logging.info('Mining %d Litecoin blocks to %s', num_blocks, self.ltc_addr)
callltcnoderpc(1, 'generatetoaddress', [num_blocks, self.ltc_addr])
self.ltc_addr = callltcnoderpc(
1, "getnewaddress", ["mining_addr", "bech32"], wallet="wallet.dat"
)
logging.info("Mining %d Litecoin blocks to %s", num_blocks, self.ltc_addr)
callltcnoderpc(1, "generatetoaddress", [num_blocks, self.ltc_addr])
mweb_addr = callltcnoderpc(1, 'getnewaddress', ['mweb_addr', 'mweb'], wallet='mweb')
callltcnoderpc(1, 'sendtoaddress', [mweb_addr, 1], wallet='wallet.dat')
mweb_addr = callltcnoderpc(
1, "getnewaddress", ["mweb_addr", "mweb"], wallet="mweb"
)
callltcnoderpc(1, "sendtoaddress", [mweb_addr, 1], wallet="wallet.dat")
num_blocks = 69
callltcnoderpc(1, 'generatetoaddress', [num_blocks, self.ltc_addr])
callltcnoderpc(1, "generatetoaddress", [num_blocks, self.ltc_addr])
self.update_thread = threading.Thread(target=updateThread, args=(self,))
self.update_thread.start()
@ -147,36 +166,35 @@ class Test(TestBase):
self.wait_for_particl_height(12701, num_blocks=3)
data = {
'addr_from': '-1',
'coin_from': 'part',
'coin_to': 'ltc',
'amt_from': '1',
'amt_to': '1',
'lockhrs': '24',
'automation_strat_id': 1}
"addr_from": "-1",
"coin_from": "part",
"coin_to": "ltc",
"amt_from": "1",
"amt_to": "1",
"lockhrs": "24",
"automation_strat_id": 1,
}
offer_id = post_json_api(12700, 'offers/new', data)['offer_id']
post_json_api(12700, "offers/new", data)["offer_id"]
summary = read_json_api(12700)
assert (summary['num_sent_offers'] == 1)
assert summary["num_sent_offers"] == 1
logger.info('Waiting for offer')
logger.info("Waiting for offer")
waitForNumOffers(self.delay_event, 12701, 1)
offers = read_json_api(12701, 'offers')
offers = read_json_api(12701, "offers")
offer = offers[0]
data = {
'offer_id': offer['offer_id'],
'amount_from': offer['amount_from']}
data = {"offer_id": offer["offer_id"], "amount_from": offer["amount_from"]}
bid_id = post_json_api(12701, 'bids/new', data)['bid_id']
bid_id = post_json_api(12701, "bids/new", data)["bid_id"]
waitForNumBids(self.delay_event, 12700, 1)
waitForBidState(self.delay_event, 12700, bid_id, 'Completed', wait_for=120)
waitForBidState(self.delay_event, 12701, bid_id, 'Completed', wait_for=120)
waitForBidState(self.delay_event, 12700, bid_id, "Completed", wait_for=120)
waitForBidState(self.delay_event, 12701, bid_id, "Completed", wait_for=120)
logging.info('Starting a new node on the same mnemonic as the first')
logging.info("Starting a new node on the same mnemonic as the first")
prepare_node(3, self.used_mnemonics[0])
processes.append(multiprocessing.Process(target=self.run_thread, args=(3,)))
processes[-1].start()
@ -186,30 +204,32 @@ class Test(TestBase):
# TODO: Attempt to detect past swaps
for coin in ('part', 'btc', 'ltc'):
logging.info(f'Checking {coin} balance')
original = read_json_api(12700, f'wallets/{coin}')
restored = read_json_api(12703, f'wallets/{coin}')
assert (float(original['balance']) + float(original['unconfirmed']) == float(restored['balance']) + float(restored['unconfirmed']))
for coin in ("part", "btc", "ltc"):
logging.info(f"Checking {coin} balance")
original = read_json_api(12700, f"wallets/{coin}")
restored = read_json_api(12703, f"wallets/{coin}")
assert float(original["balance"]) + float(
original["unconfirmed"]
) == float(restored["balance"]) + float(restored["unconfirmed"])
wallets_original = read_json_api(12700, 'wallets')
wallets_original = read_json_api(12700, "wallets")
# TODO: After restoring a new deposit address should be generated, should be automated
# Swaps should use a new key path, not the external path
next_addr = read_json_api(12700, 'wallets/part/nextdepositaddr')
next_addr = read_json_api(12703, 'wallets/part/nextdepositaddr')
wallets_restored = read_json_api(12703, 'wallets')
_ = read_json_api(12700, "wallets/part/nextdepositaddr")
_ = read_json_api(12703, "wallets/part/nextdepositaddr")
wallets_restored = read_json_api(12703, "wallets")
for k, w in wallets_original.items():
assert (w['deposit_address'] == wallets_restored[k]['deposit_address'])
assert w["deposit_address"] == wallets_restored[k]["deposit_address"]
except Exception as e:
traceback.print_exc()
self.finalise(processes)
logging.info('Test failed.')
logging.info("Test failed.")
raise e
self.finalise(processes)
logging.info('Test passed.')
logging.info("Test passed.")
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -30,9 +30,11 @@ from tests.basicswap.extended.test_dcr import (
NUM_NODES = 3
WOW_BINDIR = os.path.expanduser(os.getenv('WOW_BINDIR', os.path.join(cfg.DEFAULT_TEST_BINDIR, 'wownero')))
WOWD = os.getenv('WOWD', 'wownerod' + cfg.bin_suffix)
WOW_WALLET_RPC = os.getenv('WOW_WALLET', 'wownero-wallet-rpc' + cfg.bin_suffix)
WOW_BINDIR = os.path.expanduser(
os.getenv("WOW_BINDIR", os.path.join(cfg.DEFAULT_TEST_BINDIR, "wownero"))
)
WOWD = os.getenv("WOWD", "wownerod" + cfg.bin_suffix)
WOW_WALLET_RPC = os.getenv("WOW_WALLET", "wownero-wallet-rpc" + cfg.bin_suffix)
WOW_BASE_PORT = 54932
WOW_BASE_RPC_PORT = 55932
@ -41,45 +43,52 @@ WOW_BASE_ZMQ_PORT = 55972
def prepareWOWDataDir(datadir, node_id, conf_file):
node_dir = os.path.join(datadir, 'wow_' + str(node_id))
node_dir = os.path.join(datadir, "wow_" + str(node_id))
if not os.path.exists(node_dir):
os.makedirs(node_dir)
cfg_file_path = os.path.join(node_dir, conf_file)
if os.path.exists(cfg_file_path):
return
with open(cfg_file_path, 'w+') as fp:
fp.write('regtest=1\n')
fp.write('log-level=4\n')
fp.write('keep-fakechain=1\n')
fp.write('data-dir={}\n'.format(node_dir))
fp.write('fixed-difficulty=1\n')
fp.write('p2p-bind-port={}\n'.format(WOW_BASE_PORT + node_id))
fp.write('rpc-bind-port={}\n'.format(WOW_BASE_RPC_PORT + node_id))
fp.write('p2p-bind-ip=127.0.0.1\n')
fp.write('rpc-bind-ip=127.0.0.1\n')
fp.write('prune-blockchain=1\n')
fp.write('zmq-rpc-bind-port={}\n'.format(WOW_BASE_ZMQ_PORT + node_id))
fp.write('zmq-rpc-bind-ip=127.0.0.1\n')
with open(cfg_file_path, "w+") as fp:
fp.write("regtest=1\n")
fp.write("log-level=4\n")
fp.write("keep-fakechain=1\n")
fp.write("data-dir={}\n".format(node_dir))
fp.write("fixed-difficulty=1\n")
fp.write("p2p-bind-port={}\n".format(WOW_BASE_PORT + node_id))
fp.write("rpc-bind-port={}\n".format(WOW_BASE_RPC_PORT + node_id))
fp.write("p2p-bind-ip=127.0.0.1\n")
fp.write("rpc-bind-ip=127.0.0.1\n")
fp.write("prune-blockchain=1\n")
fp.write("zmq-rpc-bind-port={}\n".format(WOW_BASE_ZMQ_PORT + node_id))
fp.write("zmq-rpc-bind-ip=127.0.0.1\n")
for i in range(0, NUM_NODES):
if node_id == i:
continue
fp.write('add-exclusive-node=127.0.0.1:{}\n'.format(WOW_BASE_PORT + i))
fp.write("add-exclusive-node=127.0.0.1:{}\n".format(WOW_BASE_PORT + i))
def waitForWOWNode(rpc_offset, max_tries=7, auth=None):
for i in range(max_tries + 1):
try:
if auth is None:
callrpc_xmr(WOW_BASE_RPC_PORT + rpc_offset, 'get_block_count')
callrpc_xmr(WOW_BASE_RPC_PORT + rpc_offset, "get_block_count")
else:
callrpc_xmr(WOW_BASE_WALLET_RPC_PORT + rpc_offset, 'get_languages', auth=auth)
callrpc_xmr(
WOW_BASE_WALLET_RPC_PORT + rpc_offset, "get_languages", auth=auth
)
return
except Exception as ex:
if i < max_tries:
logging.warning('Can\'t connect to WOW%s RPC: %s. Retrying in %d second/s.', '' if auth is None else ' wallet', str(ex), (i + 1))
logging.warning(
"Can't connect to WOW%s RPC: %s. Retrying in %d second/s.",
"" if auth is None else " wallet",
str(ex),
(i + 1),
)
time.sleep(i + 1)
raise ValueError('waitForWOWNode failed')
raise ValueError("waitForWOWNode failed")
class Test(BaseTest):
@ -96,15 +105,22 @@ class Test(BaseTest):
def prepareExtraCoins(cls):
pass
num_blocks = 300
cls.wow_addr = cls.callwownodewallet(cls, 1, 'get_address')['address']
if callrpc_xmr(WOW_BASE_RPC_PORT + 1, 'get_block_count')['count'] < num_blocks:
logging.info('Mining %d Wownero blocks to %s.', num_blocks, cls.wow_addr)
callrpc_xmr(WOW_BASE_RPC_PORT + 1, 'generateblocks', {'wallet_address': cls.wow_addr, 'amount_of_blocks': num_blocks})
logging.info('WOW blocks: %d', callrpc_xmr(WOW_BASE_RPC_PORT + 1, 'get_block_count')['count'])
cls.wow_addr = cls.callwownodewallet(cls, 1, "get_address")["address"]
if callrpc_xmr(WOW_BASE_RPC_PORT + 1, "get_block_count")["count"] < num_blocks:
logging.info("Mining %d Wownero blocks to %s.", num_blocks, cls.wow_addr)
callrpc_xmr(
WOW_BASE_RPC_PORT + 1,
"generateblocks",
{"wallet_address": cls.wow_addr, "amount_of_blocks": num_blocks},
)
logging.info(
"WOW blocks: %d",
callrpc_xmr(WOW_BASE_RPC_PORT + 1, "get_block_count")["count"],
)
@classmethod
def tearDownClass(cls):
logging.info('Finalising Wownero Test')
logging.info("Finalising Wownero Test")
super(Test, cls).tearDownClass()
stopDaemons(cls.wow_daemons)
@ -115,38 +131,51 @@ class Test(BaseTest):
super(Test, cls).coins_loop()
if cls.wow_addr is not None:
callrpc_xmr(WOW_BASE_RPC_PORT + 0, 'generateblocks', {'wallet_address': cls.wow_addr, 'amount_of_blocks': 1})
callrpc_xmr(
WOW_BASE_RPC_PORT + 0,
"generateblocks",
{"wallet_address": cls.wow_addr, "amount_of_blocks": 1},
)
@classmethod
def prepareExtraDataDir(cls, i):
if not cls.restore_instance:
prepareWOWDataDir(cfg.TEST_DATADIRS, i, 'wownerod.conf')
prepareWOWDataDir(cfg.TEST_DATADIRS, i, "wownerod.conf")
node_dir = os.path.join(cfg.TEST_DATADIRS, 'wow_' + str(i))
node_dir = os.path.join(cfg.TEST_DATADIRS, "wow_" + str(i))
cls.wow_daemons.append(startXmrDaemon(node_dir, WOW_BINDIR, WOWD))
logging.info('Started %s %d', WOWD, cls.wow_daemons[-1].handle.pid)
logging.info("Started %s %d", WOWD, cls.wow_daemons[-1].handle.pid)
waitForWOWNode(i)
opts = [
'--daemon-address=127.0.0.1:{}'.format(WOW_BASE_RPC_PORT + i),
'--no-dns',
'--rpc-bind-port={}'.format(WOW_BASE_WALLET_RPC_PORT + i),
'--wallet-dir={}'.format(os.path.join(node_dir, 'wallets')),
'--log-file={}'.format(os.path.join(node_dir, 'wallet.log')),
'--rpc-login=test{0}:test_pass{0}'.format(i),
'--wow-shared-ringdb-dir={}'.format(os.path.join(node_dir, 'shared-ringdb')),
'--allow-mismatched-daemon-version',
"--daemon-address=127.0.0.1:{}".format(WOW_BASE_RPC_PORT + i),
"--no-dns",
"--rpc-bind-port={}".format(WOW_BASE_WALLET_RPC_PORT + i),
"--wallet-dir={}".format(os.path.join(node_dir, "wallets")),
"--log-file={}".format(os.path.join(node_dir, "wallet.log")),
"--rpc-login=test{0}:test_pass{0}".format(i),
"--wow-shared-ringdb-dir={}".format(
os.path.join(node_dir, "shared-ringdb")
),
"--allow-mismatched-daemon-version",
]
cls.wow_daemons.append(startXmrWalletDaemon(node_dir, WOW_BINDIR, WOW_WALLET_RPC, opts=opts))
cls.wow_daemons.append(
startXmrWalletDaemon(node_dir, WOW_BINDIR, WOW_WALLET_RPC, opts=opts)
)
cls.wow_wallet_auth.append(('test{0}'.format(i), 'test_pass{0}'.format(i)))
cls.wow_wallet_auth.append(("test{0}".format(i), "test_pass{0}".format(i)))
waitForWOWNode(i, auth=cls.wow_wallet_auth[i])
if not cls.restore_instance:
logging.info('Creating WOW wallet %i', i)
cls.callwownodewallet(cls, i, 'create_wallet', {'filename': 'testwallet', 'language': 'English'})
cls.callwownodewallet(cls, i, 'open_wallet', {'filename': 'testwallet'})
logging.info("Creating WOW wallet %i", i)
cls.callwownodewallet(
cls,
i,
"create_wallet",
{"filename": "testwallet", "language": "English"},
)
cls.callwownodewallet(cls, i, "open_wallet", {"filename": "testwallet"})
@classmethod
def addPIDInfo(cls, sc, i):
@ -154,20 +183,25 @@ class Test(BaseTest):
@classmethod
def addCoinSettings(cls, settings, datadir, node_id):
settings['chainclients']['wownero'] = {
'connection_type': 'rpc',
'manage_daemon': False,
'rpcport': WOW_BASE_RPC_PORT + node_id,
'walletrpcport': WOW_BASE_WALLET_RPC_PORT + node_id,
'walletrpcuser': 'test' + str(node_id),
'walletrpcpassword': 'test_pass' + str(node_id),
'walletfile': 'testwallet',
'datadir': os.path.join(datadir, 'xmr_' + str(node_id)),
'bindir': WOW_BINDIR,
settings["chainclients"]["wownero"] = {
"connection_type": "rpc",
"manage_daemon": False,
"rpcport": WOW_BASE_RPC_PORT + node_id,
"walletrpcport": WOW_BASE_WALLET_RPC_PORT + node_id,
"walletrpcuser": "test" + str(node_id),
"walletrpcpassword": "test_pass" + str(node_id),
"walletfile": "testwallet",
"datadir": os.path.join(datadir, "xmr_" + str(node_id)),
"bindir": WOW_BINDIR,
}
def callwownodewallet(self, node_id, method, params=None):
return callrpc_xmr(WOW_BASE_WALLET_RPC_PORT + node_id, method, params, auth=self.wow_wallet_auth[node_id])
return callrpc_xmr(
WOW_BASE_WALLET_RPC_PORT + node_id,
method,
params,
auth=self.wow_wallet_auth[node_id],
)
def test_01_ads_part_coin(self):
run_test_ads_success_path(self, Coins.PART, self.test_coin)

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021-2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -60,22 +61,24 @@ from basicswap.interface.dcr.rpc import callrpc as callrpc_dcr
import basicswap.bin.run as runSystem
test_path = os.path.expanduser(os.getenv('TEST_PATH', '/tmp/test_persistent'))
RESET_TEST = make_boolean(os.getenv('RESET_TEST', 'false'))
test_path = os.path.expanduser(os.getenv("TEST_PATH", "/tmp/test_persistent"))
RESET_TEST = make_boolean(os.getenv("RESET_TEST", "false"))
PORT_OFS = int(os.getenv('PORT_OFS', 1))
PORT_OFS = int(os.getenv("PORT_OFS", 1))
UI_PORT = 12700 + PORT_OFS
PARTICL_RPC_PORT_BASE = int(os.getenv('PARTICL_RPC_PORT_BASE', BASE_RPC_PORT))
BITCOIN_RPC_PORT_BASE = int(os.getenv('BITCOIN_RPC_PORT_BASE', BTC_BASE_RPC_PORT))
LITECOIN_RPC_PORT_BASE = int(os.getenv('LITECOIN_RPC_PORT_BASE', LTC_BASE_RPC_PORT))
BITCOINCASH_RPC_PORT_BASE = int(os.getenv('BITCOINCASH_RPC_PORT_BASE', BCH_BASE_RPC_PORT))
DECRED_WALLET_RPC_PORT_BASE = int(os.getenv('DECRED_WALLET_RPC_PORT_BASE', 9210))
XMR_BASE_RPC_PORT = int(os.getenv('XMR_BASE_RPC_PORT', XMR_BASE_RPC_PORT))
TEST_COINS_LIST = os.getenv('TEST_COINS_LIST', 'bitcoin,monero')
PARTICL_RPC_PORT_BASE = int(os.getenv("PARTICL_RPC_PORT_BASE", BASE_RPC_PORT))
BITCOIN_RPC_PORT_BASE = int(os.getenv("BITCOIN_RPC_PORT_BASE", BTC_BASE_RPC_PORT))
LITECOIN_RPC_PORT_BASE = int(os.getenv("LITECOIN_RPC_PORT_BASE", LTC_BASE_RPC_PORT))
BITCOINCASH_RPC_PORT_BASE = int(
os.getenv("BITCOINCASH_RPC_PORT_BASE", BCH_BASE_RPC_PORT)
)
DECRED_WALLET_RPC_PORT_BASE = int(os.getenv("DECRED_WALLET_RPC_PORT_BASE", 9210))
XMR_BASE_RPC_PORT = int(os.getenv("XMR_BASE_RPC_PORT", XMR_BASE_RPC_PORT))
TEST_COINS_LIST = os.getenv("TEST_COINS_LIST", "bitcoin,monero")
NUM_NODES = int(os.getenv('NUM_NODES', 3))
EXTRA_CONFIG_JSON = json.loads(os.getenv('EXTRA_CONFIG_JSON', '{}'))
NUM_NODES = int(os.getenv("NUM_NODES", 3))
EXTRA_CONFIG_JSON = json.loads(os.getenv("EXTRA_CONFIG_JSON", "{}"))
logger = logging.getLogger()
logger.level = logging.DEBUG
@ -83,28 +86,54 @@ if not len(logger.handlers):
logger.addHandler(logging.StreamHandler(sys.stdout))
def callpartrpc(node_id, method, params=[], wallet=None, base_rpc_port=PARTICL_RPC_PORT_BASE + PORT_OFS):
auth = 'test_part_{0}:test_part_pwd_{0}'.format(node_id)
def callpartrpc(
node_id,
method,
params=[],
wallet=None,
base_rpc_port=PARTICL_RPC_PORT_BASE + PORT_OFS,
):
auth = "test_part_{0}:test_part_pwd_{0}".format(node_id)
return callrpc(base_rpc_port + node_id, auth, method, params, wallet)
def callbtcrpc(node_id, method, params=[], wallet=None, base_rpc_port=BITCOIN_RPC_PORT_BASE + PORT_OFS):
auth = 'test_btc_{0}:test_btc_pwd_{0}'.format(node_id)
def callbtcrpc(
node_id,
method,
params=[],
wallet=None,
base_rpc_port=BITCOIN_RPC_PORT_BASE + PORT_OFS,
):
auth = "test_btc_{0}:test_btc_pwd_{0}".format(node_id)
return callrpc(base_rpc_port + node_id, auth, method, params, wallet)
def callltcrpc(node_id, method, params=[], wallet=None, base_rpc_port=LITECOIN_RPC_PORT_BASE + PORT_OFS):
auth = 'test_ltc_{0}:test_ltc_pwd_{0}'.format(node_id)
def callltcrpc(
node_id,
method,
params=[],
wallet=None,
base_rpc_port=LITECOIN_RPC_PORT_BASE + PORT_OFS,
):
auth = "test_ltc_{0}:test_ltc_pwd_{0}".format(node_id)
return callrpc(base_rpc_port + node_id, auth, method, params, wallet)
def calldcrrpc(node_id, method, params=[], wallet=None, base_rpc_port=DECRED_WALLET_RPC_PORT_BASE):
auth = 'user:dcr_pwd'
def calldcrrpc(
node_id, method, params=[], wallet=None, base_rpc_port=DECRED_WALLET_RPC_PORT_BASE
):
auth = "user:dcr_pwd"
return callrpc_dcr(base_rpc_port + node_id, auth, method, params)
def callbchrpc(node_id, method, params=[], wallet=None, base_rpc_port=BITCOINCASH_RPC_PORT_BASE + PORT_OFS):
auth = 'test_bch_{0}:test_bch_pwd_{0}'.format(node_id)
def callbchrpc(
node_id,
method,
params=[],
wallet=None,
base_rpc_port=BITCOINCASH_RPC_PORT_BASE + PORT_OFS,
):
auth = "test_bch_{0}:test_bch_pwd_{0}".format(node_id)
return callrpc(base_rpc_port + node_id, auth, method, params, wallet)
@ -112,27 +141,32 @@ def updateThread(cls):
while not cls.delay_event.is_set():
try:
if cls.btc_addr is not None:
callbtcrpc(0, 'generatetoaddress', [1, cls.btc_addr])
callbtcrpc(0, "generatetoaddress", [1, cls.btc_addr])
if cls.ltc_addr is not None:
callltcrpc(0, 'generatetoaddress', [1, cls.ltc_addr])
callltcrpc(0, "generatetoaddress", [1, cls.ltc_addr])
if cls.bch_addr is not None:
callbchrpc(0, 'generatetoaddress', [1, cls.bch_addr])
callbchrpc(0, "generatetoaddress", [1, cls.bch_addr])
except Exception as e:
print('updateThread error', str(e))
print("updateThread error", str(e))
cls.delay_event.wait(random.randrange(cls.update_min, cls.update_max))
def updateThreadXMR(cls):
xmr_auth = None
if os.getenv('XMR_RPC_USER', '') != '':
xmr_auth = (os.getenv('XMR_RPC_USER', ''), os.getenv('XMR_RPC_PWD', ''))
if os.getenv("XMR_RPC_USER", "") != "":
xmr_auth = (os.getenv("XMR_RPC_USER", ""), os.getenv("XMR_RPC_PWD", ""))
while not cls.delay_event.is_set():
try:
if cls.xmr_addr is not None:
callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'generateblocks', {'wallet_address': cls.xmr_addr, 'amount_of_blocks': 1}, auth=xmr_auth)
callrpc_xmr(
XMR_BASE_RPC_PORT + 1,
"generateblocks",
{"wallet_address": cls.xmr_addr, "amount_of_blocks": 1},
auth=xmr_auth,
)
except Exception as e:
print('updateThreadXMR error', str(e))
print("updateThreadXMR error", str(e))
cls.delay_event.wait(random.randrange(cls.xmr_update_min, cls.xmr_update_max))
@ -143,24 +177,30 @@ def updateThreadDCR(cls):
num_passed: int = 0
for i in range(30):
try:
calldcrrpc(0, 'purchaseticket', [cls.dcr_acc, 0.1, 0])
calldcrrpc(0, "purchaseticket", [cls.dcr_acc, 0.1, 0])
num_passed += 1
if num_passed >= 5:
break
cls.delay_event.wait(0.1)
except Exception as e:
if 'double spend' in str(e):
if "double spend" in str(e):
pass
else:
logging.warning('updateThreadDCR purchaseticket {}'.format(e))
logging.warning("updateThreadDCR purchaseticket {}".format(e))
cls.delay_event.wait(0.5)
try:
if num_passed >= 5:
calldcrrpc(0, 'generate', [1,])
calldcrrpc(
0,
"generate",
[
1,
],
)
except Exception as e:
logging.warning('updateThreadDCR generate {}'.format(e))
logging.warning("updateThreadDCR generate {}".format(e))
except Exception as e:
print('updateThreadDCR error', str(e))
print("updateThreadDCR error", str(e))
cls.delay_event.wait(random.randrange(cls.dcr_update_min, cls.dcr_update_max))
@ -169,13 +209,13 @@ class Test(unittest.TestCase):
def setUpClass(cls):
super(Test, cls).setUpClass()
cls.update_min = int(os.getenv('UPDATE_THREAD_MIN_WAIT', '1'))
cls.update_min = int(os.getenv("UPDATE_THREAD_MIN_WAIT", "1"))
cls.update_max = cls.update_min * 4
cls.xmr_update_min = int(os.getenv('XMR_UPDATE_THREAD_MIN_WAIT', '1'))
cls.xmr_update_min = int(os.getenv("XMR_UPDATE_THREAD_MIN_WAIT", "1"))
cls.xmr_update_max = cls.xmr_update_min * 4
cls.dcr_update_min = int(os.getenv('DCR_UPDATE_THREAD_MIN_WAIT', '1'))
cls.dcr_update_min = int(os.getenv("DCR_UPDATE_THREAD_MIN_WAIT", "1"))
cls.dcr_update_max = cls.dcr_update_min * 4
cls.delay_event = threading.Event()
@ -187,100 +227,181 @@ class Test(unittest.TestCase):
cls.ltc_addr = None
cls.bch_addr = None
cls.xmr_addr = None
cls.dcr_addr = 'SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH'
cls.dcr_addr = "SsYbXyjkKAEXXcGdFgr4u4bo4L8RkCxwQpH"
cls.dcr_acc = None
random.seed(time.time())
if os.path.exists(test_path) and not RESET_TEST:
logging.info(f'Continuing with existing directory: {test_path}')
logging.info(f"Continuing with existing directory: {test_path}")
else:
logging.info('Preparing %d nodes.', NUM_NODES)
prepare_nodes(NUM_NODES, TEST_COINS_LIST, True, {'min_sequence_lock_seconds': 60}, PORT_OFS)
logging.info("Preparing %d nodes.", NUM_NODES)
prepare_nodes(
NUM_NODES,
TEST_COINS_LIST,
True,
{"min_sequence_lock_seconds": 60},
PORT_OFS,
)
signal.signal(signal.SIGINT, lambda signal, frame: cls.signal_handler(cls, signal, frame))
signal.signal(
signal.SIGINT, lambda signal, frame: cls.signal_handler(cls, signal, frame)
)
def signal_handler(self, sig, frame):
logging.info('signal {} detected.'.format(sig))
logging.info("signal {} detected.".format(sig))
self.delay_event.set()
def run_thread(self, client_id):
client_path = os.path.join(test_path, 'client{}'.format(client_id))
testargs = ['basicswap-run', '-datadir=' + client_path, '-regtest']
with patch.object(sys, 'argv', testargs):
client_path = os.path.join(test_path, "client{}".format(client_id))
testargs = ["basicswap-run", "-datadir=" + client_path, "-regtest"]
with patch.object(sys, "argv", testargs):
runSystem.main()
def start_processes(self):
self.delay_event.clear()
for i in range(NUM_NODES):
self.processes.append(multiprocessing.Process(target=self.run_thread, args=(i,)))
self.processes.append(
multiprocessing.Process(target=self.run_thread, args=(i,))
)
self.processes[-1].start()
for i in range(NUM_NODES):
waitForServer(self.delay_event, UI_PORT + i)
wallets = read_json_api(UI_PORT + 1, 'wallets')
wallets = read_json_api(UI_PORT + 1, "wallets")
xmr_auth = None
if os.getenv('XMR_RPC_USER', '') != '':
xmr_auth = (os.getenv('XMR_RPC_USER', ''), os.getenv('XMR_RPC_PWD', ''))
if os.getenv("XMR_RPC_USER", "") != "":
xmr_auth = (os.getenv("XMR_RPC_USER", ""), os.getenv("XMR_RPC_PWD", ""))
self.xmr_addr = wallets['XMR']['main_address']
self.xmr_addr = wallets["XMR"]["main_address"]
num_blocks = 100
if callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'get_block_count', auth=xmr_auth)['count'] < num_blocks:
logging.info('Mining {} Monero blocks to {}.'.format(num_blocks, self.xmr_addr))
callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'generateblocks', {'wallet_address': self.xmr_addr, 'amount_of_blocks': num_blocks}, auth=xmr_auth)
logging.info('XMR blocks: %d', callrpc_xmr(XMR_BASE_RPC_PORT + 1, 'get_block_count', auth=xmr_auth)['count'])
if (
callrpc_xmr(XMR_BASE_RPC_PORT + 1, "get_block_count", auth=xmr_auth)[
"count"
]
< num_blocks
):
logging.info(
"Mining {} Monero blocks to {}.".format(num_blocks, self.xmr_addr)
)
callrpc_xmr(
XMR_BASE_RPC_PORT + 1,
"generateblocks",
{"wallet_address": self.xmr_addr, "amount_of_blocks": num_blocks},
auth=xmr_auth,
)
logging.info(
"XMR blocks: %d",
callrpc_xmr(XMR_BASE_RPC_PORT + 1, "get_block_count", auth=xmr_auth)[
"count"
],
)
self.btc_addr = callbtcrpc(0, 'getnewaddress', ['mining_addr', 'bech32'])
self.btc_addr = callbtcrpc(0, "getnewaddress", ["mining_addr", "bech32"])
num_blocks: int = 500 # Mine enough to activate segwit
if callbtcrpc(0, 'getblockcount') < num_blocks:
logging.info('Mining %d Bitcoin blocks to %s', num_blocks, self.btc_addr)
callbtcrpc(0, 'generatetoaddress', [num_blocks, self.btc_addr])
logging.info('BTC blocks: %d', callbtcrpc(0, 'getblockcount'))
if callbtcrpc(0, "getblockcount") < num_blocks:
logging.info("Mining %d Bitcoin blocks to %s", num_blocks, self.btc_addr)
callbtcrpc(0, "generatetoaddress", [num_blocks, self.btc_addr])
logging.info("BTC blocks: %d", callbtcrpc(0, "getblockcount"))
if 'litecoin' in TEST_COINS_LIST:
self.ltc_addr = callltcrpc(0, 'getnewaddress', ['mining_addr'], wallet='wallet.dat')
if "litecoin" in TEST_COINS_LIST:
self.ltc_addr = callltcrpc(
0, "getnewaddress", ["mining_addr"], wallet="wallet.dat"
)
num_blocks: int = 431
have_blocks: int = callltcrpc(0, 'getblockcount')
have_blocks: int = callltcrpc(0, "getblockcount")
if have_blocks < 500:
logging.info('Mining %d Litecoin blocks to %s', num_blocks, self.ltc_addr)
callltcrpc(0, 'generatetoaddress', [num_blocks - have_blocks, self.ltc_addr], wallet='wallet.dat')
logging.info(
"Mining %d Litecoin blocks to %s", num_blocks, self.ltc_addr
)
callltcrpc(
0,
"generatetoaddress",
[num_blocks - have_blocks, self.ltc_addr],
wallet="wallet.dat",
)
# https://github.com/litecoin-project/litecoin/issues/807
# Block 432 is when MWEB activates. It requires a peg-in. You'll need to generate an mweb address and send some coins to it. Then it will allow you to mine the next block.
mweb_addr = callltcrpc(0, 'getnewaddress', ['mweb_addr', 'mweb'], wallet='mweb')
callltcrpc(0, 'sendtoaddress', [mweb_addr, 1.0], wallet='wallet.dat')
mweb_addr = callltcrpc(
0, "getnewaddress", ["mweb_addr", "mweb"], wallet="mweb"
)
callltcrpc(0, "sendtoaddress", [mweb_addr, 1.0], wallet="wallet.dat")
num_blocks = 69
have_blocks: int = callltcrpc(0, 'getblockcount')
callltcrpc(0, 'generatetoaddress', [500 - have_blocks, self.ltc_addr], wallet='wallet.dat')
have_blocks: int = callltcrpc(0, "getblockcount")
callltcrpc(
0,
"generatetoaddress",
[500 - have_blocks, self.ltc_addr],
wallet="wallet.dat",
)
if 'decred' in TEST_COINS_LIST:
if "decred" in TEST_COINS_LIST:
if RESET_TEST:
addr = calldcrrpc(0, 'getnewaddress')
_ = calldcrrpc(0, "getnewaddress")
# assert (addr == self.dcr_addr)
self.dcr_acc = calldcrrpc(0, 'getaccount', [self.dcr_addr, ])
addr = calldcrrpc(0, 'generate', [110,])
self.dcr_acc = calldcrrpc(
0,
"getaccount",
[
self.dcr_addr,
],
)
calldcrrpc(
0,
"generate",
[
110,
],
)
else:
self.dcr_acc = calldcrrpc(0, 'getaccount', [self.dcr_addr, ])
self.dcr_acc = calldcrrpc(
0,
"getaccount",
[
self.dcr_addr,
],
)
self.update_thread_dcr = threading.Thread(target=updateThreadDCR, args=(self,))
self.update_thread_dcr = threading.Thread(
target=updateThreadDCR, args=(self,)
)
self.update_thread_dcr.start()
if 'bitcoincash' in TEST_COINS_LIST:
self.bch_addr = callbchrpc(0, 'getnewaddress', ['mining_addr'], wallet='wallet.dat')
if "bitcoincash" in TEST_COINS_LIST:
self.bch_addr = callbchrpc(
0, "getnewaddress", ["mining_addr"], wallet="wallet.dat"
)
num_blocks: int = 200
have_blocks: int = callbchrpc(0, 'getblockcount')
have_blocks: int = callbchrpc(0, "getblockcount")
if have_blocks < num_blocks:
logging.info('Mining %d Bitcoincash blocks to %s', num_blocks - have_blocks, self.bch_addr)
callbchrpc(0, 'generatetoaddress', [num_blocks - have_blocks, self.bch_addr], wallet='wallet.dat')
logging.info(
"Mining %d Bitcoincash blocks to %s",
num_blocks - have_blocks,
self.bch_addr,
)
callbchrpc(
0,
"generatetoaddress",
[num_blocks - have_blocks, self.bch_addr],
wallet="wallet.dat",
)
if RESET_TEST:
# Lower output split threshold for more stakeable outputs
for i in range(NUM_NODES):
callpartrpc(i, 'walletsettings', ['stakingoptions', {'stakecombinethreshold': 100, 'stakesplitthreshold': 200}])
callpartrpc(
i,
"walletsettings",
[
"stakingoptions",
{"stakecombinethreshold": 100, "stakesplitthreshold": 200},
],
)
self.update_thread = threading.Thread(target=updateThread, args=(self,))
self.update_thread.start()
@ -289,21 +410,21 @@ class Test(unittest.TestCase):
# Wait for height, or sequencelock is thrown off by genesis blocktime
num_blocks = 3
logging.info('Waiting for Particl chain height %d', num_blocks)
logging.info("Waiting for Particl chain height %d", num_blocks)
for i in range(60):
if self.delay_event.is_set():
raise ValueError('Test stopped.')
particl_blocks = callpartrpc(0, 'getblockcount')
print('particl_blocks', particl_blocks)
raise ValueError("Test stopped.")
particl_blocks = callpartrpc(0, "getblockcount")
print("particl_blocks", particl_blocks)
if particl_blocks >= num_blocks:
break
self.delay_event.wait(1)
logging.info('PART blocks: %d', callpartrpc(0, 'getblockcount'))
logging.info("PART blocks: %d", callpartrpc(0, "getblockcount"))
assert particl_blocks >= num_blocks
@classmethod
def tearDownClass(cls):
logging.info('Stopping test')
logging.info("Stopping test")
cls.delay_event.set()
if cls.update_thread:
cls.update_thread.join()
@ -328,9 +449,9 @@ class Test(unittest.TestCase):
waitForServer(self.delay_event, UI_PORT + 1)
while not self.delay_event.is_set():
logging.info('Looping indefinitely, ctrl+c to exit.')
logging.info("Looping indefinitely, ctrl+c to exit.")
self.delay_event.wait(10)
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

View file

@ -2,11 +2,12 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
mnemonics = [
'abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb',
'actuel comédie poésie noble facile éprouver brave cellule rotule académie hilarant chambre',
'ちしき いてざ きおち あしあと ぽちぶくろ こえる さつえい むえき あける ほんき むさぼる ねいろ',
"abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb",
"actuel comédie poésie noble facile éprouver brave cellule rotule académie hilarant chambre",
"ちしき いてざ きおち あしあと ぽちぶくろ こえる さつえい むえき あける ほんき むさぼる ねいろ",
]

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2023-2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -18,106 +19,125 @@ from util import get_driver
def test_offer(driver):
node1_url = 'http://localhost:12701'
node2_url = 'http://localhost:12702'
node1_url = "http://localhost:12701"
driver.get(node1_url + '/newoffer')
driver.get(node1_url + "/newoffer")
time.sleep(1)
select = Select(driver.find_element(By.ID, 'coin_from'))
select.select_by_visible_text('Bitcoin')
select = Select(driver.find_element(By.ID, 'coin_to'))
select.select_by_visible_text('Monero')
select = Select(driver.find_element(By.ID, "coin_from"))
select.select_by_visible_text("Bitcoin")
select = Select(driver.find_element(By.ID, "coin_to"))
select.select_by_visible_text("Monero")
amt_from = driver.find_element(By.NAME, 'amt_from')
amt_to = driver.find_element(By.NAME, 'amt_to')
rate = driver.find_element(By.ID, 'rate')
amt_from.send_keys('1')
amt_to.send_keys('2')
amt_from = driver.find_element(By.NAME, "amt_from")
amt_to = driver.find_element(By.NAME, "amt_to")
rate = driver.find_element(By.ID, "rate")
amt_from.send_keys("1")
amt_to.send_keys("2")
amt_from.click()
time.sleep(0.5)
rate_value = rate.get_attribute('value')
assert (float(rate_value) == 2.0)
rate_value = rate.get_attribute("value")
assert float(rate_value) == 2.0
rate.clear()
rate.send_keys('3')
rate.send_keys("3")
amt_from.click()
time.sleep(0.5)
amt_to_value = amt_to.get_attribute('value')
assert (float(amt_to_value) == 3.0)
amt_to_value = amt_to.get_attribute("value")
assert float(amt_to_value) == 3.0
amt_from.clear()
amt_from.send_keys('2')
amt_from.send_keys("2")
amt_to.click()
time.sleep(0.5)
amt_to_value = amt_to.get_attribute('value')
assert (float(amt_to_value) == 6.0)
amt_to_value = amt_to.get_attribute("value")
assert float(amt_to_value) == 6.0
amt_from.clear()
amt_to.clear()
rate.clear()
amt_to.send_keys('2')
rate.send_keys('2')
amt_to.send_keys("2")
rate.send_keys("2")
amt_to.click()
time.sleep(0.2)
amt_from_value = amt_from.get_attribute('value')
assert (float(amt_from_value) == 1.0)
amt_from_value = amt_from.get_attribute("value")
assert float(amt_from_value) == 1.0
driver.find_element(By.NAME, 'continue').click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'check_offer'))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'submit_offer'))).click()
driver.find_element(By.NAME, "continue").click()
WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.NAME, "check_offer"))
).click()
WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.NAME, "submit_offer"))
).click()
time.sleep(1)
offer_link = driver.find_element(By.XPATH, "//a[contains(text(),'Sent Offer')]")
offer1_id = offer_link.text.split(' ')[2]
offer1_id = offer_link.text.split(" ")[2]
driver.get(node1_url + '/newoffer')
driver.get(node1_url + "/newoffer")
time.sleep(1)
select = Select(driver.find_element(By.ID, 'coin_from'))
select.select_by_visible_text('Particl')
select = Select(driver.find_element(By.ID, 'coin_to'))
select.select_by_visible_text('Monero')
select = Select(driver.find_element(By.ID, "coin_from"))
select.select_by_visible_text("Particl")
select = Select(driver.find_element(By.ID, "coin_to"))
select.select_by_visible_text("Monero")
driver.find_element(By.NAME, 'amt_from').send_keys('3')
driver.find_element(By.NAME, 'amt_to').send_keys('4')
driver.find_element(By.NAME, "amt_from").send_keys("3")
driver.find_element(By.NAME, "amt_to").send_keys("4")
driver.find_element(By.NAME, 'continue').click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'check_offer'))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'submit_offer'))).click()
driver.find_element(By.NAME, "continue").click()
WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.NAME, "check_offer"))
).click()
WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.NAME, "submit_offer"))
).click()
time.sleep(1)
offer_link = driver.find_element(By.XPATH, "//a[contains(text(),'Sent Offer')]")
offer2_id = offer_link.text.split(' ')[2]
offer2_id = offer_link.text.split(" ")[2]
driver.get(node1_url + '/offer/' + offer1_id)
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'repeat_offer'))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'check_offer'))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'submit_offer'))).click()
driver.get(node1_url + "/offer/" + offer1_id)
WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.NAME, "repeat_offer"))
).click()
WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.NAME, "check_offer"))
).click()
WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.NAME, "submit_offer"))
).click()
time.sleep(1)
offer_link = driver.find_element(By.XPATH, "//a[contains(text(),'Sent Offer')]")
offer3_id = offer_link.text.split(' ')[2]
offer3_id = offer_link.text.split(" ")[2]
offer3_json = json.loads(urlopen(node1_url + '/json/offers/' + offer3_id).read())[0]
assert (offer3_json['coin_from'] == 'Bitcoin')
assert (offer3_json['coin_to'] == 'Monero')
offer3_json = json.loads(urlopen(node1_url + "/json/offers/" + offer3_id).read())[0]
assert offer3_json["coin_from"] == "Bitcoin"
assert offer3_json["coin_to"] == "Monero"
driver.get(node1_url + '/offer/' + offer2_id)
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'repeat_offer'))).click()
driver.get(node1_url + "/offer/" + offer2_id)
WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.NAME, "repeat_offer"))
).click()
time.sleep(1) # Add time for setupCustomSelect to fire
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'check_offer'))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'submit_offer'))).click()
WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.NAME, "check_offer"))
).click()
WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.NAME, "submit_offer"))
).click()
time.sleep(1)
offer_link = driver.find_element(By.XPATH, "//a[contains(text(),'Sent Offer')]")
offer4_id = offer_link.text.split(' ')[2]
offer4_id = offer_link.text.split(" ")[2]
offer4_json = json.loads(urlopen(node1_url + '/json/offers/' + offer4_id).read())[0]
assert (offer4_json['coin_from'] == 'Particl')
assert (offer4_json['coin_to'] == 'Monero')
offer4_json = json.loads(urlopen(node1_url + "/json/offers/" + offer4_id).read())[0]
assert offer4_json["coin_from"] == "Particl"
assert offer4_json["coin_to"] == "Monero"
print('Test Passed!')
print("Test Passed!")
def run_tests():
@ -128,5 +148,5 @@ def run_tests():
driver.close()
if __name__ == '__main__':
if __name__ == "__main__":
run_tests()

View file

@ -13,196 +13,229 @@ from selenium.webdriver.support.select import Select
from selenium.webdriver.support import expected_conditions as EC
from util import (
BSX_0_PORT, BSX_1_PORT,
BSX_0_PORT,
BSX_1_PORT,
click_option,
get_driver,
)
from tests.basicswap.util import read_json_api
base_url = 'http://localhost'
base_url = "http://localhost"
def recover_chain_b_lock_tx(driver, offer_data, offerer_port, bidder_port):
print('Test case: {} -> {}'.format(offer_data['coin_from'], offer_data['coin_to']))
offerer_url = f'{base_url}:{offerer_port}'
bidder_url = f'{base_url}:{bidder_port}'
print("Test case: {} -> {}".format(offer_data["coin_from"], offer_data["coin_to"]))
offerer_url = f"{base_url}:{offerer_port}"
bidder_url = f"{base_url}:{bidder_port}"
rv = read_json_api(offerer_port, 'offers/new', offer_data)
offer0_id = rv['offer_id']
rv = read_json_api(offerer_port, "offers/new", offer_data)
offer0_id = rv["offer_id"]
for i in range(10):
rv = read_json_api(bidder_port, f'offers/{offer0_id}')
rv = read_json_api(bidder_port, f"offers/{offer0_id}")
if len(rv) > 0:
break
print('Bidder: Waiting for offer')
print("Bidder: Waiting for offer")
time.sleep(1)
bid_data = {
'offer_id': offer0_id,
'amount_from': 1.0}
rv = read_json_api(bidder_port, 'bids/new', bid_data)
bid0_id = rv['bid_id']
bid_data = {"offer_id": offer0_id, "amount_from": 1.0}
rv = read_json_api(bidder_port, "bids/new", bid_data)
bid0_id = rv["bid_id"]
bid_state = None
for i in range(10):
rv = read_json_api(offerer_port, f'bids/{bid0_id}')
if 'error' not in rv:
bid_state = rv['bid_state']
if bid_state == 'Received':
rv = read_json_api(offerer_port, f"bids/{bid0_id}")
if "error" not in rv:
bid_state = rv["bid_state"]
if bid_state == "Received":
break
print('Offerer: Waiting for bid')
print("Offerer: Waiting for bid")
time.sleep(2)
assert (bid_state == 'Received')
assert bid_state == "Received"
# Set BID_STOP_AFTER_COIN_B_LOCK (13) debugind
rv = read_json_api(offerer_port, f'bids/{bid0_id}', {'debugind': 13})
assert ('error' not in rv)
rv = read_json_api(offerer_port, f"bids/{bid0_id}", {"debugind": 13})
assert "error" not in rv
# Accept bid
rv = read_json_api(offerer_port, f'bids/{bid0_id}', {'accept': 1})
assert ('error' not in rv)
rv = read_json_api(offerer_port, f"bids/{bid0_id}", {"accept": 1})
assert "error" not in rv
for i in range(100):
rv = read_json_api(bidder_port, f'bids/{bid0_id}')
bid_state = rv['bid_state']
if bid_state == 'Scriptless coin locked':
rv = read_json_api(bidder_port, f"bids/{bid0_id}")
bid_state = rv["bid_state"]
if bid_state == "Scriptless coin locked":
break
print('Bidder: Waiting for state')
print("Bidder: Waiting for state")
time.sleep(5)
assert (bid_state == 'Scriptless coin locked')
assert bid_state == "Scriptless coin locked"
for i in range(100):
rv = read_json_api(offerer_port, f'bids/{bid0_id}')
bid_state = rv['bid_state']
if bid_state == 'Stalled (debug)':
rv = read_json_api(offerer_port, f"bids/{bid0_id}")
bid_state = rv["bid_state"]
if bid_state == "Stalled (debug)":
break
print('Offerer: Waiting for state')
print("Offerer: Waiting for state")
time.sleep(5)
assert (bid_state == 'Stalled (debug)')
assert bid_state == "Stalled (debug)"
# Show bid state history
rv = read_json_api(offerer_port, f'bids/{bid0_id}/states')
assert (len(rv) > 1)
rv = read_json_api(offerer_port, f"bids/{bid0_id}/states")
assert len(rv) > 1
url = f'{bidder_url}/bid/{bid0_id}'
url = f"{bidder_url}/bid/{bid0_id}"
driver.get(url)
btn_more_info = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'show_txns')))
btn_more_info = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.NAME, "show_txns"))
)
btn_more_info.click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'hide_txns')))
bidder_localkeyhalf = driver.find_element(By.ID, 'localkeyhalf').text
print('Bidder keyhalf', bidder_localkeyhalf)
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, "hide_txns")))
bidder_localkeyhalf = driver.find_element(By.ID, "localkeyhalf").text
print("Bidder keyhalf", bidder_localkeyhalf)
try:
driver.find_element(By.ID, 'remotekeyhalf')
driver.find_element(By.ID, "remotekeyhalf")
except Exception:
pass
else:
raise ValueError('Nodes should not have remotekeyhalves yet.')
raise ValueError("Nodes should not have remotekeyhalves yet.")
url = f'{offerer_url}/bid/{bid0_id}'
url = f"{offerer_url}/bid/{bid0_id}"
driver.get(url)
btn_more_info = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'show_txns')))
btn_more_info = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.NAME, "show_txns"))
)
btn_more_info.click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'hide_txns')))
offerer_localkeyhalf = driver.find_element(By.ID, 'localkeyhalf').text
print('Offerer keyhalf', offerer_localkeyhalf)
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, "hide_txns")))
offerer_localkeyhalf = driver.find_element(By.ID, "localkeyhalf").text
print("Offerer keyhalf", offerer_localkeyhalf)
print('Trying with the local key in place of remote')
btn_edit = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'edit_bid')))
print("Trying with the local key in place of remote")
btn_edit = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.NAME, "edit_bid"))
)
btn_edit.click()
btn_submit = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'edit_bid_submit')))
kbs_other = driver.find_element(By.ID, 'kbs_other')
btn_submit = WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.NAME, "edit_bid_submit"))
)
kbs_other = driver.find_element(By.ID, "kbs_other")
kbs_other.send_keys(offerer_localkeyhalf)
btn_submit.click()
btn_edit = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'edit_bid')))
elements = driver.find_elements(By.CLASS_NAME, 'error_msg')
expect_err_msg: str = 'Provided key matches local key'
assert (any(expect_err_msg in el.text for el in elements))
print('Found expected error: ' + expect_err_msg)
btn_edit = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.NAME, "edit_bid"))
)
elements = driver.find_elements(By.CLASS_NAME, "error_msg")
expect_err_msg: str = "Provided key matches local key"
assert any(expect_err_msg in el.text for el in elements)
print("Found expected error: " + expect_err_msg)
print('Trying with incorrect key')
btn_edit = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'edit_bid')))
print("Trying with incorrect key")
btn_edit = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.NAME, "edit_bid"))
)
btn_edit.click()
btn_submit = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'edit_bid_submit')))
kbs_other = driver.find_element(By.ID, 'kbs_other')
btn_submit = WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.NAME, "edit_bid_submit"))
)
kbs_other = driver.find_element(By.ID, "kbs_other")
last_byte = bidder_localkeyhalf[-2:]
invalid_byte = '01' if last_byte == '00' else '00'
invalid_byte = "01" if last_byte == "00" else "00"
kbs_other.send_keys(bidder_localkeyhalf[:-2] + invalid_byte)
btn_submit.click()
btn_edit = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'edit_bid')))
elements = driver.find_elements(By.CLASS_NAME, 'error_msg')
expect_err_msg: str = 'Summed key does not match expected wallet'
assert (any(expect_err_msg in el.text for el in elements))
print('Found expected error: ' + expect_err_msg)
btn_edit = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.NAME, "edit_bid"))
)
elements = driver.find_elements(By.CLASS_NAME, "error_msg")
expect_err_msg: str = "Summed key does not match expected wallet"
assert any(expect_err_msg in el.text for el in elements)
print("Found expected error: " + expect_err_msg)
print('Trying with correct key')
print("Trying with correct key")
btn_edit.click()
btn_submit = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'edit_bid_submit')))
btn_submit = WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.NAME, "edit_bid_submit"))
)
lock_tx_b_depth = -1
for i in range(100):
# Check the non-stalled node
rv = read_json_api(bidder_port, f'bids/{bid0_id}', {'show_extra': True})
for tx in rv['txns']:
if tx['type'] == 'Chain B Lock' and tx['confirms'] is not None:
lock_tx_b_depth = tx['confirms']
rv = read_json_api(bidder_port, f"bids/{bid0_id}", {"show_extra": True})
for tx in rv["txns"]:
if tx["type"] == "Chain B Lock" and tx["confirms"] is not None:
lock_tx_b_depth = tx["confirms"]
break
if lock_tx_b_depth >= 10:
break
print(f'Waiting for lock tx B depth, have {lock_tx_b_depth}')
print(f"Waiting for lock tx B depth, have {lock_tx_b_depth}")
time.sleep(2)
kbs_other = driver.find_element(By.ID, 'kbs_other')
kbs_other = driver.find_element(By.ID, "kbs_other")
kbs_other.send_keys(bidder_localkeyhalf)
btn_submit.click()
btn_edit = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'edit_bid')))
elements = driver.find_elements(By.CLASS_NAME, 'infomsg')
expect_msg: str = 'Bid edited'
assert (any(expect_msg in el.text for el in elements))
print('Found expected message: ' + expect_msg)
btn_edit = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.NAME, "edit_bid"))
)
elements = driver.find_elements(By.CLASS_NAME, "infomsg")
expect_msg: str = "Bid edited"
assert any(expect_msg in el.text for el in elements)
print("Found expected message: " + expect_msg)
print('Trying with nodes reversed (should fail as already spent)') # But should sum to the expected wallet key
url = f'{bidder_url}/bid/{bid0_id}'
print(
"Trying with nodes reversed (should fail as already spent)"
) # But should sum to the expected wallet key
url = f"{bidder_url}/bid/{bid0_id}"
driver.get(url)
btn_edit = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'edit_bid')))
btn_edit = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.NAME, "edit_bid"))
)
btn_edit.click()
btn_submit = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'edit_bid_submit')))
btn_submit = WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.NAME, "edit_bid_submit"))
)
driver.get(url)
btn_edit = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'edit_bid')))
btn_edit = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.NAME, "edit_bid"))
)
btn_edit.click()
btn_submit = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'edit_bid_submit')))
btn_submit = WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.NAME, "edit_bid_submit"))
)
kbs_other = driver.find_element(By.ID, 'kbs_other')
kbs_other = driver.find_element(By.ID, "kbs_other")
kbs_other.send_keys(offerer_localkeyhalf)
btn_submit.click()
btn_edit = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'edit_bid')))
btn_edit = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.NAME, "edit_bid"))
)
# In log: "Balance is too low, checking for existing spend"
# Should error here, but the code can't tell where the tx was sent, and treats any existing send as correct.
elements = driver.find_elements(By.CLASS_NAME, 'infomsg')
expect_msg: str = 'Bid edited'
assert (any(expect_msg in el.text for el in elements))
elements = driver.find_elements(By.CLASS_NAME, "infomsg")
expect_msg: str = "Bid edited"
assert any(expect_msg in el.text for el in elements)
def enable_debug_ui(driver):
for port in (BSX_0_PORT, BSX_1_PORT):
url = f'{base_url}:{port}/settings'
url = f"{base_url}:{port}/settings"
driver.get(url)
driver.find_element(By.ID, 'general-tab').click()
driver.find_element(By.ID, "general-tab").click()
btn_apply_general = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, 'apply_general')))
btn_apply_general = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.NAME, "apply_general"))
)
el = driver.find_element(By.NAME, 'debugmode')
el = driver.find_element(By.NAME, "debugmode")
selected_option = Select(el).first_selected_option
if selected_option.text != 'True':
click_option(el, 'True')
if selected_option.text != "True":
click_option(el, "True")
el = driver.find_element(By.NAME, 'debugui')
el = driver.find_element(By.NAME, "debugui")
selected_option = Select(el).first_selected_option
if selected_option.text != 'True':
click_option(el, 'True')
if selected_option.text != "True":
click_option(el, "True")
btn_apply_general.click()
@ -213,25 +246,27 @@ def run_tests():
enable_debug_ui(driver)
offer_data = {
'coin_from': 'BTC',
'coin_to': 'XMR',
'amt_from': 1.0,
'amt_to': 2.0,
'lockhrs': 24}
"coin_from": "BTC",
"coin_to": "XMR",
"amt_from": 1.0,
"amt_to": 2.0,
"lockhrs": 24,
}
recover_chain_b_lock_tx(driver, offer_data, BSX_0_PORT, BSX_1_PORT)
offer_data = {
'coin_from': 'XMR',
'coin_to': 'BTC',
'amt_from': 1.0,
'amt_to': 2.0,
'lockhrs': 24}
"coin_from": "XMR",
"coin_to": "BTC",
"amt_from": 1.0,
"amt_to": 2.0,
"lockhrs": 24,
}
recover_chain_b_lock_tx(driver, offer_data, BSX_1_PORT, BSX_0_PORT)
print('Test Passed!')
print("Test Passed!")
finally:
driver.close()
if __name__ == '__main__':
if __name__ == "__main__":
run_tests()

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022-2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -14,7 +15,7 @@ from selenium.webdriver.support.select import Select
from selenium.webdriver.support import expected_conditions as EC
from util import (
BSX_0_PORT, BSX_1_PORT,
BSX_0_PORT,
click_option,
get_driver,
)
@ -22,118 +23,121 @@ from basicswap.ui.page_offers import default_chart_api_key
def test_settings(driver):
base_url = f'http://localhost:{BSX_0_PORT}'
node2_url = f'http://localhost:{BSX_1_PORT}'
base_url = f"http://localhost:{BSX_0_PORT}"
url = base_url + '/settings'
url = base_url + "/settings"
driver.get(url)
driver.find_element(By.ID, 'general-tab').click()
driver.find_element(By.ID, "general-tab").click()
wait = WebDriverWait(driver, 10)
btn_apply_general = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_general')))
btn_apply_general = wait.until(
EC.element_to_be_clickable((By.NAME, "apply_general"))
)
el = driver.find_element(By.NAME, 'debugmode')
el = driver.find_element(By.NAME, "debugmode")
selected_option = Select(el).first_selected_option
assert (selected_option.text == 'True')
click_option(el, 'False')
assert selected_option.text == "True"
click_option(el, "False")
el = driver.find_element(By.NAME, 'debugui')
el = driver.find_element(By.NAME, "debugui")
selected_option = Select(el).first_selected_option
assert (selected_option.text == 'False')
click_option(el, 'True')
assert selected_option.text == "False"
click_option(el, "True")
btn_apply_general.click()
time.sleep(1)
settings_path_0 = '/tmp/test_persistent/client0/basicswap.json'
settings_path_0 = "/tmp/test_persistent/client0/basicswap.json"
with open(settings_path_0) as fs:
settings = json.load(fs)
assert (settings['debug'] is False)
assert (settings['debug_ui'] is True)
assert settings["debug"] is False
assert settings["debug_ui"] is True
el = driver.find_element(By.NAME, 'showchart')
el = driver.find_element(By.NAME, "showchart")
selected_option = Select(el).first_selected_option
assert (selected_option.text == 'True')
click_option(el, 'False')
assert selected_option.text == "True"
click_option(el, "False")
difficult_text = '`~!@#$%^&*()-_=+[{}]\\|;:\'",<>./? '
el = driver.find_element(By.NAME, 'chartapikey')
difficult_text = "`~!@#$%^&*()-_=+[{}]\\|;:'\",<>./? "
el = driver.find_element(By.NAME, "chartapikey")
el.clear()
el.send_keys(difficult_text)
btn_apply_chart = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_chart')))
btn_apply_chart = wait.until(EC.element_to_be_clickable((By.NAME, "apply_chart")))
btn_apply_chart.click()
time.sleep(1)
with open(settings_path_0) as fs:
settings = json.load(fs)
assert (settings['show_chart'] is False)
chart_api_key = bytes.fromhex(settings.get('chart_api_key_enc', '')).decode('utf-8')
assert (chart_api_key == difficult_text)
assert settings["show_chart"] is False
chart_api_key = bytes.fromhex(settings.get("chart_api_key_enc", "")).decode("utf-8")
assert chart_api_key == difficult_text
hex_text = default_chart_api_key
el = driver.find_element(By.NAME, 'chartapikey')
el = driver.find_element(By.NAME, "chartapikey")
el.clear()
el.send_keys(hex_text)
btn_apply_chart = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_chart')))
btn_apply_chart = wait.until(EC.element_to_be_clickable((By.NAME, "apply_chart")))
btn_apply_chart.click()
time.sleep(1)
el = driver.find_element(By.NAME, 'chartapikey')
assert el.get_property('value') == hex_text
el = driver.find_element(By.NAME, "chartapikey")
assert el.get_property("value") == hex_text
with open(settings_path_0) as fs:
settings = json.load(fs)
assert (settings.get('chart_api_key') == hex_text)
assert settings.get("chart_api_key") == hex_text
# Reset
btn_apply_general = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_general')))
click_option(driver.find_element(By.NAME, 'debugmode'), 'True')
click_option(driver.find_element(By.NAME, 'debugui'), 'False')
btn_apply_general = wait.until(
EC.element_to_be_clickable((By.NAME, "apply_general"))
)
click_option(driver.find_element(By.NAME, "debugmode"), "True")
click_option(driver.find_element(By.NAME, "debugui"), "False")
btn_apply_general.click()
btn_apply_chart = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_chart')))
click_option(driver.find_element(By.NAME, 'showchart'), 'True')
btn_apply_chart = wait.until(EC.element_to_be_clickable((By.NAME, "apply_chart")))
click_option(driver.find_element(By.NAME, "showchart"), "True")
btn_apply_chart.click()
time.sleep(1)
# Apply XMR settings with blank nodes list
driver.find_element(By.ID, 'coins-tab').click()
btn_apply_monero = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_monero')))
el = driver.find_element(By.NAME, 'remotedaemonurls_monero')
driver.find_element(By.ID, "coins-tab").click()
btn_apply_monero = wait.until(EC.element_to_be_clickable((By.NAME, "apply_monero")))
el = driver.find_element(By.NAME, "remotedaemonurls_monero")
el.clear()
btn_apply_monero.click()
time.sleep(1)
with open(settings_path_0) as fs:
settings = json.load(fs)
assert (len(settings['chainclients']['monero']['remote_daemon_urls']) == 0)
assert len(settings["chainclients"]["monero"]["remote_daemon_urls"]) == 0
btn_apply_monero = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_monero')))
el = driver.find_element(By.NAME, 'remotedaemonurls_monero')
btn_apply_monero = wait.until(EC.element_to_be_clickable((By.NAME, "apply_monero")))
el = driver.find_element(By.NAME, "remotedaemonurls_monero")
el.clear()
el.send_keys('node.xmr.to:18081\nnode1.xmr.to:18082')
el.send_keys("node.xmr.to:18081\nnode1.xmr.to:18082")
btn_apply_monero.click()
time.sleep(1)
with open(settings_path_0) as fs:
settings = json.load(fs)
remotedaemonurls = settings['chainclients']['monero']['remote_daemon_urls']
assert (len(remotedaemonurls) == 2)
remotedaemonurls = settings["chainclients"]["monero"]["remote_daemon_urls"]
assert len(remotedaemonurls) == 2
btn_apply_monero = wait.until(EC.element_to_be_clickable((By.NAME, 'apply_monero')))
el = driver.find_element(By.NAME, 'remotedaemonurls_monero')
btn_apply_monero = wait.until(EC.element_to_be_clickable((By.NAME, "apply_monero")))
el = driver.find_element(By.NAME, "remotedaemonurls_monero")
el.clear()
btn_apply_monero.click()
time.sleep(1)
with open(settings_path_0) as fs:
settings = json.load(fs)
assert (len(settings['chainclients']['monero']['remote_daemon_urls']) == 0)
assert len(settings["chainclients"]["monero"]["remote_daemon_urls"]) == 0
print('Test Passed!')
print("Test Passed!")
def run_tests():
@ -144,5 +148,5 @@ def run_tests():
driver.close()
if __name__ == '__main__':
if __name__ == "__main__":
run_tests()

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022-2023 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -17,47 +18,48 @@ from util import get_driver
def test_swap_dir(driver):
node_1_port = 12701
node_2_port = 12702
node1_url = f'http://localhost:{node_1_port}'
node2_url = f'http://localhost:{node_2_port}'
node1_url = f"http://localhost:{node_1_port}"
node2_url = f"http://localhost:{node_2_port}"
offer_data = {
'addr_from': -1,
'coin_from': 'PART',
'coin_to': 'XMR',
'amt_from': 1,
'amt_to': 2,
'lockhrs': 24}
rv = read_json_api(node_1_port, 'offers/new', offer_data)
offer0_id = rv['offer_id']
"addr_from": -1,
"coin_from": "PART",
"coin_to": "XMR",
"amt_from": 1,
"amt_to": 2,
"lockhrs": 24,
}
read_json_api(node_1_port, "offers/new", offer_data)
offer_data = {
'addr_from': -1,
'coin_from': 'PART',
'coin_to': 'BTC',
'amt_from': 3,
'amt_to': 4,
'lockhrs': 24}
rv = read_json_api(node_1_port, 'offers/new', offer_data)
offer0_id = rv['offer_id']
"addr_from": -1,
"coin_from": "PART",
"coin_to": "BTC",
"amt_from": 3,
"amt_to": 4,
"lockhrs": 24,
}
read_json_api(node_1_port, "offers/new", offer_data)
# Wait for offer to propagate
offers_api_1 = read_json_api(node_1_port, 'offers')
print('offers_api_1', offers_api_1)
offers_api_1 = read_json_api(node_1_port, "offers")
print("offers_api_1", offers_api_1)
offers_api_2 = read_json_api(node_2_port, 'offers')
offers_api_2 = read_json_api(node_2_port, "offers")
while len(offers_api_2) < 1:
rv = read_json_api(node_2_port, 'offers')
print('offers_api_2', offers_api_2)
offers_api_2 = read_json_api(node_2_port, "offers")
time.sleep(0.1)
print("offers_api_2", offers_api_2)
driver.get(f'{node1_url}/offers')
driver.get(f"{node1_url}/offers")
time.sleep(1)
driver.get(f'{node2_url}/offers')
driver.get(f"{node2_url}/offers")
time.sleep(300)
raise ValueError('TODO')
raise ValueError("TODO")
print('Test Passed!')
print("Test Passed!")
def run_tests():
@ -68,5 +70,5 @@ def run_tests():
driver.close()
if __name__ == '__main__':
if __name__ == "__main__":
run_tests()

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022-2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -16,109 +17,113 @@ from util import get_driver
def test_wallets(driver):
base_url = 'http://localhost:12701'
node2_url = 'http://localhost:12702'
base_url = "http://localhost:12701"
node2_url = "http://localhost:12702"
# Check json coins data
coins = json.loads(urlopen(base_url + '/json/coins').read())
part_coin = [f for f in coins if f['ticker'] == 'PART'][0]
part_id = part_coin['id']
assert (part_id == 1)
coins = json.loads(urlopen(base_url + "/json/coins").read())
part_coin = [f for f in coins if f["ticker"] == "PART"][0]
part_id = part_coin["id"]
assert part_id == 1
# Check 404 pages
url = base_url + '/unknown'
url = base_url + "/unknown"
driver.get(url)
p1 = driver.find_element(By.TAG_NAME, 'body')
assert ('Error 404' in p1.text)
p1 = driver.find_element(By.TAG_NAME, "body")
assert "Error 404" in p1.text
url = base_url + '/static/nothing.png'
url = base_url + "/static/nothing.png"
driver.get(url)
p1 = driver.find_element(By.TAG_NAME, 'body')
assert ('Error 404' in p1.text)
p1 = driver.find_element(By.TAG_NAME, "body")
assert "Error 404" in p1.text
url = base_url + '/wallet'
url = base_url + "/wallet"
driver.get(url)
h2 = driver.find_element(By.TAG_NAME, 'h2')
assert ('Error' in h2.text)
p1 = driver.find_element(By.TAG_NAME, 'p')
assert ('Wallet not specified' in p1.text)
h2 = driver.find_element(By.TAG_NAME, "h2")
assert "Error" in h2.text
p1 = driver.find_element(By.TAG_NAME, "p")
assert "Wallet not specified" in p1.text
url = base_url + '/wallet/NOCOIN'
url = base_url + "/wallet/NOCOIN"
driver.get(url)
h2 = driver.find_element(By.TAG_NAME, 'h2')
assert ('Error' in h2.text)
p1 = driver.find_element(By.TAG_NAME, 'p')
assert ('Unknown coin' in p1.text)
h2 = driver.find_element(By.TAG_NAME, "h2")
assert "Error" in h2.text
p1 = driver.find_element(By.TAG_NAME, "p")
assert "Unknown coin" in p1.text
driver.get(base_url + '/wallets')
driver.get(base_url + "/wallets")
time.sleep(1)
driver.refresh()
driver.find_element(By.ID, 'refresh').click()
driver.find_element(By.ID, "refresh").click()
time.sleep(1)
driver.refresh()
print('Finding deposit address of node 2')
driver.get(node2_url + '/wallet/PART')
e = driver.find_element(By.ID, 'deposit_address')
print("Finding deposit address of node 2")
driver.get(node2_url + "/wallet/PART")
e = driver.find_element(By.ID, "deposit_address")
node2_deposit_address = e.text
print('Withdrawing from node 1')
driver.get(base_url + '/wallet/PART')
driver.find_element(By.NAME, f'to_{part_id}').send_keys(node2_deposit_address)
driver.find_element(By.NAME, f'amt_{part_id}').send_keys('10')
driver.find_element(By.NAME, f'withdraw_{part_id}').click()
print("Withdrawing from node 1")
driver.get(base_url + "/wallet/PART")
driver.find_element(By.NAME, f"to_{part_id}").send_keys(node2_deposit_address)
driver.find_element(By.NAME, f"amt_{part_id}").send_keys("10")
driver.find_element(By.NAME, f"withdraw_{part_id}").click()
driver.switch_to.alert.accept()
time.sleep(1)
elements = driver.find_elements(By.CLASS_NAME, 'infomsg')
assert (len(elements) == 1)
elements = driver.find_elements(By.CLASS_NAME, "infomsg")
assert len(elements) == 1
e = elements[0]
assert ('Withdrew 10 rtPART (plain to plain) to address' in e.text)
assert "Withdrew 10 rtPART (plain to plain) to address" in e.text
print('Locking UTXO')
driver.get(base_url + '/rpc')
el = driver.find_element(By.NAME, 'coin_type')
for option in el.find_elements(By.TAG_NAME, 'option'):
if option.text == 'Particl':
print("Locking UTXO")
driver.get(base_url + "/rpc")
el = driver.find_element(By.NAME, "coin_type")
for option in el.find_elements(By.TAG_NAME, "option"):
if option.text == "Particl":
option.click()
break
driver.find_element(By.NAME, 'cmd').send_keys('listunspent')
driver.find_element(By.NAME, 'apply').click()
driver.find_element(By.NAME, "cmd").send_keys("listunspent")
driver.find_element(By.NAME, "apply").click()
time.sleep(1)
text_value = driver.find_element(By.NAME, 'result').text
utxos = json.loads(text_value.split('\n', 1)[1])
text_value = driver.find_element(By.NAME, "result").text
utxos = json.loads(text_value.split("\n", 1)[1])
lock_utxos = [{'txid': utxos[0]['txid'], 'vout': utxos[0]['vout']}]
driver.find_element(By.NAME, 'cmd').send_keys('lockunspent false "{}"'.format(dumpje(lock_utxos)))
driver.find_element(By.NAME, 'apply').click()
lock_utxos = [{"txid": utxos[0]["txid"], "vout": utxos[0]["vout"]}]
driver.find_element(By.NAME, "cmd").send_keys(
'lockunspent false "{}"'.format(dumpje(lock_utxos))
)
driver.find_element(By.NAME, "apply").click()
print('Check for locked UTXO count')
driver.get(base_url + '/wallet/PART')
print("Check for locked UTXO count")
driver.get(base_url + "/wallet/PART")
found = False
for i in range(5):
try:
el = driver.find_element(By.ID, 'locked_utxos')
el = driver.find_element(By.ID, "locked_utxos")
found = True
break
except Exception:
continue
driver.find_element(By.ID, 'refresh').click()
driver.find_element(By.ID, "refresh").click()
time.sleep(2)
found = True
assert (found)
assert found
driver.refresh()
print('Unlocking UTXO')
driver.get(base_url + '/rpc')
el = driver.find_element(By.NAME, 'coin_type')
for option in el.find_elements(By.TAG_NAME, 'option'):
if option.text == 'Particl':
print("Unlocking UTXO")
driver.get(base_url + "/rpc")
el = driver.find_element(By.NAME, "coin_type")
for option in el.find_elements(By.TAG_NAME, "option"):
if option.text == "Particl":
option.click()
break
driver.find_element(By.NAME, 'cmd').send_keys('lockunspent true "{}"'.format(dumpje(lock_utxos)))
driver.find_element(By.NAME, 'apply').click()
driver.find_element(By.NAME, "cmd").send_keys(
'lockunspent true "{}"'.format(dumpje(lock_utxos))
)
driver.find_element(By.NAME, "apply").click()
print('Test Passed!')
print("Test Passed!")
def run_tests():
@ -129,5 +134,5 @@ def run_tests():
driver.close()
if __name__ == '__main__':
if __name__ == "__main__":
run_tests()

View file

@ -10,31 +10,34 @@ import os
from selenium.webdriver.common.by import By
BSX_0_PORT = int(os.getenv('BSX_0_PORT', 12701))
BSX_1_PORT = int(os.getenv('BSX_1_PORT', BSX_0_PORT + 1))
BSX_2_PORT = int(os.getenv('BSX_1_PORT', BSX_0_PORT + 2))
BSX_0_PORT = int(os.getenv("BSX_0_PORT", 12701))
BSX_1_PORT = int(os.getenv("BSX_1_PORT", BSX_0_PORT + 1))
BSX_2_PORT = int(os.getenv("BSX_1_PORT", BSX_0_PORT + 2))
BSX_SELENIUM_DRIVER = os.getenv('BSX_SELENIUM_DRIVER', 'firefox')
BSX_SELENIUM_DRIVER = os.getenv("BSX_SELENIUM_DRIVER", "firefox")
def get_driver():
if BSX_SELENIUM_DRIVER == 'firefox':
if BSX_SELENIUM_DRIVER == "firefox":
from selenium.webdriver import Firefox, FirefoxOptions
driver = Firefox(options=FirefoxOptions())
elif BSX_SELENIUM_DRIVER == 'chrome':
elif BSX_SELENIUM_DRIVER == "chrome":
from selenium.webdriver import Chrome, ChromeOptions
driver = Chrome(options=ChromeOptions())
elif BSX_SELENIUM_DRIVER == 'safari':
elif BSX_SELENIUM_DRIVER == "safari":
from selenium.webdriver import Safari, SafariOptions
driver = Safari(options=SafariOptions())
else:
raise ValueError('Unknown driver ' + BSX_SELENIUM_DRIVER)
raise ValueError("Unknown driver " + BSX_SELENIUM_DRIVER)
return driver
def click_option(el, option_text):
for option in el.find_elements(By.TAG_NAME, 'option'):
for option in el.find_elements(By.TAG_NAME, "option"):
if option.text == option_text:
option.click()
break

View file

@ -47,13 +47,17 @@ from .test_xmr import test_delay_event, callnoderpc
from coincurve.ecdsaotves import (
ecdsaotves_enc_sign,
ecdsaotves_enc_verify,
ecdsaotves_dec_sig
ecdsaotves_dec_sig,
)
BITCOINCASH_BINDIR = os.path.expanduser(os.getenv('BITCOINCASH_BINDIR', os.path.join(cfg.DEFAULT_TEST_BINDIR, 'bitcoincash')))
BITCOINCASHD = os.getenv('BITCOINCASHD', 'bitcoind' + cfg.bin_suffix)
BITCOINCASH_CLI = os.getenv('BITCOINCASH_CLI', 'bitcoin-cli' + cfg.bin_suffix)
BITCOINCASH_TX = os.getenv('BITCOINCASH_TX', 'bitcoin-tx' + cfg.bin_suffix)
BITCOINCASH_BINDIR = os.path.expanduser(
os.getenv(
"BITCOINCASH_BINDIR", os.path.join(cfg.DEFAULT_TEST_BINDIR, "bitcoincash")
)
)
BITCOINCASHD = os.getenv("BITCOINCASHD", "bitcoind" + cfg.bin_suffix)
BITCOINCASH_CLI = os.getenv("BITCOINCASH_CLI", "bitcoin-cli" + cfg.bin_suffix)
BITCOINCASH_TX = os.getenv("BITCOINCASH_TX", "bitcoin-tx" + cfg.bin_suffix)
BCH_BASE_PORT = 41792
BCH_BASE_RPC_PORT = 42792
@ -63,12 +67,19 @@ BCH_BASE_TOR_PORT = 43732
logger = logging.getLogger()
bch_lock_spend_tx = '0200000001bfc6bbb47851441c7827059ae337a06aa9064da7f9537eb9243e45766c3dd34c00000000d8473045022100a0161ea14d3b41ed41250c8474fc8ec6ce1cab8df7f401e69ecf77c2ab63d82102207a2a57ddf2ea400e09ea059f3b261da96f5098858b17239931f3cc2fb929bb2a4c8ec3519dc4519d02e80300c600cc949d00ce00d18800cf00d28800d000d39d00cb641976a91481ec21969399d15c26af089d5db437ead066c5ba88ac00cd788821024ffcc0481629866671d89f05f3da813a2aacec1b52e69b8c0c586b665f5d4574ba6752b27523aa20df65a90e9becc316ff5aca44d4e06dfaade56622f32bafa197aba706c5e589758700cd87680000000001251cde06000000001976a91481ec21969399d15c26af089d5db437ead066c5ba88ac00000000'
bch_lock_script = 'c3519dc4519d02e80300c600cc949d00ce00d18800cf00d28800d000d39d00cb641976a91481ec21969399d15c26af089d5db437ead066c5ba88ac00cd788821024ffcc0481629866671d89f05f3da813a2aacec1b52e69b8c0c586b665f5d4574ba6752b27523aa20df65a90e9becc316ff5aca44d4e06dfaade56622f32bafa197aba706c5e589758700cd8768'
bch_lock_spend_script = '473045022100a0161ea14d3b41ed41250c8474fc8ec6ce1cab8df7f401e69ecf77c2ab63d82102207a2a57ddf2ea400e09ea059f3b261da96f5098858b17239931f3cc2fb929bb2a4c8ec3519dc4519d02e80300c600cc949d00ce00d18800cf00d28800d000d39d00cb641976a91481ec21969399d15c26af089d5db437ead066c5ba88ac00cd788821024ffcc0481629866671d89f05f3da813a2aacec1b52e69b8c0c586b665f5d4574ba6752b27523aa20df65a90e9becc316ff5aca44d4e06dfaade56622f32bafa197aba706c5e589758700cd8768'
bch_lock_swipe_script = '4c8fc3519dc4519d02e80300c600cc949d00ce00d18800cf00d28800d000d39d00cb641976a9141ab50aedd2e48297073f0f6eef46f97b37c9354e88ac00cd7888210234fe304a5b129b8265c177c92aa40b7840e8303f8b0fcca2359023163c7c2768ba670120b27523aa20191b09e40d1277fa14fea1e9b41e4fcc4528c9cb77e39e1b7b1a0b3332180cb78700cd8768'
bch_lock_spend_tx = "0200000001bfc6bbb47851441c7827059ae337a06aa9064da7f9537eb9243e45766c3dd34c00000000d8473045022100a0161ea14d3b41ed41250c8474fc8ec6ce1cab8df7f401e69ecf77c2ab63d82102207a2a57ddf2ea400e09ea059f3b261da96f5098858b17239931f3cc2fb929bb2a4c8ec3519dc4519d02e80300c600cc949d00ce00d18800cf00d28800d000d39d00cb641976a91481ec21969399d15c26af089d5db437ead066c5ba88ac00cd788821024ffcc0481629866671d89f05f3da813a2aacec1b52e69b8c0c586b665f5d4574ba6752b27523aa20df65a90e9becc316ff5aca44d4e06dfaade56622f32bafa197aba706c5e589758700cd87680000000001251cde06000000001976a91481ec21969399d15c26af089d5db437ead066c5ba88ac00000000"
bch_lock_script = "c3519dc4519d02e80300c600cc949d00ce00d18800cf00d28800d000d39d00cb641976a91481ec21969399d15c26af089d5db437ead066c5ba88ac00cd788821024ffcc0481629866671d89f05f3da813a2aacec1b52e69b8c0c586b665f5d4574ba6752b27523aa20df65a90e9becc316ff5aca44d4e06dfaade56622f32bafa197aba706c5e589758700cd8768"
bch_lock_spend_script = "473045022100a0161ea14d3b41ed41250c8474fc8ec6ce1cab8df7f401e69ecf77c2ab63d82102207a2a57ddf2ea400e09ea059f3b261da96f5098858b17239931f3cc2fb929bb2a4c8ec3519dc4519d02e80300c600cc949d00ce00d18800cf00d28800d000d39d00cb641976a91481ec21969399d15c26af089d5db437ead066c5ba88ac00cd788821024ffcc0481629866671d89f05f3da813a2aacec1b52e69b8c0c586b665f5d4574ba6752b27523aa20df65a90e9becc316ff5aca44d4e06dfaade56622f32bafa197aba706c5e589758700cd8768"
bch_lock_swipe_script = "4c8fc3519dc4519d02e80300c600cc949d00ce00d18800cf00d28800d000d39d00cb641976a9141ab50aedd2e48297073f0f6eef46f97b37c9354e88ac00cd7888210234fe304a5b129b8265c177c92aa40b7840e8303f8b0fcca2359023163c7c2768ba670120b27523aa20191b09e40d1277fa14fea1e9b41e4fcc4528c9cb77e39e1b7b1a0b3332180cb78700cd8768"
coin_settings = {'rpcport': 0, 'rpcauth': 'none', 'blocks_confirmed': 1, 'conf_target': 1, 'use_segwit': False, 'connection_type': 'rpc'}
coin_settings = {
"rpcport": 0,
"rpcauth": "none",
"blocks_confirmed": 1,
"conf_target": 1,
"use_segwit": False,
"connection_type": "rpc",
}
class TestXmrBchSwapInterface(unittest.TestCase):
@ -79,12 +90,16 @@ class TestXmrBchSwapInterface(unittest.TestCase):
ci.extractScriptLockScriptValues(script_bytes)
script_bytes = CScript(bytes.fromhex(bch_lock_spend_script))
signature, mining_fee, out_1, out_2, public_key, timelock = ci.extractScriptLockScriptValuesFromScriptSig(script_bytes)
ensure(signature is not None, 'signature not present')
signature, mining_fee, out_1, out_2, public_key, timelock = (
ci.extractScriptLockScriptValuesFromScriptSig(script_bytes)
)
ensure(signature is not None, "signature not present")
script_bytes = CScript(bytes.fromhex(bch_lock_swipe_script))
signature, mining_fee, out_1, out_2, public_key, timelock = ci.extractScriptLockScriptValuesFromScriptSig(script_bytes)
ensure(signature is None, 'signature present')
signature, mining_fee, out_1, out_2, public_key, timelock = (
ci.extractScriptLockScriptValuesFromScriptSig(script_bytes)
)
ensure(signature is None, "signature present")
class TestBCH(BasicSwapTest):
@ -100,26 +115,47 @@ class TestBCH(BasicSwapTest):
@classmethod
def prepareExtraDataDir(cls, i):
if not cls.restore_instance:
data_dir = prepareDataDir(cfg.TEST_DATADIRS, i, 'bitcoin.conf', 'bch_', base_p2p_port=BCH_BASE_PORT, base_rpc_port=BCH_BASE_RPC_PORT)
data_dir = prepareDataDir(
cfg.TEST_DATADIRS,
i,
"bitcoin.conf",
"bch_",
base_p2p_port=BCH_BASE_PORT,
base_rpc_port=BCH_BASE_RPC_PORT,
)
# Rewrite conf file
config_filename: str = os.path.join(cfg.TEST_DATADIRS, 'bch_' + str(i), 'bitcoin.conf')
with open(config_filename, 'r') as fp:
config_filename: str = os.path.join(
cfg.TEST_DATADIRS, "bch_" + str(i), "bitcoin.conf"
)
with open(config_filename, "r") as fp:
lines = fp.readlines()
with open(config_filename, 'w') as fp:
with open(config_filename, "w") as fp:
for line in lines:
if not line.startswith('findpeers'):
if not line.startswith("findpeers"):
fp.write(line)
if os.path.exists(os.path.join(BITCOINCASH_BINDIR, 'bitcoin-wallet')):
if os.path.exists(os.path.join(BITCOINCASH_BINDIR, "bitcoin-wallet")):
try:
callrpc_cli(BITCOINCASH_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat create', 'bitcoin-wallet')
callrpc_cli(
BITCOINCASH_BINDIR,
data_dir,
"regtest",
"-wallet=wallet.dat create",
"bitcoin-wallet",
)
except Exception as e:
logging.warning('bch: bitcoin-wallet create failed')
logging.warning("bch: bitcoin-wallet create failed")
raise e
cls.bch_daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, 'bch_' + str(i)), BITCOINCASH_BINDIR, BITCOINCASHD))
logging.info('BCH: Started %s %d', BITCOINCASHD, cls.bch_daemons[-1].handle.pid)
cls.bch_daemons.append(
startDaemon(
os.path.join(cfg.TEST_DATADIRS, "bch_" + str(i)),
BITCOINCASH_BINDIR,
BITCOINCASHD,
)
)
logging.info("BCH: Started %s %d", BITCOINCASHD, cls.bch_daemons[-1].handle.pid)
waitForRPC(make_rpc_func(i, base_rpc_port=BCH_BASE_RPC_PORT), test_delay_event)
@classmethod
@ -128,24 +164,36 @@ class TestBCH(BasicSwapTest):
@classmethod
def prepareExtraCoins(cls):
cls.bch_addr = callnoderpc(0, 'getnewaddress', ['mining_addr'], base_rpc_port=BCH_BASE_RPC_PORT, wallet='wallet.dat')
cls.bch_addr = callnoderpc(
0,
"getnewaddress",
["mining_addr"],
base_rpc_port=BCH_BASE_RPC_PORT,
wallet="wallet.dat",
)
if not cls.restore_instance:
num_blocks: int = 200
logging.info('Mining %d BitcoinCash blocks to %s', num_blocks, cls.bch_addr)
callnoderpc(0, 'generatetoaddress', [num_blocks, cls.bch_addr], base_rpc_port=BCH_BASE_RPC_PORT, wallet='wallet.dat')
logging.info("Mining %d BitcoinCash blocks to %s", num_blocks, cls.bch_addr)
callnoderpc(
0,
"generatetoaddress",
[num_blocks, cls.bch_addr],
base_rpc_port=BCH_BASE_RPC_PORT,
wallet="wallet.dat",
)
@classmethod
def addCoinSettings(cls, settings, datadir, node_id):
settings['chainclients']['bitcoincash'] = {
'connection_type': 'rpc',
'manage_daemon': False,
'rpcport': BCH_BASE_RPC_PORT + node_id,
'rpcuser': 'test' + str(node_id),
'rpcpassword': 'test_pass' + str(node_id),
'datadir': os.path.join(datadir, 'bch_' + str(node_id)),
'bindir': BITCOINCASH_BINDIR,
'use_segwit': False,
settings["chainclients"]["bitcoincash"] = {
"connection_type": "rpc",
"manage_daemon": False,
"rpcport": BCH_BASE_RPC_PORT + node_id,
"rpcuser": "test" + str(node_id),
"rpcpassword": "test_pass" + str(node_id),
"datadir": os.path.join(datadir, "bch_" + str(node_id)),
"bindir": BITCOINCASH_BINDIR,
"use_segwit": False,
}
@classmethod
@ -154,60 +202,88 @@ class TestBCH(BasicSwapTest):
ci0 = cls.swap_clients[0].ci(cls.test_coin)
try:
if cls.bch_addr is not None:
ci0.rpc_wallet('generatetoaddress', [1, cls.bch_addr])
ci0.rpc_wallet("generatetoaddress", [1, cls.bch_addr])
except Exception as e:
logging.warning('coins_loop generate {}'.format(e))
logging.warning("coins_loop generate {}".format(e))
@classmethod
def tearDownClass(cls):
logging.info('Finalising Bitcoincash Test')
logging.info("Finalising Bitcoincash Test")
super(TestBCH, cls).tearDownClass()
stopDaemons(cls.bch_daemons)
cls.bch_daemons.clear()
def mineBlock(self, num_blocks=1):
self.callnoderpc('generatetoaddress', [num_blocks, self.bch_addr])
self.callnoderpc("generatetoaddress", [num_blocks, self.bch_addr])
def check_softfork_active(self, feature_name):
return True
def test_001_nested_segwit(self):
logging.info('---------- Test {} p2sh nested segwit'.format(self.test_coin.name))
logging.info('Skipped')
logging.info(
"---------- Test {} p2sh nested segwit".format(self.test_coin.name)
)
logging.info("Skipped")
def test_002_native_segwit(self):
logging.info('---------- Test {} p2sh native segwit'.format(self.test_coin.name))
logging.info('Skipped')
logging.info(
"---------- Test {} p2sh native segwit".format(self.test_coin.name)
)
logging.info("Skipped")
def test_003_cltv(self):
logging.info('---------- Test {} cltv'.format(self.test_coin.name))
logging.info("---------- Test {} cltv".format(self.test_coin.name))
ci = self.swap_clients[0].ci(self.test_coin)
self.check_softfork_active('bip65')
self.check_softfork_active("bip65")
chain_height = self.callnoderpc('getblockcount')
script = CScript([chain_height + 3, OP_CHECKLOCKTIMEVERIFY, ])
chain_height = self.callnoderpc("getblockcount")
script = CScript(
[
chain_height + 3,
OP_CHECKLOCKTIMEVERIFY,
]
)
script_dest = ci.getScriptDest(script)
tx = CTransaction()
tx.nVersion = ci.txVersion()
tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest))
tx_hex = ToHex(tx)
tx_funded = ci.rpc_wallet('fundrawtransaction', [tx_hex])
utxo_pos = 0 if tx_funded['changepos'] == 1 else 1
tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex']
txid = ci.rpc('sendrawtransaction', [tx_signed, ])
tx_funded = ci.rpc_wallet("fundrawtransaction", [tx_hex])
utxo_pos = 0 if tx_funded["changepos"] == 1 else 1
tx_signed = ci.rpc_wallet(
"signrawtransactionwithwallet",
[
tx_funded["hex"],
],
)["hex"]
txid = ci.rpc(
"sendrawtransaction",
[
tx_signed,
],
)
addr_out = ci.rpc_wallet('getnewaddress', ['cltv test'])
addr_out = ci.rpc_wallet("getnewaddress", ["cltv test"])
pkh = ci.decodeAddress(addr_out)
script_out = ci.getScriptForPubkeyHash(pkh)
tx_spend = CTransaction()
tx_spend.nVersion = ci.txVersion()
tx_spend.nLockTime = chain_height + 3
tx_spend.vin.append(CTxIn(COutPoint(int(txid, 16), utxo_pos), scriptSig=CScript([script,])))
tx_spend.vin.append(
CTxIn(
COutPoint(int(txid, 16), utxo_pos),
scriptSig=CScript(
[
script,
]
),
)
)
tx_spend.vout.append(ci.txoType()(ci.make_int(1.0999), script_out))
tx_spend_hex = ToHex(tx_spend)
@ -216,116 +292,205 @@ class TestBCH(BasicSwapTest):
for tx_hex in [tx_spend_invalid_hex, tx_spend_hex]:
try:
txid = self.callnoderpc('sendrawtransaction', [tx_hex, ])
txid = self.callnoderpc(
"sendrawtransaction",
[
tx_hex,
],
)
except Exception as e:
assert ('non-final' in str(e))
assert "non-final" in str(e)
else:
assert False, 'Should fail'
assert False, "Should fail"
self.mineBlock(5)
try:
txid = ci.rpc('sendrawtransaction', [tx_spend_invalid_hex, ])
txid = ci.rpc(
"sendrawtransaction",
[
tx_spend_invalid_hex,
],
)
except Exception as e:
assert ('Locktime requirement not satisfied' in str(e))
assert "Locktime requirement not satisfied" in str(e)
else:
assert False, 'Should fail'
assert False, "Should fail"
txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ])
txid = ci.rpc(
"sendrawtransaction",
[
tx_spend_hex,
],
)
self.mineBlock()
ro = ci.rpc_wallet('listreceivedbyaddress', [0, ])
ro = ci.rpc_wallet(
"listreceivedbyaddress",
[
0,
],
)
sum_addr = 0
for entry in ro:
if entry['address'] == addr_out:
sum_addr += entry['amount']
assert (sum_addr == 1.0999)
if entry["address"] == addr_out:
sum_addr += entry["amount"]
assert sum_addr == 1.0999
# Ensure tx was mined
tx_wallet = ci.rpc_wallet('gettransaction', [txid, ])
assert (len(tx_wallet['blockhash']) == 64)
tx_wallet = ci.rpc_wallet(
"gettransaction",
[
txid,
],
)
assert len(tx_wallet["blockhash"]) == 64
def test_004_csv(self):
logging.info('---------- Test {} csv'.format(self.test_coin.name))
logging.info("---------- Test {} csv".format(self.test_coin.name))
swap_clients = self.swap_clients
ci = self.swap_clients[0].ci(self.test_coin)
self.check_softfork_active('csv')
self.check_softfork_active("csv")
script = CScript([3, OP_CHECKSEQUENCEVERIFY, ])
script = CScript(
[
3,
OP_CHECKSEQUENCEVERIFY,
]
)
script_dest = ci.getScriptDest(script)
tx = CTransaction()
tx.nVersion = ci.txVersion()
tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest))
tx_hex = ToHex(tx)
tx_funded = ci.rpc_wallet('fundrawtransaction', [tx_hex])
utxo_pos = 0 if tx_funded['changepos'] == 1 else 1
tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex']
txid = ci.rpc('sendrawtransaction', [tx_signed, ])
tx_funded = ci.rpc_wallet("fundrawtransaction", [tx_hex])
utxo_pos = 0 if tx_funded["changepos"] == 1 else 1
tx_signed = ci.rpc_wallet(
"signrawtransactionwithwallet",
[
tx_funded["hex"],
],
)["hex"]
txid = ci.rpc(
"sendrawtransaction",
[
tx_signed,
],
)
addr_out = ci.rpc_wallet('getnewaddress', ['csv test'])
addr_out = ci.rpc_wallet("getnewaddress", ["csv test"])
pkh = ci.decodeAddress(addr_out)
script_out = ci.getScriptForPubkeyHash(pkh)
# Double check output type
prev_tx = ci.rpc('decoderawtransaction', [tx_signed, ])
assert (prev_tx['vout'][utxo_pos]['scriptPubKey']['type'] == 'scripthash')
prev_tx = ci.rpc(
"decoderawtransaction",
[
tx_signed,
],
)
assert prev_tx["vout"][utxo_pos]["scriptPubKey"]["type"] == "scripthash"
tx_spend = CTransaction()
tx_spend.nVersion = ci.txVersion()
tx_spend.vin.append(CTxIn(COutPoint(int(txid, 16), utxo_pos),
nSequence=3,
scriptSig=CScript([script,])))
tx_spend.vin.append(
CTxIn(
COutPoint(int(txid, 16), utxo_pos),
nSequence=3,
scriptSig=CScript(
[
script,
]
),
)
)
tx_spend.vout.append(ci.txoType()(ci.make_int(1.0999), script_out))
tx_spend_hex = ToHex(tx_spend)
try:
txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ])
txid = ci.rpc(
"sendrawtransaction",
[
tx_spend_hex,
],
)
except Exception as e:
assert ('non-BIP68-final' in str(e))
assert "non-BIP68-final" in str(e)
else:
assert False, 'Should fail'
assert False, "Should fail"
self.mineBlock(3)
txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ])
txid = ci.rpc(
"sendrawtransaction",
[
tx_spend_hex,
],
)
self.mineBlock(1)
ro = ci.rpc_wallet('listreceivedbyaddress', [0, ])
ro = ci.rpc_wallet(
"listreceivedbyaddress",
[
0,
],
)
sum_addr = 0
for entry in ro:
if entry['address'] == addr_out:
sum_addr += entry['amount']
assert (sum_addr == 1.0999)
if entry["address"] == addr_out:
sum_addr += entry["amount"]
assert sum_addr == 1.0999
# Ensure tx was mined
tx_wallet = ci.rpc_wallet('gettransaction', [txid, ])
assert (len(tx_wallet['blockhash']) == 64)
tx_wallet = ci.rpc_wallet(
"gettransaction",
[
txid,
],
)
assert len(tx_wallet["blockhash"]) == 64
def test_005_watchonly(self):
logging.info('---------- Test {} watchonly'.format(self.test_coin.name))
logging.info("---------- Test {} watchonly".format(self.test_coin.name))
ci = self.swap_clients[0].ci(self.test_coin)
ci1 = self.swap_clients[1].ci(self.test_coin)
addr = ci.rpc_wallet('getnewaddress', ['watchonly test'])
ro = ci1.rpc_wallet('importaddress', [addr, '', False])
txid = ci.rpc_wallet('sendtoaddress', [addr, 1.0])
tx_hex = ci.rpc('getrawtransaction', [txid, ])
ci1.rpc_wallet('sendrawtransaction', [tx_hex, ])
ro = ci1.rpc_wallet('gettransaction', [txid, ])
assert (ro['txid'] == txid)
addr = ci.rpc_wallet("getnewaddress", ["watchonly test"])
ro = ci1.rpc_wallet("importaddress", [addr, "", False])
txid = ci.rpc_wallet("sendtoaddress", [addr, 1.0])
tx_hex = ci.rpc(
"getrawtransaction",
[
txid,
],
)
ci1.rpc_wallet(
"sendrawtransaction",
[
tx_hex,
],
)
ro = ci1.rpc_wallet(
"gettransaction",
[
txid,
],
)
assert ro["txid"] == txid
def test_006_getblock_verbosity(self):
super().test_006_getblock_verbosity()
def test_007_hdwallet(self):
logging.info('---------- Test {} hdwallet'.format(self.test_coin.name))
logging.info("---------- Test {} hdwallet".format(self.test_coin.name))
test_seed = '8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b'
test_wif = self.swap_clients[0].ci(self.test_coin).encodeKey(bytes.fromhex(test_seed))
test_seed = "8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b"
test_wif = (
self.swap_clients[0].ci(self.test_coin).encodeKey(bytes.fromhex(test_seed))
)
new_wallet_name = random.randbytes(10).hex()
self.callnoderpc('createwallet', [new_wallet_name])
self.callnoderpc('sethdseed', [True, test_wif], wallet=new_wallet_name)
addr = self.callnoderpc('getnewaddress', wallet=new_wallet_name)
self.callnoderpc('unloadwallet', [new_wallet_name])
assert (addr == 'bchreg:qqxr67wf5ltty5jvm44zryywmpt7ntdaa50carjt59')
self.callnoderpc("createwallet", [new_wallet_name])
self.callnoderpc("sethdseed", [True, test_wif], wallet=new_wallet_name)
addr = self.callnoderpc("getnewaddress", wallet=new_wallet_name)
self.callnoderpc("unloadwallet", [new_wallet_name])
assert addr == "bchreg:qqxr67wf5ltty5jvm44zryywmpt7ntdaa50carjt59"
def test_008_gettxout(self):
super().test_008_gettxout()
@ -334,7 +499,7 @@ class TestBCH(BasicSwapTest):
super().test_009_scantxoutset()
def test_010_txn_size(self):
logging.info('---------- Test {} txn_size'.format(Coins.BCH))
logging.info("---------- Test {} txn_size".format(Coins.BCH))
swap_clients = self.swap_clients
ci = swap_clients[0].ci(Coins.BCH)
@ -343,7 +508,7 @@ class TestBCH(BasicSwapTest):
amount: int = ci.make_int(random.uniform(0.1, 2.0), r=1)
# Record unspents before createSCLockTx as the used ones will be locked
unspents = ci.rpc('listunspent')
unspents = ci.rpc("listunspent")
# fee_rate is in sats/B
fee_rate: int = 1
@ -355,29 +520,28 @@ class TestBCH(BasicSwapTest):
B = ci.getPubkey(b)
mining_fee = 1000
timelock = 2
b_receive = ci.getNewAddress()
a_refund = ci.getNewAddress()
refundExtraArgs = dict()
lockExtraArgs = dict()
refundExtraArgs['mining_fee'] = 1000
refundExtraArgs['out_1'] = ci.addressToLockingBytecode(a_refund)
refundExtraArgs['out_2'] = ci.addressToLockingBytecode(b_receive)
refundExtraArgs['public_key'] = B
refundExtraArgs['timelock'] = 5
refundExtraArgs["mining_fee"] = 1000
refundExtraArgs["out_1"] = ci.addressToLockingBytecode(a_refund)
refundExtraArgs["out_2"] = ci.addressToLockingBytecode(b_receive)
refundExtraArgs["public_key"] = B
refundExtraArgs["timelock"] = 5
refund_lock_tx_script = pi.genScriptLockTxScript(ci, A, B, **refundExtraArgs)
# will make use of this in `createSCLockRefundTx`
refundExtraArgs['refund_lock_tx_script'] = refund_lock_tx_script
refundExtraArgs["refund_lock_tx_script"] = refund_lock_tx_script
# lock script
lockExtraArgs['mining_fee'] = 1000
lockExtraArgs['out_1'] = ci.addressToLockingBytecode(b_receive)
lockExtraArgs['out_2'] = ci.scriptToP2SH32LockingBytecode(refund_lock_tx_script)
lockExtraArgs['public_key'] = A
lockExtraArgs['timelock'] = 2
lockExtraArgs["mining_fee"] = 1000
lockExtraArgs["out_1"] = ci.addressToLockingBytecode(b_receive)
lockExtraArgs["out_2"] = ci.scriptToP2SH32LockingBytecode(refund_lock_tx_script)
lockExtraArgs["public_key"] = A
lockExtraArgs["timelock"] = 2
lock_tx_script = pi.genScriptLockTxScript(ci, A, B, **lockExtraArgs)
@ -386,36 +550,35 @@ class TestBCH(BasicSwapTest):
lock_tx = ci.signTxWithWallet(lock_tx)
print(lock_tx.hex())
unspents_after = ci.rpc('listunspent')
assert (len(unspents) > len(unspents_after))
unspents_after = ci.rpc("listunspent")
assert len(unspents) > len(unspents_after)
tx_decoded = ci.rpc('decoderawtransaction', [lock_tx.hex()])
txid = tx_decoded['txid']
tx_decoded = ci.rpc("decoderawtransaction", [lock_tx.hex()])
txid = tx_decoded["txid"]
vsize = tx_decoded['size']
vsize = tx_decoded["size"]
expect_fee_int = round(fee_rate * vsize)
expect_fee = ci.format_amount(expect_fee_int)
out_value: int = 0
for txo in tx_decoded['vout']:
if 'value' in txo:
out_value += ci.make_int(txo['value'])
for txo in tx_decoded["vout"]:
if "value" in txo:
out_value += ci.make_int(txo["value"])
in_value: int = 0
for txi in tx_decoded['vin']:
for txi in tx_decoded["vin"]:
for utxo in unspents:
if 'vout' not in utxo:
if "vout" not in utxo:
continue
if utxo['txid'] == txi['txid'] and utxo['vout'] == txi['vout']:
in_value += ci.make_int(utxo['amount'])
if utxo["txid"] == txi["txid"] and utxo["vout"] == txi["vout"]:
in_value += ci.make_int(utxo["amount"])
break
fee_value = in_value - out_value
ci.rpc('sendrawtransaction', [lock_tx.hex()])
rv = ci.rpc('gettransaction', [txid])
wallet_tx_fee = -ci.make_int(rv['fee'])
ci.rpc("sendrawtransaction", [lock_tx.hex()])
rv = ci.rpc("gettransaction", [txid])
wallet_tx_fee = -ci.make_int(rv["fee"])
assert (wallet_tx_fee == fee_value)
assert (wallet_tx_fee == expect_fee_int)
assert wallet_tx_fee == fee_value
assert wallet_tx_fee == expect_fee_int
pkh_out = ci.decodeAddress(b_receive)
@ -425,126 +588,219 @@ class TestBCH(BasicSwapTest):
aAdaptorSig = ecdsaotves_enc_sign(a, B, msg)
# alice verifies the adaptor signature
assert (ecdsaotves_enc_verify(A, B, msg, aAdaptorSig))
assert ecdsaotves_enc_verify(A, B, msg, aAdaptorSig)
# alice decrypts the adaptor signature
aAdaptorSig_dec = ecdsaotves_dec_sig(b, aAdaptorSig)
fee_info = {}
lock_spend_tx = ci.createSCLockSpendTx(lock_tx, lock_tx_script, pkh_out, mining_fee, fee_info=fee_info, ves=aAdaptorSig_dec)
vsize_estimated: int = fee_info['vsize']
lock_spend_tx = ci.createSCLockSpendTx(
lock_tx,
lock_tx_script,
pkh_out,
mining_fee,
fee_info=fee_info,
ves=aAdaptorSig_dec,
)
vsize_estimated: int = fee_info["vsize"]
tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()])
print('lock_spend_tx', lock_spend_tx.hex(), '\n', 'tx_decoded', tx_decoded)
txid = tx_decoded['txid']
tx_decoded = ci.rpc("decoderawtransaction", [lock_spend_tx.hex()])
print("lock_spend_tx", lock_spend_tx.hex(), "\n", "tx_decoded", tx_decoded)
txid = tx_decoded["txid"]
tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()])
vsize_actual: int = tx_decoded['size']
tx_decoded = ci.rpc("decoderawtransaction", [lock_spend_tx.hex()])
vsize_actual: int = tx_decoded["size"]
assert (vsize_actual <= vsize_estimated and vsize_estimated - vsize_actual < 4)
assert (ci.rpc('sendrawtransaction', [lock_spend_tx.hex()]) == txid)
assert vsize_actual <= vsize_estimated and vsize_estimated - vsize_actual < 4
assert ci.rpc("sendrawtransaction", [lock_spend_tx.hex()]) == txid
expect_size: int = ci.xmr_swap_a_lock_spend_tx_vsize()
assert (expect_size >= vsize_actual)
assert (expect_size - vsize_actual < 10)
assert expect_size >= vsize_actual
assert expect_size - vsize_actual < 10
def test_011_p2sh(self):
# Not used in bsx for native-segwit coins
logging.info('---------- Test {} p2sh'.format(self.test_coin.name))
logging.info("---------- Test {} p2sh".format(self.test_coin.name))
swap_clients = self.swap_clients
ci = self.swap_clients[0].ci(self.test_coin)
script = CScript([2, 2, OP_EQUAL, ])
script = CScript(
[
2,
2,
OP_EQUAL,
]
)
script_dest = ci.get_p2sh_script_pubkey(script)
tx = CTransaction()
tx.nVersion = ci.txVersion()
tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest))
tx_hex = ToHex(tx)
tx_funded = ci.rpc_wallet('fundrawtransaction', [tx_hex])
utxo_pos = 0 if tx_funded['changepos'] == 1 else 1
tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex']
txid = ci.rpc('sendrawtransaction', [tx_signed, ])
tx_funded = ci.rpc_wallet("fundrawtransaction", [tx_hex])
utxo_pos = 0 if tx_funded["changepos"] == 1 else 1
tx_signed = ci.rpc_wallet(
"signrawtransactionwithwallet",
[
tx_funded["hex"],
],
)["hex"]
txid = ci.rpc(
"sendrawtransaction",
[
tx_signed,
],
)
addr_out = ci.rpc_wallet('getnewaddress', ['csv test'])
addr_out = ci.rpc_wallet("getnewaddress", ["csv test"])
pkh = ci.decodeAddress(addr_out)
script_out = ci.getScriptForPubkeyHash(pkh)
# Double check output type
prev_tx = ci.rpc('decoderawtransaction', [tx_signed, ])
assert (prev_tx['vout'][utxo_pos]['scriptPubKey']['type'] == 'scripthash')
prev_tx = ci.rpc(
"decoderawtransaction",
[
tx_signed,
],
)
assert prev_tx["vout"][utxo_pos]["scriptPubKey"]["type"] == "scripthash"
tx_spend = CTransaction()
tx_spend.nVersion = ci.txVersion()
tx_spend.vin.append(CTxIn(COutPoint(int(txid, 16), utxo_pos),
scriptSig=CScript([script,])))
tx_spend.vin.append(
CTxIn(
COutPoint(int(txid, 16), utxo_pos),
scriptSig=CScript(
[
script,
]
),
)
)
tx_spend.vout.append(ci.txoType()(ci.make_int(1.0999), script_out))
tx_spend_hex = ToHex(tx_spend)
txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ])
txid = ci.rpc(
"sendrawtransaction",
[
tx_spend_hex,
],
)
self.mineBlock(1)
ro = ci.rpc_wallet('listreceivedbyaddress', [0, ])
ro = ci.rpc_wallet(
"listreceivedbyaddress",
[
0,
],
)
sum_addr = 0
for entry in ro:
if entry['address'] == addr_out:
sum_addr += entry['amount']
assert (sum_addr == 1.0999)
if entry["address"] == addr_out:
sum_addr += entry["amount"]
assert sum_addr == 1.0999
# Ensure tx was mined
tx_wallet = ci.rpc_wallet('gettransaction', [txid, ])
assert (len(tx_wallet['blockhash']) == 64)
tx_wallet = ci.rpc_wallet(
"gettransaction",
[
txid,
],
)
assert len(tx_wallet["blockhash"]) == 64
def test_011_p2sh32(self):
# Not used in bsx for native-segwit coins
logging.info('---------- Test {} p2sh32'.format(self.test_coin.name))
logging.info("---------- Test {} p2sh32".format(self.test_coin.name))
swap_clients = self.swap_clients
ci = self.swap_clients[0].ci(self.test_coin)
script = CScript([2, 2, OP_EQUAL, ])
script = CScript(
[
2,
2,
OP_EQUAL,
]
)
script_dest = ci.scriptToP2SH32LockingBytecode(script)
tx = CTransaction()
tx.nVersion = ci.txVersion()
tx.vout.append(ci.txoType()(ci.make_int(1.1), script_dest))
tx_hex = ToHex(tx)
tx_funded = ci.rpc_wallet('fundrawtransaction', [tx_hex])
utxo_pos = 0 if tx_funded['changepos'] == 1 else 1
tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded['hex'], ])['hex']
txid = ci.rpc('sendrawtransaction', [tx_signed, ])
tx_funded = ci.rpc_wallet("fundrawtransaction", [tx_hex])
utxo_pos = 0 if tx_funded["changepos"] == 1 else 1
tx_signed = ci.rpc_wallet(
"signrawtransactionwithwallet",
[
tx_funded["hex"],
],
)["hex"]
txid = ci.rpc(
"sendrawtransaction",
[
tx_signed,
],
)
addr_out = ci.rpc_wallet('getnewaddress', ['csv test'])
addr_out = ci.rpc_wallet("getnewaddress", ["csv test"])
pkh = ci.decodeAddress(addr_out)
script_out = ci.getScriptForPubkeyHash(pkh)
# Double check output type
prev_tx = ci.rpc('decoderawtransaction', [tx_signed, ])
assert (prev_tx['vout'][utxo_pos]['scriptPubKey']['type'] == 'scripthash')
prev_tx = ci.rpc(
"decoderawtransaction",
[
tx_signed,
],
)
assert prev_tx["vout"][utxo_pos]["scriptPubKey"]["type"] == "scripthash"
tx_spend = CTransaction()
tx_spend.nVersion = ci.txVersion()
tx_spend.vin.append(CTxIn(COutPoint(int(txid, 16), utxo_pos),
scriptSig=CScript([script,])))
tx_spend.vin.append(
CTxIn(
COutPoint(int(txid, 16), utxo_pos),
scriptSig=CScript(
[
script,
]
),
)
)
tx_spend.vout.append(ci.txoType()(ci.make_int(1.0999), script_out))
tx_spend_hex = ToHex(tx_spend)
txid = ci.rpc('sendrawtransaction', [tx_spend_hex, ])
txid = ci.rpc(
"sendrawtransaction",
[
tx_spend_hex,
],
)
self.mineBlock(1)
ro = ci.rpc_wallet('listreceivedbyaddress', [0, ])
ro = ci.rpc_wallet(
"listreceivedbyaddress",
[
0,
],
)
sum_addr = 0
for entry in ro:
if entry['address'] == addr_out:
sum_addr += entry['amount']
assert (sum_addr == 1.0999)
if entry["address"] == addr_out:
sum_addr += entry["amount"]
assert sum_addr == 1.0999
# Ensure tx was mined
tx_wallet = ci.rpc_wallet('gettransaction', [txid, ])
assert (len(tx_wallet['blockhash']) == 64)
tx_wallet = ci.rpc_wallet(
"gettransaction",
[
txid,
],
)
assert len(tx_wallet["blockhash"]) == 64
def test_012_p2sh_p2wsh(self):
logging.info('---------- Test {} p2sh-p2wsh'.format(self.test_coin.name))
logging.info('Skipped')
logging.info("---------- Test {} p2sh-p2wsh".format(self.test_coin.name))
logging.info("Skipped")
def test_01_a_full_swap(self):
super().test_01_a_full_swap()
@ -564,12 +820,16 @@ class TestBCH(BasicSwapTest):
super().test_02_a_leader_recover_a_lock_tx()
def test_03_a_follower_recover_a_lock_tx(self):
self.do_test_03_follower_recover_a_lock_tx(self.test_coin_from, Coins.XMR, with_mercy=True)
self.do_test_03_follower_recover_a_lock_tx(
self.test_coin_from, Coins.XMR, with_mercy=True
)
def test_03_b_follower_recover_a_lock_tx_reverse(self):
self.prepare_balance(Coins.BCH, 100.0, 1801, 1800)
self.prepare_balance(Coins.XMR, 100.0, 1800, 1801)
self.do_test_03_follower_recover_a_lock_tx(Coins.XMR, self.test_coin_from, lock_value=12, with_mercy=True)
self.do_test_03_follower_recover_a_lock_tx(
Coins.XMR, self.test_coin_from, lock_value=12, with_mercy=True
)
def test_03_c_follower_recover_a_lock_tx_to_part(self):
super().test_03_c_follower_recover_a_lock_tx_to_part()
@ -610,8 +870,8 @@ class TestBCH(BasicSwapTest):
def test_06_preselect_inputs(self):
tla_from = self.test_coin.name
logging.info('---------- Test {} Preselected inputs'.format(tla_from))
logging.info('Skipped')
logging.info("---------- Test {} Preselected inputs".format(tla_from))
logging.info("Skipped")
def test_07_expire_stuck_accepted(self):
super().test_07_expire_stuck_accepted()

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021-2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -40,64 +41,112 @@ class TestLTC(BasicSwapTest):
base_rpc_port = LTC_BASE_RPC_PORT
def mineBlock(self, num_blocks=1):
self.callnoderpc('generatetoaddress', [num_blocks, self.ltc_addr])
self.callnoderpc("generatetoaddress", [num_blocks, self.ltc_addr])
def check_softfork_active(self, feature_name):
deploymentinfo = self.callnoderpc('getblockchaininfo')
assert (deploymentinfo['softforks'][feature_name]['active'] is True)
deploymentinfo = self.callnoderpc("getblockchaininfo")
assert deploymentinfo["softforks"][feature_name]["active"] is True
def test_001_nested_segwit(self):
logging.info('---------- Test {} p2sh nested segwit'.format(self.test_coin_from.name))
logging.info('Skipped')
logging.info(
"---------- Test {} p2sh nested segwit".format(self.test_coin_from.name)
)
logging.info("Skipped")
def test_002_native_segwit(self):
logging.info('---------- Test {} p2sh native segwit'.format(self.test_coin_from.name))
logging.info(
"---------- Test {} p2sh native segwit".format(self.test_coin_from.name)
)
ci = self.swap_clients[0].ci(self.test_coin_from)
addr_segwit = ci.rpc_wallet('getnewaddress', ['segwit test', 'bech32'])
addr_info = ci.rpc_wallet('getaddressinfo', [addr_segwit, ])
assert addr_info['iswitness'] is True
addr_segwit = ci.rpc_wallet("getnewaddress", ["segwit test", "bech32"])
addr_info = ci.rpc_wallet(
"getaddressinfo",
[
addr_segwit,
],
)
assert addr_info["iswitness"] is True
txid = ci.rpc_wallet('sendtoaddress', [addr_segwit, 1.0])
txid = ci.rpc_wallet("sendtoaddress", [addr_segwit, 1.0])
assert len(txid) == 64
tx_wallet = ci.rpc_wallet('gettransaction', [txid, ])['hex']
tx = ci.rpc('decoderawtransaction', [tx_wallet, ])
tx_wallet = ci.rpc_wallet(
"gettransaction",
[
txid,
],
)["hex"]
tx = ci.rpc(
"decoderawtransaction",
[
tx_wallet,
],
)
self.mineBlock()
ro = ci.rpc('scantxoutset', ['start', ['addr({})'.format(addr_segwit)]])
assert (len(ro['unspents']) == 1)
assert (ro['unspents'][0]['txid'] == txid)
ro = ci.rpc("scantxoutset", ["start", ["addr({})".format(addr_segwit)]])
assert len(ro["unspents"]) == 1
assert ro["unspents"][0]["txid"] == txid
prevout_n = -1
for txo in tx['vout']:
if addr_segwit in txo['scriptPubKey']['addresses']:
prevout_n = txo['n']
for txo in tx["vout"]:
if addr_segwit in txo["scriptPubKey"]["addresses"]:
prevout_n = txo["n"]
break
assert prevout_n > -1
tx_funded = ci.rpc('createrawtransaction', [[{'txid': txid, 'vout': prevout_n}], {addr_segwit: 0.99}])
tx_signed = ci.rpc_wallet('signrawtransactionwithwallet', [tx_funded, ])['hex']
tx_funded_decoded = ci.rpc('decoderawtransaction', [tx_funded, ])
tx_signed_decoded = ci.rpc('decoderawtransaction', [tx_signed, ])
assert tx_funded_decoded['txid'] == tx_signed_decoded['txid']
tx_funded = ci.rpc(
"createrawtransaction",
[[{"txid": txid, "vout": prevout_n}], {addr_segwit: 0.99}],
)
tx_signed = ci.rpc_wallet(
"signrawtransactionwithwallet",
[
tx_funded,
],
)["hex"]
tx_funded_decoded = ci.rpc(
"decoderawtransaction",
[
tx_funded,
],
)
tx_signed_decoded = ci.rpc(
"decoderawtransaction",
[
tx_signed,
],
)
assert tx_funded_decoded["txid"] == tx_signed_decoded["txid"]
def test_007_hdwallet(self):
logging.info('---------- Test {} hdwallet'.format(self.test_coin_from.name))
logging.info("---------- Test {} hdwallet".format(self.test_coin_from.name))
test_seed = '8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b'
test_wif = self.swap_clients[0].ci(self.test_coin_from).encodeKey(bytes.fromhex(test_seed))
test_seed = "8e54a313e6df8918df6d758fafdbf127a115175fdd2238d0e908dd8093c9ac3b"
test_wif = (
self.swap_clients[0]
.ci(self.test_coin_from)
.encodeKey(bytes.fromhex(test_seed))
)
new_wallet_name = random.randbytes(10).hex()
self.callnoderpc('createwallet', [new_wallet_name])
self.callnoderpc('sethdseed', [True, test_wif], wallet=new_wallet_name)
addr = self.callnoderpc('getnewaddress', wallet=new_wallet_name)
self.callnoderpc('unloadwallet', [new_wallet_name])
assert (addr == 'rltc1qps7hnjd866e9ynxadgseprkc2l56m00djr82la')
self.callnoderpc("createwallet", [new_wallet_name])
self.callnoderpc("sethdseed", [True, test_wif], wallet=new_wallet_name)
addr = self.callnoderpc("getnewaddress", wallet=new_wallet_name)
self.callnoderpc("unloadwallet", [new_wallet_name])
assert addr == "rltc1qps7hnjd866e9ynxadgseprkc2l56m00djr82la"
def test_20_btc_coin(self):
logging.info('---------- Test BTC to {}'.format(self.test_coin_from.name))
logging.info("---------- Test BTC to {}".format(self.test_coin_from.name))
swap_clients = self.swap_clients
offer_id = swap_clients[0].postOffer(Coins.BTC, self.test_coin_from, 100 * COIN, 0.1 * COIN, 100 * COIN, SwapTypes.SELLER_FIRST)
offer_id = swap_clients[0].postOffer(
Coins.BTC,
self.test_coin_from,
100 * COIN,
0.1 * COIN,
100 * COIN,
SwapTypes.SELLER_FIRST,
)
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
offer = swap_clients[1].getOffer(offer_id)
@ -107,147 +156,187 @@ class TestLTC(BasicSwapTest):
swap_clients[0].acceptBid(bid_id)
wait_for_in_progress(test_delay_event, swap_clients[1], bid_id, sent=True)
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=60)
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=60)
wait_for_bid(
test_delay_event,
swap_clients[0],
bid_id,
BidStates.SWAP_COMPLETED,
wait_for=60,
)
wait_for_bid(
test_delay_event,
swap_clients[1],
bid_id,
BidStates.SWAP_COMPLETED,
sent=True,
wait_for=60,
)
js_0 = read_json_api(1800)
js_1 = read_json_api(1801)
assert (js_0['num_swapping'] == 0 and js_0['num_watched_outputs'] == 0)
assert (js_1['num_swapping'] == 0 and js_1['num_watched_outputs'] == 0)
assert js_0["num_swapping"] == 0 and js_0["num_watched_outputs"] == 0
assert js_1["num_swapping"] == 0 and js_1["num_watched_outputs"] == 0
def test_21_mweb(self):
logging.info('---------- Test MWEB {}'.format(self.test_coin_from.name))
logging.info("---------- Test MWEB {}".format(self.test_coin_from.name))
swap_clients = self.swap_clients
ci0 = swap_clients[0].ci(self.test_coin_from)
ci1 = swap_clients[1].ci(self.test_coin_from)
mweb_addr_0 = ci0.rpc_wallet('getnewaddress', ['mweb addr test 0', 'mweb'])
mweb_addr_1 = ci1.rpc_wallet('getnewaddress', ['mweb addr test 1', 'mweb'])
mweb_addr_0 = ci0.rpc_wallet("getnewaddress", ["mweb addr test 0", "mweb"])
mweb_addr_1 = ci1.rpc_wallet("getnewaddress", ["mweb addr test 1", "mweb"])
addr_info0 = ci0.rpc_wallet('getaddressinfo', [mweb_addr_0,])
assert (addr_info0['ismweb'] is True)
addr_info0 = ci0.rpc_wallet(
"getaddressinfo",
[
mweb_addr_0,
],
)
assert addr_info0["ismweb"] is True
addr_info1 = ci1.rpc_wallet('getaddressinfo', [mweb_addr_1,])
assert (addr_info1['ismweb'] is True)
addr_info1 = ci1.rpc_wallet(
"getaddressinfo",
[
mweb_addr_1,
],
)
assert addr_info1["ismweb"] is True
trusted_before = ci0.rpc_wallet('getbalances')['mine']['trusted']
ci0.rpc_wallet('sendtoaddress', [mweb_addr_0, 10.0])
assert (trusted_before - float(ci0.rpc_wallet('getbalances')['mine']['trusted']) < 0.1)
trusted_before = ci0.rpc_wallet("getbalances")["mine"]["trusted"]
ci0.rpc_wallet("sendtoaddress", [mweb_addr_0, 10.0])
assert (
trusted_before - float(ci0.rpc_wallet("getbalances")["mine"]["trusted"])
< 0.1
)
try:
pause_event.clear() # Stop mining
ci0.rpc_wallet('sendtoaddress', [mweb_addr_1, 10.0])
ci0.rpc_wallet("sendtoaddress", [mweb_addr_1, 10.0])
found_unconfirmed: bool = False
for i in range(20):
test_delay_event.wait(1)
ltc_wallet = read_json_api(TEST_HTTP_PORT + 1, 'wallets/ltc')
if float(ltc_wallet['unconfirmed']) == 10.0:
ltc_wallet = read_json_api(TEST_HTTP_PORT + 1, "wallets/ltc")
if float(ltc_wallet["unconfirmed"]) == 10.0:
found_unconfirmed = True
break
finally:
pause_event.set()
assert (found_unconfirmed)
assert found_unconfirmed
self.mineBlock()
txns = ci0.rpc_wallet('listtransactions')
utxos = ci0.rpc_wallet('listunspent')
balances = ci0.rpc_wallet('getbalances')
wi = ci0.rpc_wallet('getwalletinfo')
txid = ci0.rpc_wallet('sendtoaddress', [mweb_addr_1, 10.0])
ci0.rpc_wallet("sendtoaddress", [mweb_addr_1, 10.0])
self.mineBlock()
txns = ci1.rpc_wallet('listtransactions')
utxos = ci1.rpc_wallet('listunspent')
balances = ci1.rpc_wallet('getbalances')
wi = ci1.rpc_wallet('getwalletinfo')
utxos = ci1.rpc_wallet("listunspent")
mweb_tx = None
for utxo in utxos:
if utxo.get('address', '') == mweb_addr_1:
if utxo.get("address", "") == mweb_addr_1:
mweb_tx = utxo
assert (mweb_tx is not None)
assert mweb_tx is not None
tx = ci1.rpc_wallet('gettransaction', [mweb_tx['txid'],])
blockhash = tx['blockhash']
block3 = ci1.rpc('getblock', [blockhash, 3])
block0 = ci1.rpc('getblock', [blockhash, 0])
require_amount: int = ci1.make_int(1)
unspent_addr = ci1.getUnspentsByAddr()
assert (len(unspent_addr) > 0)
assert len(unspent_addr) > 0
for addr, _ in unspent_addr.items():
if 'mweb1' in addr:
raise ValueError('getUnspentsByAddr should exclude mweb UTXOs.')
if "mweb1" in addr:
raise ValueError("getUnspentsByAddr should exclude mweb UTXOs.")
# TODO
def test_22_mweb_balance(self):
logging.info('---------- Test MWEB balance {}'.format(self.test_coin_from.name))
logging.info("---------- Test MWEB balance {}".format(self.test_coin_from.name))
swap_clients = self.swap_clients
ci_mweb = swap_clients[0].ci(Coins.LTC_MWEB)
mweb_addr_0 = ci_mweb.getNewAddress()
addr_info0 = ci_mweb.rpc_wallet('getaddressinfo', [mweb_addr_0,])
assert (addr_info0['ismweb'] is True)
addr_info0 = ci_mweb.rpc_wallet(
"getaddressinfo",
[
mweb_addr_0,
],
)
assert addr_info0["ismweb"] is True
ltc_addr = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc/nextdepositaddr')
ltc_mweb_addr = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc_mweb/nextdepositaddr')
ltc_mweb_addr2 = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc/newmwebaddress')
ltc_addr = read_json_api(TEST_HTTP_PORT + 0, "wallets/ltc/nextdepositaddr")
ltc_mweb_addr = read_json_api(
TEST_HTTP_PORT + 0, "wallets/ltc_mweb/nextdepositaddr"
)
ltc_mweb_addr2 = read_json_api(TEST_HTTP_PORT + 0, "wallets/ltc/newmwebaddress")
assert (ci_mweb.rpc_wallet('getaddressinfo', [ltc_addr,])['ismweb'] is False)
assert (ci_mweb.rpc_wallet('getaddressinfo', [ltc_mweb_addr,])['ismweb'] is True)
assert (ci_mweb.rpc_wallet('getaddressinfo', [ltc_mweb_addr2,])['ismweb'] is True)
assert (
ci_mweb.rpc_wallet(
"getaddressinfo",
[
ltc_addr,
],
)["ismweb"]
is False
)
assert (
ci_mweb.rpc_wallet(
"getaddressinfo",
[
ltc_mweb_addr,
],
)["ismweb"]
is True
)
assert (
ci_mweb.rpc_wallet(
"getaddressinfo",
[
ltc_mweb_addr2,
],
)["ismweb"]
is True
)
post_json = {
'value': 10,
'address': ltc_mweb_addr,
'subfee': False,
"value": 10,
"address": ltc_mweb_addr,
"subfee": False,
}
json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc/withdraw', post_json)
assert (len(json_rv['txid']) == 64)
json_rv = read_json_api(TEST_HTTP_PORT + 0, "wallets/ltc/withdraw", post_json)
assert len(json_rv["txid"]) == 64
self.mineBlock()
json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc', post_json)
assert (json_rv['mweb_balance'] == 10.0)
mweb_address = json_rv['mweb_address']
json_rv = read_json_api(TEST_HTTP_PORT + 0, "wallets/ltc", post_json)
assert json_rv["mweb_balance"] == 10.0
mweb_address = json_rv["mweb_address"]
post_json = {
'value': 11,
'address': mweb_address,
'subfee': False,
"value": 11,
"address": mweb_address,
"subfee": False,
}
json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc/withdraw', post_json)
assert (len(json_rv['txid']) == 64)
json_rv = read_json_api(TEST_HTTP_PORT + 0, "wallets/ltc/withdraw", post_json)
assert len(json_rv["txid"]) == 64
self.mineBlock()
json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc_mweb', post_json)
assert (json_rv['mweb_balance'] == 21.0)
assert (json_rv['mweb_address'] == mweb_address)
ltc_address = json_rv['deposit_address']
json_rv = read_json_api(TEST_HTTP_PORT + 0, "wallets/ltc_mweb", post_json)
assert json_rv["mweb_balance"] == 21.0
assert json_rv["mweb_address"] == mweb_address
ltc_address = json_rv["deposit_address"]
# Check that spending the mweb balance takes from the correct wallet
post_json = {
'value': 1,
'address': ltc_address,
'subfee': False,
'type_from': 'mweb',
"value": 1,
"address": ltc_address,
"subfee": False,
"type_from": "mweb",
}
json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc/withdraw', post_json)
assert (len(json_rv['txid']) == 64)
json_rv = read_json_api(TEST_HTTP_PORT + 0, "wallets/ltc/withdraw", post_json)
assert len(json_rv["txid"]) == 64
json_rv = read_json_api(TEST_HTTP_PORT + 0, 'wallets/ltc', post_json)
assert (json_rv['mweb_balance'] <= 20.0)
json_rv = read_json_api(TEST_HTTP_PORT + 0, "wallets/ltc", post_json)
assert json_rv["mweb_balance"] <= 20.0
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -18,9 +19,9 @@ from coincurve.ecdsaotves import (
ecdsaotves_enc_sign,
ecdsaotves_enc_verify,
ecdsaotves_dec_sig,
ecdsaotves_rec_enc_key)
from coincurve.keys import (
PrivateKey)
ecdsaotves_rec_enc_key,
)
from coincurve.keys import PrivateKey
from basicswap.contrib.mnemonic import Mnemonic
from basicswap.util import i2b, h2b
@ -36,14 +37,14 @@ from basicswap.interface.xmr import XMRInterface
from tests.basicswap.mnemonics import mnemonics
from tests.basicswap.util import REQUIRED_SETTINGS
from basicswap.basicswap_util import (
TxLockTypes)
from basicswap.basicswap_util import TxLockTypes
from basicswap.util import (
make_int,
SerialiseNum,
format_amount,
DeserialiseNum,
validate_amount)
validate_amount,
)
from basicswap.messages_npb import (
BidMessage,
)
@ -56,8 +57,9 @@ class Test(unittest.TestCase):
def test_case(v, nb=None):
b = SerialiseNum(v)
if nb is not None:
assert (len(b) == nb)
assert (v == DeserialiseNum(b))
assert len(b) == nb
assert v == DeserialiseNum(b)
test_case(0, 1)
test_case(1, 1)
test_case(16, 1)
@ -70,104 +72,106 @@ class Test(unittest.TestCase):
test_case(4194642)
def test_sequence(self):
coin_settings = {'rpcport': 0, 'rpcauth': 'none'}
coin_settings = {"rpcport": 0, "rpcauth": "none"}
coin_settings.update(REQUIRED_SETTINGS)
ci = BTCInterface(coin_settings, 'regtest')
ci = BTCInterface(coin_settings, "regtest")
time_val = 48 * 60 * 60
encoded = ci.getExpectedSequence(TxLockTypes.SEQUENCE_LOCK_TIME, time_val)
decoded = ci.decodeSequence(encoded)
assert (decoded >= time_val)
assert (decoded <= time_val + 512)
assert decoded >= time_val
assert decoded <= time_val + 512
time_val = 24 * 60
encoded = ci.getExpectedSequence(TxLockTypes.SEQUENCE_LOCK_TIME, time_val)
decoded = ci.decodeSequence(encoded)
assert (decoded >= time_val)
assert (decoded <= time_val + 512)
assert decoded >= time_val
assert decoded <= time_val + 512
blocks_val = 123
encoded = ci.getExpectedSequence(TxLockTypes.SEQUENCE_LOCK_BLOCKS, blocks_val)
decoded = ci.decodeSequence(encoded)
assert (decoded == blocks_val)
assert decoded == blocks_val
def test_make_int(self):
def test_case(vs, vf, expect_int):
i = make_int(vs)
assert (i == expect_int and isinstance(i, int))
assert i == expect_int and isinstance(i, int)
i = make_int(vf)
assert (i == expect_int and isinstance(i, int))
assert i == expect_int and isinstance(i, int)
vs_out = format_amount(i, 8)
# Strip
for i in range(7):
if vs_out[-1] == '0':
if vs_out[-1] == "0":
vs_out = vs_out[:-1]
if '.' in vs:
assert (vs_out == vs)
if "." in vs:
assert vs_out == vs
else:
assert (vs_out[:-2] == vs)
test_case('0', 0, 0)
test_case('1', 1, 100000000)
test_case('10', 10, 1000000000)
test_case('0.00899999', 0.00899999, 899999)
test_case('899999.0', 899999.0, 89999900000000)
test_case('899999.00899999', 899999.00899999, 89999900899999)
test_case('0.0', 0.0, 0)
test_case('1.0', 1.0, 100000000)
test_case('1.1', 1.1, 110000000)
test_case('1.2', 1.2, 120000000)
test_case('0.00899991', 0.00899991, 899991)
test_case('0.0089999', 0.0089999, 899990)
test_case('0.0089991', 0.0089991, 899910)
test_case('0.123', 0.123, 12300000)
test_case('123000.000123', 123000.000123, 12300000012300)
assert vs_out[:-2] == vs
test_case("0", 0, 0)
test_case("1", 1, 100000000)
test_case("10", 10, 1000000000)
test_case("0.00899999", 0.00899999, 899999)
test_case("899999.0", 899999.0, 89999900000000)
test_case("899999.00899999", 899999.00899999, 89999900899999)
test_case("0.0", 0.0, 0)
test_case("1.0", 1.0, 100000000)
test_case("1.1", 1.1, 110000000)
test_case("1.2", 1.2, 120000000)
test_case("0.00899991", 0.00899991, 899991)
test_case("0.0089999", 0.0089999, 899990)
test_case("0.0089991", 0.0089991, 899910)
test_case("0.123", 0.123, 12300000)
test_case("123000.000123", 123000.000123, 12300000012300)
try:
make_int('0.123456789')
assert (False)
make_int("0.123456789")
assert False
except Exception as e:
assert (str(e) == 'Mantissa too long')
validate_amount('0.12345678')
assert str(e) == "Mantissa too long"
validate_amount("0.12345678")
# floor
assert (make_int('0.123456789', r=-1) == 12345678)
assert make_int("0.123456789", r=-1) == 12345678
# Round up
assert (make_int('0.123456789', r=1) == 12345679)
assert make_int("0.123456789", r=1) == 12345679
def test_make_int12(self):
def test_case(vs, vf, expect_int):
i = make_int(vs, 12)
assert (i == expect_int and isinstance(i, int))
assert i == expect_int and isinstance(i, int)
i = make_int(vf, 12)
assert (i == expect_int and isinstance(i, int))
assert i == expect_int and isinstance(i, int)
vs_out = format_amount(i, 12)
# Strip
for i in range(7):
if vs_out[-1] == '0':
if vs_out[-1] == "0":
vs_out = vs_out[:-1]
if '.' in vs:
assert (vs_out == vs)
if "." in vs:
assert vs_out == vs
else:
assert (vs_out[:-2] == vs)
test_case('0.123456789', 0.123456789, 123456789000)
test_case('0.123456789123', 0.123456789123, 123456789123)
assert vs_out[:-2] == vs
test_case("0.123456789", 0.123456789, 123456789000)
test_case("0.123456789123", 0.123456789123, 123456789123)
try:
make_int('0.1234567891234', 12)
assert (False)
make_int("0.1234567891234", 12)
assert False
except Exception as e:
assert (str(e) == 'Mantissa too long')
validate_amount('0.123456789123', 12)
assert str(e) == "Mantissa too long"
validate_amount("0.123456789123", 12)
try:
validate_amount('0.1234567891234', 12)
assert (False)
validate_amount("0.1234567891234", 12)
assert False
except Exception as e:
assert ('Too many decimal places' in str(e))
assert "Too many decimal places" in str(e)
try:
validate_amount(0.1234567891234, 12)
assert (False)
assert False
except Exception as e:
assert ('Too many decimal places' in str(e))
assert "Too many decimal places" in str(e)
def test_ed25519(self):
privkey = edu.get_secret()
@ -175,12 +179,12 @@ class Test(unittest.TestCase):
privkey_bytes = i2b(privkey)
pubkey_test = ed25519_get_pubkey(privkey_bytes)
assert (pubkey == pubkey_test)
assert pubkey == pubkey_test
def test_ecdsa_otves(self):
coin_settings = {'rpcport': 0, 'rpcauth': 'none'}
coin_settings = {"rpcport": 0, "rpcauth": "none"}
coin_settings.update(REQUIRED_SETTINGS)
ci = BTCInterface(coin_settings, 'regtest')
ci = BTCInterface(coin_settings, "regtest")
vk_sign = ci.getNewSecretKey()
vk_encrypt = ci.getNewSecretKey()
@ -190,79 +194,79 @@ class Test(unittest.TestCase):
cipher_text = ecdsaotves_enc_sign(vk_sign, pk_encrypt, sign_hash)
assert (ecdsaotves_enc_verify(pk_sign, pk_encrypt, sign_hash, cipher_text))
assert ecdsaotves_enc_verify(pk_sign, pk_encrypt, sign_hash, cipher_text)
sig = ecdsaotves_dec_sig(vk_encrypt, cipher_text)
assert (ci.verifySig(pk_sign, sign_hash, sig))
assert ci.verifySig(pk_sign, sign_hash, sig)
recovered_key = ecdsaotves_rec_enc_key(pk_encrypt, cipher_text, sig)
assert (vk_encrypt == recovered_key)
assert vk_encrypt == recovered_key
def test_sign(self):
coin_settings = {'rpcport': 0, 'rpcauth': 'none'}
coin_settings = {"rpcport": 0, "rpcauth": "none"}
coin_settings.update(REQUIRED_SETTINGS)
ci = BTCInterface(coin_settings, 'regtest')
ci = BTCInterface(coin_settings, "regtest")
vk = ci.getNewSecretKey()
pk = ci.getPubkey(vk)
message = 'test signing message'
message_hash = hashlib.sha256(bytes(message, 'utf-8')).digest()
message = "test signing message"
message_hash = hashlib.sha256(bytes(message, "utf-8")).digest()
eck = PrivateKey(vk)
sig = eck.sign(message.encode('utf-8'))
sig = eck.sign(message.encode("utf-8"))
ci.verifySig(pk, message_hash, sig)
def test_sign_compact(self):
coin_settings = {'rpcport': 0, 'rpcauth': 'none'}
coin_settings = {"rpcport": 0, "rpcauth": "none"}
coin_settings.update(REQUIRED_SETTINGS)
ci = BTCInterface(coin_settings, 'regtest')
ci = BTCInterface(coin_settings, "regtest")
vk = ci.getNewSecretKey()
pk = ci.getPubkey(vk)
sig = ci.signCompact(vk, 'test signing message')
assert (len(sig) == 64)
ci.verifyCompactSig(pk, 'test signing message', sig)
sig = ci.signCompact(vk, "test signing message")
assert len(sig) == 64
ci.verifyCompactSig(pk, "test signing message", sig)
# Nonce is set deterministically (using default libsecp256k1 method rfc6979)
sig2 = ci.signCompact(vk, 'test signing message')
assert (sig == sig2)
sig2 = ci.signCompact(vk, "test signing message")
assert sig == sig2
def test_sign_recoverable(self):
coin_settings = {'rpcport': 0, 'rpcauth': 'none'}
coin_settings = {"rpcport": 0, "rpcauth": "none"}
coin_settings.update(REQUIRED_SETTINGS)
ci = BTCInterface(coin_settings, 'regtest')
ci = BTCInterface(coin_settings, "regtest")
vk = ci.getNewSecretKey()
pk = ci.getPubkey(vk)
sig = ci.signRecoverable(vk, 'test signing message')
assert (len(sig) == 65)
pk_rec = ci.verifySigAndRecover(sig, 'test signing message')
assert (pk == pk_rec)
sig = ci.signRecoverable(vk, "test signing message")
assert len(sig) == 65
pk_rec = ci.verifySigAndRecover(sig, "test signing message")
assert pk == pk_rec
# Nonce is set deterministically (using default libsecp256k1 method rfc6979)
sig2 = ci.signRecoverable(vk, 'test signing message')
assert (sig == sig2)
sig2 = ci.signRecoverable(vk, "test signing message")
assert sig == sig2
def test_pubkey_to_address(self):
coin_settings = {'rpcport': 0, 'rpcauth': 'none'}
coin_settings = {"rpcport": 0, "rpcauth": "none"}
coin_settings.update(REQUIRED_SETTINGS)
ci = BTCInterface(coin_settings, 'regtest')
pk = h2b('02c26a344e7d21bcc6f291532679559f2fd234c881271ff98714855edc753763a6')
ci = BTCInterface(coin_settings, "regtest")
pk = h2b("02c26a344e7d21bcc6f291532679559f2fd234c881271ff98714855edc753763a6")
addr = ci.pubkey_to_address(pk)
assert (addr == 'mj6SdSxmWRmdDqR5R3FfZmRiLmQfQAsLE8')
assert addr == "mj6SdSxmWRmdDqR5R3FfZmRiLmQfQAsLE8"
def test_dleag(self):
coin_settings = {'rpcport': 0, 'walletrpcport': 0, 'walletrpcauth': 'none'}
coin_settings = {"rpcport": 0, "walletrpcport": 0, "walletrpcauth": "none"}
coin_settings.update(REQUIRED_SETTINGS)
ci = XMRInterface(coin_settings, 'regtest')
ci = XMRInterface(coin_settings, "regtest")
key = ci.getNewSecretKey()
proof = ci.proveDLEAG(key)
assert (ci.verifyDLEAG(proof))
assert ci.verifyDLEAG(proof)
def test_rate(self):
scale_from = 8
@ -270,53 +274,58 @@ class Test(unittest.TestCase):
amount_from = make_int(100, scale_from)
rate = make_int(0.1, scale_to)
amount_to = int((amount_from * rate) // (10 ** scale_from))
assert ('100.00000000' == format_amount(amount_from, scale_from))
assert ('10.000000000000' == format_amount(amount_to, scale_to))
amount_to = int((amount_from * rate) // (10**scale_from))
assert "100.00000000" == format_amount(amount_from, scale_from)
assert "10.000000000000" == format_amount(amount_to, scale_to)
rate_check = make_int((amount_to / amount_from), scale_from)
assert (rate == rate_check)
assert rate == rate_check
scale_from = 12
scale_to = 8
amount_from = make_int(1, scale_from)
rate = make_int(12, scale_to)
amount_to = int((amount_from * rate) // (10 ** scale_from))
assert ('1.000000000000' == format_amount(amount_from, scale_from))
assert ('12.00000000' == format_amount(amount_to, scale_to))
amount_to = int((amount_from * rate) // (10**scale_from))
assert "1.000000000000" == format_amount(amount_from, scale_from)
assert "12.00000000" == format_amount(amount_to, scale_to)
rate_check = make_int((amount_to / amount_from), scale_from)
assert (rate == rate_check)
assert rate == rate_check
scale_from = 8
scale_to = 8
amount_from = make_int(0.073, scale_from)
amount_to = make_int(10, scale_to)
rate = make_int(amount_to / amount_from, scale_to, r=1)
amount_to_recreate = int((amount_from * rate) // (10 ** scale_from))
assert ('10.00000000' == format_amount(amount_to_recreate, scale_to))
amount_to_recreate = int((amount_from * rate) // (10**scale_from))
assert "10.00000000" == format_amount(amount_to_recreate, scale_to)
scale_from = 8
scale_to = 12
amount_from = make_int(10.0, scale_from)
amount_to = make_int(0.06935, scale_to)
rate = make_int(amount_to / amount_from, scale_from, r=1)
amount_to_recreate = int((amount_from * rate) // (10 ** scale_from))
assert ('0.069350000000' == format_amount(amount_to_recreate, scale_to))
amount_to_recreate = int((amount_from * rate) // (10**scale_from))
assert "0.069350000000" == format_amount(amount_to_recreate, scale_to)
scale_from = 12
scale_to = 8
amount_from = make_int(0.06935, scale_from)
amount_to = make_int(10.0, scale_to)
rate = make_int(amount_to / amount_from, scale_from, r=1)
amount_to_recreate = int((amount_from * rate) // (10 ** scale_from))
assert ('10.00000000' == format_amount(amount_to_recreate, scale_to))
amount_to_recreate = int((amount_from * rate) // (10**scale_from))
assert "10.00000000" == format_amount(amount_to_recreate, scale_to)
coin_settings = {'rpcport': 0, 'rpcauth': 'none', 'walletrpcport': 0, 'walletrpcauth': 'none'}
coin_settings = {
"rpcport": 0,
"rpcauth": "none",
"walletrpcport": 0,
"walletrpcauth": "none",
}
coin_settings.update(REQUIRED_SETTINGS)
ci_xmr = XMRInterface(coin_settings, 'regtest')
ci_btc = BTCInterface(coin_settings, 'regtest')
ci_xmr = XMRInterface(coin_settings, "regtest")
ci_btc = BTCInterface(coin_settings, "regtest")
for i in range(10000):
test_pairs = random.randint(0, 3)
@ -362,55 +371,73 @@ class Test(unittest.TestCase):
amount_to = random.randint(10000, 2100000000 * ci_to.COIN())
offer_rate = ci_from.make_int(amount_to / amount_from, r=1)
amount_to_from_rate: int = int((int(amount_from) * offer_rate) // (10 ** scale_from))
amount_to_from_rate: int = int(
(int(amount_from) * offer_rate) // (10**scale_from)
)
scale_from = 24
offer_rate = make_int(amount_to, scale_from) // amount_from
amount_to_from_rate: int = int((int(amount_from) * offer_rate) // (10 ** scale_from))
amount_to_from_rate: int = int(
(int(amount_from) * offer_rate) // (10**scale_from)
)
if abs(amount_to - amount_to_from_rate) == 1:
offer_rate += 1
offer_rate_human_read: int = int(offer_rate // (10 ** (scale_from - ci_from.exp())))
amount_to_from_rate: int = int((int(amount_from) * offer_rate) // (10 ** scale_from))
offer_rate_human_read: int = int(
offer_rate // (10 ** (scale_from - ci_from.exp()))
)
amount_to_from_rate: int = int(
(int(amount_from) * offer_rate) // (10**scale_from)
)
if amount_to != amount_to_from_rate:
print('from exp, amount', ci_from.exp(), amount_from)
print('to exp, amount', ci_to.exp(), amount_to)
print('amount_to_from_rate', amount_to_from_rate)
raise ValueError('Bad amount_to')
print("from exp, amount", ci_from.exp(), amount_from)
print("to exp, amount", ci_to.exp(), amount_to)
print("offer_rate_human_read", offer_rate_human_read)
print("amount_to_from_rate", amount_to_from_rate)
raise ValueError("Bad amount_to")
scale_to = 24
reversed_rate = make_int(amount_from, scale_to) // amount_to
amount_from_from_rate: int = int((int(amount_to) * reversed_rate) // (10 ** scale_to))
amount_from_from_rate: int = int(
(int(amount_to) * reversed_rate) // (10**scale_to)
)
if abs(amount_from - amount_from_from_rate) == 1:
reversed_rate += 1
amount_from_from_rate: int = int((int(amount_to) * reversed_rate) // (10 ** scale_to))
amount_from_from_rate: int = int(
(int(amount_to) * reversed_rate) // (10**scale_to)
)
if amount_from != amount_from_from_rate:
print('from exp, amount', ci_from.exp(), amount_from)
print('to exp, amount', ci_to.exp(), amount_to)
print('amount_from_from_rate', amount_from_from_rate)
raise ValueError('Bad amount_from')
print("from exp, amount", ci_from.exp(), amount_from)
print("to exp, amount", ci_to.exp(), amount_to)
print("amount_from_from_rate", amount_from_from_rate)
raise ValueError("Bad amount_from")
def test_rfc2440(self):
password = 'test'
salt = bytes.fromhex('B7A94A7E4988630E')
password = "test"
salt = bytes.fromhex("B7A94A7E4988630E")
password_hash = rfc2440_hash_password(password, salt=salt)
assert (password_hash == '16:B7A94A7E4988630E6095334BA67F06FBA509B2A7136A04C9C1B430F539')
assert (
password_hash
== "16:B7A94A7E4988630E6095334BA67F06FBA509B2A7136A04C9C1B430F539"
)
def test_ripemd160(self):
input_data = b'hash this'
assert (ripemd160(input_data).hex() == 'd5443a154f167e2c1332f6de72cfb4c6ab9c8c17')
input_data = b"hash this"
assert ripemd160(input_data).hex() == "d5443a154f167e2c1332f6de72cfb4c6ab9c8c17"
def test_hash160(self):
# hash160 is RIPEMD(SHA256(data))
input_data = b'hash this'
assert (hash160(input_data).hex() == '072985b3583a4a71f548494a5e1d5f6b00d0fe13')
assert (hash160_btc(input_data).hex() == '072985b3583a4a71f548494a5e1d5f6b00d0fe13')
input_data = b"hash this"
assert hash160(input_data).hex() == "072985b3583a4a71f548494a5e1d5f6b00d0fe13"
assert (
hash160_btc(input_data).hex() == "072985b3583a4a71f548494a5e1d5f6b00d0fe13"
)
def test_protobuf(self):
msg_buf = BidMessage()
@ -420,37 +447,37 @@ class Test(unittest.TestCase):
msg_buf_2 = BidMessage()
msg_buf_2.from_bytes(serialised_msg)
assert (msg_buf_2.protocol_version == 2)
assert (msg_buf_2.time_valid == 1024)
assert (msg_buf_2.amount == 0)
assert (msg_buf_2.pkhash_buyer is not None)
assert (len(msg_buf_2.pkhash_buyer) == 0)
assert msg_buf_2.protocol_version == 2
assert msg_buf_2.time_valid == 1024
assert msg_buf_2.amount == 0
assert msg_buf_2.pkhash_buyer is not None
assert len(msg_buf_2.pkhash_buyer) == 0
# Decode only the first field
msg_buf_3 = BidMessage()
msg_buf_3.from_bytes(serialised_msg[:2])
assert (msg_buf_3.protocol_version == 2)
assert (msg_buf_3.time_valid == 0)
assert msg_buf_3.protocol_version == 2
assert msg_buf_3.time_valid == 0
try:
msg_buf_4 = BidMessage(doesnotexist=1)
_ = BidMessage(doesnotexist=1)
except Exception as e:
assert ('unexpected keyword argument' in str(e))
assert "unexpected keyword argument" in str(e)
else:
raise ValueError('Should have errored.')
raise ValueError("Should have errored.")
def test_is_private_ip_address(self):
test_addresses = [
('localhost', True),
('127.0.0.1', True),
('10.0.0.0', True),
('172.16.0.0', True),
('192.168.0.0', True),
('20.87.245.0', False),
('particl.io', False),
("localhost", True),
("127.0.0.1", True),
("10.0.0.0", True),
("172.16.0.0", True),
("192.168.0.0", True),
("20.87.245.0", False),
("particl.io", False),
]
for addr, is_private in test_addresses:
assert (is_private_ip_address(addr) is is_private)
assert is_private_ip_address(addr) is is_private
def test_varint(self):
test_vectors = [
@ -467,8 +494,8 @@ class Test(unittest.TestCase):
]
for i, expect_length in test_vectors:
b = encode_varint(i)
assert (len(b) == expect_length)
assert (decode_varint(b) == (i, expect_length))
assert len(b) == expect_length
assert decode_varint(b) == (i, expect_length)
def test_base58(self):
kv = edu.get_secret()
@ -477,55 +504,58 @@ class Test(unittest.TestCase):
Ks = edu.encodepoint(edf.scalarmult_B(ks))
addr = xmr_encode_address(Kv, Ks)
assert (addr.startswith('4'))
assert addr.startswith("4")
addr = xmr_encode_address(Kv, Ks, 4146)
assert (addr.startswith('Wo'))
assert addr.startswith("Wo")
def test_blake256(self):
test_vectors = [
('716f6e863f744b9ac22c97ec7b76ea5f5908bc5b2f67c61510bfc4751384ea7a', b''),
('7576698ee9cad30173080678e5965916adbb11cb5245d386bf1ffda1cb26c9d7', b'The quick brown fox jumps over the lazy dog'),
("716f6e863f744b9ac22c97ec7b76ea5f5908bc5b2f67c61510bfc4751384ea7a", b""),
(
"7576698ee9cad30173080678e5965916adbb11cb5245d386bf1ffda1cb26c9d7",
b"The quick brown fox jumps over the lazy dog",
),
]
for expect_hash, data in test_vectors:
assert (blake256(data).hex() == expect_hash)
assert blake256(data).hex() == expect_hash
def test_extkey(self):
test_key = 'XPARHAr37YxmFP8wyjkaHAQWmp84GiyLikL7EL8j9BCx4LkB8Q1Bw5Kr8sA1GA3Ym53zNLcaxxFHr6u81JVTeCaD61c6fKS1YRAuti8Zu5SzJCjh'
test_key_c0 = 'XPARHAt1XMcNYAwP5wEnQXknBAkGSzaetdZt2eoJZehdB4WXfV1xbSjpgHe44AivmumcSejW5KaYx6L5M6MyR1WyXrsWTwaiUEfHq2RrqCfXj3ZW'
test_key_c0_p = 'PPARTKPL4rp5WLnrYP6jZfuRjx6jrmvbsz5QdHofPfFqJdm918mQwdPLq6Dd9TkdbQeKUqjbHWkyzWe7Pftd7itzm7ETEoUMq4cbG4fY9FKH1YSU'
test_key_c0h = 'XPARHAt1XMcNgWbv48LwoQbjs1bC8kCXKomzvJLRT5xmbQ2GKf9e8Vfr1MMcfiWJC34RyDp5HvAfjeiNyLDfkFm1UrRCrPkVC9GGaAWa3nXMWew8'
test_key = "XPARHAr37YxmFP8wyjkaHAQWmp84GiyLikL7EL8j9BCx4LkB8Q1Bw5Kr8sA1GA3Ym53zNLcaxxFHr6u81JVTeCaD61c6fKS1YRAuti8Zu5SzJCjh"
test_key_c0 = "XPARHAt1XMcNYAwP5wEnQXknBAkGSzaetdZt2eoJZehdB4WXfV1xbSjpgHe44AivmumcSejW5KaYx6L5M6MyR1WyXrsWTwaiUEfHq2RrqCfXj3ZW"
test_key_c0_p = "PPARTKPL4rp5WLnrYP6jZfuRjx6jrmvbsz5QdHofPfFqJdm918mQwdPLq6Dd9TkdbQeKUqjbHWkyzWe7Pftd7itzm7ETEoUMq4cbG4fY9FKH1YSU"
test_key_c0h = "XPARHAt1XMcNgWbv48LwoQbjs1bC8kCXKomzvJLRT5xmbQ2GKf9e8Vfr1MMcfiWJC34RyDp5HvAfjeiNyLDfkFm1UrRCrPkVC9GGaAWa3nXMWew8"
ek_data = decodeAddress(test_key)[4:]
ek = ExtKeyPair()
ek.decode(ek_data)
assert (ek.encode_v() == ek_data)
assert ek.encode_v() == ek_data
m_0 = ek.derive(0)
ek_c0_data = decodeAddress(test_key_c0)[4:]
assert (m_0.encode_v() == ek_c0_data)
assert m_0.encode_v() == ek_c0_data
child_no: int = 0 | (1 << 31)
m_0h = ek.derive(child_no)
ek_c0h_data = decodeAddress(test_key_c0h)[4:]
assert (m_0h.encode_v() == ek_c0h_data)
assert m_0h.encode_v() == ek_c0h_data
ek.neuter()
assert (ek.has_key() is False)
assert ek.has_key() is False
m_0 = ek.derive(0)
ek_c0_p_data = decodeAddress(test_key_c0_p)[4:]
assert (m_0.encode_p() == ek_c0_p_data)
assert m_0.encode_p() == ek_c0_p_data
def test_mnemonic(self):
entropy0: bytes = Mnemonic('english').to_entropy(mnemonics[0])
assert (entropy0.hex() == '0002207e9b744ea2d7ab41702f31f000')
mnemonic_recovered: str = Mnemonic('english').to_mnemonic(entropy0)
assert (mnemonic_recovered == mnemonics[0])
entropy0: bytes = Mnemonic("english").to_entropy(mnemonics[0])
assert entropy0.hex() == "0002207e9b744ea2d7ab41702f31f000"
mnemonic_recovered: str = Mnemonic("english").to_mnemonic(entropy0)
assert mnemonic_recovered == mnemonics[0]
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021-2023 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -51,45 +52,65 @@ class Test(BaseTest):
def setUpClass(cls):
super(Test, cls).setUpClass()
js_0 = read_json_api(1800, 'wallets/part')
node0_blind_before = js_0['blind_balance'] + js_0['blind_unconfirmed']
js_0 = read_json_api(1800, "wallets/part")
node0_blind_before = js_0["blind_balance"] + js_0["blind_unconfirmed"]
post_json = {
'value': 100,
'address': js_0['stealth_address'],
'subfee': False,
'type_to': 'blind',
"value": 100,
"address": js_0["stealth_address"],
"subfee": False,
"type_to": "blind",
}
json_rv = json.loads(post_json_req('http://127.0.0.1:1800/json/wallets/part/withdraw', post_json))
assert (len(json_rv['txid']) == 64)
json_rv = json.loads(
post_json_req("http://127.0.0.1:1800/json/wallets/part/withdraw", post_json)
)
assert len(json_rv["txid"]) == 64
logging.info('Waiting for blind balance')
wait_for_balance(test_delay_event, 'http://127.0.0.1:1800/json/wallets/part', 'blind_balance', 100.0 + node0_blind_before)
js_0 = read_json_api(1800, 'wallets/part')
logging.info("Waiting for blind balance")
wait_for_balance(
test_delay_event,
"http://127.0.0.1:1800/json/wallets/part",
"blind_balance",
100.0 + node0_blind_before,
)
js_0 = read_json_api(1800, "wallets/part")
def ensure_balance(self, coin_type, node_id, amount):
tla = 'PART'
js_w = read_json_api(1800 + node_id, 'wallets')
print('js_w', js_w)
if float(js_w[tla]['blind_balance']) < amount:
tla = "PART"
js_w = read_json_api(1800 + node_id, "wallets")
print("js_w", js_w)
if float(js_w[tla]["blind_balance"]) < amount:
post_json = {
'value': amount,
'type_to': 'blind',
'address': js_w[tla]['stealth_address'],
'subfee': False,
"value": amount,
"type_to": "blind",
"address": js_w[tla]["stealth_address"],
"subfee": False,
}
json_rv = read_json_api(1800, 'wallets/{}/withdraw'.format(tla.lower()), post_json)
assert (len(json_rv['txid']) == 64)
wait_for_balance(test_delay_event, 'http://127.0.0.1:{}/json/wallets/{}'.format(1800 + node_id, tla.lower()), 'blind_balance', amount)
json_rv = read_json_api(
1800, "wallets/{}/withdraw".format(tla.lower()), post_json
)
assert len(json_rv["txid"]) == 64
wait_for_balance(
test_delay_event,
"http://127.0.0.1:{}/json/wallets/{}".format(
1800 + node_id, tla.lower()
),
"blind_balance",
amount,
)
def getBalance(self, js_wallets):
return float(js_wallets[Coins.PART.name]['blind_balance']) + float(js_wallets[Coins.PART.name]['blind_unconfirmed'])
return float(js_wallets[Coins.PART.name]["blind_balance"]) + float(
js_wallets[Coins.PART.name]["blind_unconfirmed"]
)
def getXmrBalance(self, js_wallets):
return float(js_wallets[Coins.XMR.name]['unconfirmed']) + float(js_wallets[Coins.XMR.name]['balance'])
return float(js_wallets[Coins.XMR.name]["unconfirmed"]) + float(
js_wallets[Coins.XMR.name]["balance"]
)
def test_010_txn_size(self):
logging.info('---------- Test {} txn_size'.format(self.test_coin_from.name))
logging.info("---------- Test {} txn_size".format(self.test_coin_from.name))
self.ensure_balance(self.test_coin_from, 0, 100.0)
@ -101,20 +122,21 @@ class Test(BaseTest):
nonlocal ci
i = 0
while not delay_event.is_set():
unspents = ci.rpc_wallet('listunspentblind')
unspents = ci.rpc_wallet("listunspentblind")
if len(unspents) >= 1:
return
delay_event.wait(delay_time)
i += 1
if i > iterations:
raise ValueError('wait_for_unspents timed out')
raise ValueError("wait_for_unspents timed out")
wait_for_unspents(test_delay_event)
amount: int = ci.make_int(random.uniform(0.1, 2.0), r=1)
# Record unspents before createSCLockTx as the used ones will be locked
unspents = ci.rpc_wallet('listunspentblind')
locked_utxos_before = ci.rpc_wallet('listlockunspent')
unspents = ci.rpc_wallet("listunspentblind")
locked_utxos_before = ci.rpc_wallet("listlockunspent")
# fee_rate is in sats/kvB
fee_rate: int = 1000
@ -131,53 +153,61 @@ class Test(BaseTest):
lock_tx = ci.fundSCLockTx(lock_tx, fee_rate, vkbv)
lock_tx = ci.signTxWithWallet(lock_tx)
unspents_after = ci.rpc_wallet('listunspentblind')
locked_utxos_after = ci.rpc_wallet('listlockunspent')
unspents_after = ci.rpc_wallet("listunspentblind")
locked_utxos_after = ci.rpc_wallet("listlockunspent")
assert (len(unspents) > len(unspents_after))
assert (len(locked_utxos_after) > len(locked_utxos_before))
lock_tx_decoded = ci.rpc_wallet('decoderawtransaction', [lock_tx.hex()])
txid = lock_tx_decoded['txid']
assert len(unspents) > len(unspents_after)
assert len(locked_utxos_after) > len(locked_utxos_before)
lock_tx_decoded = ci.rpc_wallet("decoderawtransaction", [lock_tx.hex()])
txid = lock_tx_decoded["txid"]
vsize = lock_tx_decoded['vsize']
vsize = lock_tx_decoded["vsize"]
expect_fee_int = round(fee_rate * vsize / 1000)
expect_fee = ci.format_amount(expect_fee_int)
ci.rpc_wallet('sendrawtransaction', [lock_tx.hex()])
rv = ci.rpc_wallet('gettransaction', [txid])
wallet_tx_fee = -ci.make_int(rv['details'][0]['fee'])
ci.rpc_wallet("sendrawtransaction", [lock_tx.hex()])
rv = ci.rpc_wallet("gettransaction", [txid])
wallet_tx_fee = -ci.make_int(rv["details"][0]["fee"])
assert (wallet_tx_fee >= expect_fee_int)
assert (wallet_tx_fee - expect_fee_int < 20)
assert wallet_tx_fee >= expect_fee_int
assert wallet_tx_fee - expect_fee_int < 20
addr_out = ci.getNewAddress(True)
addrinfo = ci.rpc_wallet('getaddressinfo', [addr_out,])
pk_out = bytes.fromhex(addrinfo['pubkey'])
addrinfo = ci.rpc_wallet(
"getaddressinfo",
[
addr_out,
],
)
pk_out = bytes.fromhex(addrinfo["pubkey"])
fee_info = {}
lock_spend_tx = ci.createSCLockSpendTx(lock_tx, lock_tx_script, pk_out, fee_rate, vkbv, fee_info=fee_info)
vsize_estimated: int = fee_info['vsize']
lock_spend_tx = ci.createSCLockSpendTx(
lock_tx, lock_tx_script, pk_out, fee_rate, vkbv, fee_info=fee_info
)
vsize_estimated: int = fee_info["vsize"]
spend_tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()])
txid = spend_tx_decoded['txid']
spend_tx_decoded = ci.rpc("decoderawtransaction", [lock_spend_tx.hex()])
txid = spend_tx_decoded["txid"]
nonce = ci.getScriptLockTxNonce(vkbv)
output_n, _ = ci.findOutputByNonce(lock_tx_decoded, nonce)
assert (output_n is not None)
valueCommitment = bytes.fromhex(lock_tx_decoded['vout'][output_n]['valueCommitment'])
assert output_n is not None
valueCommitment = bytes.fromhex(
lock_tx_decoded["vout"][output_n]["valueCommitment"]
)
witness_stack = [
b'',
b"",
ci.signTx(a, lock_spend_tx, 0, lock_tx_script, valueCommitment),
ci.signTx(b, lock_spend_tx, 0, lock_tx_script, valueCommitment),
lock_tx_script,
]
lock_spend_tx = ci.setTxSignature(lock_spend_tx, witness_stack)
tx_decoded = ci.rpc('decoderawtransaction', [lock_spend_tx.hex()])
vsize_actual: int = tx_decoded['vsize']
tx_decoded = ci.rpc("decoderawtransaction", [lock_spend_tx.hex()])
vsize_actual: int = tx_decoded["vsize"]
# Note: The fee is set allowing 9 bytes for the encoded fee amount, causing a small overestimate
assert (vsize_actual <= vsize_estimated and vsize_estimated - vsize_actual < 10)
assert (ci.rpc('sendrawtransaction', [lock_spend_tx.hex()]) == txid)
assert vsize_actual <= vsize_estimated and vsize_estimated - vsize_actual < 10
assert ci.rpc("sendrawtransaction", [lock_spend_tx.hex()]) == txid
# Test chain b (no-script) lock tx size
v = ci.getNewSecretKey()
@ -189,40 +219,50 @@ class Test(BaseTest):
lock_tx_b_spend_txid = None
for i in range(20):
try:
lock_tx_b_spend_txid = ci.spendBLockTx(lock_tx_b_txid, addr_out, v, s, amount, fee_rate, 0)
lock_tx_b_spend_txid = ci.spendBLockTx(
lock_tx_b_txid, addr_out, v, s, amount, fee_rate, 0
)
break
except Exception as e:
print('spendBLockTx failed', str(e))
print("spendBLockTx failed", str(e))
test_delay_event.wait(2)
assert (lock_tx_b_spend_txid is not None)
assert lock_tx_b_spend_txid is not None
lock_tx_b_spend = ci.getTransaction(lock_tx_b_spend_txid)
if lock_tx_b_spend is None:
lock_tx_b_spend = ci.getWalletTransaction(lock_tx_b_spend_txid)
lock_tx_b_spend_decoded = ci.rpc('decoderawtransaction', [lock_tx_b_spend.hex()])
lock_tx_b_spend_decoded = ci.rpc(
"decoderawtransaction", [lock_tx_b_spend.hex()]
)
expect_vsize: int = ci.xmr_swap_b_lock_spend_tx_vsize()
assert (expect_vsize >= lock_tx_b_spend_decoded['vsize'])
assert (expect_vsize - lock_tx_b_spend_decoded['vsize'] < 10)
assert expect_vsize >= lock_tx_b_spend_decoded["vsize"]
assert expect_vsize - lock_tx_b_spend_decoded["vsize"] < 10
def test_01_part_xmr(self):
logging.info('---------- Test PARTct to XMR')
logging.info("---------- Test PARTct to XMR")
swap_clients = self.swap_clients
js_0 = read_json_api(1800, 'wallets/part')
assert (float(js_0['blind_balance']) > 10.0)
node0_blind_before = js_0['blind_balance'] + js_0['blind_unconfirmed']
js_0 = read_json_api(1800, "wallets/part")
assert float(js_0["blind_balance"]) > 10.0
node0_blind_before = js_0["blind_balance"] + js_0["blind_unconfirmed"]
js_1 = read_json_api(1801, 'wallets/part')
node1_blind_before = js_1['blind_balance'] + js_1['blind_unconfirmed']
js_1 = read_json_api(1801, "wallets/part")
node1_blind_before = js_1["blind_balance"] + js_1["blind_unconfirmed"]
js_0_xmr = read_json_api(1800, 'wallets/xmr')
js_1_xmr = read_json_api(1801, 'wallets/xmr')
js_1_xmr = read_json_api(1801, "wallets/xmr")
amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1)
rate_swap = make_int(random.uniform(0.2, 20.0), scale=12, r=1)
offer_id = swap_clients[0].postOffer(Coins.PART_BLIND, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP)
offer_id = swap_clients[0].postOffer(
Coins.PART_BLIND,
Coins.XMR,
amt_swap,
rate_swap,
amt_swap,
SwapTypes.XMR_SWAP,
)
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
offers = swap_clients[0].listOffers(filters={'offer_id': offer_id})
offers = swap_clients[0].listOffers(filters={"offer_id": offer_id})
offer = offers[0]
bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from)
@ -231,40 +271,60 @@ class Test(BaseTest):
swap_clients[0].acceptXmrBid(bid_id)
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180)
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True)
wait_for_bid(
test_delay_event,
swap_clients[0],
bid_id,
BidStates.SWAP_COMPLETED,
wait_for=180,
)
wait_for_bid(
test_delay_event,
swap_clients[1],
bid_id,
BidStates.SWAP_COMPLETED,
sent=True,
)
amount_from = float(format_amount(amt_swap, 8))
js_1 = read_json_api(1801, 'wallets/part')
node1_blind_after = js_1['blind_balance'] + js_1['blind_unconfirmed']
assert (node1_blind_after > node1_blind_before + (amount_from - 0.05))
js_1 = read_json_api(1801, "wallets/part")
node1_blind_after = js_1["blind_balance"] + js_1["blind_unconfirmed"]
assert node1_blind_after > node1_blind_before + (amount_from - 0.05)
js_0 = read_json_api(1800, 'wallets/part')
node0_blind_after = js_0['blind_balance'] + js_0['blind_unconfirmed']
assert (node0_blind_after < node0_blind_before - amount_from)
js_0 = read_json_api(1800, "wallets/part")
node0_blind_after = js_0["blind_balance"] + js_0["blind_unconfirmed"]
assert node0_blind_after < node0_blind_before - amount_from
js_0_xmr_after = read_json_api(1800, 'wallets/xmr')
js_1_xmr_after = read_json_api(1801, 'wallets/xmr')
js_1_xmr_after = read_json_api(1801, "wallets/xmr")
scale_from = 8
amount_to = int((amt_swap * rate_swap) // (10 ** scale_from))
amount_to = int((amt_swap * rate_swap) // (10**scale_from))
amount_to_float = float(format_amount(amount_to, 12))
node1_xmr_after = float(js_1_xmr_after['unconfirmed']) + float(js_1_xmr_after['balance'])
node1_xmr_before = float(js_1_xmr['unconfirmed']) + float(js_1_xmr['balance'])
assert (node1_xmr_after > node1_xmr_before + (amount_to_float - 0.02))
node1_xmr_after = float(js_1_xmr_after["unconfirmed"]) + float(
js_1_xmr_after["balance"]
)
node1_xmr_before = float(js_1_xmr["unconfirmed"]) + float(js_1_xmr["balance"])
assert node1_xmr_after > node1_xmr_before + (amount_to_float - 0.02)
def test_02_leader_recover_a_lock_tx(self):
logging.info('---------- Test PARTct to XMR leader recovers coin a lock tx')
logging.info("---------- Test PARTct to XMR leader recovers coin a lock tx")
swap_clients = self.swap_clients
js_w0_before = read_json_api(1800, 'wallets')
js_w0_before = read_json_api(1800, "wallets")
node0_blind_before = self.getBalance(js_w0_before)
amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1)
rate_swap = make_int(random.uniform(0.2, 20.0), scale=12, r=1)
offer_id = swap_clients[0].postOffer(
Coins.PART_BLIND, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=12)
Coins.PART_BLIND,
Coins.XMR,
amt_swap,
rate_swap,
amt_swap,
SwapTypes.XMR_SWAP,
lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS,
lock_value=12,
)
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
offer = swap_clients[1].getOffer(offer_id)
@ -273,31 +333,49 @@ class Test(BaseTest):
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED)
bid, xmr_swap = swap_clients[0].getXmrBid(bid_id)
assert (xmr_swap)
assert xmr_swap
swap_clients[1].setBidDebugInd(bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK)
swap_clients[0].acceptXmrBid(bid_id)
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=180)
wait_for_bid(test_delay_event, swap_clients[1], bid_id, [BidStates.BID_STALLED_FOR_TEST, BidStates.XMR_SWAP_FAILED], sent=True)
wait_for_bid(
test_delay_event,
swap_clients[0],
bid_id,
BidStates.XMR_SWAP_FAILED_REFUNDED,
wait_for=180,
)
wait_for_bid(
test_delay_event,
swap_clients[1],
bid_id,
[BidStates.BID_STALLED_FOR_TEST, BidStates.XMR_SWAP_FAILED],
sent=True,
)
js_w0_after = read_json_api(1800, 'wallets')
js_w0_after = read_json_api(1800, "wallets")
node0_blind_after = self.getBalance(js_w0_after)
assert (node0_blind_before - node0_blind_after < 0.02)
assert node0_blind_before - node0_blind_after < 0.02
def test_03_follower_recover_a_lock_tx(self):
logging.info('---------- Test PARTct to XMR follower recovers coin a lock tx')
logging.info("---------- Test PARTct to XMR follower recovers coin a lock tx")
swap_clients = self.swap_clients
js_w0_before = read_json_api(1800, 'wallets')
js_w1_before = read_json_api(1801, 'wallets')
js_w1_before = read_json_api(1801, "wallets")
amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1)
rate_swap = make_int(random.uniform(0.2, 20.0), scale=12, r=1)
offer_id = swap_clients[0].postOffer(
Coins.PART_BLIND, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=32)
Coins.PART_BLIND,
Coins.XMR,
amt_swap,
rate_swap,
amt_swap,
SwapTypes.XMR_SWAP,
lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS,
lock_value=32,
)
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
offer = swap_clients[1].getOffer(offer_id)
@ -306,22 +384,37 @@ class Test(BaseTest):
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED)
bid, xmr_swap = swap_clients[0].getXmrBid(bid_id)
assert (xmr_swap)
assert xmr_swap
swap_clients[1].setBidDebugInd(bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK)
swap_clients[0].setBidDebugInd(bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND)
swap_clients[0].setBidDebugInd(
bid_id, DebugTypes.BID_DONT_SPEND_COIN_A_LOCK_REFUND
)
swap_clients[0].acceptXmrBid(bid_id)
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_STALLED_FOR_TEST, wait_for=180)
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_SWIPED, wait_for=80, sent=True)
wait_for_bid(
test_delay_event,
swap_clients[0],
bid_id,
BidStates.BID_STALLED_FOR_TEST,
wait_for=180,
)
wait_for_bid(
test_delay_event,
swap_clients[1],
bid_id,
BidStates.XMR_SWAP_FAILED_SWIPED,
wait_for=80,
sent=True,
)
js_w1_after = read_json_api(1801, 'wallets')
js_w1_after = read_json_api(1801, "wallets")
node1_blind_before = self.getBalance(js_w1_before)
node1_blind_after = self.getBalance(js_w1_after)
amount_from = float(format_amount(amt_swap, 8))
assert (node1_blind_after - node1_blind_before > (amount_from - 0.02))
assert node1_blind_after - node1_blind_before > (amount_from - 0.02)
swap_clients[0].abandonBid(bid_id)
swap_clients[1].abandonBid(bid_id)
@ -329,20 +422,29 @@ class Test(BaseTest):
wait_for_none_active(test_delay_event, 1800)
wait_for_none_active(test_delay_event, 1801)
data = parse.urlencode({
'chainbkeysplit': True
}).encode()
offerer_key = json.loads(urlopen('http://127.0.0.1:1800/json/bids/{}'.format(bid_id.hex()), data=data).read())['splitkey']
data = parse.urlencode({"chainbkeysplit": True}).encode()
offerer_key = json.loads(
urlopen(
"http://127.0.0.1:1800/json/bids/{}".format(bid_id.hex()), data=data
).read()
)["splitkey"]
data = parse.urlencode({
'spendchainblocktx': True,
'remote_key': offerer_key
}).encode()
redeemed_txid = json.loads(urlopen('http://127.0.0.1:1801/json/bids/{}'.format(bid_id.hex()), data=data).read())['txid']
assert (len(redeemed_txid) == 64)
data = parse.urlencode(
{"spendchainblocktx": True, "remote_key": offerer_key}
).encode()
redeemed_txid = json.loads(
urlopen(
"http://127.0.0.1:1801/json/bids/{}".format(bid_id.hex()), data=data
).read()
)["txid"]
assert len(redeemed_txid) == 64
def do_test_04_follower_recover_b_lock_tx(self, coin_from, coin_to):
logging.info('---------- Test {} to {} follower recovers coin b lock tx'.format(coin_from.name, coin_to.name))
logging.info(
"---------- Test {} to {} follower recovers coin b lock tx".format(
coin_from.name, coin_to.name
)
)
swap_clients = self.swap_clients
ci_from = swap_clients[0].ci(coin_from)
@ -351,8 +453,15 @@ class Test(BaseTest):
amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
offer_id = swap_clients[0].postOffer(
coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=28)
coin_from,
coin_to,
amt_swap,
rate_swap,
amt_swap,
SwapTypes.XMR_SWAP,
lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS,
lock_value=28,
)
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
offer = swap_clients[1].getOffer(offer_id)
@ -361,36 +470,50 @@ class Test(BaseTest):
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.BID_RECEIVED)
bid, xmr_swap = swap_clients[0].getXmrBid(bid_id)
assert (xmr_swap)
assert xmr_swap
swap_clients[1].setBidDebugInd(bid_id, DebugTypes.CREATE_INVALID_COIN_B_LOCK)
swap_clients[0].acceptXmrBid(bid_id)
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=180)
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=True)
wait_for_bid(
test_delay_event,
swap_clients[0],
bid_id,
BidStates.XMR_SWAP_FAILED_REFUNDED,
wait_for=180,
)
wait_for_bid(
test_delay_event,
swap_clients[1],
bid_id,
BidStates.XMR_SWAP_FAILED_REFUNDED,
sent=True,
)
def test_04_follower_recover_b_lock_tx(self):
js_w0_before = read_json_api(1800, 'wallets')
js_w1_before = read_json_api(1801, 'wallets')
js_w0_before = read_json_api(1800, "wallets")
js_w1_before = read_json_api(1801, "wallets")
self.do_test_04_follower_recover_b_lock_tx(self.test_coin_from, Coins.XMR)
js_w0_after = read_json_api(1800, 'wallets')
js_w1_after = read_json_api(1801, 'wallets')
js_w0_after = read_json_api(1800, "wallets")
js_w1_after = read_json_api(1801, "wallets")
node0_blind_before = self.getBalance(js_w0_before)
node0_blind_after = self.getBalance(js_w0_after)
assert (node0_blind_before - node0_blind_after < 0.02)
assert node0_blind_before - node0_blind_after < 0.02
node1_xmr_before = self.getXmrBalance(js_w1_before)
node1_xmr_after = self.getXmrBalance(js_w1_after)
assert (node1_xmr_before - node1_xmr_after < 0.02)
assert node1_xmr_before - node1_xmr_after < 0.02
def test_04_follower_recover_b_lock_tx_from_part(self):
self.ensure_balance(self.test_coin_from, 1, 50.0)
self.do_test_04_follower_recover_b_lock_tx(Coins.PART, self.test_coin_from)
def do_test_05_self_bid(self, coin_from, coin_to):
logging.info('---------- Test {} to {} same client'.format(coin_from.name, coin_to.name))
logging.info(
"---------- Test {} to {} same client".format(coin_from.name, coin_to.name)
)
swap_clients = self.swap_clients
ci_to = swap_clients[0].ci(coin_to)
@ -400,10 +523,24 @@ class Test(BaseTest):
amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1)
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
offer_id = swap_clients[1].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, auto_accept_bids=True)
offer_id = swap_clients[1].postOffer(
coin_from,
coin_to,
amt_swap,
rate_swap,
amt_swap,
SwapTypes.XMR_SWAP,
auto_accept_bids=True,
)
bid_id = swap_clients[1].postXmrBid(offer_id, amt_swap)
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=180)
wait_for_bid(
test_delay_event,
swap_clients[1],
bid_id,
BidStates.SWAP_COMPLETED,
wait_for=180,
)
def test_05_self_bid(self):
if not self.has_segwit:
@ -419,45 +556,58 @@ class Test(BaseTest):
self.do_test_05_self_bid(Coins.PART, self.test_coin_from)
def test_06_preselect_inputs(self):
raise ValueError('TODO')
raise ValueError("TODO")
tla_from = self.test_coin_from.name
logging.info('---------- Test {} Preselected inputs'.format(tla_from))
logging.info("---------- Test {} Preselected inputs".format(tla_from))
swap_clients = self.swap_clients
# Prepare balance
self.ensure_balance(self.test_coin_from, 2, 100.0)
js_w2 = read_json_api(1802, 'wallets')
js_w2 = read_json_api(1802, "wallets")
post_json = {
'value': float(js_w2['PART']['blind_balance']),
'type_from': 'blind',
'type_to': 'blind',
'address': js_w2['PART']['stealth_address'],
'subfee': True,
"value": float(js_w2["PART"]["blind_balance"]),
"type_from": "blind",
"type_to": "blind",
"address": js_w2["PART"]["stealth_address"],
"subfee": True,
}
json_rv = read_json_api(1802, 'wallets/{}/withdraw'.format('part'), post_json)
wait_for_balance(test_delay_event, 'http://127.0.0.1:1802/json/wallets/{}'.format('part'), 'blind_balance', 10.0)
assert (len(json_rv['txid']) == 64)
json_rv = read_json_api(1802, "wallets/{}/withdraw".format("part"), post_json)
wait_for_balance(
test_delay_event,
"http://127.0.0.1:1802/json/wallets/{}".format("part"),
"blind_balance",
10.0,
)
assert len(json_rv["txid"]) == 64
# Create prefunded ITX
ci = swap_clients[2].ci(self.test_coin_from)
ci_to = swap_clients[2].ci(Coins.XMR)
pi = swap_clients[2].pi(SwapTypes.XMR_SWAP)
js_w2 = read_json_api(1802, 'wallets')
swap_value = ci.make_int(js_w2['PART']['blind_balance'])
assert (swap_value > ci.make_int(95))
js_w2 = read_json_api(1802, "wallets")
swap_value = ci.make_int(js_w2["PART"]["blind_balance"])
assert swap_value > ci.make_int(95)
itx = pi.getFundedInitiateTxTemplate(ci, swap_value, True)
itx_decoded = ci.describeTx(itx.hex())
n = pi.findMockVout(ci, itx_decoded)
value_after_subfee = ci.make_int(itx_decoded['vout'][n]['value'])
assert (value_after_subfee < swap_value)
value_after_subfee = ci.make_int(itx_decoded["vout"][n]["value"])
assert value_after_subfee < swap_value
swap_value = value_after_subfee
wait_for_unspent(test_delay_event, ci, swap_value)
extra_options = {'prefunded_itx': itx}
extra_options = {"prefunded_itx": itx}
rate_swap = ci_to.make_int(random.uniform(0.2, 20.0))
offer_id = swap_clients[2].postOffer(self.test_coin_from, Coins.XMR, swap_value, rate_swap, swap_value, SwapTypes.XMR_SWAP, extra_options=extra_options)
offer_id = swap_clients[2].postOffer(
self.test_coin_from,
Coins.XMR,
swap_value,
rate_swap,
swap_value,
SwapTypes.XMR_SWAP,
extra_options=extra_options,
)
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
offer = swap_clients[1].getOffer(offer_id)
@ -466,20 +616,38 @@ class Test(BaseTest):
wait_for_bid(test_delay_event, swap_clients[2], bid_id, BidStates.BID_RECEIVED)
swap_clients[2].acceptBid(bid_id)
wait_for_bid(test_delay_event, swap_clients[2], bid_id, BidStates.SWAP_COMPLETED, wait_for=120)
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=120)
wait_for_bid(
test_delay_event,
swap_clients[2],
bid_id,
BidStates.SWAP_COMPLETED,
wait_for=120,
)
wait_for_bid(
test_delay_event,
swap_clients[1],
bid_id,
BidStates.SWAP_COMPLETED,
sent=True,
wait_for=120,
)
# Verify expected inputs were used
bid, _, _, _, _ = swap_clients[2].getXmrBidAndOffer(bid_id)
assert (bid.xmr_a_lock_tx)
wtx = ci.rpc_wallet('gettransaction', [bid.xmr_a_lock_tx.txid.hex(),])
itx_after = ci.describeTx(wtx['hex'])
assert (len(itx_after['vin']) == len(itx_decoded['vin']))
for i, txin in enumerate(itx_decoded['vin']):
txin_after = itx_after['vin'][i]
assert (txin['txid'] == txin_after['txid'])
assert (txin['vout'] == txin_after['vout'])
assert bid.xmr_a_lock_tx
wtx = ci.rpc_wallet(
"gettransaction",
[
bid.xmr_a_lock_tx.txid.hex(),
],
)
itx_after = ci.describeTx(wtx["hex"])
assert len(itx_after["vin"]) == len(itx_decoded["vin"])
for i, txin in enumerate(itx_decoded["vin"]):
txin_after = itx_after["vin"][i]
assert txin["txid"] == txin_after["txid"]
assert txin["vout"] == txin_after["vout"]
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019-2023 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -41,7 +42,7 @@ from tests.basicswap.common_xmr import (
)
import basicswap.bin.run as runSystem
TEST_PATH = os.path.expanduser(os.getenv('TEST_PATH', '~/test_basicswap1'))
TEST_PATH = os.path.expanduser(os.getenv("TEST_PATH", "~/test_basicswap1"))
delay_event = threading.Event()
logger = logging.getLogger()
@ -51,22 +52,22 @@ if not len(logger.handlers):
def btcRpc(client_no, cmd):
bin_path = os.path.join(TEST_PATH, 'bin', 'bitcoin')
data_path = os.path.join(TEST_PATH, 'client{}'.format(client_no), 'bitcoin')
return callrpc_cli(bin_path, data_path, 'regtest', cmd, 'bitcoin-cli')
bin_path = os.path.join(TEST_PATH, "bin", "bitcoin")
data_path = os.path.join(TEST_PATH, "client{}".format(client_no), "bitcoin")
return callrpc_cli(bin_path, data_path, "regtest", cmd, "bitcoin-cli")
def partRpc(client_no, cmd):
bin_path = os.path.join(TEST_PATH, 'bin', 'particl')
data_path = os.path.join(TEST_PATH, 'client{}'.format(client_no), 'particl')
return callrpc_cli(bin_path, data_path, 'regtest', cmd, 'particl-cli')
bin_path = os.path.join(TEST_PATH, "bin", "particl")
data_path = os.path.join(TEST_PATH, "client{}".format(client_no), "particl")
return callrpc_cli(bin_path, data_path, "regtest", cmd, "particl-cli")
def updateThread():
btc_addr = btcRpc(0, 'getnewaddress mining_addr bech32')
btc_addr = btcRpc(0, "getnewaddress mining_addr bech32")
while not delay_event.is_set():
btcRpc(0, 'generatetoaddress {} {}'.format(1, btc_addr))
btcRpc(0, "generatetoaddress {} {}".format(1, btc_addr))
delay_event.wait(5)
@ -75,30 +76,34 @@ class Test(unittest.TestCase):
def setUpClass(cls):
super(Test, cls).setUpClass()
prepare_nodes(3, 'bitcoin')
prepare_nodes(3, "bitcoin")
def run_thread(self, client_id):
client_path = os.path.join(TEST_PATH, 'client{}'.format(client_id))
testargs = ['basicswap-run', '-datadir=' + client_path, '-regtest']
with patch.object(sys, 'argv', testargs):
client_path = os.path.join(TEST_PATH, "client{}".format(client_id))
testargs = ["basicswap-run", "-datadir=" + client_path, "-regtest"]
with patch.object(sys, "argv", testargs):
runSystem.main()
def wait_for_node_height(self, port=12701, wallet_ticker='part', wait_for_blocks=3):
def wait_for_node_height(self, port=12701, wallet_ticker="part", wait_for_blocks=3):
# Wait for height, or sequencelock is thrown off by genesis blocktime
logging.info(f'Waiting for {wallet_ticker} chain height {wait_for_blocks} at port {port}', )
logging.info(
f"Waiting for {wallet_ticker} chain height {wait_for_blocks} at port {port}",
)
for i in range(60):
if delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
try:
wallet = read_json_api(port, f'wallets/{wallet_ticker}')
node_blocks = wallet['blocks']
print(f'{wallet_ticker} node_blocks {node_blocks}')
wallet = read_json_api(port, f"wallets/{wallet_ticker}")
node_blocks = wallet["blocks"]
print(f"{wallet_ticker} node_blocks {node_blocks}")
if node_blocks >= wait_for_blocks:
return
except Exception as e:
print('Error reading wallets', str(e))
print("Error reading wallets", str(e))
delay_event.wait(1)
raise ValueError(f'wait_for_node_height timed out, {wallet_ticker}, {wait_for_blocks}, {port}')
raise ValueError(
f"wait_for_node_height timed out, {wallet_ticker}, {wait_for_blocks}, {port}"
)
def test_reload(self):
global stop_test
@ -110,58 +115,55 @@ class Test(unittest.TestCase):
try:
waitForServer(delay_event, 12700)
partRpc(0, 'reservebalance false') # WakeThreadStakeMiner
partRpc(0, "reservebalance false") # WakeThreadStakeMiner
self.wait_for_node_height()
num_blocks = 500
btc_addr = btcRpc(1, 'getnewaddress mining_addr bech32')
logging.info('Mining %d Bitcoin blocks to %s', num_blocks, btc_addr)
btcRpc(1, 'generatetoaddress {} {}'.format(num_blocks, btc_addr))
self.wait_for_node_height(12700, 'btc', num_blocks)
btc_addr = btcRpc(1, "getnewaddress mining_addr bech32")
logging.info("Mining %d Bitcoin blocks to %s", num_blocks, btc_addr)
btcRpc(1, "generatetoaddress {} {}".format(num_blocks, btc_addr))
self.wait_for_node_height(12700, "btc", num_blocks)
data = {
'addr_from': '-1',
'coin_from': 'PART',
'coin_to': '2',
'amt_from': '1',
'amt_to': '1',
'lockhrs': '24'}
"addr_from": "-1",
"coin_from": "PART",
"coin_to": "2",
"amt_from": "1",
"amt_to": "1",
"lockhrs": "24",
}
offer_id = post_json_api(12700, 'offers/new', data)['offer_id']
offer_id = post_json_api(12700, "offers/new", data)["offer_id"]
summary = read_json_api(12700)
assert (summary['num_sent_offers'] == 1)
assert summary["num_sent_offers"] == 1
except Exception:
traceback.print_exc()
sentoffers = read_json_api(12700, 'sentoffers', {'active': True})
assert sentoffers[0]['offer_id'] == offer_id
sentoffers = read_json_api(12700, "sentoffers", {"active": True})
assert sentoffers[0]["offer_id"] == offer_id
logger.info('Waiting for offer:')
logger.info("Waiting for offer:")
waitForNumOffers(delay_event, 12701, 1)
offers = read_json_api(12701, 'offers')
offers = read_json_api(12701, "offers")
offer = offers[0]
data = {
'offer_id': offer['offer_id'],
'amount_from': offer['amount_from']}
data = {"offer_id": offer["offer_id"], "amount_from": offer["amount_from"]}
bid_id = post_json_api(12701, 'bids/new', data)
post_json_api(12701, "bids/new", data)
waitForNumBids(delay_event, 12700, 1)
bids = read_json_api(12700, 'bids')
bids = read_json_api(12700, "bids")
bid = bids[0]
data = {
'accept': True
}
rv = post_json_api(12700, 'bids/{}'.format(bid['bid_id']), data)
assert (rv['bid_state'] == 'Accepted')
data = {"accept": True}
rv = post_json_api(12700, "bids/{}".format(bid["bid_id"]), data)
assert rv["bid_state"] == "Accepted"
waitForNumSwapping(delay_event, 12701, 1)
logger.info('Restarting client:')
logger.info("Restarting client:")
c1 = processes[1]
c1.terminate()
c1.join()
@ -170,19 +172,19 @@ class Test(unittest.TestCase):
waitForServer(delay_event, 12701)
rv = read_json_api(12701)
assert (rv['num_swapping'] == 1)
assert rv["num_swapping"] == 1
update_thread = threading.Thread(target=updateThread)
update_thread.start()
logger.info('Completing swap:')
logger.info("Completing swap:")
for i in range(240):
delay_event.wait(5)
rv = read_json_api(12700, 'bids/{}'.format(bid['bid_id']))
if rv['bid_state'] == 'Completed':
rv = read_json_api(12700, "bids/{}".format(bid["bid_id"]))
if rv["bid_state"] == "Completed":
break
assert (rv['bid_state'] == 'Completed')
assert rv["bid_state"] == "Completed"
delay_event.set()
update_thread.join()
@ -192,5 +194,5 @@ class Test(unittest.TestCase):
p.join()
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021-2022 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -51,105 +52,140 @@ class Test(XmrTestBase):
waitForServer(self.delay_event, 12700)
waitForServer(self.delay_event, 12701)
wallets1 = read_json_api(12701, 'wallets')
assert (float(wallets1['XMR']['balance']) > 0.0)
wallets1 = read_json_api(12701, "wallets")
assert float(wallets1["XMR"]["balance"]) > 0.0
offer_data = {
'addr_from': -1,
'coin_from': 'PART',
'coin_to': 'XMR',
'amt_from': 1,
'amt_to': 1,
'lockhrs': 24,
'automation_strat_id': 1}
rv = json.loads(urlopen('http://127.0.0.1:12700/json/offers/new', data=parse.urlencode(offer_data).encode()).read())
offer0_id = rv['offer_id']
"addr_from": -1,
"coin_from": "PART",
"coin_to": "XMR",
"amt_from": 1,
"amt_to": 1,
"lockhrs": 24,
"automation_strat_id": 1,
}
rv = json.loads(
urlopen(
"http://127.0.0.1:12700/json/offers/new",
data=parse.urlencode(offer_data).encode(),
).read()
)
offer0_id = rv["offer_id"]
offer_data['amt_from'] = '2'
rv = json.loads(urlopen('http://127.0.0.1:12700/json/offers/new', data=parse.urlencode(offer_data).encode()).read())
offer1_id = rv['offer_id']
offer_data["amt_from"] = "2"
rv = json.loads(
urlopen(
"http://127.0.0.1:12700/json/offers/new",
data=parse.urlencode(offer_data).encode(),
).read()
)
offer1_id = rv["offer_id"]
summary = read_json_api(12700)
assert (summary['num_sent_offers'] > 1)
assert summary["num_sent_offers"] > 1
logger.info('Waiting for offer')
logger.info("Waiting for offer")
waitForNumOffers(self.delay_event, 12701, 2)
logger.info('Stopping node 0')
logger.info("Stopping node 0")
c0 = self.processes[0]
c0.terminate()
c0.join()
offers = json.loads(urlopen('http://127.0.0.1:12701/json/offers/{}'.format(offer0_id)).read())
assert (len(offers) == 1)
offers = json.loads(
urlopen("http://127.0.0.1:12701/json/offers/{}".format(offer0_id)).read()
)
assert len(offers) == 1
offer0 = offers[0]
post_data = {
'coin_from': 'PART'
}
test_post_offers = json.loads(urlopen('http://127.0.0.1:12701/json/offers', data=parse.urlencode(post_data).encode()).read())
assert (len(test_post_offers) == 2)
post_data['coin_from'] = '2'
test_post_offers = json.loads(urlopen('http://127.0.0.1:12701/json/offers', data=parse.urlencode(post_data).encode()).read())
assert (len(test_post_offers) == 0)
post_data = {"coin_from": "PART"}
test_post_offers = json.loads(
urlopen(
"http://127.0.0.1:12701/json/offers",
data=parse.urlencode(post_data).encode(),
).read()
)
assert len(test_post_offers) == 2
post_data["coin_from"] = "2"
test_post_offers = json.loads(
urlopen(
"http://127.0.0.1:12701/json/offers",
data=parse.urlencode(post_data).encode(),
).read()
)
assert len(test_post_offers) == 0
bid_data = {
'offer_id': offer0_id,
'amount_from': offer0['amount_from']}
bid_data = {"offer_id": offer0_id, "amount_from": offer0["amount_from"]}
bid0_id = json.loads(urlopen('http://127.0.0.1:12701/json/bids/new', data=parse.urlencode(bid_data).encode()).read())['bid_id']
bid0_id = json.loads(
urlopen(
"http://127.0.0.1:12701/json/bids/new",
data=parse.urlencode(bid_data).encode(),
).read()
)["bid_id"]
offers = json.loads(urlopen('http://127.0.0.1:12701/json/offers/{}'.format(offer1_id)).read())
assert (len(offers) == 1)
offers = json.loads(
urlopen("http://127.0.0.1:12701/json/offers/{}".format(offer1_id)).read()
)
assert len(offers) == 1
offer1 = offers[0]
bid_data = {
'offer_id': offer1_id,
'amount_from': offer1['amount_from']}
bid_data = {"offer_id": offer1_id, "amount_from": offer1["amount_from"]}
bid1_id = json.loads(urlopen('http://127.0.0.1:12701/json/bids/new', data=parse.urlencode(bid_data).encode()).read())['bid_id']
bid1_id = json.loads(
urlopen(
"http://127.0.0.1:12701/json/bids/new",
data=parse.urlencode(bid_data).encode(),
).read()
)["bid_id"]
logger.info('Delaying for 5 seconds.')
logger.info("Delaying for 5 seconds.")
self.delay_event.wait(5)
logger.info('Starting node 0')
logger.info("Starting node 0")
self.processes[0] = multiprocessing.Process(target=self.run_thread, args=(0,))
self.processes[0].start()
waitForServer(self.delay_event, 12700)
waitForNumBids(self.delay_event, 12700, 2)
waitForBidState(self.delay_event, 12700, bid0_id, 'Received')
waitForBidState(self.delay_event, 12700, bid1_id, 'Received')
waitForBidState(self.delay_event, 12700, bid0_id, "Received")
waitForBidState(self.delay_event, 12700, bid1_id, "Received")
# Manually accept on top of auto-accept for extra chaos
data = parse.urlencode({
'accept': True
}).encode()
data = parse.urlencode({"accept": True}).encode()
try:
rv = json.loads(urlopen('http://127.0.0.1:12700/json/bids/{}'.format(bid0_id), data=data).read())
assert rv['bid_state'] == 'Accepted'
rv = json.loads(
urlopen(
"http://127.0.0.1:12700/json/bids/{}".format(bid0_id), data=data
).read()
)
assert rv["bid_state"] == "Accepted"
except Exception as e:
print('Accept bid failed', str(e), rv)
print("Accept bid failed", str(e), rv)
try:
rv = json.loads(urlopen('http://127.0.0.1:12700/json/bids/{}'.format(bid1_id), data=data).read())
assert (rv['bid_state'] == 'Accepted')
rv = json.loads(
urlopen(
"http://127.0.0.1:12700/json/bids/{}".format(bid1_id), data=data
).read()
)
assert rv["bid_state"] == "Accepted"
except Exception as e:
print('Accept bid failed', str(e), rv)
print("Accept bid failed", str(e), rv)
logger.info('Completing swap')
logger.info("Completing swap")
for i in range(240):
if self.delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
self.delay_event.wait(4)
rv0 = read_json_api(12700, 'bids/{}'.format(bid0_id))
rv1 = read_json_api(12700, 'bids/{}'.format(bid1_id))
if rv0['bid_state'] == 'Completed' and rv1['bid_state'] == 'Completed':
rv0 = read_json_api(12700, "bids/{}".format(bid0_id))
rv1 = read_json_api(12700, "bids/{}".format(bid1_id))
if rv0["bid_state"] == "Completed" and rv1["bid_state"] == "Completed":
break
assert rv0['bid_state'] == 'Completed'
assert rv1['bid_state'] == 'Completed'
assert rv0["bid_state"] == "Completed"
assert rv1["bid_state"] == "Completed"
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2022 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@ -47,70 +48,67 @@ class Test(XmrTestBase):
waitForServer(self.delay_event, 12700)
waitForServer(self.delay_event, 12701)
wallets1 = read_json_api(12701, 'wallets')
assert (float(wallets1['XMR']['balance']) > 0.0)
wallets1 = read_json_api(12701, "wallets")
assert float(wallets1["XMR"]["balance"]) > 0.0
data = {
'addr_from': '-1',
'coin_from': 'part',
'coin_to': 'xmr',
'amt_from': '1',
'amt_to': '1',
'lockhrs': '24'}
"addr_from": "-1",
"coin_from": "part",
"coin_to": "xmr",
"amt_from": "1",
"amt_to": "1",
"lockhrs": "24",
}
offer_id = post_json_api(12700, 'offers/new', data)['offer_id']
offer_id = post_json_api(12700, "offers/new", data)["offer_id"]
summary = read_json_api(12700)
assert (summary['num_sent_offers'] == 1)
assert summary["num_sent_offers"] == 1
logger.info('Waiting for offer')
logger.info("Waiting for offer")
waitForNumOffers(self.delay_event, 12701, 1)
offers = read_json_api(12701, 'offers')
offers = read_json_api(12701, "offers")
offer = offers[0]
data = {
'offer_id': offer['offer_id'],
'amount_from': offer['amount_from']}
data = {"offer_id": offer["offer_id"], "amount_from": offer["amount_from"]}
data['valid_for_seconds'] = 24 * 60 * 60 + 1
bid = post_json_api(12701, 'bids/new', data)
assert (bid['error'] == 'Bid TTL too high')
del data['valid_for_seconds']
data['validmins'] = 24 * 60 + 1
bid = post_json_api(12701, 'bids/new', data)
assert (bid['error'] == 'Bid TTL too high')
data["valid_for_seconds"] = 24 * 60 * 60 + 1
bid = post_json_api(12701, "bids/new", data)
assert bid["error"] == "Bid TTL too high"
del data["valid_for_seconds"]
data["validmins"] = 24 * 60 + 1
bid = post_json_api(12701, "bids/new", data)
assert bid["error"] == "Bid TTL too high"
del data['validmins']
data['valid_for_seconds'] = 10
bid = post_json_api(12701, 'bids/new', data)
assert (bid['error'] == 'Bid TTL too low')
del data['valid_for_seconds']
data['validmins'] = 1
bid = post_json_api(12701, 'bids/new', data)
assert (bid['error'] == 'Bid TTL too low')
del data["validmins"]
data["valid_for_seconds"] = 10
bid = post_json_api(12701, "bids/new", data)
assert bid["error"] == "Bid TTL too low"
del data["valid_for_seconds"]
data["validmins"] = 1
bid = post_json_api(12701, "bids/new", data)
assert bid["error"] == "Bid TTL too low"
data['validmins'] = 60
bid_id = post_json_api(12701, 'bids/new', data)
data["validmins"] = 60
post_json_api(12701, "bids/new", data)
waitForNumBids(self.delay_event, 12700, 1)
for i in range(10):
bids = read_json_api(12700, 'bids')
bids = read_json_api(12700, "bids")
bid = bids[0]
if bid['bid_state'] == 'Received':
if bid["bid_state"] == "Received":
break
self.delay_event.wait(1)
assert (bid['expire_at'] == bid['created_at'] + data['validmins'] * 60)
assert bid["expire_at"] == bid["created_at"] + data["validmins"] * 60
data = {
'accept': True
}
rv = post_json_api(12700, 'bids/{}'.format(bid['bid_id']), data)
assert (rv['bid_state'] == 'Accepted')
data = {"accept": True}
rv = post_json_api(12700, "bids/{}".format(bid["bid_id"]), data)
assert rv["bid_state"] == "Accepted"
waitForNumSwapping(self.delay_event, 12701, 1)
logger.info('Restarting client')
logger.info("Restarting client")
c1 = self.processes[1]
c1.terminate()
c1.join()
@ -119,29 +117,29 @@ class Test(XmrTestBase):
waitForServer(self.delay_event, 12701)
rv = read_json_api(12701)
assert (rv['num_swapping'] == 1)
assert rv["num_swapping"] == 1
rv = read_json_api(12700, 'revokeoffer/{}'.format(offer_id))
assert (rv['revoked_offer'] == offer_id)
rv = read_json_api(12700, "revokeoffer/{}".format(offer_id))
assert rv["revoked_offer"] == offer_id
logger.info('Completing swap')
logger.info("Completing swap")
for i in range(240):
if self.delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
self.delay_event.wait(4)
rv = read_json_api(12700, 'bids/{}'.format(bid['bid_id']))
if rv['bid_state'] == 'Completed':
rv = read_json_api(12700, "bids/{}".format(bid["bid_id"]))
if rv["bid_state"] == "Completed":
break
assert (rv['bid_state'] == 'Completed')
assert rv["bid_state"] == "Completed"
# Ensure offer was revoked
summary = read_json_api(12700)
assert (summary['num_network_offers'] == 0)
assert summary["num_network_offers"] == 0
# Wait for bid to be removed from in-progress
waitForNumBids(self.delay_event, 12700, 0)
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main()

View file

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022-2024 tecnovert
# Copyright (c) 2024 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE.txt or http://www.opensource.org/licenses/mit-license.php.
@ -10,32 +11,37 @@ import urllib
from urllib.request import urlopen
REQUIRED_SETTINGS = {'blocks_confirmed': 1, 'conf_target': 1, 'use_segwit': True, 'connection_type': 'rpc'}
REQUIRED_SETTINGS = {
"blocks_confirmed": 1,
"conf_target": 1,
"use_segwit": True,
"connection_type": "rpc",
}
def make_boolean(s):
return s.lower() in ['1', 'true']
return s.lower() in ["1", "true"]
def post_json_req(url, json_data):
req = urllib.request.Request(url)
req.add_header('Content-Type', 'application/json; charset=utf-8')
post_bytes = json.dumps(json_data).encode('utf-8')
req.add_header('Content-Length', len(post_bytes))
req.add_header("Content-Type", "application/json; charset=utf-8")
post_bytes = json.dumps(json_data).encode("utf-8")
req.add_header("Content-Length", len(post_bytes))
return urlopen(req, post_bytes, timeout=300).read()
def read_text_api(port, path=None):
url = f'http://127.0.0.1:{port}/json'
url = f"http://127.0.0.1:{port}/json"
if path is not None:
url += '/' + path
return urlopen(url, timeout=300).read().decode('utf-8')
url += "/" + path
return urlopen(url, timeout=300).read().decode("utf-8")
def read_json_api(port, path=None, json_data=None):
url = f'http://127.0.0.1:{port}/json'
url = f"http://127.0.0.1:{port}/json"
if path is not None:
url += '/' + path
url += "/" + path
if json_data is not None:
return json.loads(post_json_req(url, json_data))
@ -43,20 +49,20 @@ def read_json_api(port, path=None, json_data=None):
def post_json_api(port, path, json_data):
url = f'http://127.0.0.1:{port}/json'
url = f"http://127.0.0.1:{port}/json"
if path is not None:
url += '/' + path
url += "/" + path
return json.loads(post_json_req(url, json_data))
def waitForServer(delay_event, port, wait_for=20):
for i in range(wait_for):
if delay_event.is_set():
raise ValueError('Test stopped.')
raise ValueError("Test stopped.")
try:
delay_event.wait(1)
summary = read_json_api(port)
_ = read_json_api(port)
return
except Exception as e:
print('waitForServer, error:', str(e))
raise ValueError('waitForServer failed')
print("waitForServer, error:", str(e))
raise ValueError("waitForServer failed")