tests: Deduplicate test_run.py

This commit is contained in:
tecnovert 2021-11-27 17:58:58 +02:00
parent 58e4b506fe
commit cd4103ce3e
No known key found for this signature in database
GPG key ID: 8ED6D8750C4E3F93
6 changed files with 157 additions and 372 deletions

View file

@ -1521,12 +1521,13 @@ class BasicSwap(BaseApp):
ensure(sign_for_addr is not None, 'Could not find address with enough funds for proof')
self.log.debug('sign_for_addr %s', sign_for_addr)
if self.coin_clients[coin_type]['use_segwit']:
if self.coin_clients[coin_type]['use_segwit']: # TODO: Use isSegwitAddress when scantxoutset can use combo
# 'Address does not refer to key' for non p2pkh
addrinfo = self.callcoinrpc(coin_type, 'getaddressinfo', [sign_for_addr])
pkh = addrinfo['scriptPubKey'][4:]
sign_for_addr = encodeAddress(bytes((chainparams[coin_type][self.chain]['pubkey_address'],)) + bytes.fromhex(pkh))
self.log.debug('sign_for_addr converted %s', sign_for_addr)
signature = self.callcoinrpc(coin_type, 'signmessage', [sign_for_addr, sign_for_addr + '_swap_proof_' + extra_commit_bytes.hex()])
return (sign_for_addr, signature)
@ -2549,7 +2550,7 @@ class BasicSwap(BaseApp):
return redeem_txn
def createRefundTxn(self, coin_type, txn, offer, bid, txn_script, addr_refund_out=None, tx_type=TxTypes.ITX_REFUND):
self.log.debug('createRefundTxn')
self.log.debug('createRefundTxn for coin %s', Coins(coin_type).name)
if self.coin_clients[coin_type]['connection_type'] != 'rpc':
return None
@ -2662,7 +2663,7 @@ class BasicSwap(BaseApp):
bid.setITxState(TxStates.TX_CONFIRMED)
if bid.debug_ind == DebugTypes.BUYER_STOP_AFTER_ITX:
self.log.debug('bid %s: Abandoning bid for testing: %d.', bid_id.hex(), bid.debug_ind)
self.log.debug('bid %s: Abandoning bid for testing: %d, %s.', bid_id.hex(), bid.debug_ind, DebugTypes(bid.debug_ind).name)
bid.setState(BidStates.BID_ABANDONED)
self.logBidEvent(bid.bid_id, EventLogTypes.DEBUG_TWEAK_APPLIED, 'ind {}'.format(bid.debug_ind), None)
return # Bid saved in checkBidState
@ -2787,7 +2788,7 @@ class BasicSwap(BaseApp):
sum_unspent = 0
self.log.debug('[rm] scantxoutset start') # scantxoutset is slow
ro = self.callcoinrpc(coin_type, 'scantxoutset', ['start', ['addr({})'.format(address)]])
ro = self.callcoinrpc(coin_type, 'scantxoutset', ['start', ['addr({})'.format(address)]]) # TODO: Use combo(address) where possible
self.log.debug('[rm] scantxoutset end')
for o in ro['unspents']:
if assert_txid and o['txid'] != assert_txid:
@ -3304,11 +3305,17 @@ class BasicSwap(BaseApp):
if bid.was_sent:
txn = self.createRedeemTxn(coin_from, bid, for_txn_type='initiate')
txid = self.submitTxn(coin_from, txn)
bid.initiate_tx.spend_txid = bytes.fromhex(txid)
# bid.initiate_txn_redeem = bytes.fromhex(txn) # Worth keeping?
self.log.debug('Submitted initiate redeem txn %s to %s chain for bid %s', txid, chainparams[coin_from]['name'], bid_id.hex())
if bid.debug_ind == DebugTypes.DONT_SPEND_ITX:
self.log.debug('bid %s: Abandoning bid for testing: %d, %s.', bid_id.hex(), bid.debug_ind, DebugTypes(bid.debug_ind).name)
bid.setState(BidStates.BID_ABANDONED)
self.logBidEvent(bid.bid_id, EventLogTypes.DEBUG_TWEAK_APPLIED, 'ind {}'.format(bid.debug_ind), None)
else:
txid = self.submitTxn(coin_from, txn)
bid.initiate_tx.spend_txid = bytes.fromhex(txid)
# bid.initiate_txn_redeem = bytes.fromhex(txn) # Worth keeping?
self.log.debug('Submitted initiate redeem txn %s to %s chain for bid %s', txid, chainparams[coin_from]['name'], bid_id.hex())
# TODO: Wait for depth? new state SWAP_TXI_REDEEM_SENT?

View file

