diff --git a/basicswap/contrib/blake256/__init__.py b/basicswap/contrib/blake256/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/basicswap/contrib/blake256/__init__.py @@ -0,0 +1 @@ + diff --git a/bin/basicswap_prepare.py b/bin/basicswap_prepare.py index 0cc8ce2..8832da9 100755 --- a/bin/basicswap_prepare.py +++ b/bin/basicswap_prepare.py @@ -64,6 +64,9 @@ FIRO_VERSION_TAG = os.getenv('FIRO_VERSION_TAG', '') NAV_VERSION = os.getenv('NAV_VERSION', '7.0.3') NAV_VERSION_TAG = os.getenv('NAV_VERSION_TAG', '') +DCR_VERSION = os.getenv('DCR_VERSION', '1.8.1') +DCR_VERSION_TAG = os.getenv('DCR_VERSION_TAG', '') + GUIX_SSL_CERT_DIR = None ADD_PUBKEY_URL = os.getenv('ADD_PUBKEY_URL', '') @@ -83,6 +86,7 @@ known_coins = { 'dash': (DASH_VERSION, DASH_VERSION_TAG, ('pasta',)), 'firo': (FIRO_VERSION, FIRO_VERSION_TAG, ('reuben',)), 'navcoin': (NAV_VERSION, NAV_VERSION_TAG, ('nav_builder',)), + 'decred': (DCR_VERSION, DCR_VERSION_TAG, ('decred_release',)), } disabled_coins = [ @@ -100,6 +104,7 @@ expected_key_ids = { 'pasta': ('52527BEDABE87984',), 'reuben': ('1290A1D0FA7EE109',), 'nav_builder': ('2782262BF6E7FADB',), + 'decred_release': ('6D897EDF518A031D',), } USE_PLATFORM = os.getenv('USE_PLATFORM', platform.system()) @@ -160,6 +165,11 @@ BTC_ONION_PORT = int(os.getenv('BTC_ONION_PORT', 8334)) BTC_RPC_USER = os.getenv('BTC_RPC_USER', '') BTC_RPC_PWD = os.getenv('BTC_RPC_PWD', '') +DCR_RPC_HOST = os.getenv('DCR_RPC_HOST', '127.0.0.1') +DCR_RPC_PORT = int(os.getenv('DCR_RPC_PORT', 9109)) +DCR_RPC_USER = os.getenv('DCR_RPC_USER', '') +DCR_RPC_PWD = os.getenv('DCR_RPC_PWD', '') + NMC_RPC_HOST = os.getenv('NMC_RPC_HOST', '127.0.0.1') NMC_RPC_PORT = int(os.getenv('NMC_RPC_PORT', 19698)) @@ -519,11 +529,25 @@ def extractCore(coin, version_data, settings, bin_dir, release_path, extra_opts= logging.warning('Unable to set file permissions: %s, for %s', str(e), out_path) return - bins = [coin + 'd', coin + '-cli', coin + '-tx'] - versions = version.split('.') dir_name = 'dashcore' if coin == 'dash' else coin - if int(versions[0]) >= 22 or int(versions[1]) >= 19: - bins.append(coin + '-wallet') + if coin == 'decred': + bins = ['dcrd', 'dcrwallet'] + else: + bins = [coin + 'd', coin + '-cli', coin + '-tx'] + versions = version.split('.') + if int(versions[0]) >= 22 or int(versions[1]) >= 19: + bins.append(coin + '-wallet') + + def get_archive_path(b): + if coin == 'pivx': + return '{}-{}/bin/{}'.format(dir_name, version, b) + elif coin == 'particl' and '_nousb-' in release_path: + return '{}-{}_nousb/bin/{}'.format(dir_name, version + version_tag, b) + elif coin == 'decred': + return '{}-{}-v{}/{}'.format(dir_name, extra_opts['arch_name'], version, b) + else: + return '{}-{}/bin/{}'.format(dir_name, version + version_tag, b) + if 'win32' in BIN_ARCH or 'win64' in BIN_ARCH: with zipfile.ZipFile(release_path) as fz: for b in bins: @@ -531,7 +555,7 @@ def extractCore(coin, version_data, settings, bin_dir, release_path, extra_opts= out_path = os.path.join(bin_dir, b) if (not os.path.exists(out_path)) or extract_core_overwrite: with open(out_path, 'wb') as fout: - fout.write(fz.read('{}-{}/bin/{}'.format(dir_name, version, b))) + fout.write(fz.read(get_archive_path(b))) try: os.chmod(out_path, stat.S_IRWXU | stat.S_IXGRP | stat.S_IXOTH) except Exception as e: @@ -541,15 +565,7 @@ def extractCore(coin, version_data, settings, bin_dir, release_path, extra_opts= for b in bins: out_path = os.path.join(bin_dir, b) if not os.path.exists(out_path) or extract_core_overwrite: - - if coin == 'pivx': - filename = '{}-{}/bin/{}'.format(dir_name, version, b) - elif coin == 'particl' and '_nousb-' in release_path: - filename = '{}-{}_nousb/bin/{}'.format(dir_name, version + version_tag, b) - else: - filename = '{}-{}/bin/{}'.format(dir_name, version + version_tag, b) - - with open(out_path, 'wb') as fout, ft.extractfile(filename) as fi: + with open(out_path, 'wb') as fout, ft.extractfile(get_archive_path(b)) as fi: fout.write(fi.read()) try: os.chmod(out_path, stat.S_IRWXU | stat.S_IXGRP | stat.S_IXOTH) @@ -602,6 +618,39 @@ def prepareCore(coin, version_data, settings, data_dir, extra_opts={}): assert_path = os.path.join(bin_dir, assert_filename) if not os.path.exists(assert_path): downloadFile(assert_url, assert_path) + + elif coin == 'decred': + arch_name = BIN_ARCH + if USE_PLATFORM == 'Darwin': + arch_name = 'darwin-amd64' + elif USE_PLATFORM == 'Windows': + arch_name = 'windows-amd64' + else: + machine: str = platform.machine() + if 'arm' in machine: + arch_name = 'linux-arm' + else: + arch_name = 'linux-amd64' + + extra_opts['arch_name'] = arch_name + release_filename = '{}-{}-{}.{}'.format(coin, version, arch_name, FILE_EXT) + release_page_url = 'https://github.com/decred/decred-binaries/releases/download/v{}'.format(version) + release_url = release_page_url + '/' + 'decred-{}-v{}.{}'.format(arch_name, version, FILE_EXT) + release_path = os.path.join(bin_dir, release_filename) + if not os.path.exists(release_path): + downloadFile(release_url, release_path) + + assert_filename = 'decred-v{}-manifest.txt'.format(version) + assert_url = release_page_url + '/' + assert_filename + assert_path = os.path.join(bin_dir, assert_filename) + if not os.path.exists(assert_path): + downloadFile(assert_url, assert_path) + + assert_sig_filename = assert_filename + '.asc' + assert_sig_url = assert_url + '.asc' + 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) else: major_version = int(version.split('.')[0]) @@ -1555,7 +1604,19 @@ def main(): 'override_feerate': 0.002, 'conf_target': 2, 'core_version_group': 21, - 'chain_lookups': 'local', + }, + 'bitcoin': { + 'connection_type': 'rpc' if 'bitcoin' in with_coins else 'none', + 'manage_daemon': True if ('bitcoin' in with_coins and BTC_RPC_HOST == '127.0.0.1') else False, + 'rpchost': BTC_RPC_HOST, + 'rpcport': BTC_RPC_PORT + port_offset, + 'onionport': BTC_ONION_PORT + port_offset, + 'datadir': os.getenv('BTC_DATA_DIR', os.path.join(data_dir, 'bitcoin')), + 'bindir': os.path.join(bin_dir, 'bitcoin'), + 'use_segwit': True, + 'blocks_confirmed': 1, + 'conf_target': 2, + 'core_version_group': 22, }, 'litecoin': { 'connection_type': 'rpc' if 'litecoin' in with_coins else 'none', @@ -1570,21 +1631,19 @@ def main(): 'conf_target': 2, 'core_version_group': 21, 'min_relay_fee': 0.00001, - 'chain_lookups': 'local', }, - 'bitcoin': { - 'connection_type': 'rpc' if 'bitcoin' in with_coins else 'none', - 'manage_daemon': True if ('bitcoin' in with_coins and BTC_RPC_HOST == '127.0.0.1') else False, - 'rpchost': BTC_RPC_HOST, - 'rpcport': BTC_RPC_PORT + port_offset, - 'onionport': BTC_ONION_PORT + port_offset, - 'datadir': os.getenv('BTC_DATA_DIR', os.path.join(data_dir, 'bitcoin')), - 'bindir': os.path.join(bin_dir, 'bitcoin'), + 'decred': { + 'connection_type': 'rpc' if 'decred' in with_coins else 'none', + 'manage_daemon': True if ('decred' in with_coins and DCR_RPC_HOST == '127.0.0.1') else False, + 'rpchost': DCR_RPC_HOST, + 'rpcport': DCR_RPC_PORT + port_offset, + 'datadir': os.getenv('DCR_DATA_DIR', os.path.join(data_dir, 'decred')), + 'bindir': os.path.join(bin_dir, 'decred'), 'use_segwit': True, - 'blocks_confirmed': 1, + 'blocks_confirmed': 2, 'conf_target': 2, - 'core_version_group': 22, - 'chain_lookups': 'local', + 'core_type_group': 'dcr', + 'min_relay_fee': 0.00001, }, 'namecoin': { 'connection_type': 'rpc' if 'namecoin' in with_coins else 'none', @@ -1620,6 +1679,7 @@ def main(): 'rpctimeout': 60, 'walletrpctimeout': 120, 'walletrpctimeoutlong': 600, + 'core_type_group': 'xmr', }, 'pivx': { 'connection_type': 'rpc' if 'pivx' in with_coins else 'none', @@ -1634,7 +1694,6 @@ def main(): 'blocks_confirmed': 1, 'conf_target': 2, 'core_version_group': 17, - 'chain_lookups': 'local', }, 'dash': { 'connection_type': 'rpc' if 'dash' in with_coins else 'none', @@ -1649,7 +1708,6 @@ def main(): 'blocks_confirmed': 1, 'conf_target': 2, 'core_version_group': 18, - 'chain_lookups': 'local', }, 'firo': { 'connection_type': 'rpc' if 'firo' in with_coins else 'none', @@ -1665,7 +1723,6 @@ def main(): 'conf_target': 2, 'core_version_group': 14, 'min_relay_fee': 0.00001, - 'chain_lookups': 'local', }, 'navcoin': { 'connection_type': 'rpc' if 'navcoin' in with_coins else 'none', diff --git a/pgp/keys/decred_release.pgp b/pgp/keys/decred_release.pgp new file mode 100644 index 0000000..8b28de8 --- /dev/null +++ b/pgp/keys/decred_release.pgp @@ -0,0 +1,96 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +O6GuapL0x1I9SeIk9WX9VRrpZmENhlri +=JrM6 +-----END PGP PUBLIC KEY BLOCK-----