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