@ -156,6 +156,7 @@ class DebugTypes(IntEnum):
CREATE_INVALID_COIN_B_LOCK = auto()
BUYER_STOP_AFTER_ITX = auto()
MAKE_INVALID_PTX = auto()
DONT_SPEND_ITX = auto()
def strOfferState(state):

View file

@ -254,9 +254,12 @@ class BTCInterface(CoinInterface):
except Exception:
return self.rpc_callback('getnetworkinfo')['relayfee'], 'relayfee'
def isSegwitAddress(self, address):
return address.startswith(self.chainparams_network()['hrp'] + '1')
def decodeAddress(self, address):
bech32_prefix = self.chainparams_network()['hrp']
if address.startswith(bech32_prefix):
if address.startswith(bech32_prefix + '1'):
return bytes(segwit_addr.decode(bech32_prefix, address)[1])
return decodeAddress(address)[1:]

View file

@ -168,6 +168,7 @@ def js_bids(self, url_split, post_string, is_json):
assert(offer), 'Offer not found.'
ci_from = swap_client.ci(offer.coin_from)
ci_to = swap_client.ci(offer.coin_to)
amount_from = inputAmount(get_data_entry(post_data, 'amount_from'), ci_from)
addr_from = None
@ -186,10 +187,10 @@ def js_bids(self, url_split, post_string, is_json):
extra_options = {
'valid_for_seconds': valid_for_seconds,
}
if have_data_entry(form_data, 'bid_rate'):
extra_options['bid_rate'] = ci_to.make_int(get_data_entry(form_data, 'bid_rate'), r=1)
if have_data_entry(form_data, 'bid_amount'):
amount_from = inputAmount(get_data_entry(form_data, 'bid_amount'), ci_from)
if have_data_entry(post_data, 'bid_rate'):
extra_options['bid_rate'] = ci_to.make_int(get_data_entry(post_data, 'bid_rate'), r=1)
if have_data_entry(post_data, 'bid_amount'):
amount_from = inputAmount(get_data_entry(post_data, 'bid_amount'), ci_from)
if offer.swap_type == SwapTypes.XMR_SWAP:
bid_id = swap_client.postXmrBid(offer_id, amount_from, addr_send_from=addr_from, extra_options=extra_options)

View file

