basicswap-prepare tries to initialise coin wallets from Particl mnemonic

Bitcoin 0.20: 'Cannot set a new HD seed while still in Initial Block Download.' Removed in 0.21
This commit is contained in:
tecnovert
2020-12-04 01:46:01 +02:00
parent 3bbb483a0a
commit 5a163e0f86
18 changed files with 754 additions and 93 deletions

View File

@@ -5,8 +5,8 @@
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import unittest
import secrets
import unittest
import basicswap.contrib.ed25519_fast as edf
import basicswap.ed25519_fast_util as edu

View File

@@ -7,12 +7,13 @@
import os
import sys
import unittest
from unittest.mock import patch
from io import StringIO
import logging
import shutil
import json
import shutil
import logging
import unittest
from io import StringIO
from unittest.mock import patch
import basicswap.config as cfg
import bin.basicswap_prepare as prepareSystem

View File

@@ -18,17 +18,17 @@ python tests/basicswap/test_reload.py
import os
import sys
import time
import unittest
import logging
import shutil
import json
import time
import shutil
import logging
import unittest
import traceback
import multiprocessing
import threading
from unittest.mock import patch
from urllib.request import urlopen
import multiprocessing
from urllib import parse
from urllib.request import urlopen
from unittest.mock import patch
from basicswap.rpc import (
callrpc_cli,

View File

@@ -0,0 +1,264 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2020 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
"""
export TEST_RELOAD_PATH=/tmp/test_basicswap
mkdir -p ${TEST_RELOAD_PATH}/bin/{particl,monero}
cp ~/tmp/particl-0.19.1.2-x86_64-linux-gnu.tar.gz ${TEST_RELOAD_PATH}/bin/particl
cp ~/tmp/monero-0.17.1.5-x86_64-linux-gnu.tar.gz ${TEST_RELOAD_PATH}/bin/monero
export PYTHONPATH=$(pwd)
python tests/basicswap/test_reload_xmr.py
"""
import os
import sys
import json
import time
import shutil
import logging
import unittest
import traceback
import threading
import multiprocessing
from urllib import parse
from urllib.request import urlopen
from unittest.mock import patch
from basicswap.rpc import (
callrpc_cli,
)
from basicswap.util import (
dumpj
)
from tests.basicswap.mnemonics import mnemonics
import basicswap.config as cfg
import bin.basicswap_prepare as prepareSystem
import bin.basicswap_run as runSystem
test_path = os.path.expanduser(os.getenv('TEST_RELOAD_PATH', '~/test_basicswap1'))
PARTICL_PORT_BASE = int(os.getenv('PARTICL_PORT_BASE', '11938'))
XMR_BASE_P2P_PORT = 17792
XMR_BASE_RPC_PORT = 21792
XMR_BASE_ZMQ_PORT = 22792
XMR_BASE_WALLET_RPC_PORT = 23792
stop_test = False
logger = logging.getLogger()
logger.level = logging.DEBUG
if not len(logger.handlers):
logger.addHandler(logging.StreamHandler(sys.stdout))
def waitForServer(port):
for i in range(20):
try:
time.sleep(1)
summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read())
break
except Exception:
traceback.print_exc()
def waitForNumOffers(port, offers):
for i in range(20):
summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read())
if summary['num_network_offers'] >= offers:
return
time.sleep(1)
raise ValueError('waitForNumOffers failed')
def waitForNumBids(port, bids):
for i in range(20):
summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read())
if summary['num_recv_bids'] >= bids:
return
time.sleep(1)
raise ValueError('waitForNumBids failed')
def waitForNumSwapping(port, bids):
for i in range(20):
summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read())
if summary['num_swapping'] >= bids:
return
time.sleep(1)
raise ValueError('waitForNumSwapping failed')
def updateThread(xmr_addr):
#btc_addr = btcRpc(0, 'getnewaddress mining_addr bech32')
while not stop_test:
#btcRpc(0, 'generatetoaddress {} {}'.format(1, btc_addr))
time.sleep(5)
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls):
super(Test, cls).setUpClass()
for i in range(3):
client_path = os.path.join(test_path, 'client{}'.format(i))
config_path = os.path.join(client_path, cfg.CONFIG_FILENAME)
try:
shutil.rmtree(client_path)
except Exception as ex:
logger.warning('setUpClass %s', str(ex))
testargs = [
'basicswap-prepare',
'-datadir="{}"'.format(client_path),
'-bindir="{}"'.format(os.path.join(test_path, 'bin')),
'-portoffset={}'.format(i),
'-particl_mnemonic="{}"'.format(mnemonics[i]),
'-regtest', '-withoutcoin=litecoin', '-withcoin=monero']
with patch.object(sys, 'argv', testargs):
prepareSystem.main()
with open(os.path.join(client_path, 'particl', 'particl.conf'), 'r') as fp:
lines = fp.readlines()
with open(os.path.join(client_path, 'particl', 'particl.conf'), 'w') as fp:
for line in lines:
if not line.startswith('staking'):
fp.write(line)
fp.write('port={}\n'.format(PARTICL_PORT_BASE + i))
fp.write('bind=127.0.0.1\n')
fp.write('dnsseed=0\n')
fp.write('minstakeinterval=5\n')
for ip in range(3):
if ip != i:
fp.write('connect=localhost:{}\n'.format(PARTICL_PORT_BASE + ip))
with open(os.path.join(client_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 + i))
for ip in range(3):
if ip != i:
fp.write('add-exclusive-node=127.0.0.1:{}\n'.format(XMR_BASE_P2P_PORT + ip))
assert(os.path.exists(config_path))
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):
runSystem.main()
def test_reload(self):
global stop_test
update_thread = None
processes = []
for i in range(3):
processes.append(multiprocessing.Process(target=self.run_thread, args=(i,)))
processes[-1].start()
try:
waitForServer(12700)
wallets = json.loads(urlopen('http://localhost:12701/json/wallets').read())
print('[rm] wallets', dumpj(wallets))
xmr_addr1 = wallets['6']['deposit_address']
num_blocks = 500
raise ValueError('TODO')
'''
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))
for i in range(20):
blocks = btcRpc(0, 'getblockchaininfo')['blocks']
if blocks >= 500:
break
assert(blocks >= 500)
'''
data = parse.urlencode({
'addr_from': '-1',
'coin_from': '1',
'coin_to': '6',
'amt_from': '1',
'amt_to': '1',
'lockhrs': '24'}).encode()
offer_id = json.loads(urlopen('http://localhost:12700/json/offers/new', data=data).read())
summary = json.loads(urlopen('http://localhost:12700/json').read())
assert(summary['num_sent_offers'] == 1)
logger.info('Waiting for offer:')
waitForNumOffers(12701, 1)
offers = json.loads(urlopen('http://localhost:12701/json/offers').read())
offer = offers[0]
data = parse.urlencode({
'offer_id': offer['offer_id'],
'amount_from': offer['amount_from']}).encode()
bid_id = json.loads(urlopen('http://localhost:12701/json/bids/new', data=data).read())
waitForNumBids(12700, 1)
bids = json.loads(urlopen('http://localhost:12700/json/bids').read())
bid = bids[0]
data = parse.urlencode({
'accept': True
}).encode()
rv = json.loads(urlopen('http://localhost:12700/json/bids/{}'.format(bid['bid_id']), data=data).read())
assert(rv['bid_state'] == 'Accepted')
waitForNumSwapping(12701, 1)
logger.info('Restarting client:')
c1 = processes[1]
c1.terminate()
c1.join()
processes[1] = multiprocessing.Process(target=self.run_thread, args=(1,))
processes[1].start()
waitForServer(12701)
rv = json.loads(urlopen('http://localhost:12701/json').read())
assert(rv['num_swapping'] == 1)
update_thread = threading.Thread(target=updateThread, args=(xmr_addr,))
update_thread.start()
logger.info('Completing swap:')
for i in range(240):
time.sleep(5)
rv = json.loads(urlopen('http://localhost:12700/json/bids/{}'.format(bid['bid_id'])).read())
print(rv)
if rv['bid_state'] == 'Completed':
break
assert(rv['bid_state'] == 'Completed')
except Exception:
traceback.print_exc()
stop_test = True
if update_thread:
update_thread.join()
for p in processes:
p.terminate()
for p in processes:
p.join()
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,202 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2020 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
"""
export TEST_PATH=/tmp/test_basicswap_wallet_init
mkdir -p ${TEST_PATH}/bin/{particl,monero,bitcoin}
cp ~/tmp/particl-0.19.1.2-x86_64-linux-gnu.tar.gz ${TEST_PATH}/bin/particl
cp ~/tmp/monero-0.17.1.5-x86_64-linux-gnu.tar.gz ${TEST_PATH}/bin/monero
cp ~/tmp/bitcoin-0.20.1-x86_64-linux-gnu.tar.gz ${TEST_PATH}/bin/bitcoin
export PYTHONPATH=$(pwd)
python tests/basicswap/test_wallet_init.py
"""
import os
import sys
import json
import time
import shutil
import logging
import unittest
import traceback
import threading
import multiprocessing
from urllib import parse
from urllib.request import urlopen
from unittest.mock import patch
from basicswap.rpc import (
callrpc_cli,
)
from basicswap.util import (
dumpj
)
from tests.basicswap.mnemonics import mnemonics
import basicswap.config as cfg
import bin.basicswap_prepare as prepareSystem
import bin.basicswap_run as runSystem
test_path = os.path.expanduser(os.getenv('TEST_PATH', '~/test_basicswap1'))
PARTICL_PORT_BASE = int(os.getenv('PARTICL_PORT_BASE', '11938'))
BITCOIN_PORT_BASE = int(os.getenv('BITCOIN_PORT_BASE', '10938'))
XMR_BASE_P2P_PORT = 17792
XMR_BASE_RPC_PORT = 21792
XMR_BASE_ZMQ_PORT = 22792
XMR_BASE_WALLET_RPC_PORT = 23792
stop_test = False
logger = logging.getLogger()
logger.level = logging.DEBUG
if not len(logger.handlers):
logger.addHandler(logging.StreamHandler(sys.stdout))
def waitForServer(port):
for i in range(20):
try:
time.sleep(1)
summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read())
break
except Exception:
traceback.print_exc()
def waitForNumOffers(port, offers):
for i in range(20):
summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read())
if summary['num_network_offers'] >= offers:
return
time.sleep(1)
raise ValueError('waitForNumOffers failed')
def waitForNumBids(port, bids):
for i in range(20):
summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read())
if summary['num_recv_bids'] >= bids:
return
time.sleep(1)
raise ValueError('waitForNumBids failed')
def waitForNumSwapping(port, bids):
for i in range(20):
summary = json.loads(urlopen('http://localhost:{}/json'.format(port)).read())
if summary['num_swapping'] >= bids:
return
time.sleep(1)
raise ValueError('waitForNumSwapping failed')
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls):
super(Test, cls).setUpClass()
for i in range(2):
client_path = os.path.join(test_path, 'client{}'.format(i))
config_path = os.path.join(client_path, cfg.CONFIG_FILENAME)
try:
shutil.rmtree(client_path)
except Exception as ex:
logger.warning('setUpClass %s', str(ex))
testargs = [
'basicswap-prepare',
'-datadir="{}"'.format(client_path),
'-bindir="{}"'.format(os.path.join(test_path, 'bin')),
'-portoffset={}'.format(i),
'-particl_mnemonic="{}"'.format(mnemonics[0]),
'-regtest', '-withoutcoin=litecoin', '-withcoin=monero,bitcoin']
with patch.object(sys, 'argv', testargs):
prepareSystem.main()
with open(os.path.join(client_path, 'particl', 'particl.conf'), 'r') as fp:
lines = fp.readlines()
with open(os.path.join(client_path, 'particl', 'particl.conf'), 'w') as fp:
for line in lines:
if not line.startswith('staking'):
fp.write(line)
fp.write('port={}\n'.format(PARTICL_PORT_BASE + i))
fp.write('bind=127.0.0.1\n')
fp.write('dnsseed=0\n')
fp.write('minstakeinterval=5\n')
for ip in range(3):
if ip != i:
fp.write('connect=localhost:{}\n'.format(PARTICL_PORT_BASE + ip))
# Pruned nodes don't provide blocks
with open(os.path.join(client_path, 'bitcoin', 'bitcoin.conf'), 'r') as fp:
lines = fp.readlines()
with open(os.path.join(client_path, 'bitcoin', 'bitcoin.conf'), 'w') as fp:
for line in lines:
if not line.startswith('prune'):
fp.write(line)
fp.write('port={}\n'.format(BITCOIN_PORT_BASE + i))
fp.write('discover=0\n')
fp.write('dnsseed=0\n')
fp.write('listenonion=0\n')
fp.write('upnp=0\n')
fp.write('bind=127.0.0.1\n')
for ip in range(3):
if ip != i:
fp.write('connect=localhost:{}\n'.format(BITCOIN_PORT_BASE + ip))
with open(os.path.join(client_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 + i))
for ip in range(3):
if ip != i:
fp.write('add-exclusive-node=127.0.0.1:{}\n'.format(XMR_BASE_P2P_PORT + ip))
assert(os.path.exists(config_path))
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):
runSystem.main()
def test_wallet(self):
global stop_test
update_thread = None
processes = []
time.sleep(5)
for i in range(2):
processes.append(multiprocessing.Process(target=self.run_thread, args=(i,)))
processes[-1].start()
try:
waitForServer(12700)
wallets = json.loads(urlopen('http://localhost:12700/json/wallets').read())
print('[rm] wallets', dumpj(wallets))
waitForServer(12701)
wallets = json.loads(urlopen('http://localhost:12701/json/wallets').read())
print('[rm] wallets', dumpj(wallets))
raise ValueError('TODO')
except Exception:
traceback.print_exc()
stop_test = True
if update_thread:
update_thread.join()
for p in processes:
p.terminate()
for p in processes:
p.join()
if __name__ == '__main__':
unittest.main()

View File

@@ -55,7 +55,7 @@ from tests.basicswap.common import (
TEST_HTTP_PORT,
)
from basicswap.contrib.rpcauth import generate_salt, password_to_hmac
from bin.basicswap_run import startDaemon
from bin.basicswap_run import startDaemon, startXmrDaemon
logger = logging.getLogger()
@@ -479,12 +479,9 @@ class Test(unittest.TestCase):
for d in cls.xmr_daemons:
try:
d.wait(timeout=20)
if d.stdout:
d.stdout.close()
if d.stderr:
d.stderr.close()
if d.stdin:
d.stdin.close()
for fp in (d.stdout, d.stderr, d.stdin):
if fp:
fp.close()
except Exception as e:
logging.info('Closing %d, error %s', d.pid, str(e))
@@ -497,12 +494,9 @@ class Test(unittest.TestCase):
for d in cls.part_daemons + cls.btc_daemons:
try:
d.wait(timeout=20)
if d.stdout:
d.stdout.close()
if d.stderr:
d.stderr.close()
if d.stdin:
d.stdin.close()
for fp in (d.stdout, d.stderr, d.stdin):
if fp:
fp.close()
except Exception as e:
logging.info('Closing %d, error %s', d.pid, str(e))