Prepare script works.
This commit is contained in:
parent
76af4a941e
commit
ecfd783cce
@ -1,117 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Copyright (c) 2019 tecnovert
|
|
||||||
# Distributed under the MIT software license, see the accompanying
|
|
||||||
# file LICENSE.txt or http://www.opensource.org/licenses/mit-license.php.
|
|
||||||
|
|
||||||
"""
|
|
||||||
Particl Atomic Swap - Proof of Concept
|
|
||||||
|
|
||||||
sudo pip install python-gnupg
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import time
|
|
||||||
import json
|
|
||||||
import hashlib
|
|
||||||
import mmap
|
|
||||||
import tarfile
|
|
||||||
import urllib.request
|
|
||||||
import urllib.parse
|
|
||||||
import logging
|
|
||||||
|
|
||||||
import gnupg
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger()
|
|
||||||
logger.level = logging.DEBUG
|
|
||||||
|
|
||||||
|
|
||||||
def printVersion():
|
|
||||||
from basicswap import __version__
|
|
||||||
logger.info('Basicswap version:', __version__)
|
|
||||||
|
|
||||||
|
|
||||||
def printHelp():
|
|
||||||
logger.info('Usage: basicswap-prepare ')
|
|
||||||
logger.info('\n--help, -h Print help.')
|
|
||||||
logger.info('\n--version, -v Print version.')
|
|
||||||
logger.info('\n--datadir=PATH Path to basicswap data directory, default:~/.basicswap.')
|
|
||||||
logger.info('\n--mainnet Run in mainnet mode.')
|
|
||||||
logger.info('\n--testnet Run in testnet mode.')
|
|
||||||
logger.info('\n--regtest Run in regtest mode.')
|
|
||||||
logger.info('\n--particl_mnemonic= Recovery phrase to use for the Particl wallet, default is randomly generated.')
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
print('main')
|
|
||||||
data_dir = None
|
|
||||||
chain = 'mainnet'
|
|
||||||
particl_wallet_mnemonic = None
|
|
||||||
|
|
||||||
for v in sys.argv[1:]:
|
|
||||||
if len(v) < 2 or v[0] != '-':
|
|
||||||
logger.warning('Unknown argument', v)
|
|
||||||
continue
|
|
||||||
|
|
||||||
s = v.split('=')
|
|
||||||
name = s[0].strip()
|
|
||||||
|
|
||||||
for i in range(2):
|
|
||||||
if name[0] == '-':
|
|
||||||
name = name[1:]
|
|
||||||
|
|
||||||
if name == 'v' or name == 'version':
|
|
||||||
printVersion()
|
|
||||||
return 0
|
|
||||||
if name == 'h' or name == 'help':
|
|
||||||
printHelp()
|
|
||||||
return 0
|
|
||||||
if name == 'mainnet':
|
|
||||||
continue
|
|
||||||
if name == 'testnet':
|
|
||||||
chain = 'testnet'
|
|
||||||
continue
|
|
||||||
if name == 'regtest':
|
|
||||||
chain = 'regtest'
|
|
||||||
continue
|
|
||||||
|
|
||||||
if len(s) == 2:
|
|
||||||
if name == 'datadir':
|
|
||||||
data_dir = os.path.expanduser(s[1])
|
|
||||||
continue
|
|
||||||
if name == 'particl_mnemonic':
|
|
||||||
particl_wallet_mnemonic = s[1]
|
|
||||||
continue
|
|
||||||
|
|
||||||
logger.warning('Unknown argument', v)
|
|
||||||
|
|
||||||
if data_dir is None:
|
|
||||||
default_datadir = '~/.basicswap'
|
|
||||||
data_dir = os.path.join(os.path.expanduser(default_datadir))
|
|
||||||
logger.info('Using datadir: %s', data_dir)
|
|
||||||
logger.info('Chain: %s', chain)
|
|
||||||
|
|
||||||
if not os.path.exists(data_dir):
|
|
||||||
os.makedirs(data_dir)
|
|
||||||
|
|
||||||
config_path = os.path.join(data_dir, 'basicswap.json')
|
|
||||||
if os.path.exists(config_path):
|
|
||||||
sys.stderr.write('Error: {} exists, exiting.'.format(config_path))
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
settings = {
|
|
||||||
'debug': True,
|
|
||||||
}
|
|
||||||
|
|
||||||
with open(config_path, 'w') as fp:
|
|
||||||
json.dump(settings, fp, indent=4)
|
|
||||||
|
|
||||||
logger.info('Done.')
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
1
bin/basicswap-prepare.py
Symbolic link
1
bin/basicswap-prepare.py
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
basicswap_prepare.py
|
@ -1,181 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Copyright (c) 2019 tecnovert
|
|
||||||
# Distributed under the MIT software license, see the accompanying
|
|
||||||
# file LICENSE.txt or http://www.opensource.org/licenses/mit-license.php.
|
|
||||||
|
|
||||||
"""
|
|
||||||
Particl Atomic Swap - Proof of Concept
|
|
||||||
|
|
||||||
Dependencies:
|
|
||||||
$ pacman -S python-pyzmq python-plyvel protobuf
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
import json
|
|
||||||
import traceback
|
|
||||||
import signal
|
|
||||||
import subprocess
|
|
||||||
import logging
|
|
||||||
|
|
||||||
import basicswap.config as cfg
|
|
||||||
from basicswap import __version__
|
|
||||||
from basicswap.basicswap import BasicSwap
|
|
||||||
from basicswap.http_server import HttpThread
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger()
|
|
||||||
logger.level = logging.DEBUG
|
|
||||||
logger.addHandler(logging.StreamHandler(sys.stdout))
|
|
||||||
|
|
||||||
ALLOW_CORS = False
|
|
||||||
swap_client = None
|
|
||||||
|
|
||||||
|
|
||||||
def signal_handler(sig, frame):
|
|
||||||
logger.info('Signal %d detected, ending program.' % (sig))
|
|
||||||
if swap_client is not None:
|
|
||||||
swap_client.stopRunning()
|
|
||||||
|
|
||||||
|
|
||||||
def startDaemon(node_dir, bin_dir, daemon_bin):
|
|
||||||
daemon_bin = os.path.join(bin_dir, daemon_bin)
|
|
||||||
|
|
||||||
args = [daemon_bin, '-datadir=' + node_dir]
|
|
||||||
logger.info('Starting node ' + daemon_bin + ' ' + '-datadir=' + node_dir)
|
|
||||||
return subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
||||||
|
|
||||||
|
|
||||||
def runClient(fp, dataDir, chain):
|
|
||||||
global swap_client
|
|
||||||
settings_path = os.path.join(dataDir, 'basicswap.json')
|
|
||||||
|
|
||||||
if not os.path.exists(settings_path):
|
|
||||||
raise ValueError('Settings file not found: ' + str(settings_path))
|
|
||||||
|
|
||||||
with open(settings_path) as fs:
|
|
||||||
settings = json.load(fs)
|
|
||||||
|
|
||||||
daemons = []
|
|
||||||
|
|
||||||
for c, v in settings['chainclients'].items():
|
|
||||||
if v['manage_daemon'] is True:
|
|
||||||
logger.info('Starting {} daemon'.format(c.capitalize()))
|
|
||||||
if c == 'particl':
|
|
||||||
daemons.append(startDaemon(v['datadir'], cfg.PARTICL_BINDIR, cfg.PARTICLD))
|
|
||||||
logger.info('Started {} {}'.format(cfg.PARTICLD, daemons[-1].pid))
|
|
||||||
elif c == 'bitcoin':
|
|
||||||
daemons.append(startDaemon(v['datadir'], cfg.BITCOIN_BINDIR, cfg.BITCOIND))
|
|
||||||
logger.info('Started {} {}'.format(cfg.BITCOIND, daemons[-1].pid))
|
|
||||||
elif c == 'litecoin':
|
|
||||||
daemons.append(startDaemon(v['datadir'], cfg.LITECOIN_BINDIR, cfg.LITECOIND))
|
|
||||||
logger.info('Started {} {}'.format(cfg.LITECOIND, daemons[-1].pid))
|
|
||||||
else:
|
|
||||||
logger.warning('Unknown chain', c)
|
|
||||||
|
|
||||||
swap_client = BasicSwap(fp, dataDir, settings, chain)
|
|
||||||
|
|
||||||
signal.signal(signal.SIGINT, signal_handler)
|
|
||||||
signal.signal(signal.SIGTERM, signal_handler)
|
|
||||||
swap_client.start()
|
|
||||||
|
|
||||||
threads = []
|
|
||||||
if 'htmlhost' in settings:
|
|
||||||
swap_client.log.info('Starting server at %s:%d.' % (settings['htmlhost'], settings['htmlport']))
|
|
||||||
allow_cors = settings['allowcors'] if 'allowcors' in settings else ALLOW_CORS
|
|
||||||
tS1 = HttpThread(fp, settings['htmlhost'], settings['htmlport'], allow_cors, swap_client)
|
|
||||||
threads.append(tS1)
|
|
||||||
tS1.start()
|
|
||||||
|
|
||||||
try:
|
|
||||||
logger.info('Exit with Ctrl + c.')
|
|
||||||
while swap_client.is_running:
|
|
||||||
time.sleep(0.5)
|
|
||||||
swap_client.update()
|
|
||||||
except Exception:
|
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
swap_client.log.info('Stopping threads.')
|
|
||||||
for t in threads:
|
|
||||||
t.stop()
|
|
||||||
t.join()
|
|
||||||
|
|
||||||
for d in daemons:
|
|
||||||
logger.info('Terminating {}'.format(d.pid))
|
|
||||||
d.terminate()
|
|
||||||
d.wait(timeout=120)
|
|
||||||
if d.stdout:
|
|
||||||
d.stdout.close()
|
|
||||||
if d.stderr:
|
|
||||||
d.stderr.close()
|
|
||||||
if d.stdin:
|
|
||||||
d.stdin.close()
|
|
||||||
|
|
||||||
|
|
||||||
def printVersion():
|
|
||||||
logger.info('Basicswap version:', __version__)
|
|
||||||
|
|
||||||
|
|
||||||
def printHelp():
|
|
||||||
logger.info('basicswap-run.py --datadir=path -testnet')
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
data_dir = None
|
|
||||||
chain = 'mainnet'
|
|
||||||
|
|
||||||
for v in sys.argv[1:]:
|
|
||||||
if len(v) < 2 or v[0] != '-':
|
|
||||||
logger.warning('Unknown argument', v)
|
|
||||||
continue
|
|
||||||
|
|
||||||
s = v.split('=')
|
|
||||||
name = s[0].strip()
|
|
||||||
|
|
||||||
for i in range(2):
|
|
||||||
if name[0] == '-':
|
|
||||||
name = name[1:]
|
|
||||||
|
|
||||||
if name == 'v' or name == 'version':
|
|
||||||
printVersion()
|
|
||||||
return 0
|
|
||||||
if name == 'h' or name == 'help':
|
|
||||||
printHelp()
|
|
||||||
return 0
|
|
||||||
if name == 'testnet':
|
|
||||||
chain = 'testnet'
|
|
||||||
continue
|
|
||||||
if name == 'regtest':
|
|
||||||
chain = 'regtest'
|
|
||||||
continue
|
|
||||||
|
|
||||||
if len(s) == 2:
|
|
||||||
if name == 'datadir':
|
|
||||||
data_dir = os.path.expanduser(s[1])
|
|
||||||
continue
|
|
||||||
|
|
||||||
logger.warning('Unknown argument', v)
|
|
||||||
|
|
||||||
if data_dir is None:
|
|
||||||
default_datadir = '~/.basicswap'
|
|
||||||
data_dir = os.path.join(os.path.expanduser(default_datadir))
|
|
||||||
logger.info('Using datadir:', data_dir)
|
|
||||||
logger.info('Chain:', chain)
|
|
||||||
|
|
||||||
if not os.path.exists(data_dir):
|
|
||||||
os.makedirs(data_dir)
|
|
||||||
|
|
||||||
with open(os.path.join(data_dir, 'basicswap.log'), 'a') as fp:
|
|
||||||
logger.info(os.path.basename(sys.argv[0]) + ', version: ' + __version__ + '\n\n')
|
|
||||||
runClient(fp, data_dir, chain)
|
|
||||||
|
|
||||||
logger.info('Done.')
|
|
||||||
return swap_client.fail_code if swap_client is not None else 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
1
bin/basicswap-run.py
Symbolic link
1
bin/basicswap-run.py
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
basicswap_run.py
|
306
bin/basicswap_prepare.py
Normal file
306
bin/basicswap_prepare.py
Normal file
@ -0,0 +1,306 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2019 tecnovert
|
||||||
|
# Distributed under the MIT software license, see the accompanying
|
||||||
|
# file LICENSE.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Atomic Swap Client - Proof of Concept
|
||||||
|
|
||||||
|
sudo pip install python-gnupg
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import hashlib
|
||||||
|
import mmap
|
||||||
|
import tarfile
|
||||||
|
import stat
|
||||||
|
from urllib.request import urlretrieve
|
||||||
|
import urllib.parse
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import gnupg
|
||||||
|
|
||||||
|
BIN_ARCH = 'x86_64-linux-gnu.tar.gz'
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
logger.level = logging.DEBUG
|
||||||
|
if not len(logger.handlers):
|
||||||
|
logger.addHandler(logging.StreamHandler(sys.stdout))
|
||||||
|
|
||||||
|
|
||||||
|
def make_reporthook():
|
||||||
|
read = 0 # number of bytes read so far
|
||||||
|
last_percent_str = ''
|
||||||
|
|
||||||
|
def reporthook(blocknum, blocksize, totalsize):
|
||||||
|
nonlocal read
|
||||||
|
nonlocal last_percent_str
|
||||||
|
read += blocksize
|
||||||
|
if totalsize > 0:
|
||||||
|
percent_str = '%5.1f%%' % (read * 1e2 / totalsize)
|
||||||
|
if percent_str != last_percent_str:
|
||||||
|
logger.info(percent_str)
|
||||||
|
last_percent_str = percent_str
|
||||||
|
else:
|
||||||
|
logger.info('read %d' % (read,))
|
||||||
|
return reporthook
|
||||||
|
|
||||||
|
|
||||||
|
def downloadFile(url, path):
|
||||||
|
logger.info('Downloading file %s', url)
|
||||||
|
opener = urllib.request.build_opener()
|
||||||
|
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
|
||||||
|
urllib.request.install_opener(opener)
|
||||||
|
urlretrieve(url, path, make_reporthook())
|
||||||
|
|
||||||
|
|
||||||
|
def prepareCore(coin, version, settings, data_dir):
|
||||||
|
logger.info('prepareCore %s v%s', coin, version)
|
||||||
|
|
||||||
|
bin_dir = settings['chainclients'][coin]['bindir']
|
||||||
|
if not os.path.exists(bin_dir):
|
||||||
|
os.makedirs(bin_dir)
|
||||||
|
|
||||||
|
if 'osx' in BIN_ARCH:
|
||||||
|
os_dir_name = 'osx-unsigned'
|
||||||
|
os_name = 'osx'
|
||||||
|
elif 'win32' in BIN_ARCH or 'win64' in BIN_ARCH:
|
||||||
|
os_dir_name = 'win-unsigned'
|
||||||
|
os_name = 'win'
|
||||||
|
else:
|
||||||
|
os_dir_name = 'linux'
|
||||||
|
os_name = 'linux'
|
||||||
|
|
||||||
|
release_filename = '{}-{}-{}'.format(coin, version, BIN_ARCH)
|
||||||
|
if coin == 'particl':
|
||||||
|
signing_key_name = 'tecnovert'
|
||||||
|
release_url = 'https://github.com/particl/particl-core/releases/download/v{}/{}'.format(version, release_filename)
|
||||||
|
assert_filename = '{}-{}-{}-build.assert'.format(coin, os_name, version)
|
||||||
|
assert_url = 'https://raw.githubusercontent.com/particl/gitian.sigs/master/%s-%s/%s/%s' % (version, os_name, signing_key_name, assert_filename)
|
||||||
|
assert_sig_filename = assert_filename + '.sig'
|
||||||
|
assert_sig_url = assert_url + '.sig'
|
||||||
|
elif coin == 'litecoin':
|
||||||
|
signing_key_name = 'thrasher'
|
||||||
|
release_url = 'https://download.litecoin.org/litecoin-{}/{}/{}'.format(version, os_name, release_filename)
|
||||||
|
assert_filename = '{}-{}-0.17-build.assert'.format(coin, os_name)
|
||||||
|
assert_url = 'https://raw.githubusercontent.com/litecoin-project/gitian.sigs.ltc/master/%s-%s/%s/%s' % (version, os_name, signing_key_name, assert_filename)
|
||||||
|
assert_sig_filename = assert_filename + '.sig'
|
||||||
|
assert_sig_url = assert_url + '.sig'
|
||||||
|
else:
|
||||||
|
raise ValueError('Unknown coin')
|
||||||
|
|
||||||
|
release_path = os.path.join(bin_dir, release_filename)
|
||||||
|
if not os.path.exists(release_path):
|
||||||
|
downloadFile(release_url, release_path)
|
||||||
|
|
||||||
|
assert_path = os.path.join(bin_dir, assert_filename)
|
||||||
|
if not os.path.exists(assert_path):
|
||||||
|
downloadFile(assert_url, assert_path)
|
||||||
|
|
||||||
|
assert_sig_path = os.path.join(bin_dir, assert_sig_filename)
|
||||||
|
if not os.path.exists(assert_sig_path):
|
||||||
|
downloadFile(assert_sig_url, assert_sig_path)
|
||||||
|
|
||||||
|
hasher = hashlib.sha256()
|
||||||
|
with open(release_path, 'rb') as fp:
|
||||||
|
hasher.update(fp.read())
|
||||||
|
release_hash = hasher.digest()
|
||||||
|
|
||||||
|
logger.info('%s hash: %s', release_filename, release_hash.hex())
|
||||||
|
with open(assert_path, 'rb', 0) as fp, mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ) as s:
|
||||||
|
if s.find(bytes(release_hash.hex(), 'utf-8')) == -1:
|
||||||
|
raise ValueError('Error: release hash %s not found in assert file.' % (release_hash.hex()))
|
||||||
|
else:
|
||||||
|
logger.info('Found release hash in assert file.')
|
||||||
|
|
||||||
|
"""
|
||||||
|
gnupghome = os.path.join(data_dir, 'gpg')
|
||||||
|
if not os.path.exists(gnupghome):
|
||||||
|
os.makedirs(gnupghome)
|
||||||
|
"""
|
||||||
|
gpg = gnupg.GPG()
|
||||||
|
|
||||||
|
with open(assert_sig_path, 'rb') as fp:
|
||||||
|
verified = gpg.verify_file(fp, assert_path)
|
||||||
|
|
||||||
|
if verified.username is None:
|
||||||
|
logger.warning('Signature not verified.')
|
||||||
|
# TODO raise ValueError('Signature verification failed.')
|
||||||
|
|
||||||
|
bins = [coin + 'd', coin + '-cli', coin + '-tx']
|
||||||
|
with tarfile.open(release_path) as ft:
|
||||||
|
for b in bins:
|
||||||
|
out_path = os.path.join(bin_dir, b)
|
||||||
|
fi = ft.extractfile('{}-{}/bin/{}'.format(coin, version, b))
|
||||||
|
with open(out_path, 'wb') as fout:
|
||||||
|
fout.write(fi.read())
|
||||||
|
fi.close()
|
||||||
|
os.chmod(out_path, stat.S_IRWXU)
|
||||||
|
|
||||||
|
|
||||||
|
def extractCore(coin, version, settings):
|
||||||
|
logger.info('extractCore %s v%s', coin, version)
|
||||||
|
|
||||||
|
|
||||||
|
def printVersion():
|
||||||
|
from basicswap import __version__
|
||||||
|
logger.info('Basicswap version:', __version__)
|
||||||
|
|
||||||
|
|
||||||
|
def printHelp():
|
||||||
|
logger.info('Usage: basicswap-prepare ')
|
||||||
|
logger.info('\n--help, -h Print help.')
|
||||||
|
logger.info('\n--version, -v Print version.')
|
||||||
|
logger.info('\n--datadir=PATH Path to basicswap data directory, default:~/.basicswap.')
|
||||||
|
logger.info('\n--mainnet Run in mainnet mode.')
|
||||||
|
logger.info('\n--testnet Run in testnet mode.')
|
||||||
|
logger.info('\n--regtest Run in regtest mode.')
|
||||||
|
logger.info('\n--particl_mnemonic= Recovery phrase to use for the Particl wallet, default is randomly generated.')
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
data_dir = None
|
||||||
|
chain = 'mainnet'
|
||||||
|
particl_wallet_mnemonic = None
|
||||||
|
|
||||||
|
for v in sys.argv[1:]:
|
||||||
|
if len(v) < 2 or v[0] != '-':
|
||||||
|
logger.warning('Unknown argument', v)
|
||||||
|
continue
|
||||||
|
|
||||||
|
s = v.split('=')
|
||||||
|
name = s[0].strip()
|
||||||
|
|
||||||
|
for i in range(2):
|
||||||
|
if name[0] == '-':
|
||||||
|
name = name[1:]
|
||||||
|
|
||||||
|
if name == 'v' or name == 'version':
|
||||||
|
printVersion()
|
||||||
|
return 0
|
||||||
|
if name == 'h' or name == 'help':
|
||||||
|
printHelp()
|
||||||
|
return 0
|
||||||
|
if name == 'mainnet':
|
||||||
|
continue
|
||||||
|
if name == 'testnet':
|
||||||
|
chain = 'testnet'
|
||||||
|
continue
|
||||||
|
if name == 'regtest':
|
||||||
|
chain = 'regtest'
|
||||||
|
continue
|
||||||
|
|
||||||
|
if len(s) == 2:
|
||||||
|
if name == 'datadir':
|
||||||
|
data_dir = os.path.expanduser(s[1])
|
||||||
|
continue
|
||||||
|
if name == 'particl_mnemonic':
|
||||||
|
particl_wallet_mnemonic = s[1]
|
||||||
|
continue
|
||||||
|
|
||||||
|
logger.warning('Unknown argument', v)
|
||||||
|
|
||||||
|
if data_dir is None:
|
||||||
|
default_datadir = '~/.basicswap'
|
||||||
|
data_dir = os.path.join(os.path.expanduser(default_datadir))
|
||||||
|
logger.info('Using datadir: %s', data_dir)
|
||||||
|
logger.info('Chain: %s', chain)
|
||||||
|
|
||||||
|
if not os.path.exists(data_dir):
|
||||||
|
os.makedirs(data_dir)
|
||||||
|
|
||||||
|
config_path = os.path.join(data_dir, 'basicswap.json')
|
||||||
|
if os.path.exists(config_path):
|
||||||
|
sys.stderr.write('Error: {} exists, exiting.\n'.format(config_path))
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
'debug': True,
|
||||||
|
'zmqhost': 'tcp://127.0.0.1',
|
||||||
|
'zmqport': 20792,
|
||||||
|
'htmlhost': 'localhost',
|
||||||
|
'htmlport': 12700,
|
||||||
|
'network_key': '7sW2UEcHXvuqEjkpE5mD584zRaQYs6WXYohue4jLFZPTvMSxwvgs',
|
||||||
|
'network_pubkey': '035758c4a22d7dd59165db02a56156e790224361eb3191f02197addcb3bde903d2',
|
||||||
|
'chainclients': {
|
||||||
|
'particl': {
|
||||||
|
'connection_type': 'rpc',
|
||||||
|
'manage_daemon': True,
|
||||||
|
'rpcport': 19792,
|
||||||
|
'datadir': os.path.join(data_dir, 'particl'),
|
||||||
|
'bindir': os.path.join(data_dir, 'bins', 'particl'),
|
||||||
|
'blocks_confirmed': 2
|
||||||
|
},
|
||||||
|
'litecoin': {
|
||||||
|
'connection_type': 'rpc',
|
||||||
|
'manage_daemon': True,
|
||||||
|
'rpcport': 19795,
|
||||||
|
'datadir': os.path.join(data_dir, 'litecoin'),
|
||||||
|
'bindir': os.path.join(data_dir, 'bins', 'litecoin'),
|
||||||
|
'use_segwit': True,
|
||||||
|
'blocks_confirmed': 2
|
||||||
|
},
|
||||||
|
'bitcoin': {
|
||||||
|
'connection_type': 'none',
|
||||||
|
'manage_daemon': False,
|
||||||
|
'rpcport': 19796,
|
||||||
|
'datadir': os.path.join(data_dir, 'bitcoin'),
|
||||||
|
'bindir': os.path.join(data_dir, 'bins', 'bitcoin'),
|
||||||
|
'use_segwit': True
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'check_progress_seconds': 60,
|
||||||
|
'check_watched_seconds': 60,
|
||||||
|
'check_expired_seconds': 60
|
||||||
|
}
|
||||||
|
|
||||||
|
with open(config_path, 'w') as fp:
|
||||||
|
json.dump(settings, fp, indent=4)
|
||||||
|
|
||||||
|
cores = [
|
||||||
|
('particl', '0.18.0.12'),
|
||||||
|
('litecoin', '0.17.1')
|
||||||
|
]
|
||||||
|
for c in cores:
|
||||||
|
prepareCore(c[0], c[1], settings, data_dir)
|
||||||
|
coin = c[0]
|
||||||
|
|
||||||
|
core_settings = settings['chainclients'][coin]
|
||||||
|
data_dir = core_settings['datadir']
|
||||||
|
|
||||||
|
if not os.path.exists(data_dir):
|
||||||
|
os.makedirs(data_dir)
|
||||||
|
|
||||||
|
core_conf_path = os.path.join(data_dir, coin + '.conf')
|
||||||
|
if os.path.exists(core_conf_path):
|
||||||
|
sys.stderr.write('Error: %s exists, exiting.\n' % (core_conf_path))
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
with open(core_conf_path, 'w') as fp:
|
||||||
|
if chain != 'mainnet':
|
||||||
|
fp.write(chain + '=1\n\n')
|
||||||
|
|
||||||
|
fp.write('rpcport={}\n'.format(core_settings['rpcport']))
|
||||||
|
fp.write('printtoconsole=0\n')
|
||||||
|
fp.write('daemon=0\n')
|
||||||
|
|
||||||
|
if coin == 'particl':
|
||||||
|
fp.write('debugexclude=libevent\n')
|
||||||
|
fp.write('zmqpubsmsg=tcp://127.0.0.1:{}\n'.format(settings['zmqport']))
|
||||||
|
fp.write('spentindex=1')
|
||||||
|
fp.write('txindex=1')
|
||||||
|
elif coin == 'litecoin':
|
||||||
|
fp.write('prune=1000\n')
|
||||||
|
else:
|
||||||
|
logger.warning('Unknown coin %s', coin)
|
||||||
|
|
||||||
|
logger.info('Done.')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
182
bin/basicswap_run.py
Normal file
182
bin/basicswap_run.py
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2019 tecnovert
|
||||||
|
# Distributed under the MIT software license, see the accompanying
|
||||||
|
# file LICENSE.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Atomic Swap Client - Proof of Concept
|
||||||
|
|
||||||
|
Dependencies:
|
||||||
|
$ pacman -S python-pyzmq python-plyvel protobuf
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
import traceback
|
||||||
|
import signal
|
||||||
|
import subprocess
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import basicswap.config as cfg
|
||||||
|
from basicswap import __version__
|
||||||
|
from basicswap.basicswap import BasicSwap
|
||||||
|
from basicswap.http_server import HttpThread
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
logger.level = logging.DEBUG
|
||||||
|
if not len(logger.handlers):
|
||||||
|
logger.addHandler(logging.StreamHandler(sys.stdout))
|
||||||
|
|
||||||
|
ALLOW_CORS = False
|
||||||
|
swap_client = None
|
||||||
|
|
||||||
|
|
||||||
|
def signal_handler(sig, frame):
|
||||||
|
logger.info('Signal %d detected, ending program.' % (sig))
|
||||||
|
if swap_client is not None:
|
||||||
|
swap_client.stopRunning()
|
||||||
|
|
||||||
|
|
||||||
|
def startDaemon(node_dir, bin_dir, daemon_bin):
|
||||||
|
daemon_bin = os.path.join(bin_dir, daemon_bin)
|
||||||
|
|
||||||
|
args = [daemon_bin, '-datadir=' + node_dir]
|
||||||
|
logger.info('Starting node ' + daemon_bin + ' ' + '-datadir=' + node_dir)
|
||||||
|
return subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
|
def runClient(fp, dataDir, chain):
|
||||||
|
global swap_client
|
||||||
|
settings_path = os.path.join(dataDir, 'basicswap.json')
|
||||||
|
|
||||||
|
if not os.path.exists(settings_path):
|
||||||
|
raise ValueError('Settings file not found: ' + str(settings_path))
|
||||||
|
|
||||||
|
with open(settings_path) as fs:
|
||||||
|
settings = json.load(fs)
|
||||||
|
|
||||||
|
daemons = []
|
||||||
|
|
||||||
|
for c, v in settings['chainclients'].items():
|
||||||
|
if v['manage_daemon'] is True:
|
||||||
|
logger.info('Starting {} daemon'.format(c.capitalize()))
|
||||||
|
if c == 'particl':
|
||||||
|
daemons.append(startDaemon(v['datadir'], v['bindir'], cfg.PARTICLD))
|
||||||
|
logger.info('Started {} {}'.format(cfg.PARTICLD, daemons[-1].pid))
|
||||||
|
elif c == 'bitcoin':
|
||||||
|
daemons.append(startDaemon(v['datadir'], v['bindir'], cfg.BITCOIND))
|
||||||
|
logger.info('Started {} {}'.format(cfg.BITCOIND, daemons[-1].pid))
|
||||||
|
elif c == 'litecoin':
|
||||||
|
daemons.append(startDaemon(v['datadir'], v['bindir'], cfg.LITECOIND))
|
||||||
|
logger.info('Started {} {}'.format(cfg.LITECOIND, daemons[-1].pid))
|
||||||
|
else:
|
||||||
|
logger.warning('Unknown chain', c)
|
||||||
|
|
||||||
|
swap_client = BasicSwap(fp, dataDir, settings, chain)
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
|
signal.signal(signal.SIGTERM, signal_handler)
|
||||||
|
swap_client.start()
|
||||||
|
|
||||||
|
threads = []
|
||||||
|
if 'htmlhost' in settings:
|
||||||
|
swap_client.log.info('Starting server at %s:%d.' % (settings['htmlhost'], settings['htmlport']))
|
||||||
|
allow_cors = settings['allowcors'] if 'allowcors' in settings else ALLOW_CORS
|
||||||
|
tS1 = HttpThread(fp, settings['htmlhost'], settings['htmlport'], allow_cors, swap_client)
|
||||||
|
threads.append(tS1)
|
||||||
|
tS1.start()
|
||||||
|
|
||||||
|
try:
|
||||||
|
logger.info('Exit with Ctrl + c.')
|
||||||
|
while swap_client.is_running:
|
||||||
|
time.sleep(0.5)
|
||||||
|
swap_client.update()
|
||||||
|
except Exception:
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
swap_client.log.info('Stopping threads.')
|
||||||
|
for t in threads:
|
||||||
|
t.stop()
|
||||||
|
t.join()
|
||||||
|
|
||||||
|
for d in daemons:
|
||||||
|
logger.info('Terminating {}'.format(d.pid))
|
||||||
|
d.terminate()
|
||||||
|
d.wait(timeout=120)
|
||||||
|
if d.stdout:
|
||||||
|
d.stdout.close()
|
||||||
|
if d.stderr:
|
||||||
|
d.stderr.close()
|
||||||
|
if d.stdin:
|
||||||
|
d.stdin.close()
|
||||||
|
|
||||||
|
|
||||||
|
def printVersion():
|
||||||
|
logger.info('Basicswap version:', __version__)
|
||||||
|
|
||||||
|
|
||||||
|
def printHelp():
|
||||||
|
logger.info('basicswap-run --datadir=path -testnet')
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
data_dir = None
|
||||||
|
chain = 'mainnet'
|
||||||
|
|
||||||
|
for v in sys.argv[1:]:
|
||||||
|
if len(v) < 2 or v[0] != '-':
|
||||||
|
logger.warning('Unknown argument', v)
|
||||||
|
continue
|
||||||
|
|
||||||
|
s = v.split('=')
|
||||||
|
name = s[0].strip()
|
||||||
|
|
||||||
|
for i in range(2):
|
||||||
|
if name[0] == '-':
|
||||||
|
name = name[1:]
|
||||||
|
|
||||||
|
if name == 'v' or name == 'version':
|
||||||
|
printVersion()
|
||||||
|
return 0
|
||||||
|
if name == 'h' or name == 'help':
|
||||||
|
printHelp()
|
||||||
|
return 0
|
||||||
|
if name == 'testnet':
|
||||||
|
chain = 'testnet'
|
||||||
|
continue
|
||||||
|
if name == 'regtest':
|
||||||
|
chain = 'regtest'
|
||||||
|
continue
|
||||||
|
|
||||||
|
if len(s) == 2:
|
||||||
|
if name == 'datadir':
|
||||||
|
data_dir = os.path.expanduser(s[1])
|
||||||
|
continue
|
||||||
|
|
||||||
|
logger.warning('Unknown argument', v)
|
||||||
|
|
||||||
|
if data_dir is None:
|
||||||
|
default_datadir = '~/.basicswap'
|
||||||
|
data_dir = os.path.join(os.path.expanduser(default_datadir))
|
||||||
|
logger.info('Using datadir:', data_dir)
|
||||||
|
logger.info('Chain:', chain)
|
||||||
|
|
||||||
|
if not os.path.exists(data_dir):
|
||||||
|
os.makedirs(data_dir)
|
||||||
|
|
||||||
|
with open(os.path.join(data_dir, 'basicswap.log'), 'a') as fp:
|
||||||
|
logger.info(os.path.basename(sys.argv[0]) + ', version: ' + __version__ + '\n\n')
|
||||||
|
runClient(fp, data_dir, chain)
|
||||||
|
|
||||||
|
logger.info('Done.')
|
||||||
|
return swap_client.fail_code if swap_client is not None else 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
5
setup.py
5
setup.py
@ -11,8 +11,8 @@ setuptools.setup(
|
|||||||
name="basicswap",
|
name="basicswap",
|
||||||
version=__version__,
|
version=__version__,
|
||||||
author="tecnovert",
|
author="tecnovert",
|
||||||
author_email="hello@particl.io",
|
author_email="tecnovert@tecnovert.net",
|
||||||
description="Particl atomic swap demo",
|
description="Simple atomic swap demo",
|
||||||
long_description=open("README.md").read(),
|
long_description=open("README.md").read(),
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type="text/markdown",
|
||||||
url="https://github.com/tecnovert/basicswap",
|
url="https://github.com/tecnovert/basicswap",
|
||||||
@ -31,6 +31,7 @@ setuptools.setup(
|
|||||||
entry_points={
|
entry_points={
|
||||||
"console_scripts": [
|
"console_scripts": [
|
||||||
"basicswap-run=bin.basicswap_run:main",
|
"basicswap-run=bin.basicswap_run:main",
|
||||||
|
"basicswap-prepare=bin.basicswap_prepare:main",
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
test_suite="tests.test_suite"
|
test_suite="tests.test_suite"
|
||||||
|
@ -7,8 +7,8 @@ import tests.test_run
|
|||||||
|
|
||||||
def test_suite():
|
def test_suite():
|
||||||
loader = unittest.TestLoader()
|
loader = unittest.TestLoader()
|
||||||
suite.addTests(loader.loadTestsFromModule(tests.test_other))
|
suite = loader.loadTestsFromModule(tests.test_other)
|
||||||
suite.addTests(loader.loadTestsFromModule(tests.test_prepare))
|
suite.addTests(loader.loadTestsFromModule(tests.test_prepare))
|
||||||
suite = loader.loadTestsFromModule(tests.test_run)
|
suite.addTests(loader.loadTestsFromModule(tests.test_run))
|
||||||
|
|
||||||
return suite
|
return suite
|
||||||
|
@ -12,13 +12,14 @@ from unittest.mock import patch
|
|||||||
from io import StringIO
|
from io import StringIO
|
||||||
import logging
|
import logging
|
||||||
import shutil
|
import shutil
|
||||||
import importlib
|
|
||||||
|
|
||||||
prepareSystem = importlib.import_module('bin.basicswap-prepare')
|
import bin.basicswap_prepare as prepareSystem
|
||||||
test_path = os.path.expanduser('~/test_basicswap')
|
test_path = os.path.expanduser('~/test_basicswap')
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
logger.level = logging.DEBUG
|
logger.level = logging.DEBUG
|
||||||
|
if not len(logger.handlers):
|
||||||
|
logger.addHandler(logging.StreamHandler(sys.stdout))
|
||||||
|
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
class Test(unittest.TestCase):
|
||||||
|
@ -50,6 +50,7 @@ import basicswap.config as cfg
|
|||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
logger.level = logging.DEBUG
|
logger.level = logging.DEBUG
|
||||||
|
if not len(logger.handlers):
|
||||||
logger.addHandler(logging.StreamHandler(sys.stdout))
|
logger.addHandler(logging.StreamHandler(sys.stdout))
|
||||||
|
|
||||||
NUM_NODES = 3
|
NUM_NODES = 3
|
||||||
|
Loading…
Reference in New Issue
Block a user