@ -13,20 +13,13 @@ $ pytest -v -s tests/basicswap/test_run.py::Test::test_04_ltc_btc
"""
import os
import sys
import json
import random
import shutil
import signal
import logging
import unittest
import threading
from urllib.request import urlopen
import basicswap.config as cfg
from basicswap.basicswap import (
BasicSwap,
Coins,
SwapTypes,
BidStates,
@ -38,346 +31,53 @@ from basicswap.basicswap_util import (
)
from basicswap.util import (
COIN,
toWIF,
dumpje,
make_int,
format_amount,
)
from basicswap.rpc import (
callrpc_cli,
waitForRPC,
)
from basicswap.contrib.key import (
ECKey,
)
from basicswap.http_server import (
HttpThread,
)
from tests.basicswap.common import (
checkForks,
stopDaemons,
wait_for_offer,
wait_for_bid,
wait_for_balance,
wait_for_bid_tx_state,
wait_for_in_progress,
post_json_req,
TEST_HTTP_HOST,
TEST_HTTP_PORT,
BASE_PORT,
BASE_RPC_PORT,
BASE_ZMQ_PORT,
PREFIX_SECRET_KEY_REGTEST,
LTC_BASE_RPC_PORT,
BTC_BASE_RPC_PORT,
)
from bin.basicswap_run import startDaemon
NUM_NODES = 3
LTC_NODE = 3
BTC_NODE = 4
test_delay_event = threading.Event()
from .test_xmr import BaseTest, test_delay_event, callnoderpc
logger = logging.getLogger()
logger.level = logging.DEBUG
if not len(logger.handlers):
logger.addHandler(logging.StreamHandler(sys.stdout))
def prepareOtherDir(datadir, nodeId, conf_file='litecoin.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')
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.0002\n')
fp.write('wallet=wallet.dat\n')
fp.write('acceptnonstdtxn=0\n')
return node_dir
def prepareDir(datadir, nodeId, network_key, network_pubkey):
node_dir = os.path.join(datadir, str(nodeId))
if not os.path.exists(node_dir):
os.makedirs(node_dir)
filePath = os.path.join(node_dir, 'particl.conf')
with open(filePath, 'w+') as fp:
fp.write('regtest=1\n')
fp.write('[regtest]\n')
fp.write('port=' + str(BASE_PORT + nodeId) + '\n')
fp.write('rpcport=' + str(BASE_RPC_PORT + nodeId) + '\n')
fp.write('daemon=0\n')
fp.write('printtoconsole=0\n')
fp.write('server=1\n')
fp.write('discover=0\n')
fp.write('listenonion=0\n')
fp.write('bind=127.0.0.1\n')
fp.write('findpeers=0\n')
fp.write('debug=1\n')
fp.write('debugexclude=libevent\n')
fp.write('zmqpubsmsg=tcp://127.0.0.1:' + str(BASE_ZMQ_PORT + nodeId) + '\n')
fp.write('wallet=wallet.dat\n')
fp.write('acceptnonstdtxn=0\n')
fp.write('minstakeinterval=2\n')
fp.write('smsgsregtestadjust=0\n')
fp.write('stakethreadconddelayms=1000\n')
for i in range(0, NUM_NODES):
if nodeId == i:
continue
fp.write('addnode=127.0.0.1:%d\n' % (BASE_PORT + i))
if nodeId < 2:
fp.write('spentindex=1\n')
fp.write('txindex=1\n')
basicswap_dir = os.path.join(datadir, str(nodeId), 'basicswap')
if not os.path.exists(basicswap_dir):
os.makedirs(basicswap_dir)
ltcdatadir = os.path.join(datadir, str(LTC_NODE))
btcdatadir = os.path.join(datadir, str(BTC_NODE))
settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
settings = {
'debug': True,
'zmqhost': 'tcp://127.0.0.1',
'zmqport': BASE_ZMQ_PORT + nodeId,
'htmlhost': '127.0.0.1',
'htmlport': 12700 + nodeId,
'network_key': network_key,
'network_pubkey': network_pubkey,
'chainclients': {
'particl': {
'connection_type': 'rpc',
'manage_daemon': False,
'rpcport': BASE_RPC_PORT + nodeId,
'datadir': node_dir,
'bindir': cfg.PARTICL_BINDIR,
'blocks_confirmed': 2, # Faster testing
},
'litecoin': {
'connection_type': 'rpc',
'manage_daemon': False,
'rpcport': BASE_RPC_PORT + LTC_NODE,
'datadir': ltcdatadir,
'bindir': cfg.LITECOIN_BINDIR,
# 'use_segwit': True,
},
'bitcoin': {
'connection_type': 'rpc',
'manage_daemon': False,
'rpcport': BASE_RPC_PORT + BTC_NODE,
'datadir': btcdatadir,
'bindir': cfg.BITCOIN_BINDIR,
'use_segwit': True,
}
},
'check_progress_seconds': 2,
'check_watched_seconds': 4,
'check_expired_seconds': 60,
'check_events_seconds': 1,
'min_delay_event': 1,
'max_delay_event': 5
}
with open(settings_path, 'w') as fp:
json.dump(settings, fp, indent=4)
return node_dir
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)
def btcRpc(cmd):
return callrpc_cli(cfg.BITCOIN_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)), 'regtest', cmd, cfg.BITCOIN_CLI)
def ltcRpc(cmd):
return callrpc_cli(cfg.LITECOIN_BINDIR, os.path.join(cfg.TEST_DATADIRS, str(LTC_NODE)), 'regtest', cmd, cfg.LITECOIN_CLI)
def signal_handler(sig, frame):
print('signal {} detected.'.format(sig))
test_delay_event.set()
def run_coins_loop(cls):
while not test_delay_event.is_set():
try:
ltcRpc('generatetoaddress 1 {}'.format(cls.ltc_addr))
btcRpc('generatetoaddress 1 {}'.format(cls.btc_addr))
except Exception as e:
logging.warning('run_coins_loop ' + str(e))
test_delay_event.wait(1.0)
def run_loop(cls):
while not test_delay_event.is_set():
for c in cls.swap_clients:
c.update()
test_delay_event.wait(1)
def make_part_cli_rpc_func(node_id):
node_id = node_id
def rpc_func(method, params=None, wallet=None):
nonlocal node_id
cmd = method
if params:
for p in params:
if isinstance(p, dict) or isinstance(p, list):
cmd += ' "' + dumpje(p) + '"'
elif isinstance(p, int):
cmd += ' ' + str(p)
else:
cmd += ' "' + p + '"'
return partRpc(cmd, node_id)
return rpc_func
class Test(unittest.TestCase):
class Test(BaseTest):
__test__ = True
@classmethod
def setUpClass(cls):
cls.start_ltc_nodes = True
cls.start_xmr_nodes = False
super(Test, cls).setUpClass()
eckey = ECKey()
eckey.generate()
cls.network_key = toWIF(PREFIX_SECRET_KEY_REGTEST, eckey.get_bytes())
cls.network_pubkey = eckey.get_pubkey().get_bytes().hex()
btc_addr1 = callnoderpc(1, 'getnewaddress', ['initial funds', 'bech32'], base_rpc_port=BTC_BASE_RPC_PORT)
ltc_addr1 = callnoderpc(1, 'getnewaddress', ['initial funds', 'bech32'], base_rpc_port=LTC_BASE_RPC_PORT)
if os.path.isdir(cfg.TEST_DATADIRS):
logging.info('Removing ' + cfg.TEST_DATADIRS)
shutil.rmtree(cfg.TEST_DATADIRS)
callnoderpc(0, 'sendtoaddress', [btc_addr1, 1000], base_rpc_port=BTC_BASE_RPC_PORT)
callnoderpc(0, 'sendtoaddress', [ltc_addr1, 1000], base_rpc_port=LTC_BASE_RPC_PORT)
for i in range(NUM_NODES):
data_dir = prepareDir(cfg.TEST_DATADIRS, i, cls.network_key, cls.network_pubkey)
callrpc_cli(cfg.PARTICL_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat create', 'particl-wallet') # Necessary for 0.21
prepareOtherDir(cfg.TEST_DATADIRS, LTC_NODE)
data_dir = prepareOtherDir(cfg.TEST_DATADIRS, BTC_NODE, 'bitcoin.conf')
callrpc_cli(cfg.BITCOIN_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat create', 'bitcoin-wallet') # Necessary for 0.21
cls.daemons = []
cls.swap_clients = []
cls.http_threads = []
cls.daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, str(BTC_NODE)), cfg.BITCOIN_BINDIR, cfg.BITCOIND))
logging.info('Started %s %d', cfg.BITCOIND, cls.daemons[-1].pid)
cls.daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, str(LTC_NODE)), cfg.LITECOIN_BINDIR, cfg.LITECOIND))
logging.info('Started %s %d', cfg.LITECOIND, cls.daemons[-1].pid)
for i in range(NUM_NODES):
cls.daemons.append(startDaemon(os.path.join(cfg.TEST_DATADIRS, str(i)), cfg.PARTICL_BINDIR, cfg.PARTICLD))
logging.info('Started %s %d', cfg.PARTICLD, cls.daemons[-1].pid)
for i in range(NUM_NODES):
# Load mnemonics after all nodes have started to avoid staking getting stuck in TryToSync
rpc = make_part_cli_rpc_func(i)
waitForRPC(rpc)
if i == 0:
rpc('extkeyimportmaster', ['abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb'])
elif i == 1:
rpc('extkeyimportmaster', ['pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic', '', 'true'])
rpc('getnewextaddress', ['lblExtTest'])
rpc('rescanblockchain')
else:
rpc('extkeyimportmaster', [rpc('mnemonic', ['new'])['master']])
# Lower output split threshold for more stakeable outputs
rpc('walletsettings', ['stakingoptions', {'stakecombinethreshold': 100, 'stakesplitthreshold': 200}])
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))
sc.setDaemonPID(Coins.BTC, cls.daemons[0].pid)
sc.setDaemonPID(Coins.LTC, cls.daemons[1].pid)
sc.setDaemonPID(Coins.PART, cls.daemons[2 + i].pid)
sc.start()
cls.swap_clients.append(sc)
t = HttpThread(cls.swap_clients[i].fp, TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, cls.swap_clients[i])
cls.http_threads.append(t)
t.start()
waitForRPC(ltcRpc)
num_blocks = 500
logging.info('Mining %d litecoin blocks', num_blocks)
cls.ltc_addr = ltcRpc('getnewaddress mining_addr legacy')
ltcRpc('generatetoaddress {} {}'.format(num_blocks, cls.ltc_addr))
ro = ltcRpc('getblockchaininfo')
checkForks(ro)
waitForRPC(btcRpc)
cls.btc_addr = btcRpc('getnewaddress mining_addr bech32')
logging.info('Mining %d Bitcoin blocks to %s', num_blocks, cls.btc_addr)
btcRpc('generatetoaddress {} {}'.format(num_blocks, cls.btc_addr))
ro = btcRpc('getblockchaininfo')
checkForks(ro)
ro = ltcRpc('getwalletinfo')
print('ltcRpc', ro)
signal.signal(signal.SIGINT, signal_handler)
cls.update_thread = threading.Thread(target=run_loop, args=(cls,))
cls.update_thread.start()
cls.coins_update_thread = threading.Thread(target=run_coins_loop, args=(cls,))
cls.coins_update_thread.start()
# Wait for height, or sequencelock is thrown off by genesis blocktime
num_blocks = 3
logging.info('Waiting for Particl chain height %d', num_blocks)
for i in range(60):
particl_blocks = cls.swap_clients[0].callrpc('getblockchaininfo')['blocks']
print('particl_blocks', particl_blocks)
if particl_blocks >= num_blocks:
break
test_delay_event.wait(1)
assert(particl_blocks >= num_blocks)
wait_for_balance(test_delay_event, 'http://127.0.0.1:1801/json/wallets/btc', 'balance', 1000.0)
wait_for_balance(test_delay_event, 'http://127.0.0.1:1801/json/wallets/ltc', 'balance', 1000.0)
@classmethod
def tearDownClass(cls):
logging.info('Finalising')
test_delay_event.set()
cls.update_thread.join()
cls.coins_update_thread.join()
for t in cls.http_threads:
t.stop()
t.join()
for c in cls.swap_clients:
c.finalise()
c.fp.close()
stopDaemons(cls.daemons)
logging.info('Finalising test')
super(Test, cls).tearDownClass()
def getBalance(self, js_wallets, coin_type):
ci = self.swap_clients[0].ci(coin_type)
return ci.make_int(float(js_wallets[str(int(coin_type))]['balance']) + float(js_wallets[str(int(coin_type))]['unconfirmed']))
def test_01_verifyrawtransaction(self):
txn = '0200000001eb6e5c4ebba4efa32f40c7314cad456a64008e91ee30b2dd0235ab9bb67fbdbb01000000ee47304402200956933242dde94f6cf8f195a470f8d02aef21ec5c9b66c5d3871594bdb74c9d02201d7e1b440de8f4da672d689f9e37e98815fb63dbc1706353290887eb6e8f7235012103dc1b24feb32841bc2f4375da91fa97834e5983668c2a39a6b7eadb60e7033f9d205a803b28fe2f86c17db91fa99d7ed2598f79b5677ffe869de2e478c0d1c02cc7514c606382012088a8201fe90717abb84b481c2a59112414ae56ec8acc72273642ca26cc7a5812fdc8f68876a914225fbfa4cb725b75e511810ac4d6f74069bdded26703520140b27576a914207eb66b2fd6ed9924d6217efc7fa7b38dfabe666888acffffffff01e0167118020000001976a9140044e188928710cecba8311f1cf412135b98145c88ac00000000'
prevout = {
@ -386,12 +86,12 @@ class Test(unittest.TestCase):
'scriptPubKey': 'a9143d37191e8b864222d14952a14c85504677a0581d87',
'redeemScript': '6382012088a8201fe90717abb84b481c2a59112414ae56ec8acc72273642ca26cc7a5812fdc8f68876a914225fbfa4cb725b75e511810ac4d6f74069bdded26703520140b27576a914207eb66b2fd6ed9924d6217efc7fa7b38dfabe666888ac',
'amount': 1.0}
ro = partRpc('verifyrawtransaction {} "{}"'.format(txn, dumpje([prevout, ])))
ro = callnoderpc(0, 'verifyrawtransaction', [txn, [prevout, ]])
assert(ro['inputs_valid'] is False)
assert(ro['validscripts'] == 1)
prevout['amount'] = 100.0
ro = partRpc('verifyrawtransaction {} "{}"'.format(txn, dumpje([prevout, ])))
ro = callnoderpc(0, 'verifyrawtransaction', [txn, [prevout, ]])
assert(ro['inputs_valid'] is True)
assert(ro['validscripts'] == 1)
@ -402,12 +102,12 @@ class Test(unittest.TestCase):
'scriptPubKey': 'a914129aee070317bbbd57062288849e85cf57d15c2687',
'redeemScript': '6382012088a8201fe90717abb84b481c2a59112414ae56ec8acc72273642ca26cc7a5812fdc8f68876a914207eb66b2fd6ed9924d6217efc7fa7b38dfabe666703a90040b27576a914225fbfa4cb725b75e511810ac4d6f74069bdded26888ac',
'amount': 1.0}
ro = partRpc('verifyrawtransaction {} "{}"'.format(txn, dumpje([prevout, ])))
ro = callnoderpc(0, 'verifyrawtransaction', [txn, [prevout, ]])
assert(ro['inputs_valid'] is False)
assert(ro['validscripts'] == 0) # Amount covered by signature
prevout['amount'] = 90.0
ro = partRpc('verifyrawtransaction {} "{}"'.format(txn, dumpje([prevout, ])))
ro = callnoderpc(0, 'verifyrawtransaction', [txn, [prevout, ]])
assert(ro['inputs_valid'] is True)
assert(ro['validscripts'] == 1)
@ -653,7 +353,7 @@ class Test(unittest.TestCase):
def test_12_withdrawal(self):
logging.info('---------- Test LTC withdrawals')
ltc_addr = ltcRpc('getnewaddress "Withdrawal test" legacy')
ltc_addr = callnoderpc(0, 'getnewaddress', ['Withdrawal test', 'legacy'], base_rpc_port=LTC_BASE_RPC_PORT)
wallets0 = json.loads(urlopen('http://127.0.0.1:{}/json/wallets'.format(TEST_HTTP_PORT + 0)).read())
assert(float(wallets0['3']['balance']) > 100)
@ -665,6 +365,54 @@ class Test(unittest.TestCase):
json_rv = json.loads(post_json_req('http://127.0.0.1:{}/json/wallets/ltc/withdraw'.format(TEST_HTTP_PORT + 0), post_json))
assert(len(json_rv['txid']) == 64)
def test_13_itx_refund(self):
logging.info('---------- Test ITX refunded')
# Initiator claims PTX and refunds ITX after lock expires
# Participant loses PTX value without gaining ITX value
swap_clients = self.swap_clients
js_w0_before = json.loads(urlopen('http://127.0.0.1:1800/json/wallets').read())
js_w1_before = json.loads(urlopen('http://127.0.0.1:1801/json/wallets').read())
swap_value = make_int(random.uniform(2.0, 20.0), scale=8, r=1)
logging.info('swap_value {}'.format(format_amount(swap_value, 8)))
offer_id = swap_clients[0].postOffer(Coins.LTC, Coins.BTC, swap_value, 0.5 * COIN, swap_value, SwapTypes.SELLER_FIRST,
SEQUENCE_LOCK_BLOCKS, 10)
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
offer = swap_clients[1].getOffer(offer_id)
bid_id = swap_clients[1].postBid(offer_id, offer.amount_from)
swap_clients[1].setBidDebugInd(bid_id, DebugTypes.DONT_SPEND_ITX)
wait_for_bid(test_delay_event, swap_clients[0], bid_id)
swap_clients[0].acceptBid(bid_id)
wait_for_bid_tx_state(test_delay_event, swap_clients[0], bid_id, TxStates.TX_REFUNDED, TxStates.TX_REDEEMED, wait_for=60)
js_w0_after = json.loads(urlopen('http://127.0.0.1:1800/json/wallets').read())
js_w1_after = json.loads(urlopen('http://127.0.0.1:1801/json/wallets').read())
ltc_swap_value = swap_value
btc_swap_value = swap_value // 2
node0_btc_before = self.getBalance(js_w0_before, Coins.BTC)
node0_btc_after = self.getBalance(js_w0_after, Coins.BTC)
node0_ltc_before = self.getBalance(js_w0_before, Coins.LTC)
node0_ltc_after = self.getBalance(js_w0_after, Coins.LTC)
node1_btc_before = self.getBalance(js_w1_before, Coins.BTC)
node1_btc_after = self.getBalance(js_w1_after, Coins.BTC)
node1_ltc_before = self.getBalance(js_w1_before, Coins.LTC)
node1_ltc_after = self.getBalance(js_w1_after, Coins.LTC)
high_fee_value_btc = int(0.001 * COIN)
high_fee_value_ltc = int(0.01 * COIN) # TODO Set fees directly, see listtransactions
assert(node0_btc_after > node0_btc_before + btc_swap_value - high_fee_value_btc)
assert(node0_ltc_after > node0_ltc_before - high_fee_value_ltc)
assert(node1_btc_after < node1_btc_before - btc_swap_value)
assert(node1_ltc_before == node1_ltc_after)
def pass_99_delay(self):
logging.info('Delay')
for i in range(60 * 10):

View file

@ -142,7 +142,7 @@ def startXmrWalletRPC(node_dir, bin_dir, wallet_bin, node_id, opts=[]):
return subprocess.Popen(args, stdin=subprocess.PIPE, stdout=wallet_stdout, stderr=wallet_stderr, cwd=data_dir)
def prepare_swapclient_dir(datadir, node_id, network_key, network_pubkey, with_ltc=False):
def prepare_swapclient_dir(datadir, node_id, network_key, network_pubkey, with_ltc=False, with_xmr=False):
basicswap_dir = os.path.join(datadir, 'basicswap_' + str(node_id))
if not os.path.exists(basicswap_dir):
os.makedirs(basicswap_dir)
@ -167,17 +167,6 @@ def prepare_swapclient_dir(datadir, node_id, network_key, network_pubkey, with_l
'bindir': cfg.PARTICL_BINDIR,
'blocks_confirmed': 2, # Faster testing
},
'monero': {
'connection_type': 'rpc',
'manage_daemon': False,
'rpcport': XMR_BASE_RPC_PORT + node_id,
'walletrpcport': XMR_BASE_WALLET_RPC_PORT + node_id,
'walletrpcuser': 'test' + str(node_id),
'walletrpcpassword': 'test_pass' + str(node_id),
'walletfile': 'testwallet',
'datadir': os.path.join(datadir, 'xmr_' + str(node_id)),
'bindir': cfg.XMR_BINDIR,
},
'bitcoin': {
'connection_type': 'rpc',
'manage_daemon': False,
@ -201,6 +190,19 @@ def prepare_swapclient_dir(datadir, node_id, network_key, network_pubkey, with_l
'debug_ui': True,
}
if with_xmr:
settings['chainclients']['monero'] = {
'connection_type': 'rpc',
'manage_daemon': False,
'rpcport': XMR_BASE_RPC_PORT + node_id,
'walletrpcport': XMR_BASE_WALLET_RPC_PORT + node_id,
'walletrpcuser': 'test' + str(node_id),
'walletrpcpassword': 'test_pass' + str(node_id),
'walletfile': 'testwallet',
'datadir': os.path.join(datadir, 'xmr_' + str(node_id)),
'bindir': cfg.XMR_BINDIR,
}
if with_ltc:
settings['chainclients']['litecoin'] = {
'connection_type': 'rpc',
@ -291,6 +293,9 @@ class BaseTest(unittest.TestCase):
def setUpClass(cls):
if not hasattr(cls, 'start_ltc_nodes'):
cls.start_ltc_nodes = False
if not hasattr(cls, 'start_xmr_nodes'):
cls.start_xmr_nodes = True
random.seed(time.time())
cls.update_thread = None
@ -371,23 +376,24 @@ class BaseTest(unittest.TestCase):
waitForRPC(make_rpc_func(i, base_rpc_port=LTC_BASE_RPC_PORT))
for i in range(NUM_XMR_NODES):
prepareXmrDataDir(TEST_DIR, i, 'monerod.conf')
if cls.start_xmr_nodes:
for i in range(NUM_XMR_NODES):
prepareXmrDataDir(TEST_DIR, i, 'monerod.conf')
cls.xmr_daemons.append(startXmrDaemon(os.path.join(TEST_DIR, 'xmr_' + str(i)), cfg.XMR_BINDIR, cfg.XMRD))
logging.info('Started %s %d', cfg.XMRD, cls.xmr_daemons[-1].pid)
waitForXMRNode(i)
cls.xmr_daemons.append(startXmrDaemon(os.path.join(TEST_DIR, 'xmr_' + str(i)), cfg.XMR_BINDIR, cfg.XMRD))
logging.info('Started %s %d', cfg.XMRD, cls.xmr_daemons[-1].pid)
waitForXMRNode(i)
cls.xmr_daemons.append(startXmrWalletRPC(os.path.join(TEST_DIR, 'xmr_' + str(i)), cfg.XMR_BINDIR, cfg.XMR_WALLET_RPC, i))
cls.xmr_daemons.append(startXmrWalletRPC(os.path.join(TEST_DIR, 'xmr_' + str(i)), cfg.XMR_BINDIR, cfg.XMR_WALLET_RPC, i))
for i in range(NUM_XMR_NODES):
cls.xmr_wallet_auth.append(('test{0}'.format(i), 'test_pass{0}'.format(i)))
logging.info('Creating XMR wallet %i', i)
for i in range(NUM_XMR_NODES):
cls.xmr_wallet_auth.append(('test{0}'.format(i), 'test_pass{0}'.format(i)))
logging.info('Creating XMR wallet %i', i)
waitForXMRWallet(i, cls.xmr_wallet_auth[i])
waitForXMRWallet(i, cls.xmr_wallet_auth[i])
cls.callxmrnodewallet(cls, i, 'create_wallet', {'filename': 'testwallet', 'language': 'English'})
cls.callxmrnodewallet(cls, i, 'open_wallet', {'filename': 'testwallet'})
cls.callxmrnodewallet(cls, i, 'create_wallet', {'filename': 'testwallet', 'language': 'English'})
cls.callxmrnodewallet(cls, i, 'open_wallet', {'filename': 'testwallet'})
logging.info('Preparing swap clients.')
eckey = ECKey()
@ -396,7 +402,7 @@ class BaseTest(unittest.TestCase):
cls.network_pubkey = eckey.get_pubkey().get_bytes().hex()
for i in range(NUM_NODES):
prepare_swapclient_dir(TEST_DIR, i, cls.network_key, cls.network_pubkey, cls.start_ltc_nodes)
prepare_swapclient_dir(TEST_DIR, i, cls.network_key, cls.network_pubkey, cls.start_ltc_nodes, cls.start_xmr_nodes)
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:
@ -410,35 +416,53 @@ class BaseTest(unittest.TestCase):
sc.setDaemonPID(Coins.LTC, cls.ltc_daemons[i].pid)
sc.start()
# Set XMR main wallet address
xmr_ci = sc.ci(Coins.XMR)
sc.setStringKV('main_wallet_addr_' + xmr_ci.coin_name().lower(), xmr_ci.getMainWalletAddress())
if cls.start_xmr_nodes:
# Set XMR main wallet address
xmr_ci = sc.ci(Coins.XMR)
sc.setStringKV('main_wallet_addr_' + xmr_ci.coin_name().lower(), xmr_ci.getMainWalletAddress())
cls.swap_clients.append(sc)
t = HttpThread(cls.swap_clients[i].fp, TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, cls.swap_clients[i])
cls.http_threads.append(t)
t.start()
cls.btc_addr = callnoderpc(0, 'getnewaddress', ['mining_addr', 'bech32'], base_rpc_port=BTC_BASE_RPC_PORT)
cls.xmr_addr = cls.callxmrnodewallet(cls, 1, 'get_address')['address']
# Set future block rewards to nowhere (a random address)
eckey = ECKey()
eckey.generate()
void_block_rewards_pubkey = eckey.get_pubkey().get_bytes()
num_blocks = 500 # Mine enough to activate segwit
cls.btc_addr = callnoderpc(0, 'getnewaddress', ['mining_addr', 'bech32'], base_rpc_port=BTC_BASE_RPC_PORT)
num_blocks = 400 # Mine enough to activate segwit
logging.info('Mining %d Bitcoin blocks to %s', num_blocks, cls.btc_addr)
callnoderpc(0, 'generatetoaddress', [num_blocks, cls.btc_addr], base_rpc_port=BTC_BASE_RPC_PORT)
num_blocks = 100
cls.btc_addr = cls.swap_clients[0].ci(Coins.BTC).pubkey_to_segwit_address(void_block_rewards_pubkey)
logging.info('Mining %d Bitcoin blocks to %s', num_blocks, cls.btc_addr)
callnoderpc(0, 'generatetoaddress', [num_blocks, cls.btc_addr], base_rpc_port=BTC_BASE_RPC_PORT)
checkForks(callnoderpc(0, 'getblockchaininfo', base_rpc_port=BTC_BASE_RPC_PORT))
if cls.start_ltc_nodes:
num_blocks = 400
cls.ltc_addr = callnoderpc(0, 'getnewaddress', ['mining_addr', 'bech32'], base_rpc_port=LTC_BASE_RPC_PORT)
logging.info('Mining %d Litecoin blocks to %s', num_blocks, cls.ltc_addr)
callnoderpc(0, 'generatetoaddress', [num_blocks, cls.ltc_addr], base_rpc_port=LTC_BASE_RPC_PORT)
num_blocks = 100
cls.ltc_addr = cls.swap_clients[0].ci(Coins.LTC).pubkey_to_address(void_block_rewards_pubkey)
logging.info('Mining %d Litecoin blocks to %s', num_blocks, cls.ltc_addr)
callnoderpc(0, 'generatetoaddress', [num_blocks, cls.ltc_addr], base_rpc_port=LTC_BASE_RPC_PORT)
checkForks(callnoderpc(0, 'getblockchaininfo', base_rpc_port=LTC_BASE_RPC_PORT))
num_blocks = 100
if callrpc_xmr_na(XMR_BASE_RPC_PORT + 1, 'get_block_count')['count'] < num_blocks:
logging.info('Mining %d Monero blocks to %s.', num_blocks, cls.xmr_addr)
callrpc_xmr_na(XMR_BASE_RPC_PORT + 1, 'generateblocks', {'wallet_address': cls.xmr_addr, 'amount_of_blocks': num_blocks})
logging.info('XMR blocks: %d', callrpc_xmr_na(XMR_BASE_RPC_PORT + 1, 'get_block_count')['count'])
if cls.start_xmr_nodes:
cls.xmr_addr = cls.callxmrnodewallet(cls, 1, 'get_address')['address']
if callrpc_xmr_na(XMR_BASE_RPC_PORT + 1, 'get_block_count')['count'] < num_blocks:
logging.info('Mining %d Monero blocks to %s.', num_blocks, cls.xmr_addr)
callrpc_xmr_na(XMR_BASE_RPC_PORT + 1, 'generateblocks', {'wallet_address': cls.xmr_addr, 'amount_of_blocks': num_blocks})
logging.info('XMR blocks: %d', callrpc_xmr_na(XMR_BASE_RPC_PORT + 1, 'get_block_count')['count'])
logging.info('Adding anon outputs')
outputs = []
@ -456,6 +480,7 @@ class BaseTest(unittest.TestCase):
pause_event.set()
cls.coins_update_thread = threading.Thread(target=run_coins_loop, args=(cls,))
cls.coins_update_thread.start()
except Exception:
traceback.print_exc()
Test.tearDownClass()