2019-07-21 18:50:32 +00:00
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
2024-02-05 12:16:34 +00:00
# Copyright (c) 2019-2024 tecnovert
2019-07-21 18:50:32 +00:00
# Distributed under the MIT software license, see the accompanying
2020-10-30 08:55:45 +00:00
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
2019-07-21 18:50:32 +00:00
2024-05-20 14:29:14 +00:00
import contextlib
import gnupg
import hashlib
2019-07-21 18:50:32 +00:00
import json
2024-05-20 14:29:14 +00:00
import logging
2019-07-21 18:50:32 +00:00
import mmap
2024-05-20 14:29:14 +00:00
import os
import platform
import random
2022-03-23 22:00:35 +00:00
import shutil
2020-12-03 23:46:01 +00:00
import signal
2022-01-23 12:00:28 +00:00
import socket
2024-05-20 14:29:14 +00:00
import socks
import stat
import sys
2019-07-21 18:50:32 +00:00
import tarfile
2024-05-20 14:29:14 +00:00
import threading
import time
2020-12-02 21:19:10 +00:00
import urllib . parse
2024-05-20 14:29:14 +00:00
import zipfile
2022-12-13 22:19:38 +00:00
from urllib . error import ContentTooShortError
from urllib . parse import _splittype
2024-05-20 14:29:14 +00:00
from urllib . request import Request , urlopen
2019-07-21 18:50:32 +00:00
2019-07-21 19:20:36 +00:00
import basicswap . config as cfg
2022-03-26 22:08:15 +00:00
from basicswap . base import getaddrinfo_tor
2020-12-03 23:46:01 +00:00
from basicswap . basicswap import BasicSwap
from basicswap . chainparams import Coins
2024-05-20 14:29:14 +00:00
from basicswap . contrib . rpcauth import generate_salt , password_to_hmac
from basicswap import __version__
2022-10-24 18:49:36 +00:00
from basicswap . ui . util import getCoinName
2022-03-23 22:00:35 +00:00
from basicswap . util import toBool
from basicswap . util . rfc2440 import rfc2440_hash_password
2020-12-03 23:46:01 +00:00
from bin . basicswap_run import startDaemon , startXmrWalletDaemon
2023-11-28 00:23:56 +00:00
PARTICL_VERSION = os . getenv ( ' PARTICL_VERSION ' , ' 23.2.7.0 ' )
2022-06-03 19:31:07 +00:00
PARTICL_VERSION_TAG = os . getenv ( ' PARTICL_VERSION_TAG ' , ' ' )
2022-11-12 16:22:44 +00:00
PARTICL_LINUX_EXTRA = os . getenv ( ' PARTICL_LINUX_EXTRA ' , ' nousb ' )
2022-06-03 19:31:07 +00:00
2024-05-04 16:39:28 +00:00
LITECOIN_VERSION = os . getenv ( ' LITECOIN_VERSION ' , ' 0.21.3 ' )
2022-06-03 19:31:07 +00:00
LITECOIN_VERSION_TAG = os . getenv ( ' LITECOIN_VERSION_TAG ' , ' ' )
2023-12-31 00:15:31 +00:00
BITCOIN_VERSION = os . getenv ( ' BITCOIN_VERSION ' , ' 26.0 ' )
2022-06-03 19:31:07 +00:00
BITCOIN_VERSION_TAG = os . getenv ( ' BITCOIN_VERSION_TAG ' , ' ' )
2024-04-06 10:03:37 +00:00
MONERO_VERSION = os . getenv ( ' MONERO_VERSION ' , ' 0.18.3.3 ' )
2022-06-03 19:31:07 +00:00
MONERO_VERSION_TAG = os . getenv ( ' MONERO_VERSION_TAG ' , ' ' )
2024-04-06 10:03:37 +00:00
XMR_SITE_COMMIT = ' d00169a6decd9470ebdf6a75e3351df4ebcd260a ' # Lock hashes.txt to monero version
2019-07-21 19:20:36 +00:00
2024-03-31 22:47:14 +00:00
WOWNERO_VERSION = os . getenv ( ' WOWNERO_VERSION ' , ' 0.11.1.0 ' )
WOWNERO_VERSION_TAG = os . getenv ( ' WOWNERO_VERSION_TAG ' , ' ' )
WOW_SITE_COMMIT = ' 97e100e1605e9f59bc8ca82a5b237d5562c8a21c ' # todo
2024-02-26 18:49:06 +00:00
PIVX_VERSION = os . getenv ( ' PIVX_VERSION ' , ' 5.6.1 ' )
2023-01-11 08:22:22 +00:00
PIVX_VERSION_TAG = os . getenv ( ' PIVX_VERSION_TAG ' , ' ' )
2022-08-10 22:02:36 +00:00
2023-12-18 13:15:16 +00:00
DASH_VERSION = os . getenv ( ' DASH_VERSION ' , ' 20.0.2 ' )
2022-10-20 20:23:25 +00:00
DASH_VERSION_TAG = os . getenv ( ' DASH_VERSION_TAG ' , ' ' )
2024-06-19 15:23:39 +00:00
FIRO_VERSION = os . getenv ( ' FIRO_VERSION ' , ' 0.14.13.3 ' )
2023-12-24 19:12:53 +00:00
FIRO_VERSION_TAG = os . getenv ( ' FIRO_VERSION_TAG ' , ' ' )
2022-11-07 20:31:10 +00:00
2023-08-29 21:08:28 +00:00
NAV_VERSION = os . getenv ( ' NAV_VERSION ' , ' 7.0.3 ' )
2023-11-27 17:01:33 +00:00
NAV_VERSION_TAG = os . getenv ( ' NAV_VERSION_TAG ' , ' ' )
2023-08-29 21:08:28 +00:00
2024-04-09 21:33:44 +00:00
DCR_VERSION = os . getenv ( ' DCR_VERSION ' , ' 1.8.1 ' )
DCR_VERSION_TAG = os . getenv ( ' DCR_VERSION_TAG ' , ' ' )
2022-12-15 08:55:20 +00:00
GUIX_SSL_CERT_DIR = None
2023-08-29 21:08:28 +00:00
ADD_PUBKEY_URL = os . getenv ( ' ADD_PUBKEY_URL ' , ' ' )
2023-10-09 14:43:09 +00:00
OVERRIDE_DISABLED_COINS = toBool ( os . getenv ( ' OVERRIDE_DISABLED_COINS ' , ' false ' ) )
2023-08-29 21:08:28 +00:00
2023-11-27 17:01:33 +00:00
# If SKIP_GPG_VALIDATION is set to true the script will check hashes but not signatures
SKIP_GPG_VALIDATION = toBool ( os . getenv ( ' SKIP_GPG_VALIDATION ' , ' false ' ) )
2022-10-20 20:23:25 +00:00
2022-03-27 11:05:53 +00:00
known_coins = {
2022-06-03 19:31:07 +00:00
' particl ' : ( PARTICL_VERSION , PARTICL_VERSION_TAG , ( ' tecnovert ' , ) ) ,
' bitcoin ' : ( BITCOIN_VERSION , BITCOIN_VERSION_TAG , ( ' laanwj ' , ) ) ,
2024-05-25 19:50:39 +00:00
' litecoin ' : ( LITECOIN_VERSION , LITECOIN_VERSION_TAG , ( ' davidburkett38 ' , ) ) ,
' decred ' : ( DCR_VERSION , DCR_VERSION_TAG , ( ' decred_release ' , ) ) ,
2022-03-27 11:05:53 +00:00
' namecoin ' : ( ' 0.18.0 ' , ' ' , ( ' JeremyRand ' , ) ) ,
2022-06-05 09:38:14 +00:00
' monero ' : ( MONERO_VERSION , MONERO_VERSION_TAG , ( ' binaryfate ' , ) ) ,
2024-03-31 22:47:14 +00:00
' wownero ' : ( WOWNERO_VERSION , WOWNERO_VERSION_TAG , ( ' wowario ' , ) ) ,
2023-01-11 08:22:22 +00:00
' pivx ' : ( PIVX_VERSION , PIVX_VERSION_TAG , ( ' fuzzbawls ' , ) ) ,
2022-10-20 20:23:25 +00:00
' dash ' : ( DASH_VERSION , DASH_VERSION_TAG , ( ' pasta ' , ) ) ,
2023-11-24 22:55:41 +00:00
' firo ' : ( FIRO_VERSION , FIRO_VERSION_TAG , ( ' reuben ' , ) ) ,
2023-08-29 21:08:28 +00:00
' navcoin ' : ( NAV_VERSION , NAV_VERSION_TAG , ( ' nav_builder ' , ) ) ,
2022-06-05 09:38:14 +00:00
}
2023-10-09 14:43:09 +00:00
disabled_coins = [
' navcoin ' ,
2024-04-22 18:59:22 +00:00
' namecoin ' , # Needs update
2023-10-09 14:43:09 +00:00
]
2022-06-05 09:38:14 +00:00
expected_key_ids = {
' tecnovert ' : ( ' 13F13651C9CF0D6B ' , ) ,
' thrasher ' : ( ' FE3348877809386C ' , ) ,
' laanwj ' : ( ' 1E4AED62986CD25D ' , ) ,
' JeremyRand ' : ( ' 2DBE339E29F6294C ' , ) ,
' binaryfate ' : ( ' F0AF4D462A0BDF92 ' , ) ,
2024-03-31 22:47:14 +00:00
' wowario ' : ( ' 793504B449C69220 ' , ) ,
2022-06-16 13:37:32 +00:00
' davidburkett38 ' : ( ' 3620E9D387E55666 ' , ) ,
2024-02-26 18:49:06 +00:00
' fuzzbawls ' : ( ' C1ABA64407731FD9 ' , ) ,
2022-10-20 20:23:25 +00:00
' pasta ' : ( ' 52527BEDABE87984 ' , ) ,
2022-11-07 20:31:10 +00:00
' reuben ' : ( ' 1290A1D0FA7EE109 ' , ) ,
2023-08-29 21:08:28 +00:00
' nav_builder ' : ( ' 2782262BF6E7FADB ' , ) ,
2024-04-09 21:33:44 +00:00
' decred_release ' : ( ' 6D897EDF518A031D ' , ) ,
2022-03-27 11:05:53 +00:00
}
2022-11-10 22:49:08 +00:00
USE_PLATFORM = os . getenv ( ' USE_PLATFORM ' , platform . system ( ) )
if USE_PLATFORM == ' Darwin ' :
2021-01-10 18:30:07 +00:00
BIN_ARCH = ' osx64 '
FILE_EXT = ' tar.gz '
2022-11-10 22:49:08 +00:00
elif USE_PLATFORM == ' Windows ' :
2021-01-10 18:30:07 +00:00
BIN_ARCH = ' win64 '
FILE_EXT = ' zip '
2019-07-24 22:59:40 +00:00
else :
2024-02-08 10:01:25 +00:00
machine : str = platform . machine ( )
if ' arm ' in machine :
BIN_ARCH = ' arm-linux-gnueabihf '
else :
BIN_ARCH = machine + ' -linux-gnu '
2021-01-10 18:30:07 +00:00
FILE_EXT = ' tar.gz '
2019-07-21 18:50:32 +00:00
2023-11-27 17:01:33 +00:00
# Allow manually overriding the arch tag
BIN_ARCH = os . getenv ( ' BIN_ARCH ' , BIN_ARCH )
FILE_EXT = os . getenv ( ' FILE_EXT ' , FILE_EXT )
2019-07-21 18:50:32 +00:00
logger = logging . getLogger ( )
2023-03-28 20:31:32 +00:00
logger . level = logging . INFO
2019-07-21 18:50:32 +00:00
if not len ( logger . handlers ) :
logger . addHandler ( logging . StreamHandler ( sys . stdout ) )
2022-07-17 20:34:39 +00:00
UI_HTML_PORT = int ( os . getenv ( ' UI_HTML_PORT ' , 12700 ) )
2022-07-31 17:33:01 +00:00
UI_WS_PORT = int ( os . getenv ( ' UI_WS_PORT ' , 11700 ) )
2022-07-17 20:34:39 +00:00
COINS_RPCBIND_IP = os . getenv ( ' COINS_RPCBIND_IP ' , ' 127.0.0.1 ' )
PART_ZMQ_PORT = int ( os . getenv ( ' PART_ZMQ_PORT ' , 20792 ) )
PART_RPC_HOST = os . getenv ( ' PART_RPC_HOST ' , ' 127.0.0.1 ' )
PART_RPC_PORT = int ( os . getenv ( ' PART_RPC_PORT ' , 19792 ) )
PART_ONION_PORT = int ( os . getenv ( ' PART_ONION_PORT ' , 51734 ) )
PART_RPC_USER = os . getenv ( ' PART_RPC_USER ' , ' ' )
PART_RPC_PWD = os . getenv ( ' PART_RPC_PWD ' , ' ' )
2021-01-11 21:48:46 +00:00
XMR_RPC_HOST = os . getenv ( ' XMR_RPC_HOST ' , ' 127.0.0.1 ' )
2020-12-04 23:59:21 +00:00
BASE_XMR_RPC_PORT = int ( os . getenv ( ' BASE_XMR_RPC_PORT ' , 29798 ) )
BASE_XMR_ZMQ_PORT = int ( os . getenv ( ' BASE_XMR_ZMQ_PORT ' , 30898 ) )
BASE_XMR_WALLET_PORT = int ( os . getenv ( ' BASE_XMR_WALLET_PORT ' , 29998 ) )
2021-01-11 21:48:46 +00:00
XMR_WALLET_RPC_HOST = os . getenv ( ' XMR_WALLET_RPC_HOST ' , ' 127.0.0.1 ' )
2020-12-03 23:46:01 +00:00
XMR_WALLET_RPC_USER = os . getenv ( ' XMR_WALLET_RPC_USER ' , ' xmr_wallet_user ' )
XMR_WALLET_RPC_PWD = os . getenv ( ' XMR_WALLET_RPC_PWD ' , ' xmr_wallet_pwd ' )
2022-11-28 17:54:41 +00:00
XMR_RPC_USER = os . getenv ( ' XMR_RPC_USER ' , ' ' )
XMR_RPC_PWD = os . getenv ( ' XMR_RPC_PWD ' , ' ' )
2022-07-11 21:36:28 +00:00
DEFAULT_XMR_RESTORE_HEIGHT = int ( os . getenv ( ' DEFAULT_XMR_RESTORE_HEIGHT ' , 2245107 ) )
2020-12-04 23:59:21 +00:00
2024-03-31 22:47:14 +00:00
WOW_RPC_HOST = os . getenv ( ' WOW_RPC_HOST ' , ' 127.0.0.1 ' )
BASE_WOW_RPC_PORT = int ( os . getenv ( ' BASE_WOW_RPC_PORT ' , 34598 ) )
BASE_WOW_ZMQ_PORT = int ( os . getenv ( ' BASE_WOW_ZMQ_PORT ' , 34698 ) )
BASE_WOW_WALLET_PORT = int ( os . getenv ( ' BASE_WOW_WALLET_PORT ' , 34798 ) )
WOW_WALLET_RPC_HOST = os . getenv ( ' WOW_WALLET_RPC_HOST ' , ' 127.0.0.1 ' )
WOW_WALLET_RPC_USER = os . getenv ( ' WOW_WALLET_RPC_USER ' , ' wow_wallet_user ' )
WOW_WALLET_RPC_PWD = os . getenv ( ' WOW_WALLET_RPC_PWD ' , ' wow_wallet_pwd ' )
WOW_RPC_USER = os . getenv ( ' WOW_RPC_USER ' , ' ' )
WOW_RPC_PWD = os . getenv ( ' WOW_RPC_PWD ' , ' ' )
DEFAULT_WOW_RESTORE_HEIGHT = int ( os . getenv ( ' DEFAULT_WOW_RESTORE_HEIGHT ' , 450000 ) )
2021-01-11 21:48:46 +00:00
LTC_RPC_HOST = os . getenv ( ' LTC_RPC_HOST ' , ' 127.0.0.1 ' )
2022-07-15 14:38:05 +00:00
LTC_RPC_PORT = int ( os . getenv ( ' LTC_RPC_PORT ' , 19895 ) )
LTC_ONION_PORT = int ( os . getenv ( ' LTC_ONION_PORT ' , 9333 ) )
2022-07-17 20:34:39 +00:00
LTC_RPC_USER = os . getenv ( ' LTC_RPC_USER ' , ' ' )
LTC_RPC_PWD = os . getenv ( ' LTC_RPC_PWD ' , ' ' )
2022-03-23 22:00:35 +00:00
2022-07-17 20:34:39 +00:00
BTC_RPC_HOST = os . getenv ( ' BTC_RPC_HOST ' , ' 127.0.0.1 ' )
BTC_RPC_PORT = int ( os . getenv ( ' BTC_RPC_PORT ' , 19996 ) )
BTC_ONION_PORT = int ( os . getenv ( ' BTC_ONION_PORT ' , 8334 ) )
2021-06-28 21:56:45 +00:00
BTC_RPC_USER = os . getenv ( ' BTC_RPC_USER ' , ' ' )
BTC_RPC_PWD = os . getenv ( ' BTC_RPC_PWD ' , ' ' )
2024-04-09 21:33:44 +00:00
DCR_RPC_HOST = os . getenv ( ' DCR_RPC_HOST ' , ' 127.0.0.1 ' )
DCR_RPC_PORT = int ( os . getenv ( ' DCR_RPC_PORT ' , 9109 ) )
2024-05-20 14:29:14 +00:00
DCR_WALLET_RPC_HOST = os . getenv ( ' DCR_WALLET_RPC_HOST ' , ' 127.0.0.1 ' )
DCR_WALLET_RPC_PORT = int ( os . getenv ( ' DCR_WALLET_RPC_PORT ' , 9209 ) )
DCR_WALLET_PWD = os . getenv ( ' DCR_WALLET_PWD ' , random . randbytes ( random . randint ( 14 , 18 ) ) . hex ( ) )
DCR_RPC_USER = os . getenv ( ' DCR_RPC_USER ' , ' user ' )
DCR_RPC_PWD = os . getenv ( ' DCR_RPC_PWD ' , random . randbytes ( random . randint ( 14 , 18 ) ) . hex ( ) )
2024-04-09 21:33:44 +00:00
2022-07-17 20:34:39 +00:00
NMC_RPC_HOST = os . getenv ( ' NMC_RPC_HOST ' , ' 127.0.0.1 ' )
NMC_RPC_PORT = int ( os . getenv ( ' NMC_RPC_PORT ' , 19698 ) )
2022-03-23 22:00:35 +00:00
2022-08-10 22:02:36 +00:00
PIVX_RPC_HOST = os . getenv ( ' PIVX_RPC_HOST ' , ' 127.0.0.1 ' )
PIVX_RPC_PORT = int ( os . getenv ( ' PIVX_RPC_PORT ' , 51473 ) )
PIVX_ONION_PORT = int ( os . getenv ( ' PIVX_ONION_PORT ' , 51472 ) ) # nDefaultPort
PIVX_RPC_USER = os . getenv ( ' PIVX_RPC_USER ' , ' ' )
PIVX_RPC_PWD = os . getenv ( ' PIVX_RPC_PWD ' , ' ' )
2022-10-20 20:23:25 +00:00
DASH_RPC_HOST = os . getenv ( ' DASH_RPC_HOST ' , ' 127.0.0.1 ' )
DASH_RPC_PORT = int ( os . getenv ( ' DASH_RPC_PORT ' , 9998 ) )
DASH_ONION_PORT = int ( os . getenv ( ' DASH_ONION_PORT ' , 9999 ) ) # nDefaultPort
DASH_RPC_USER = os . getenv ( ' DASH_RPC_USER ' , ' ' )
DASH_RPC_PWD = os . getenv ( ' DASH_RPC_PWD ' , ' ' )
2022-11-07 20:31:10 +00:00
FIRO_RPC_HOST = os . getenv ( ' FIRO_RPC_HOST ' , ' 127.0.0.1 ' )
FIRO_RPC_PORT = int ( os . getenv ( ' FIRO_RPC_PORT ' , 8888 ) )
FIRO_ONION_PORT = int ( os . getenv ( ' FIRO_ONION_PORT ' , 8168 ) ) # nDefaultPort
FIRO_RPC_USER = os . getenv ( ' FIRO_RPC_USER ' , ' ' )
FIRO_RPC_PWD = os . getenv ( ' FIRO_RPC_PWD ' , ' ' )
2023-08-29 21:08:28 +00:00
NAV_RPC_HOST = os . getenv ( ' NAV_RPC_HOST ' , ' 127.0.0.1 ' )
NAV_RPC_PORT = int ( os . getenv ( ' NAV_RPC_PORT ' , 44444 ) )
NAV_ONION_PORT = int ( os . getenv ( ' NAV_ONION_PORT ' , 8334 ) ) # TODO?
NAV_RPC_USER = os . getenv ( ' NAV_RPC_USER ' , ' ' )
NAV_RPC_PWD = os . getenv ( ' NAV_RPC_PWD ' , ' ' )
2022-03-23 22:00:35 +00:00
TOR_PROXY_HOST = os . getenv ( ' TOR_PROXY_HOST ' , ' 127.0.0.1 ' )
TOR_PROXY_PORT = int ( os . getenv ( ' TOR_PROXY_PORT ' , 9050 ) )
TOR_CONTROL_PORT = int ( os . getenv ( ' TOR_CONTROL_PORT ' , 9051 ) )
TOR_DNS_PORT = int ( os . getenv ( ' TOR_DNS_PORT ' , 5353 ) )
TEST_TOR_PROXY = toBool ( os . getenv ( ' TEST_TOR_PROXY ' , ' true ' ) ) # Expects a known exit node
TEST_ONION_LINK = toBool ( os . getenv ( ' TEST_ONION_LINK ' , ' false ' ) )
2021-01-16 08:21:59 +00:00
2023-03-28 13:47:29 +00:00
BITCOIN_FASTSYNC_URL = os . getenv ( ' BITCOIN_FASTSYNC_URL ' , ' https://eu2.contabostorage.com/1f50a74c9dc14888a8664415dad3d020:utxosets/ ' )
BITCOIN_FASTSYNC_FILE = os . getenv ( ' BITCOIN_FASTSYNC_FILE ' , ' utxo-snapshot-bitcoin-mainnet-769818.tar ' )
2022-06-04 20:41:24 +00:00
2022-11-16 22:36:13 +00:00
# Encrypt new wallets with this password, must match the Particl wallet password when adding coins
WALLET_ENCRYPTION_PWD = os . getenv ( ' WALLET_ENCRYPTION_PWD ' , ' ' )
2022-11-09 17:10:17 +00:00
2024-02-05 12:16:34 +00:00
use_tor_proxy : bool = False
2022-03-23 22:00:35 +00:00
2024-02-08 20:40:14 +00:00
monerod_proxy_config = [
f ' proxy= { TOR_PROXY_HOST } : { TOR_PROXY_PORT } ' ,
' proxy-allow-dns-leaks=0 ' ,
' no-igd=1 ' , # Disable UPnP port mapping
' hide-my-port=1 ' , # Don't share the p2p port
' p2p-bind-ip=127.0.0.1 ' , # Don't broadcast ip
' in-peers=0 ' , # Changes "error" in log to "incoming connections disabled"
2024-03-31 22:47:14 +00:00
' out-peers=24 ' ,
f ' tx-proxy=tor, { TOR_PROXY_HOST } : { TOR_PROXY_PORT } ,disable_noise,16 ' # Outgoing tx relay to onion
2024-02-08 20:40:14 +00:00
]
monero_wallet_rpc_proxy_config = [
2024-03-31 22:47:14 +00:00
# 'daemon-ssl-allow-any-cert=1', moved to startup flag
2024-02-08 20:40:14 +00:00
]
2024-03-31 22:47:14 +00:00
wownerod_proxy_config = [
f ' proxy= { TOR_PROXY_HOST } : { TOR_PROXY_PORT } ' ,
' proxy-allow-dns-leaks=0 ' ,
' no-igd=1 ' , # Disable UPnP port mapping
' hide-my-port=1 ' , # Don't share the p2p port
' p2p-bind-ip=127.0.0.1 ' , # Don't broadcast ip
' in-peers=0 ' , # Changes "error" in log to "incoming connections disabled"
' out-peers=24 ' ,
f ' tx-proxy=tor, { TOR_PROXY_HOST } : { TOR_PROXY_PORT } ,disable_noise,16 ' # Outgoing tx relay to onion
]
wownero_wallet_rpc_proxy_config = [
# 'daemon-ssl-allow-any-cert=1', moved to startup flag
]
2024-02-08 20:40:14 +00:00
2022-03-23 22:00:35 +00:00
default_socket = socket . socket
default_socket_timeout = socket . getdefaulttimeout ( )
default_socket_getaddrinfo = socket . getaddrinfo
2021-01-10 18:30:07 +00:00
2020-12-27 19:39:10 +00:00
2023-12-18 13:15:16 +00:00
def exitWithError ( error_msg ) :
sys . stderr . write ( ' Error: {} , exiting. \n ' . format ( error_msg ) )
sys . exit ( 1 )
2022-12-13 22:19:38 +00:00
def make_reporthook ( read_start = 0 ) :
read = read_start # Number of bytes read so far
2019-07-21 18:50:32 +00:00
last_percent_str = ' '
2022-12-13 22:19:38 +00:00
time_last = time . time ( )
read_last = read_start
display_last = time_last
abo = 7
average_buffer = [ - 1 ] * 8
2019-07-21 18:50:32 +00:00
def reporthook ( blocknum , blocksize , totalsize ) :
2022-12-13 22:19:38 +00:00
nonlocal read , last_percent_str , time_last , read_last , display_last , read_start
nonlocal average_buffer , abo
2019-07-21 18:50:32 +00:00
read + = blocksize
2022-12-13 22:19:38 +00:00
# totalsize excludes read_start
use_size = totalsize + read_start
dl_complete : bool = totalsize > 0 and read > = use_size
time_now = time . time ( )
time_delta = time_now - time_last
2023-09-27 23:00:07 +00:00
if time_delta < 4.0 and not dl_complete :
2022-12-13 22:19:38 +00:00
return
2023-09-27 23:00:07 +00:00
# Avoid division by zero by picking a value
if time_delta < = 0.0 :
time_delta = 0.01
2022-12-13 22:19:38 +00:00
bytes_delta = read - read_last
time_last = time_now
read_last = read
bits_per_second = ( bytes_delta * 8 ) / time_delta
abo = 0 if abo > = 7 else abo + 1
average_buffer [ abo ] = bits_per_second
samples = 0
average_bits_per_second = 0
for sample in average_buffer :
if sample < 0 :
continue
average_bits_per_second + = sample
samples + = 1
average_bits_per_second / = samples
speed_str : str
if average_bits_per_second > 1000 * * 3 :
speed_str = ' {:.2f} Gbps ' . format ( average_bits_per_second / ( 1000 * * 3 ) )
elif average_bits_per_second > 1000 * * 2 :
speed_str = ' {:.2f} Mbps ' . format ( average_bits_per_second / ( 1000 * * 2 ) )
else :
speed_str = ' {:.2f} kbps ' . format ( average_bits_per_second / 1000 )
2019-07-21 18:50:32 +00:00
if totalsize > 0 :
2022-12-13 22:19:38 +00:00
percent_str = ' %5.0f %% ' % ( read * 1e2 / use_size )
if percent_str != last_percent_str or time_now - display_last > 10 :
logger . info ( percent_str + ' ' + speed_str )
2019-07-21 18:50:32 +00:00
last_percent_str = percent_str
2022-12-13 22:19:38 +00:00
display_last = time_now
2019-07-21 18:50:32 +00:00
else :
2022-12-13 22:19:38 +00:00
logger . info ( f ' Read { read } , { speed_str } ' )
2019-07-21 18:50:32 +00:00
return reporthook
2022-12-13 22:19:38 +00:00
def urlretrieve ( url , filename , reporthook = None , data = None , resume_from = 0 ) :
# urlretrieve with resume
url_type , path = _splittype ( url )
req = Request ( url )
if resume_from > 0 :
logger . info ( f ' Attempting to resume from byte { resume_from } ' )
req . add_header ( ' Range ' , f ' bytes= { resume_from } - ' )
with contextlib . closing ( urlopen ( req ) ) as fp :
headers = fp . info ( )
# Just return the local path and the "headers" for file://
# URLs. No sense in performing a copy unless requested.
if url_type == " file " and not filename :
return os . path . normpath ( path ) , headers
with open ( filename , ' ab ' if resume_from > 0 else ' wb ' ) as tfp :
result = filename , headers
bs = 1024 * 8
size = - 1
read = resume_from
blocknum = 0
range_from = 0
if " content-length " in headers :
size = int ( headers [ " Content-Length " ] )
if " Content-Range " in headers :
range_str = headers [ " Content-Range " ]
offset = range_str . find ( ' - ' )
range_from = int ( range_str [ 6 : offset ] )
if resume_from != range_from :
raise ValueError ( ' Download is not resuming from the expected byte ' )
if reporthook :
reporthook ( blocknum , bs , size )
while True :
block = fp . read ( bs )
if not block :
break
read + = len ( block )
tfp . write ( block )
blocknum + = 1
if reporthook :
reporthook ( blocknum , bs , size )
if size > = 0 and read < size :
raise ContentTooShortError (
" retrieval incomplete: got only %i out of %i bytes "
% ( read , size ) , result )
return result
2024-02-05 12:16:34 +00:00
def setConnectionParameters ( timeout : int = 5 , allow_set_tor : bool = True ) :
2019-07-21 18:50:32 +00:00
opener = urllib . request . build_opener ( )
opener . addheaders = [ ( ' User-agent ' , ' Mozilla/5.0 ' ) ]
urllib . request . install_opener ( opener )
2022-01-23 12:00:28 +00:00
2022-03-23 22:00:35 +00:00
if use_tor_proxy :
socks . setdefaultproxy ( socks . PROXY_TYPE_SOCKS5 , TOR_PROXY_HOST , TOR_PROXY_PORT , rdns = True )
socket . socket = socks . socksocket
2022-03-26 22:08:15 +00:00
socket . getaddrinfo = getaddrinfo_tor # Without this accessing .onion links would fail
2022-03-23 22:00:35 +00:00
# Set low timeout for urlretrieve connections
2022-12-13 22:19:38 +00:00
socket . setdefaulttimeout ( timeout )
2022-03-23 22:00:35 +00:00
2024-05-20 14:29:14 +00:00
def popConnectionParameters ( ) - > None :
2022-03-23 22:00:35 +00:00
if use_tor_proxy :
socket . socket = default_socket
socket . getaddrinfo = default_socket_getaddrinfo
socket . setdefaulttimeout ( default_socket_timeout )
2024-05-20 14:29:14 +00:00
def downloadFile ( url : str , path : str , timeout = 5 , resume_from = 0 ) - > None :
logger . info ( f ' Downloading file { url } ' )
logger . info ( f ' To { path } ' )
2022-03-23 22:00:35 +00:00
try :
2022-12-13 22:19:38 +00:00
setConnectionParameters ( timeout = timeout )
urlretrieve ( url , path , make_reporthook ( resume_from ) , resume_from = resume_from )
2022-03-23 22:00:35 +00:00
finally :
popConnectionParameters ( )
def downloadBytes ( url ) :
try :
setConnectionParameters ( )
return urllib . request . urlopen ( url ) . read ( )
finally :
popConnectionParameters ( )
2022-11-07 20:31:10 +00:00
def importPubkeyFromUrls ( gpg , pubkeyurls ) :
for url in pubkeyurls :
try :
logger . info ( ' Importing public key from url: ' + url )
rv = gpg . import_keys ( downloadBytes ( url ) )
2024-05-20 14:29:14 +00:00
for key in rv . fingerprints :
gpg . trust_keys ( key , ' TRUST_FULLY ' )
2022-11-07 20:31:10 +00:00
break
except Exception as e :
logging . warning ( ' Import from url failed: %s ' , str ( e ) )
2022-03-23 22:00:35 +00:00
def testTorConnection ( ) :
test_url = ' https://check.torproject.org/ '
logger . info ( ' Testing TOR connection at: ' + test_url )
test_response = downloadBytes ( test_url ) . decode ( ' utf-8 ' )
2022-07-31 18:01:49 +00:00
assert ( ' Congratulations. This browser is configured to use Tor. ' in test_response )
2022-03-23 22:00:35 +00:00
logger . info ( ' TOR is working. ' )
def testOnionLink ( ) :
test_url = ' http://jqyzxhjk6psc6ul5jnfwloamhtyh7si74b4743k2qgpskwwxrzhsxmad.onion '
logger . info ( ' Testing onion site: ' + test_url )
test_response = downloadBytes ( test_url ) . decode ( ' utf-8 ' )
2022-07-31 18:01:49 +00:00
assert ( ' The Tor Project \' s free software protects your privacy online. ' in test_response )
2022-03-23 22:00:35 +00:00
logger . info ( ' Onion links work. ' )
2019-07-21 18:50:32 +00:00
2023-01-04 11:45:16 +00:00
def havePubkey ( gpg , key_id ) :
for key in gpg . list_keys ( ) :
if key [ ' keyid ' ] == key_id :
return True
return False
2022-08-10 22:02:36 +00:00
def downloadPIVXParams ( output_dir ) :
# util/fetch-params.sh
if os . path . exists ( output_dir ) :
logger . info ( f ' Skipping PIVX params download, path exists: { output_dir } ' )
return
os . makedirs ( output_dir )
source_url = ' https://download.z.cash/downloads/ '
files = {
' sapling-spend.params ' : ' 8e48ffd23abb3a5fd9c5589204f32d9c31285a04b78096ba40a79b75677efc13 ' ,
' sapling-output.params ' : ' 2f0ebbcbb9bb0bcffe95a397e7eba89c29eb4dde6191c339db88570e3f3fb0e4 ' ,
}
try :
setConnectionParameters ( )
for k , v in files . items ( ) :
url = urllib . parse . urljoin ( source_url , k )
path = os . path . join ( output_dir , k )
downloadFile ( url , path )
hasher = hashlib . sha256 ( )
with open ( path , ' rb ' ) as fp :
hasher . update ( fp . read ( ) )
file_hash = hasher . hexdigest ( )
logger . info ( ' %s hash: %s ' , k , file_hash )
assert file_hash == v
finally :
popConnectionParameters ( )
2022-07-17 20:34:39 +00:00
def isValidSignature ( result ) :
2022-06-05 09:38:14 +00:00
if result . valid is False \
2022-07-17 20:34:39 +00:00
and ( result . status == ' signature valid ' and result . key_status == ' signing key has expired ' ) :
return True
return result . valid
def ensureValidSignatureBy ( result , signing_key_name ) :
if not isValidSignature ( result ) :
2022-06-05 09:38:14 +00:00
raise ValueError ( ' Signature verification failed. ' )
if result . key_id not in expected_key_ids [ signing_key_name ] :
raise ValueError ( ' Signature made by unexpected keyid: ' + result . key_id )
2022-06-04 20:41:24 +00:00
def extractCore ( coin , version_data , settings , bin_dir , release_path , extra_opts = { } ) :
2022-03-27 11:05:53 +00:00
version , version_tag , signers = version_data
2021-04-16 21:25:13 +00:00
logger . info ( ' extractCore %s v %s %s ' , coin , version , version_tag )
2022-06-04 20:41:24 +00:00
extract_core_overwrite = extra_opts . get ( ' extract_core_overwrite ' , True )
2020-09-11 14:49:01 +00:00
2024-03-31 22:47:14 +00:00
if coin in ( ' monero ' , ' firo ' , ' wownero ' ) :
if coin in ( ' monero ' , ' wownero ' ) :
bins = [ coin + ' d ' , coin + ' -wallet-rpc ' ]
2022-11-07 20:31:10 +00:00
elif coin == ' firo ' :
bins = [ coin + ' d ' , coin + ' -cli ' , coin + ' -tx ' ]
else :
raise ValueError ( ' Unknown coin ' )
2022-12-02 23:07:41 +00:00
if ' win32 ' in BIN_ARCH or ' win64 ' in BIN_ARCH :
with zipfile . ZipFile ( release_path ) as fz :
namelist = fz . namelist ( )
for b in bins :
b + = ' .exe '
out_path = os . path . join ( bin_dir , b )
if ( not os . path . exists ( out_path ) ) or extract_core_overwrite :
for entry in namelist :
if entry . endswith ( b ) :
with open ( out_path , ' wb ' ) as fout :
fout . write ( fz . read ( entry ) )
try :
os . chmod ( out_path , stat . S_IRWXU | stat . S_IXGRP | stat . S_IXOTH )
except Exception as e :
logging . warning ( ' Unable to set file permissions: %s , for %s ' , str ( e ) , out_path )
break
return
2021-01-10 18:30:07 +00:00
num_exist = 0
for b in bins :
out_path = os . path . join ( bin_dir , b )
if os . path . exists ( out_path ) :
num_exist + = 1
if not extract_core_overwrite and num_exist == len ( bins ) :
logger . info ( ' Skipping extract, files exist. ' )
return
2020-11-30 17:07:55 +00:00
with tarfile . open ( release_path ) as ft :
for member in ft . getmembers ( ) :
if member . isdir ( ) :
continue
2021-01-10 18:30:07 +00:00
bin_name = os . path . basename ( member . name )
if bin_name not in bins :
continue
out_path = os . path . join ( bin_dir , bin_name )
if ( not os . path . exists ( out_path ) ) or extract_core_overwrite :
2021-02-16 21:41:07 +00:00
with open ( out_path , ' wb ' ) as fout , ft . extractfile ( member ) as fi :
2021-01-10 18:30:07 +00:00
fout . write ( fi . read ( ) )
2021-02-16 21:41:07 +00:00
try :
os . chmod ( out_path , stat . S_IRWXU | stat . S_IXGRP | stat . S_IXOTH )
except Exception as e :
logging . warning ( ' Unable to set file permissions: %s , for %s ' , str ( e ) , out_path )
2020-11-30 17:07:55 +00:00
return
2022-10-20 20:23:25 +00:00
dir_name = ' dashcore ' if coin == ' dash ' else coin
2024-04-09 21:33:44 +00:00
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 )
2020-09-11 14:49:01 +00:00
if ' win32 ' in BIN_ARCH or ' win64 ' in BIN_ARCH :
with zipfile . ZipFile ( release_path ) as fz :
for b in bins :
b + = ' .exe '
out_path = os . path . join ( bin_dir , b )
2021-01-10 18:30:07 +00:00
if ( not os . path . exists ( out_path ) ) or extract_core_overwrite :
with open ( out_path , ' wb ' ) as fout :
2024-04-09 21:33:44 +00:00
fout . write ( fz . read ( get_archive_path ( b ) ) )
2021-02-16 21:41:07 +00:00
try :
os . chmod ( out_path , stat . S_IRWXU | stat . S_IXGRP | stat . S_IXOTH )
except Exception as e :
logging . warning ( ' Unable to set file permissions: %s , for %s ' , str ( e ) , out_path )
2020-09-11 14:49:01 +00:00
else :
with tarfile . open ( release_path ) as ft :
for b in bins :
out_path = os . path . join ( bin_dir , b )
2021-01-10 18:30:07 +00:00
if not os . path . exists ( out_path ) or extract_core_overwrite :
2024-04-09 21:33:44 +00:00
with open ( out_path , ' wb ' ) as fout , ft . extractfile ( get_archive_path ( b ) ) as fi :
2021-01-10 18:30:07 +00:00
fout . write ( fi . read ( ) )
2021-02-16 21:41:07 +00:00
try :
os . chmod ( out_path , stat . S_IRWXU | stat . S_IXGRP | stat . S_IXOTH )
except Exception as e :
logging . warning ( ' Unable to set file permissions: %s , for %s ' , str ( e ) , out_path )
2020-09-11 14:49:01 +00:00
2022-06-04 20:41:24 +00:00
def prepareCore ( coin , version_data , settings , data_dir , extra_opts = { } ) :
2022-03-27 11:05:53 +00:00
version , version_tag , signers = version_data
2021-04-16 21:25:13 +00:00
logger . info ( ' prepareCore %s v %s %s ' , coin , version , version_tag )
2019-07-21 18:50:32 +00:00
2019-10-05 09:20:46 +00:00
bin_dir = os . path . expanduser ( settings [ ' chainclients ' ] [ coin ] [ ' bindir ' ] )
2019-07-21 18:50:32 +00:00
if not os . path . exists ( bin_dir ) :
os . makedirs ( bin_dir )
2022-06-03 19:31:07 +00:00
filename_extra = ' '
2019-07-21 18:50:32 +00:00
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 '
2022-06-03 19:31:07 +00:00
if coin == ' particl ' :
filename_extra = PARTICL_LINUX_EXTRA
2019-07-21 18:50:32 +00:00
2022-06-05 09:38:14 +00:00
signing_key_name = signers [ 0 ]
2020-11-07 11:08:07 +00:00
if coin == ' monero ' :
2021-01-10 18:30:07 +00:00
use_file_ext = ' tar.bz2 ' if FILE_EXT == ' tar.gz ' else FILE_EXT
release_filename = ' {} - {} - {} . {} ' . format ( coin , version , BIN_ARCH , use_file_ext )
2020-12-30 21:01:21 +00:00
if os_name == ' osx ' :
os_name = ' mac '
2024-02-08 10:01:25 +00:00
architecture = ' x64 '
if ' aarch64 ' in BIN_ARCH :
architecture = ' armv8 '
elif ' arm ' in BIN_ARCH :
architecture = ' armv7 '
release_url = ' https://downloads.getmonero.org/cli/monero- {} - {} -v {} . {} ' . format ( os_name , architecture , version , use_file_ext )
2020-11-07 11:08:07 +00:00
release_path = os . path . join ( bin_dir , release_filename )
if not os . path . exists ( release_path ) :
downloadFile ( release_url , release_path )
2020-11-30 17:07:55 +00:00
assert_filename = ' monero- {} -hashes.txt ' . format ( version )
2020-12-27 12:09:06 +00:00
# assert_url = 'https://www.getmonero.org/downloads/hashes.txt'
assert_url = ' https://raw.githubusercontent.com/monero-project/monero-site/ {} /downloads/hashes.txt ' . format ( XMR_SITE_COMMIT )
2020-11-30 17:07:55 +00:00
assert_path = os . path . join ( bin_dir , assert_filename )
if not os . path . exists ( assert_path ) :
downloadFile ( assert_url , assert_path )
2024-03-31 22:47:14 +00:00
elif coin == ' wownero ' :
use_file_ext = ' tar.bz2 ' if FILE_EXT == ' tar.gz ' else FILE_EXT
release_filename = ' {} - {} - {} . {} ' . format ( coin , version , BIN_ARCH , use_file_ext )
if os_name == ' osx ' :
os_name = ' mac '
architecture = ' x64 '
release_url = ' https://git.wownero.com/attachments/280753b0-3af0-4a78-a248-8b925e8f4593 '
if ' aarch64 ' in BIN_ARCH :
architecture = ' armv8 '
release_url = ' https://git.wownero.com/attachments/0869ffe3-eeff-4240-a185-168ca80fa1e3 '
elif ' arm ' in BIN_ARCH :
architecture = ' armv7 ' # 32bit doesn't work
release_url = ' https://git.wownero.com/attachments/ff0c4886-3865-4670-9bc6-63dd60ded0e3 '
2024-06-05 16:03:29 +00:00
elif ' osx64 ' in BIN_ARCH :
release_url = ' https://git.wownero.com/attachments/7e3fd17c-1bcd-442c-b82d-92a00cccffb8 '
elif ' win64 ' in BIN_ARCH :
release_url = ' https://git.wownero.com/attachments/a1cf8611-1727-4b49-a8e5-1c66fe4f72a3 '
elif ' win32 ' in BIN_ARCH :
release_url = ' https://git.wownero.com/attachments/007d606d-56e0-4c8a-92c1-d0974a781e80 '
2024-03-31 22:47:14 +00:00
release_path = os . path . join ( bin_dir , release_filename )
if not os . path . exists ( release_path ) :
downloadFile ( release_url , release_path )
assert_filename = ' wownero- {} -hashes.txt ' . format ( version )
assert_url = ' https://git.wownero.com/wownero/wownero.org-website/raw/commit/ {} /hashes.txt ' . format ( WOW_SITE_COMMIT )
assert_path = os . path . join ( bin_dir , assert_filename )
if not os . path . exists ( assert_path ) :
downloadFile ( assert_url , assert_path )
2024-04-09 21:33:44 +00:00
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 )
2024-03-31 22:47:14 +00:00
2024-04-09 21:33:44 +00:00
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 )
2019-07-21 18:50:32 +00:00
else :
2022-03-27 11:05:53 +00:00
major_version = int ( version . split ( ' . ' ) [ 0 ] )
2023-12-22 15:31:05 +00:00
use_guix : bool = coin in ( ' dash ' , ) or major_version > = 22
2022-11-12 16:22:44 +00:00
arch_name = BIN_ARCH
2023-12-22 15:31:05 +00:00
if os_name == ' osx ' and use_guix :
arch_name = ' x86_64-apple-darwin '
if coin == ' particl ' :
arch_name + = ' 18 '
2022-11-12 16:22:44 +00:00
release_filename = ' {} - {} - {} . {} ' . format ( coin , version + version_tag , arch_name , FILE_EXT )
if filename_extra != ' ' :
2023-12-22 15:31:05 +00:00
if use_guix :
2022-11-12 16:22:44 +00:00
release_filename = ' {} - {} _ {} - {} . {} ' . format ( coin , version + version_tag , filename_extra , arch_name , FILE_EXT )
else :
release_filename = ' {} - {} - {} _ {} . {} ' . format ( coin , version + version_tag , arch_name , filename_extra , FILE_EXT )
2020-11-30 17:07:55 +00:00
if coin == ' particl ' :
2021-10-15 18:26:37 +00:00
release_url = ' https://github.com/particl/particl-core/releases/download/v {} / {} ' . format ( version + version_tag , release_filename )
2020-11-30 17:07:55 +00:00
assert_filename = ' {} - {} - {} -build.assert ' . format ( coin , os_name , version )
2023-12-22 15:31:05 +00:00
if use_guix :
2022-11-12 16:22:44 +00:00
assert_url = f ' https://raw.githubusercontent.com/particl/guix.sigs/master/ { version } / { signing_key_name } /all.SHA256SUMS '
else :
assert_url = ' https://raw.githubusercontent.com/particl/gitian.sigs/master/ %s - %s / %s / %s ' % ( version + version_tag , os_dir_name , signing_key_name , assert_filename )
2020-11-30 17:07:55 +00:00
elif coin == ' litecoin ' :
2024-02-05 16:34:39 +00:00
release_url = ' https://github.com/litecoin-project/litecoin/releases/download/v {} / {} ' . format ( version + version_tag , release_filename )
2023-12-29 13:36:00 +00:00
assert_filename = ' {} -core- {} - {} -build.assert ' . format ( coin , os_name , ' . ' . join ( version . split ( ' . ' ) [ : 2 ] ) )
2024-05-04 16:39:28 +00:00
assert_url = ' https://raw.githubusercontent.com/litecoin-project/gitian.sigs.ltc/master/ %s - %s / %s / %s ' % ( version , os_dir_name , signing_key_name , assert_filename )
2020-11-30 17:07:55 +00:00
elif coin == ' bitcoin ' :
release_url = ' https://bitcoincore.org/bin/bitcoin-core- {} / {} ' . format ( version , release_filename )
assert_filename = ' {} -core- {} - {} -build.assert ' . format ( coin , os_name , ' . ' . join ( version . split ( ' . ' ) [ : 2 ] ) )
2023-12-22 15:31:05 +00:00
if use_guix :
2022-03-27 11:05:53 +00:00
assert_url = f ' https://raw.githubusercontent.com/bitcoin-core/guix.sigs/main/ { version } / { signing_key_name } /all.SHA256SUMS '
else :
assert_url = ' https://raw.githubusercontent.com/bitcoin-core/gitian.sigs/master/ %s - %s / %s / %s ' % ( version , os_dir_name , signing_key_name , assert_filename )
2020-11-30 17:07:55 +00:00
elif coin == ' namecoin ' :
release_url = ' https://beta.namecoin.org/files/namecoin-core/namecoin-core- {} / {} ' . format ( version , release_filename )
assert_filename = ' {} - {} - {} -build.assert ' . format ( coin , os_name , version . rsplit ( ' . ' , 1 ) [ 0 ] )
assert_url = ' https://raw.githubusercontent.com/namecoin/gitian.sigs/master/ %s - %s / %s / %s ' % ( version , os_dir_name , signing_key_name , assert_filename )
2022-08-10 22:02:36 +00:00
elif coin == ' pivx ' :
2022-11-12 16:22:44 +00:00
release_filename = ' {} - {} - {} . {} ' . format ( coin , version , BIN_ARCH , FILE_EXT )
2023-01-11 08:22:22 +00:00
release_url = ' https://github.com/PIVX-Project/PIVX/releases/download/v {} / {} ' . format ( version + version_tag , release_filename )
assert_filename = ' {} - {} - {} -build.assert ' . format ( coin , os_name , version . rsplit ( ' . ' , 1 ) [ 0 ] )
assert_url = ' https://raw.githubusercontent.com/PIVX-Project/gitian.sigs/master/ %s - %s / %s / %s ' % ( version + version_tag , os_dir_name , signing_key_name . capitalize ( ) , assert_filename )
2022-10-20 20:23:25 +00:00
elif coin == ' dash ' :
2023-12-22 15:31:05 +00:00
release_filename = ' {} - {} - {} . {} ' . format ( ' dashcore ' , version + version_tag , arch_name , FILE_EXT )
2022-10-20 20:23:25 +00:00
release_url = ' https://github.com/dashpay/dash/releases/download/v {} / {} ' . format ( version + version_tag , release_filename )
2023-12-22 15:31:05 +00:00
assert_filename = ' {} - {} - {} -build.assert ' . format ( coin , arch_name , major_version )
2023-12-18 13:15:16 +00:00
assert_url = f ' https://raw.githubusercontent.com/dashpay/guix.sigs/master/ { version } / { signing_key_name } /codesigned.SHA256SUMS '
2022-11-07 20:31:10 +00:00
elif coin == ' firo ' :
2023-11-27 17:01:33 +00:00
arch_name = BIN_ARCH
2022-11-07 20:31:10 +00:00
if BIN_ARCH == ' x86_64-linux-gnu ' :
arch_name = ' linux64 '
2023-12-24 19:12:53 +00:00
elif BIN_ARCH == ' osx64 ' :
arch_name = ' macos '
2023-11-27 17:01:33 +00:00
release_filename = ' {} - {} - {} {} . {} ' . format ( ' firo ' , version + version_tag , arch_name , filename_extra , FILE_EXT )
release_url = ' https://github.com/firoorg/firo/releases/download/v {} / {} ' . format ( version + version_tag , release_filename )
2023-11-24 22:55:41 +00:00
assert_url = ' https://github.com/firoorg/firo/releases/download/v %s /SHA256SUMS ' % ( version + version_tag )
2023-08-29 21:08:28 +00:00
elif coin == ' navcoin ' :
release_filename = ' {} - {} - {} . {} ' . format ( coin , version , BIN_ARCH , FILE_EXT )
release_url = ' https://github.com/navcoin/navcoin-core/releases/download/ {} / {} ' . format ( version + version_tag , release_filename )
assert_filename = ' SHA256SUM_7.0.3.asc '
assert_sig_filename = ' SHA256SUM_7.0.3.asc.sig '
assert_url = ' https://github.com/navcoin/navcoin-core/releases/download/ {} / {} ' . format ( version + version_tag , assert_filename )
2020-11-30 17:07:55 +00:00
else :
raise ValueError ( ' Unknown coin ' )
2019-07-21 18:50:32 +00:00
2020-11-30 17:07:55 +00:00
release_path = os . path . join ( bin_dir , release_filename )
if not os . path . exists ( release_path ) :
downloadFile ( release_url , release_path )
2019-07-21 18:50:32 +00:00
2020-11-30 17:07:55 +00:00
# Rename assert files with full version
2022-03-27 11:05:53 +00:00
assert_filename = ' {} - {} - {} -build- {} .assert ' . format ( coin , os_name , version , signing_key_name )
2020-11-30 17:07:55 +00:00
assert_path = os . path . join ( bin_dir , assert_filename )
if not os . path . exists ( assert_path ) :
downloadFile ( assert_url , assert_path )
2019-07-21 18:50:32 +00:00
2022-11-07 20:31:10 +00:00
if coin not in ( ' firo ' , ) :
2023-12-18 13:15:16 +00:00
assert_sig_url = assert_url + ( ' .asc ' if use_guix else ' .sig ' )
2023-08-29 21:08:28 +00:00
if coin not in ( ' nav ' , ) :
assert_sig_filename = ' {} - {} - {} -build- {} .assert.sig ' . format ( coin , os_name , version , signing_key_name )
2022-11-07 20:31:10 +00:00
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 )
2019-07-21 18:50:32 +00:00
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. ' )
2023-11-27 17:01:33 +00:00
if SKIP_GPG_VALIDATION :
logger . warning ( ' Skipping binary signature check as SKIP_GPG_VALIDATION env var is set. ' )
extractCore ( coin , version_data , settings , bin_dir , release_path , extra_opts )
return
2019-07-21 18:50:32 +00:00
"""
gnupghome = os . path . join ( data_dir , ' gpg ' )
if not os . path . exists ( gnupghome ) :
os . makedirs ( gnupghome )
"""
gpg = gnupg . GPG ( )
2022-07-17 20:34:39 +00:00
keysdirpath = extra_opts . get ( ' keysdirpath ' , None )
if keysdirpath is not None :
logger . info ( f ' Loading PGP keys from: { keysdirpath } . ' )
for path in os . scandir ( keysdirpath ) :
if path . is_file ( ) :
with open ( path , ' rb ' ) as fp :
rv = gpg . import_keys ( fp . read ( ) )
for key in rv . fingerprints :
gpg . trust_keys ( rv . fingerprints [ 0 ] , ' TRUST_FULLY ' )
2023-11-27 17:01:33 +00:00
if coin in ( ' navcoin ' , ) :
2023-08-29 21:08:28 +00:00
pubkey_filename = ' {} _builder.pgp ' . format ( coin )
2024-05-20 14:29:14 +00:00
elif coin in ( ' decred ' , ) :
pubkey_filename = ' {} _release.pgp ' . format ( coin )
2022-11-07 20:31:10 +00:00
else :
pubkey_filename = ' {} _ {} .pgp ' . format ( coin , signing_key_name )
pubkeyurls = [
2024-06-11 07:56:09 +00:00
' https://raw.githubusercontent.com/basicswap/basicswap/master/pgp/keys/ ' + pubkey_filename ,
2022-11-07 20:31:10 +00:00
' https://gitlab.com/particl/basicswap/-/raw/master/pgp/keys/ ' + pubkey_filename ,
]
if coin == ' dash ' :
pubkeyurls . append ( ' https://raw.githubusercontent.com/dashpay/dash/master/contrib/gitian-keys/pasta.pgp ' )
2020-11-30 17:07:55 +00:00
if coin == ' monero ' :
2022-11-07 20:31:10 +00:00
pubkeyurls . append ( ' https://raw.githubusercontent.com/monero-project/monero/master/utils/gpg_keys/binaryfate.asc ' )
2024-03-31 22:47:14 +00:00
if coin == ' wownero ' :
pubkeyurls . append ( ' https://git.wownero.com/wownero/wownero/raw/branch/master/utils/gpg_keys/wowario.asc ' )
2022-11-07 20:31:10 +00:00
if coin == ' firo ' :
pubkeyurls . append ( ' https://firo.org/reuben.asc ' )
2023-08-29 21:08:28 +00:00
if ADD_PUBKEY_URL != ' ' :
pubkeyurls . append ( ADD_PUBKEY_URL + ' / ' + pubkey_filename )
2024-03-31 22:47:14 +00:00
if coin in ( ' monero ' , ' wownero ' , ' firo ' ) :
2020-11-30 17:07:55 +00:00
with open ( assert_path , ' rb ' ) as fp :
verified = gpg . verify_file ( fp )
2022-07-17 20:34:39 +00:00
if not isValidSignature ( verified ) and verified . username is None :
2022-06-05 09:38:14 +00:00
logger . warning ( ' Signature made by unknown key. ' )
2022-11-07 20:31:10 +00:00
importPubkeyFromUrls ( gpg , pubkeyurls )
2020-11-30 17:07:55 +00:00
with open ( assert_path , ' rb ' ) as fp :
verified = gpg . verify_file ( fp )
2023-08-29 21:08:28 +00:00
elif coin in ( ' navcoin ' ) :
with open ( assert_sig_path , ' rb ' ) as fp :
verified = gpg . verify_file ( fp )
if not isValidSignature ( verified ) and verified . username is None :
logger . warning ( ' Signature made by unknown key. ' )
importPubkeyFromUrls ( gpg , pubkeyurls )
with open ( assert_sig_path , ' rb ' ) as fp :
verified = gpg . verify_file ( fp )
# .sig file is not a detached signature, recheck release hash in decrypted data
logger . warning ( ' Double checking Navcoin release hash. ' )
with open ( assert_sig_path , ' rb ' ) as fp :
decrypted = gpg . decrypt_file ( fp )
assert ( release_hash . hex ( ) in str ( decrypted ) )
2020-11-30 17:07:55 +00:00
else :
with open ( assert_sig_path , ' rb ' ) as fp :
verified = gpg . verify_file ( fp , assert_path )
2019-07-21 18:50:32 +00:00
2022-07-17 20:34:39 +00:00
if not isValidSignature ( verified ) and verified . username is None :
2022-06-05 09:38:14 +00:00
logger . warning ( ' Signature made by unknown key. ' )
2022-11-07 20:31:10 +00:00
importPubkeyFromUrls ( gpg , pubkeyurls )
2020-11-30 17:07:55 +00:00
with open ( assert_sig_path , ' rb ' ) as fp :
verified = gpg . verify_file ( fp , assert_path )
2019-07-25 10:45:27 +00:00
2022-06-05 09:38:14 +00:00
ensureValidSignatureBy ( verified , signing_key_name )
2019-07-21 18:50:32 +00:00
2022-06-04 20:41:24 +00:00
extractCore ( coin , version_data , settings , bin_dir , release_path , extra_opts )
2019-07-21 18:50:32 +00:00
2022-03-26 22:08:15 +00:00
def writeTorSettings ( fp , coin , coin_settings , tor_control_password ) :
2022-03-27 09:28:17 +00:00
'''
TOR_PROXY_HOST must be an ip address .
BTC versions > 21 and Particl with lookuptorcontrolhost = any can accept hostnames , XMR and LTC cannot
'''
2022-03-26 22:08:15 +00:00
fp . write ( f ' proxy= { TOR_PROXY_HOST } : { TOR_PROXY_PORT } \n ' )
2024-05-25 09:22:12 +00:00
if coin in ( ' decred ' , ) :
return
onionport = coin_settings [ ' onionport ' ]
2022-03-27 09:28:17 +00:00
fp . write ( f ' torpassword= { tor_control_password } \n ' )
fp . write ( f ' torcontrol= { TOR_PROXY_HOST } : { TOR_CONTROL_PORT } \n ' )
2022-03-26 22:08:15 +00:00
2022-07-15 14:38:05 +00:00
if coin_settings [ ' core_version_group ' ] > = 21 :
2022-03-26 22:08:15 +00:00
fp . write ( f ' bind=0.0.0.0: { onionport } =onion \n ' )
2022-07-15 14:38:05 +00:00
else :
fp . write ( f ' bind=0.0.0.0: { onionport } \n ' )
2022-03-26 22:08:15 +00:00
2022-06-04 20:41:24 +00:00
def prepareDataDir ( coin , settings , chain , particl_mnemonic , extra_opts = { } ) :
2019-07-24 18:57:31 +00:00
core_settings = settings [ ' chainclients ' ] [ coin ]
2021-01-16 21:01:23 +00:00
bin_dir = core_settings [ ' bindir ' ]
2019-07-24 18:57:31 +00:00
data_dir = core_settings [ ' datadir ' ]
2022-06-04 20:41:24 +00:00
tor_control_password = extra_opts . get ( ' tor_control_password ' , None )
2019-07-24 18:57:31 +00:00
if not os . path . exists ( data_dir ) :
os . makedirs ( data_dir )
2024-03-31 22:47:14 +00:00
if coin in ( ' wownero ' , ' monero ' ) :
2020-12-03 23:46:01 +00:00
core_conf_path = os . path . join ( data_dir , coin + ' d.conf ' )
if os . path . exists ( core_conf_path ) :
exitWithError ( ' {} exists ' . format ( core_conf_path ) )
with open ( core_conf_path , ' w ' ) as fp :
if chain == ' regtest ' :
fp . write ( ' regtest=1 \n ' )
fp . write ( ' keep-fakechain=1 \n ' )
fp . write ( ' fixed-difficulty=1 \n ' )
2021-01-10 18:30:07 +00:00
else :
fp . write ( ' bootstrap-daemon-address=auto \n ' )
fp . write ( ' restricted-rpc=1 \n ' )
if chain == ' testnet ' :
2020-12-03 23:46:01 +00:00
fp . write ( ' testnet=1 \n ' )
2022-07-11 21:36:28 +00:00
config_datadir = data_dir
2022-12-27 18:35:42 +00:00
if extra_opts . get ( ' use_containers ' , False ) is True :
2022-07-11 21:36:28 +00:00
config_datadir = ' /data '
fp . write ( f ' data-dir= { config_datadir } \n ' )
2020-12-03 23:46:01 +00:00
fp . write ( ' rpc-bind-port= {} \n ' . format ( core_settings [ ' rpcport ' ] ) )
2022-03-23 22:00:35 +00:00
fp . write ( ' rpc-bind-ip= {} \n ' . format ( COINS_RPCBIND_IP ) )
2020-12-03 23:46:01 +00:00
fp . write ( ' zmq-rpc-bind-port= {} \n ' . format ( core_settings [ ' zmqport ' ] ) )
2022-03-23 22:00:35 +00:00
fp . write ( ' zmq-rpc-bind-ip= {} \n ' . format ( COINS_RPCBIND_IP ) )
2021-01-10 18:30:07 +00:00
fp . write ( ' prune-blockchain=1 \n ' )
2020-12-03 23:46:01 +00:00
2024-03-31 22:47:14 +00:00
if coin == ' monero ' :
if XMR_RPC_USER != ' ' :
fp . write ( f ' rpc-login= { XMR_RPC_USER } : { XMR_RPC_PWD } \n ' )
if tor_control_password is not None :
for opt_line in monerod_proxy_config :
fp . write ( opt_line + ' \n ' )
2022-03-23 22:00:35 +00:00
2024-03-31 22:47:14 +00:00
if coin == ' wownero ' :
if WOW_RPC_USER != ' ' :
fp . write ( f ' rpc-login= { WOW_RPC_USER } : { WOW_RPC_PWD } \n ' )
if tor_control_password is not None :
for opt_line in wownerod_proxy_config :
fp . write ( opt_line + ' \n ' )
2022-11-28 17:54:41 +00:00
2024-03-31 22:47:14 +00:00
if coin in ( ' wownero ' , ' monero ' ) :
2021-06-28 21:56:45 +00:00
wallets_dir = core_settings . get ( ' walletsdir ' , data_dir )
if not os . path . exists ( wallets_dir ) :
os . makedirs ( wallets_dir )
2024-03-31 22:47:14 +00:00
wallet_conf_path = os . path . join ( wallets_dir , coin + ' -wallet-rpc.conf ' )
if coin == ' monero ' :
wallet_conf_path = os . path . join ( wallets_dir , ' monero_wallet.conf ' )
2020-12-03 23:46:01 +00:00
if os . path . exists ( wallet_conf_path ) :
exitWithError ( ' {} exists ' . format ( wallet_conf_path ) )
with open ( wallet_conf_path , ' w ' ) as fp :
2022-12-27 18:35:42 +00:00
config_datadir = os . path . join ( data_dir , ' wallets ' )
2022-06-04 20:41:24 +00:00
if extra_opts . get ( ' use_containers ' , False ) is True :
2021-11-15 09:34:54 +00:00
fp . write ( ' daemon-address= {} : {} \n ' . format ( core_settings [ ' rpchost ' ] , core_settings [ ' rpcport ' ] ) )
2022-12-27 18:35:42 +00:00
config_datadir = ' /data '
2024-02-07 20:48:34 +00:00
2020-12-03 23:46:01 +00:00
fp . write ( ' no-dns=1 \n ' )
fp . write ( ' rpc-bind-port= {} \n ' . format ( core_settings [ ' walletrpcport ' ] ) )
2022-03-23 22:00:35 +00:00
fp . write ( ' rpc-bind-ip= {} \n ' . format ( COINS_RPCBIND_IP ) )
2022-07-11 21:36:28 +00:00
fp . write ( f ' wallet-dir= { config_datadir } \n ' )
fp . write ( ' log-file= {} \n ' . format ( os . path . join ( config_datadir , ' wallet.log ' ) ) )
2020-12-03 23:46:01 +00:00
fp . write ( ' rpc-login= {} : {} \n ' . format ( core_settings [ ' walletrpcuser ' ] , core_settings [ ' walletrpcpassword ' ] ) )
2024-03-31 22:47:14 +00:00
if coin == ' monero ' :
fp . write ( ' shared-ringdb-dir= {} \n ' . format ( os . path . join ( config_datadir , ' shared-ringdb ' ) ) )
elif coin == ' wownero ' :
fp . write ( ' wow-shared-ringdb-dir= {} \n ' . format ( os . path . join ( config_datadir , ' shared-ringdb ' ) ) )
2022-11-21 13:36:36 +00:00
if chain == ' regtest ' :
fp . write ( ' allow-mismatched-daemon-version=1 \n ' )
2022-03-23 22:00:35 +00:00
if tor_control_password is not None :
if not core_settings [ ' manage_daemon ' ] :
2024-02-08 20:40:14 +00:00
for opt_line in monero_wallet_rpc_proxy_config :
fp . write ( opt_line + ' \n ' )
2020-12-03 23:46:01 +00:00
return
2022-06-04 20:41:24 +00:00
2024-05-20 14:29:14 +00:00
if coin == ' decred ' :
chainname = ' simnet ' if chain == ' regtest ' else chain
core_conf_path = os . path . join ( data_dir , ' dcrd.conf ' )
if os . path . exists ( core_conf_path ) :
exitWithError ( ' {} exists ' . format ( core_conf_path ) )
with open ( core_conf_path , ' w ' ) as fp :
if chain != ' mainnet ' :
fp . write ( chainname + ' =1 \n ' )
2024-05-30 19:23:37 +00:00
fp . write ( ' debuglevel=info \n ' )
2024-05-20 14:29:14 +00:00
fp . write ( ' notls=1 \n ' )
fp . write ( ' rpclisten= {} : {} \n ' . format ( core_settings [ ' rpchost ' ] , core_settings [ ' rpcport ' ] ) )
fp . write ( ' rpcuser= {} \n ' . format ( core_settings [ ' rpcuser ' ] ) )
fp . write ( ' rpcpass= {} \n ' . format ( core_settings [ ' rpcpassword ' ] ) )
2024-05-25 09:22:12 +00:00
if tor_control_password is not None :
writeTorSettings ( fp , coin , core_settings , tor_control_password )
2024-05-20 14:29:14 +00:00
wallet_conf_path = os . path . join ( data_dir , ' dcrwallet.conf ' )
if os . path . exists ( wallet_conf_path ) :
exitWithError ( ' {} exists ' . format ( wallet_conf_path ) )
with open ( wallet_conf_path , ' w ' ) as fp :
if chain != ' mainnet ' :
fp . write ( chainname + ' =1 \n ' )
2024-05-30 19:23:37 +00:00
fp . write ( ' debuglevel=info \n ' )
2024-05-20 14:29:14 +00:00
fp . write ( ' noservertls=1 \n ' )
fp . write ( ' noclienttls=1 \n ' )
fp . write ( ' rpcconnect= {} : {} \n ' . format ( core_settings [ ' rpchost ' ] , core_settings [ ' rpcport ' ] ) )
fp . write ( ' rpclisten= {} : {} \n ' . format ( core_settings [ ' walletrpchost ' ] , core_settings [ ' walletrpcport ' ] ) )
fp . write ( ' username= {} \n ' . format ( core_settings [ ' rpcuser ' ] ) )
fp . write ( ' password= {} \n ' . format ( core_settings [ ' rpcpassword ' ] ) )
return
2019-07-24 18:57:31 +00:00
core_conf_path = os . path . join ( data_dir , coin + ' .conf ' )
if os . path . exists ( core_conf_path ) :
exitWithError ( ' {} exists ' . format ( core_conf_path ) )
with open ( core_conf_path , ' w ' ) as fp :
if chain != ' mainnet ' :
2023-08-29 21:08:28 +00:00
if coin in ( ' navcoin ' , ) :
chainname = ' devnet ' if chain == ' regtest ' else chain
fp . write ( chainname + ' =1 \n ' )
else :
fp . write ( chain + ' =1 \n ' )
if coin not in ( ' firo ' , ' navcoin ' ) :
2022-11-07 20:31:10 +00:00
if chain == ' testnet ' :
fp . write ( ' [test] \n \n ' )
elif chain == ' regtest ' :
fp . write ( ' [regtest] \n \n ' )
else :
logger . warning ( ' Unknown chain %s ' , chain )
2019-07-24 18:57:31 +00:00
2022-03-23 22:00:35 +00:00
if COINS_RPCBIND_IP != ' 127.0.0.1 ' :
2021-06-28 21:56:45 +00:00
fp . write ( ' rpcallowip=127.0.0.1 \n ' )
fp . write ( ' rpcallowip=172.0.0.0/8 \n ' ) # Allow 172.x.x.x, range used by docker
2022-03-23 22:00:35 +00:00
fp . write ( ' rpcbind= {} \n ' . format ( COINS_RPCBIND_IP ) )
2021-06-28 21:56:45 +00:00
2019-07-24 18:57:31 +00:00
fp . write ( ' rpcport= {} \n ' . format ( core_settings [ ' rpcport ' ] ) )
fp . write ( ' printtoconsole=0 \n ' )
fp . write ( ' daemon=0 \n ' )
2021-01-16 21:01:23 +00:00
fp . write ( ' wallet=wallet.dat \n ' )
2019-07-24 18:57:31 +00:00
2022-03-23 22:00:35 +00:00
if tor_control_password is not None :
2022-03-26 22:08:15 +00:00
writeTorSettings ( fp , coin , core_settings , tor_control_password )
2022-03-23 22:00:35 +00:00
2021-06-28 21:56:45 +00:00
salt = generate_salt ( 16 )
2019-07-24 18:57:31 +00:00
if coin == ' particl ' :
fp . write ( ' debugexclude=libevent \n ' )
2022-03-23 22:00:35 +00:00
fp . write ( ' zmqpubsmsg=tcp:// {} : {} \n ' . format ( COINS_RPCBIND_IP , settings [ ' zmqport ' ] ) )
2019-08-15 22:31:39 +00:00
fp . write ( ' spentindex=1 \n ' )
fp . write ( ' txindex=1 \n ' )
fp . write ( ' staking=0 \n ' )
2021-06-28 21:56:45 +00:00
if PART_RPC_USER != ' ' :
fp . write ( ' rpcauth= {} : {} $ {} \n ' . format ( PART_RPC_USER , salt , password_to_hmac ( salt , PART_RPC_PWD ) ) )
2019-07-24 18:57:31 +00:00
elif coin == ' litecoin ' :
2022-06-16 21:29:57 +00:00
fp . write ( ' prune=4000 \n ' )
2024-05-04 16:39:28 +00:00
fp . write ( ' blockfilterindex=0 \n ' )
fp . write ( ' peerblockfilters=0 \n ' )
2021-06-28 21:56:45 +00:00
if LTC_RPC_USER != ' ' :
fp . write ( ' rpcauth= {} : {} $ {} \n ' . format ( LTC_RPC_USER , salt , password_to_hmac ( salt , LTC_RPC_PWD ) ) )
2019-07-24 18:57:31 +00:00
elif coin == ' bitcoin ' :
2023-12-31 00:15:31 +00:00
fp . write ( ' deprecatedrpc=create_bdb \n ' )
2021-01-16 21:01:23 +00:00
fp . write ( ' prune=2000 \n ' )
2020-09-11 16:32:33 +00:00
fp . write ( ' fallbackfee=0.0002 \n ' )
2021-06-28 21:56:45 +00:00
if BTC_RPC_USER != ' ' :
fp . write ( ' rpcauth= {} : {} $ {} \n ' . format ( BTC_RPC_USER , salt , password_to_hmac ( salt , BTC_RPC_PWD ) ) )
2019-07-24 18:57:31 +00:00
elif coin == ' namecoin ' :
2021-01-16 21:01:23 +00:00
fp . write ( ' prune=2000 \n ' )
2022-08-10 22:02:36 +00:00
elif coin == ' pivx ' :
2022-11-09 17:10:17 +00:00
params_dir = os . path . join ( data_dir , ' pivx-params ' )
2022-08-10 22:02:36 +00:00
downloadPIVXParams ( params_dir )
2023-01-03 18:03:36 +00:00
PIVX_PARAMSDIR = os . getenv ( ' PIVX_PARAMSDIR ' , ' /data/pivx-params ' if extra_opts . get ( ' use_containers ' , False ) else params_dir )
2022-11-09 17:10:17 +00:00
fp . write ( f ' paramsdir= { PIVX_PARAMSDIR } \n ' )
2022-08-10 22:02:36 +00:00
if PIVX_RPC_USER != ' ' :
fp . write ( ' rpcauth= {} : {} $ {} \n ' . format ( PIVX_RPC_USER , salt , password_to_hmac ( salt , PIVX_RPC_PWD ) ) )
2022-10-20 20:23:25 +00:00
elif coin == ' dash ' :
fp . write ( ' prune=4000 \n ' )
fp . write ( ' fallbackfee=0.0002 \n ' )
if DASH_RPC_USER != ' ' :
fp . write ( ' rpcauth= {} : {} $ {} \n ' . format ( DASH_RPC_USER , salt , password_to_hmac ( salt , DASH_RPC_PWD ) ) )
2022-11-07 20:31:10 +00:00
elif coin == ' firo ' :
fp . write ( ' prune=4000 \n ' )
fp . write ( ' fallbackfee=0.0002 \n ' )
fp . write ( ' txindex=0 \n ' )
fp . write ( ' usehd=1 \n ' )
if FIRO_RPC_USER != ' ' :
fp . write ( ' rpcauth= {} : {} $ {} \n ' . format ( FIRO_RPC_USER , salt , password_to_hmac ( salt , FIRO_RPC_PWD ) ) )
2023-08-29 21:08:28 +00:00
elif coin == ' navcoin ' :
fp . write ( ' prune=4000 \n ' )
fp . write ( ' fallbackfee=0.0002 \n ' )
if NAV_RPC_USER != ' ' :
fp . write ( ' rpcauth= {} : {} $ {} \n ' . format ( NAV_RPC_USER , salt , password_to_hmac ( salt , NAV_RPC_PWD ) ) )
2019-07-24 18:57:31 +00:00
else :
logger . warning ( ' Unknown coin %s ' , coin )
2022-06-04 20:41:24 +00:00
if coin == ' bitcoin ' and extra_opts . get ( ' use_btc_fastsync ' , False ) is True :
logger . info ( ' Initialising BTC chain with fastsync %s ' , BITCOIN_FASTSYNC_FILE )
base_dir = extra_opts [ ' data_dir ' ]
2022-06-05 09:38:14 +00:00
for dirname in ( ' blocks ' , ' chainstate ' ) :
if os . path . exists ( os . path . join ( data_dir , dirname ) ) :
raise ValueError ( f ' { dirname } directory already exists, not overwriting. ' )
2022-06-04 20:41:24 +00:00
sync_file_path = os . path . join ( base_dir , BITCOIN_FASTSYNC_FILE )
if not os . path . exists ( sync_file_path ) :
2022-12-13 22:19:38 +00:00
raise ValueError ( f ' BTC fastsync file not found: { sync_file_path } ' )
2022-06-04 20:41:24 +00:00
2022-12-13 22:19:38 +00:00
# Double check
2023-03-28 13:47:29 +00:00
if extra_opts . get ( ' check_btc_fastsync ' , True ) :
check_btc_fastsync_data ( base_dir , sync_file_path )
2022-06-04 20:41:24 +00:00
with tarfile . open ( sync_file_path ) as ft :
ft . extractall ( path = data_dir )
2021-01-16 21:01:23 +00:00
2019-07-24 18:57:31 +00:00
2022-03-23 22:00:35 +00:00
def write_torrc ( data_dir , tor_control_password ) :
tor_dir = os . path . join ( data_dir , ' tor ' )
if not os . path . exists ( tor_dir ) :
os . makedirs ( tor_dir )
torrc_path = os . path . join ( tor_dir , ' torrc ' )
tor_control_hash = rfc2440_hash_password ( tor_control_password )
with open ( torrc_path , ' w ' ) as fp :
fp . write ( f ' SocksPort 0.0.0.0: { TOR_PROXY_PORT } \n ' )
fp . write ( f ' ControlPort 0.0.0.0: { TOR_CONTROL_PORT } \n ' )
fp . write ( f ' DNSPort 0.0.0.0: { TOR_DNS_PORT } \n ' )
fp . write ( f ' HashedControlPassword { tor_control_hash } \n ' )
def addTorSettings ( settings , tor_control_password ) :
settings [ ' use_tor ' ] = True
settings [ ' tor_proxy_host ' ] = TOR_PROXY_HOST
settings [ ' tor_proxy_port ' ] = TOR_PROXY_PORT
2022-03-26 22:08:15 +00:00
settings [ ' tor_control_password ' ] = tor_control_password
2022-03-23 22:00:35 +00:00
settings [ ' tor_control_port ' ] = TOR_CONTROL_PORT
2024-02-07 20:48:34 +00:00
def modify_tor_config ( settings , coin , tor_control_password = None , enable = False , extra_opts = { } ) :
2022-03-23 22:00:35 +00:00
coin_settings = settings [ ' chainclients ' ] [ coin ]
data_dir = coin_settings [ ' datadir ' ]
2024-03-31 22:47:14 +00:00
if coin in ( ' monero ' , ' wownero ' ) :
2022-03-23 22:00:35 +00:00
core_conf_path = os . path . join ( data_dir , coin + ' d.conf ' )
if not os . path . exists ( core_conf_path ) :
exitWithError ( ' {} does not exist ' . format ( core_conf_path ) )
2024-03-31 22:47:14 +00:00
2022-03-23 22:00:35 +00:00
wallets_dir = coin_settings . get ( ' walletsdir ' , data_dir )
2024-03-31 22:47:14 +00:00
wallet_conf_path = os . path . join ( wallets_dir , coin + ' -wallet-rpc.conf ' )
if coin == ' monero ' :
wallet_conf_path = os . path . join ( wallets_dir , ' monero_wallet.conf ' )
2022-03-23 22:00:35 +00:00
if not os . path . exists ( wallet_conf_path ) :
exitWithError ( ' {} does not exist ' . format ( wallet_conf_path ) )
# Backup
shutil . copyfile ( core_conf_path , core_conf_path + ' .last ' )
shutil . copyfile ( wallet_conf_path , wallet_conf_path + ' .last ' )
with open ( core_conf_path , ' w ' ) as fp :
with open ( core_conf_path + ' .last ' ) as fp_in :
# Disable tor first
for line in fp_in :
2024-02-08 20:40:14 +00:00
skip_line : bool = False
2024-03-31 22:47:14 +00:00
if coin == ' monero ' :
for opt_line in monerod_proxy_config :
setting : str = opt_line [ 0 : opt_line . find ( ' = ' ) + 1 ]
if line . startswith ( setting ) :
skip_line = True
break
if coin == ' wownero ' :
for opt_line in wownerod_proxy_config :
setting : str = opt_line [ 0 : opt_line . find ( ' = ' ) + 1 ]
if line . startswith ( setting ) :
skip_line = True
break
2022-03-23 22:00:35 +00:00
if not skip_line :
fp . write ( line )
if enable :
2024-03-31 22:47:14 +00:00
if coin == ' monero ' :
for opt_line in monerod_proxy_config :
fp . write ( opt_line + ' \n ' )
if coin == ' wownero ' :
for opt_line in wownerod_proxy_config :
fp . write ( opt_line + ' \n ' )
2022-03-23 22:00:35 +00:00
with open ( wallet_conf_path , ' w ' ) as fp :
with open ( wallet_conf_path + ' .last ' ) as fp_in :
# Disable tor first
for line in fp_in :
skip_line = False
2024-02-08 20:40:14 +00:00
for opt_line in monero_wallet_rpc_proxy_config + [ ' proxy= ' , ] :
setting : str = opt_line [ 0 : opt_line . find ( ' = ' ) + 1 ]
2022-03-23 22:00:35 +00:00
if line . startswith ( setting ) :
skip_line = True
break
if not skip_line :
fp . write ( line )
if enable :
if not coin_settings [ ' manage_daemon ' ] :
2024-02-08 20:40:14 +00:00
for opt_line in monero_wallet_rpc_proxy_config :
fp . write ( opt_line + ' \n ' )
2024-02-07 20:48:34 +00:00
2024-02-08 08:43:02 +00:00
coin_settings [ ' trusted_daemon ' ] = extra_opts . get ( ' trust_remote_node ' , ' auto ' )
2022-03-23 22:00:35 +00:00
return
2024-05-25 09:22:12 +00:00
if coin == ' decred ' :
config_path = os . path . join ( data_dir , ' dcrd.conf ' )
else :
config_path = os . path . join ( data_dir , coin + ' .conf ' )
2022-03-23 22:00:35 +00:00
if not os . path . exists ( config_path ) :
exitWithError ( ' {} does not exist ' . format ( config_path ) )
if ' onionport ' not in coin_settings :
default_onionport = 0
if coin == ' bitcoin ' :
default_onionport = BTC_ONION_PORT
elif coin == ' particl ' :
default_onionport = PART_ONION_PORT
elif coin == ' litecoin ' :
default_onionport = LTC_ONION_PORT
2024-05-25 09:22:12 +00:00
elif coin in ( ' decred ' , ) :
pass
2022-03-23 22:00:35 +00:00
else :
exitWithError ( ' Unknown default onion listening port for {} ' . format ( coin ) )
2024-05-25 09:22:12 +00:00
if default_onionport > 0 :
coin_settings [ ' onionport ' ] = default_onionport
2022-03-23 22:00:35 +00:00
# Backup
shutil . copyfile ( config_path , config_path + ' .last ' )
tor_settings = ( ' proxy= ' , ' torpassword= ' , ' torcontrol= ' , ' bind= ' )
with open ( config_path , ' w ' ) as fp :
with open ( config_path + ' .last ' ) as fp_in :
# Disable tor first
for line in fp_in :
skip_line = False
for setting in tor_settings :
if line . startswith ( setting ) :
skip_line = True
break
if not skip_line :
fp . write ( line )
if enable :
2022-03-26 22:08:15 +00:00
writeTorSettings ( fp , coin , coin_settings , tor_control_password )
2022-03-23 22:00:35 +00:00
2019-07-21 18:50:32 +00:00
def printVersion ( ) :
2022-11-22 08:28:02 +00:00
logger . info ( f ' Basicswap version: { __version__ } ' )
2021-01-10 18:30:07 +00:00
logger . info ( ' Core versions: ' )
for coin , version in known_coins . items ( ) :
2023-10-09 14:43:09 +00:00
postfix = ' (Disabled) ' if coin in disabled_coins else ' '
logger . info ( ' \t %s : %s %s %s ' , coin . capitalize ( ) , version [ 0 ] , version [ 1 ] , postfix )
2019-07-21 18:50:32 +00:00
def printHelp ( ) :
2022-11-20 18:58:10 +00:00
print ( ' Usage: basicswap-prepare ' )
print ( ' \n --help, -h Print help. ' )
print ( ' --version, -v Print version. ' )
print ( ' --datadir=PATH Path to basicswap data directory, default: {} . ' . format ( cfg . BASICSWAP_DATADIR ) )
print ( ' --bindir=PATH Path to cores directory, default:datadir/bin. ' )
print ( ' --mainnet Run in mainnet mode. ' )
print ( ' --testnet Run in testnet mode. ' )
print ( ' --regtest Run in regtest mode. ' )
print ( ' --particl_mnemonic= Recovery phrase to use for the Particl wallet, default is randomly generated, \n '
+ ' " auto " to create a wallet automatically - No mnemonic. '
+ ' " none " to disable wallet initialisation. ' )
print ( ' --withcoin= Prepare system to run daemon for coin. ' )
print ( ' --withoutcoin= Do not prepare system to run daemon for coin. ' )
print ( ' --addcoin= Add coin to existing setup. ' )
print ( ' --disablecoin= Make coin inactive. ' )
print ( ' --preparebinonly Don \' t prepare settings or datadirs. ' )
print ( ' --nocores Don \' t download and extract any coin clients. ' )
print ( ' --usecontainers Expect each core to run in a unique container. ' )
print ( ' --portoffset=n Raise all ports by n. ' )
print ( ' --htmlhost= Interface to host html server on, default:127.0.0.1. ' )
2024-02-08 08:53:10 +00:00
print ( ' --wshost= Interface to host websocket server on, disable by setting to " none " , default \' s to --htmlhost. ' )
2022-11-20 18:58:10 +00:00
print ( ' --xmrrestoreheight=n Block height to restore Monero wallet from, default: {} . ' . format ( DEFAULT_XMR_RESTORE_HEIGHT ) )
2024-03-31 22:47:14 +00:00
print ( ' --wowrestoreheight=n Block height to restore Wownero wallet from, default: {} . ' . format ( DEFAULT_WOW_RESTORE_HEIGHT ) )
2024-02-08 08:43:02 +00:00
print ( ' --trustremotenode Set trusted-daemon for XMR, defaults to auto: true when daemon rpchost value is a private ip address else false ' )
2022-11-20 18:58:10 +00:00
print ( ' --noextractover Prevent extracting cores if files exist. Speeds up tests ' )
print ( ' --usetorproxy Use TOR proxy during setup. Note that some download links may be inaccessible over TOR. ' )
2024-02-05 12:16:34 +00:00
print ( ' --notorproxy Force usetorproxy off, usetorproxy is automatically set when tor is enabled ' )
2022-11-20 18:58:10 +00:00
print ( ' --enabletor Setup Basicswap instance to use TOR. ' )
print ( ' --disabletor Setup Basicswap instance to not use TOR. ' )
print ( ' --usebtcfastsync Initialise the BTC chain with a snapshot from btcpayserver FastSync. \n '
+ ' See https://github.com/btcpayserver/btcpayserver-docker/blob/master/contrib/FastSync/README.md ' )
2023-03-28 20:31:32 +00:00
print ( ' --skipbtcfastsyncchecks Use the provided btcfastsync file without checking it \' s size or signature. ' )
2022-11-20 18:58:10 +00:00
print ( ' --initwalletsonly Setup coin wallets only. ' )
print ( ' --keysdirpath Speed up tests by preloading all PGP keys in directory. ' )
2023-10-09 14:43:09 +00:00
active_coins = [ ]
for coin_name in known_coins . keys ( ) :
if coin_name not in disabled_coins :
active_coins . append ( coin_name )
print ( ' \n ' + ' Known coins: {} ' . format ( ' , ' . join ( active_coins ) ) )
2019-07-21 18:50:32 +00:00
2022-06-18 17:28:40 +00:00
def finalise_daemon ( d ) :
2024-05-05 12:43:26 +00:00
logging . info ( ' Interrupting {} ' . format ( d . handle . pid ) )
2022-12-02 23:07:41 +00:00
try :
2024-05-05 12:43:26 +00:00
d . handle . send_signal ( signal . CTRL_C_EVENT if os . name == ' nt ' else signal . SIGINT )
d . handle . wait ( timeout = 120 )
2022-12-02 23:07:41 +00:00
except Exception as e :
2024-05-06 22:20:22 +00:00
logging . info ( f ' Error { e } for process { d . handle . pid } ' )
2024-05-05 12:43:26 +00:00
for fp in [ d . handle . stdout , d . handle . stderr , d . handle . stdin ] + d . files :
2022-06-18 17:28:40 +00:00
if fp :
fp . close ( )
2022-11-16 22:36:13 +00:00
def test_particl_encryption ( data_dir , settings , chain , use_tor_proxy ) :
swap_client = None
daemons = [ ]
daemon_args = [ ' -noconnect ' , ' -nodnsseed ' , ' -nofindpeers ' , ' -nostaking ' ]
with open ( os . path . join ( data_dir , ' basicswap.log ' ) , ' a ' ) as fp :
try :
2024-02-08 20:58:56 +00:00
swap_client = BasicSwap ( fp , data_dir , settings , chain , transient_instance = True )
2024-02-05 17:06:07 +00:00
if not swap_client . use_tor_proxy :
# Cannot set -bind or -whitebind together with -listen=0
daemon_args . append ( ' -nolisten ' )
2022-11-16 22:36:13 +00:00
c = Coins . PART
coin_name = ' particl '
coin_settings = settings [ ' chainclients ' ] [ coin_name ]
if coin_settings [ ' manage_daemon ' ] :
filename = coin_name + ' d ' + ( ' .exe ' if os . name == ' nt ' else ' ' )
daemons . append ( startDaemon ( coin_settings [ ' datadir ' ] , coin_settings [ ' bindir ' ] , filename , daemon_args ) )
2024-05-05 12:43:26 +00:00
swap_client . setDaemonPID ( c , daemons [ - 1 ] . handle . pid )
2022-11-16 22:36:13 +00:00
swap_client . setCoinRunParams ( c )
swap_client . createCoinInterface ( c )
2022-12-08 01:13:39 +00:00
swap_client . waitForDaemonRPC ( c , with_wallet = True )
2022-11-16 22:36:13 +00:00
if swap_client . ci ( c ) . isWalletEncrypted ( ) :
logger . info ( ' Particl Wallet is encrypted ' )
if WALLET_ENCRYPTION_PWD == ' ' :
raise ValueError ( ' Must set WALLET_ENCRYPTION_PWD to add coin when Particl wallet is encrypted ' )
swap_client . ci ( c ) . unlockWallet ( WALLET_ENCRYPTION_PWD )
finally :
if swap_client :
swap_client . finalise ( )
del swap_client
for d in daemons :
finalise_daemon ( d )
2023-12-29 13:36:00 +00:00
def encrypt_wallet ( swap_client , coin_type ) - > None :
ci = swap_client . ci ( coin_type )
ci . changeWalletPassword ( ' ' , WALLET_ENCRYPTION_PWD )
ci . unlockWallet ( WALLET_ENCRYPTION_PWD )
2022-07-09 21:58:40 +00:00
def initialise_wallets ( particl_wallet_mnemonic , with_coins , data_dir , settings , chain , use_tor_proxy ) :
2022-11-16 22:36:13 +00:00
swap_client = None
2022-07-09 21:58:40 +00:00
daemons = [ ]
daemon_args = [ ' -noconnect ' , ' -nodnsseed ' ]
2024-05-27 13:44:48 +00:00
generated_mnemonic : bool = False
2022-11-16 22:36:13 +00:00
2024-02-14 09:06:40 +00:00
coins_failed_to_initialise = [ ]
2022-11-16 22:36:13 +00:00
with open ( os . path . join ( data_dir , ' basicswap.log ' ) , ' a ' ) as fp :
try :
2024-02-08 20:58:56 +00:00
swap_client = BasicSwap ( fp , data_dir , settings , chain , transient_instance = True )
2024-02-05 17:06:07 +00:00
if not swap_client . use_tor_proxy :
# Cannot set -bind or -whitebind together with -listen=0
daemon_args . append ( ' -nolisten ' )
2024-05-30 10:46:59 +00:00
coins_to_create_wallets_for = ( Coins . PART , Coins . BTC , Coins . LTC , Coins . DCR , Coins . DASH )
2022-10-20 20:23:25 +00:00
# Always start Particl, it must be running to initialise a wallet in addcoin mode
# Particl must be loaded first as subsequent coins are initialised from the Particl mnemonic
start_daemons = [ ' particl ' , ] + [ c for c in with_coins if c != ' particl ' ]
2022-07-09 21:58:40 +00:00
for coin_name in start_daemons :
coin_settings = settings [ ' chainclients ' ] [ coin_name ]
c = swap_client . getCoinIdFromName ( coin_name )
2022-11-16 22:36:13 +00:00
if c == Coins . XMR :
if coin_settings [ ' manage_wallet_daemon ' ] :
2024-03-31 22:47:14 +00:00
filename = coin_name + ' -wallet-rpc ' + ( ' .exe ' if os . name == ' nt ' else ' ' )
daemons . append ( startXmrWalletDaemon ( coin_settings [ ' datadir ' ] , coin_settings [ ' bindir ' ] , filename ) )
elif c == Coins . WOW :
if coin_settings [ ' manage_wallet_daemon ' ] :
filename = coin_name + ' -wallet-rpc ' + ( ' .exe ' if os . name == ' nt ' else ' ' )
2022-12-02 23:07:41 +00:00
daemons . append ( startXmrWalletDaemon ( coin_settings [ ' datadir ' ] , coin_settings [ ' bindir ' ] , filename ) )
2024-05-20 14:29:14 +00:00
elif c == Coins . DCR :
pass
2022-11-16 22:36:13 +00:00
else :
if coin_settings [ ' manage_daemon ' ] :
filename = coin_name + ' d ' + ( ' .exe ' if os . name == ' nt ' else ' ' )
coin_args = [ ' -nofindpeers ' , ' -nostaking ' ] if c == Coins . PART else [ ]
2022-10-20 20:23:25 +00:00
2022-11-16 22:36:13 +00:00
if c == Coins . FIRO :
coin_args + = [ ' -hdseed= {} ' . format ( swap_client . getWalletKey ( Coins . FIRO , 1 ) . hex ( ) ) ]
2022-11-07 20:31:10 +00:00
2022-11-16 22:36:13 +00:00
daemons . append ( startDaemon ( coin_settings [ ' datadir ' ] , coin_settings [ ' bindir ' ] , filename , daemon_args + coin_args ) )
2024-05-06 22:20:22 +00:00
swap_client . setDaemonPID ( c , daemons [ - 1 ] . handle . pid )
2022-07-09 21:58:40 +00:00
swap_client . setCoinRunParams ( c )
swap_client . createCoinInterface ( c )
2024-05-30 10:46:59 +00:00
if c in coins_to_create_wallets_for :
if c == Coins . DCR :
if coin_settings [ ' manage_wallet_daemon ' ] is False :
continue
2024-05-20 14:29:14 +00:00
from basicswap . interface . dcr . util import createDCRWallet
2024-05-22 07:59:57 +00:00
dcr_password = coin_settings [ ' wallet_pwd ' ] if WALLET_ENCRYPTION_PWD == ' ' else WALLET_ENCRYPTION_PWD
2024-05-20 14:29:14 +00:00
extra_opts = [ ' --appdata= " {} " ' . format ( coin_settings [ ' datadir ' ] ) ,
2024-05-22 07:59:57 +00:00
' --pass= {} ' . format ( dcr_password ) ,
2024-05-20 14:29:14 +00:00
]
filename = ' dcrwallet ' + ( ' .exe ' if os . name == ' nt ' else ' ' )
args = [ os . path . join ( coin_settings [ ' bindir ' ] , filename ) , ' --create ' ] + extra_opts
hex_seed = swap_client . getWalletKey ( Coins . DCR , 1 ) . hex ( )
createDCRWallet ( args , hex_seed , logger , threading . Event ( ) )
2024-05-30 10:46:59 +00:00
continue
2022-07-09 21:58:40 +00:00
swap_client . waitForDaemonRPC ( c , with_wallet = False )
# Create wallet if it doesn't exist yet
wallets = swap_client . callcoinrpc ( c , ' listwallets ' )
2022-08-17 22:21:32 +00:00
if len ( wallets ) < 1 :
2022-10-24 18:49:36 +00:00
logger . info ( ' Creating wallet.dat for {} . ' . format ( getCoinName ( c ) ) )
2022-11-12 20:17:49 +00:00
2023-12-29 13:36:00 +00:00
if c in ( Coins . BTC , Coins . LTC ) :
2022-11-16 22:36:13 +00:00
# wallet_name, disable_private_keys, blank, passphrase, avoid_reuse, descriptors
2023-12-29 13:36:00 +00:00
swap_client . callcoinrpc ( c , ' createwallet ' , [ ' wallet.dat ' , False , True , WALLET_ENCRYPTION_PWD , False , False ] )
swap_client . ci ( c ) . unlockWallet ( WALLET_ENCRYPTION_PWD )
2022-11-12 20:17:49 +00:00
else :
swap_client . callcoinrpc ( c , ' createwallet ' , [ ' wallet.dat ' ] )
2023-12-29 13:36:00 +00:00
if WALLET_ENCRYPTION_PWD != ' ' :
encrypt_wallet ( swap_client , c )
2022-07-09 21:58:40 +00:00
2023-12-29 13:36:00 +00:00
if c == Coins . LTC :
password = WALLET_ENCRYPTION_PWD if WALLET_ENCRYPTION_PWD != ' ' else None
swap_client . ci ( Coins . LTC_MWEB ) . init_wallet ( password )
2022-12-12 22:12:28 +00:00
if c == Coins . PART :
if ' particl ' in with_coins :
logger . info ( ' Loading Particl mnemonic ' )
if particl_wallet_mnemonic is None :
particl_wallet_mnemonic = swap_client . callcoinrpc ( Coins . PART , ' mnemonic ' , [ ' new ' ] ) [ ' mnemonic ' ]
2024-05-27 13:44:48 +00:00
generated_mnemonic = True
2022-12-12 22:12:28 +00:00
swap_client . callcoinrpc ( Coins . PART , ' extkeyimportmaster ' , [ particl_wallet_mnemonic ] )
# Particl wallet must be unlocked to call getWalletKey
if WALLET_ENCRYPTION_PWD != ' ' :
swap_client . ci ( c ) . unlockWallet ( WALLET_ENCRYPTION_PWD )
2022-07-09 21:58:40 +00:00
for coin_name in with_coins :
c = swap_client . getCoinIdFromName ( coin_name )
2022-10-21 11:00:28 +00:00
if c in ( Coins . PART , ) :
2022-07-09 21:58:40 +00:00
continue
2024-05-20 14:29:14 +00:00
if c not in ( Coins . DCR , ) :
# initialiseWallet only sets main_wallet_seedid_
swap_client . waitForDaemonRPC ( c )
2024-02-14 09:06:40 +00:00
try :
swap_client . initialiseWallet ( c , raise_errors = True )
except Exception as e :
coins_failed_to_initialise . append ( ( c , e ) )
2022-12-12 22:12:28 +00:00
if WALLET_ENCRYPTION_PWD != ' ' and c not in coins_to_create_wallets_for :
2023-01-03 18:03:36 +00:00
try :
swap_client . ci ( c ) . changeWalletPassword ( ' ' , WALLET_ENCRYPTION_PWD )
except Exception as e :
logger . warning ( f ' changeWalletPassword failed for { coin_name } . ' )
2022-07-09 21:58:40 +00:00
2022-11-16 22:36:13 +00:00
finally :
if swap_client :
swap_client . finalise ( )
del swap_client
for d in daemons :
finalise_daemon ( d )
2022-07-11 21:36:28 +00:00
2024-02-14 09:06:40 +00:00
print ( ' ' )
for pair in coins_failed_to_initialise :
2024-05-20 14:29:14 +00:00
c , e = pair
2024-02-14 09:06:40 +00:00
if c in ( Coins . PIVX , ) :
print ( f ' NOTE - Unable to initialise wallet for { getCoinName ( c ) } . To complete setup click \' Reseed Wallet \' from the ui page once chain is synced. ' )
else :
2024-05-20 14:29:14 +00:00
print ( f ' WARNING - Failed to initialise wallet for { getCoinName ( c ) } : { e } ' )
2024-02-14 09:06:40 +00:00
2024-05-22 07:59:57 +00:00
if ' decred ' in with_coins and WALLET_ENCRYPTION_PWD != ' ' :
print ( ' WARNING - dcrwallet requires the password to be entered at the first startup when encrypted. \n Please use basicswap-run with --startonlycoin=decred and the WALLET_ENCRYPTION_PWD environment var set for the initial sync. ' )
2022-07-11 21:36:28 +00:00
if particl_wallet_mnemonic is not None :
2024-05-27 13:44:48 +00:00
if generated_mnemonic :
2022-07-11 21:36:28 +00:00
# Print directly to stdout for tests
print ( ' IMPORTANT - Save your particl wallet recovery phrase: \n {} \n ' . format ( particl_wallet_mnemonic ) )
def load_config ( config_path ) :
if not os . path . exists ( config_path ) :
exitWithError ( ' {} does not exist ' . format ( config_path ) )
with open ( config_path ) as fs :
return json . load ( fs )
2022-07-09 21:58:40 +00:00
2022-12-02 23:07:41 +00:00
def signal_handler ( sig , frame ) :
logger . info ( ' Signal %d detected ' % ( sig ) )
2022-12-13 22:19:38 +00:00
def check_btc_fastsync_data ( base_dir , sync_file_path ) :
2024-06-11 07:56:09 +00:00
github_pgp_url = ' https://raw.githubusercontent.com/basicswap/basicswap/master/pgp '
2023-01-04 11:45:16 +00:00
gitlab_pgp_url = ' https://gitlab.com/particl/basicswap/-/raw/master/pgp '
2022-12-13 22:19:38 +00:00
asc_filename = BITCOIN_FASTSYNC_FILE + ' .asc '
asc_file_path = os . path . join ( base_dir , asc_filename )
if not os . path . exists ( asc_file_path ) :
asc_file_urls = (
2023-01-04 11:45:16 +00:00
github_pgp_url + ' /sigs/ ' + asc_filename ,
gitlab_pgp_url + ' /sigs/ ' + asc_filename ,
2022-12-13 22:19:38 +00:00
)
for url in asc_file_urls :
try :
downloadFile ( url , asc_file_path )
break
except Exception as e :
logging . warning ( ' Download failed: %s ' , str ( e ) )
gpg = gnupg . GPG ( )
2023-01-04 11:45:16 +00:00
pubkey_filename = ' {} _ {} .pgp ' . format ( ' particl ' , ' tecnovert ' )
pubkeyurls = [
github_pgp_url + ' /keys/ ' + pubkey_filename ,
gitlab_pgp_url + ' /keys/ ' + pubkey_filename ,
]
if not havePubkey ( gpg , expected_key_ids [ ' tecnovert ' ] [ 0 ] ) :
importPubkeyFromUrls ( gpg , pubkeyurls )
2022-12-13 22:19:38 +00:00
with open ( asc_file_path , ' rb ' ) as fp :
verified = gpg . verify_file ( fp , sync_file_path )
ensureValidSignatureBy ( verified , ' tecnovert ' )
2023-10-09 14:43:09 +00:00
def ensure_coin_valid ( coin : str , test_disabled : bool = True ) - > None :
if coin not in known_coins :
exitWithError ( f ' Unknown coin { coin . capitalize ( ) } ' )
if test_disabled and not OVERRIDE_DISABLED_COINS and coin in disabled_coins :
exitWithError ( f ' { coin . capitalize ( ) } is disabled ' )
2019-07-21 18:50:32 +00:00
def main ( ) :
2022-03-23 22:00:35 +00:00
global use_tor_proxy
2019-07-21 18:50:32 +00:00
data_dir = None
2019-08-15 19:14:28 +00:00
bin_dir = None
port_offset = None
2019-07-21 18:50:32 +00:00
chain = ' mainnet '
particl_wallet_mnemonic = None
2021-11-15 09:34:54 +00:00
with_coins = { ' particl ' , }
2019-07-24 18:57:31 +00:00
add_coin = ' '
2019-07-25 18:30:01 +00:00
disable_coin = ' '
2022-12-09 16:14:09 +00:00
coins_changed = False
2021-01-11 21:48:46 +00:00
htmlhost = ' 127.0.0.1 '
2020-12-04 23:59:21 +00:00
xmr_restore_height = DEFAULT_XMR_RESTORE_HEIGHT
2024-03-31 22:47:14 +00:00
wow_restore_height = DEFAULT_WOW_RESTORE_HEIGHT
2022-07-11 21:36:28 +00:00
prepare_bin_only = False
no_cores = False
2022-03-23 22:00:35 +00:00
enable_tor = False
disable_tor = False
2022-07-11 21:36:28 +00:00
initwalletsonly = False
2022-07-17 20:34:39 +00:00
tor_control_password = None
extra_opts = { }
2019-07-21 18:50:32 +00:00
2022-12-15 08:55:20 +00:00
if os . getenv ( ' SSL_CERT_DIR ' , ' ' ) == ' ' and GUIX_SSL_CERT_DIR is not None :
os . environ [ ' SSL_CERT_DIR ' ] = GUIX_SSL_CERT_DIR
2022-12-02 23:07:41 +00:00
if os . name == ' nt ' :
# On windows sending signal.CTRL_C_EVENT to a subprocess causes it to be sent to the parent process too
signal . signal ( signal . SIGINT , signal_handler )
2019-07-21 18:50:32 +00:00
for v in sys . argv [ 1 : ] :
if len ( v ) < 2 or v [ 0 ] != ' - ' :
2019-07-24 18:57:31 +00:00
exitWithError ( ' Unknown argument {} ' . format ( v ) )
2019-07-21 18:50:32 +00:00
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
2023-12-18 13:15:16 +00:00
if name in ( ' mainnet ' , ' testnet ' , ' regtest ' ) :
chain = name
2019-07-21 18:50:32 +00:00
continue
2019-07-25 12:06:58 +00:00
if name == ' preparebinonly ' :
prepare_bin_only = True
continue
2020-12-27 19:39:10 +00:00
if name == ' nocores ' :
no_cores = True
continue
2021-11-15 09:34:54 +00:00
if name == ' usecontainers ' :
2022-07-17 20:34:39 +00:00
extra_opts [ ' use_containers ' ] = True
2021-11-15 09:34:54 +00:00
continue
2021-01-10 18:30:07 +00:00
if name == ' noextractover ' :
2022-07-17 20:34:39 +00:00
extra_opts [ ' extract_core_overwrite ' ] = False
2021-01-10 18:30:07 +00:00
continue
2022-03-23 22:00:35 +00:00
if name == ' usetorproxy ' :
use_tor_proxy = True
continue
2024-02-05 12:16:34 +00:00
if name == ' notorproxy ' :
extra_opts [ ' no_tor_proxy ' ] = True
continue
2022-03-23 22:00:35 +00:00
if name == ' enabletor ' :
enable_tor = True
continue
if name == ' disabletor ' :
disable_tor = True
continue
2022-06-04 20:41:24 +00:00
if name == ' usebtcfastsync ' :
2022-07-17 20:34:39 +00:00
extra_opts [ ' use_btc_fastsync ' ] = True
2022-06-04 20:41:24 +00:00
continue
2023-03-28 13:47:29 +00:00
if name == ' skipbtcfastsyncchecks ' :
extra_opts [ ' check_btc_fastsync ' ] = False
continue
2024-02-07 20:48:34 +00:00
if name == ' trustremotenode ' :
extra_opts [ ' trust_remote_node ' ] = True
continue
2022-07-11 21:36:28 +00:00
if name == ' initwalletsonly ' :
initwalletsonly = True
continue
2019-07-21 18:50:32 +00:00
if len ( s ) == 2 :
if name == ' datadir ' :
2019-08-15 19:14:28 +00:00
data_dir = os . path . expanduser ( s [ 1 ] . strip ( ' " ' ) )
continue
if name == ' bindir ' :
bin_dir = os . path . expanduser ( s [ 1 ] . strip ( ' " ' ) )
continue
if name == ' portoffset ' :
port_offset = int ( s [ 1 ] )
2019-07-21 18:50:32 +00:00
continue
if name == ' particl_mnemonic ' :
2019-08-15 19:14:28 +00:00
particl_wallet_mnemonic = s [ 1 ] . strip ( ' " ' )
2019-07-21 18:50:32 +00:00
continue
2023-12-18 13:15:16 +00:00
if name in ( ' withcoin ' , ' withcoins ' ) :
2024-05-30 16:55:35 +00:00
for coin in [ s . strip ( ) . lower ( ) for s in s [ 1 ] . split ( ' , ' ) ] :
2023-10-09 14:43:09 +00:00
ensure_coin_valid ( coin )
2020-12-01 20:45:03 +00:00
with_coins . add ( coin )
2022-12-09 16:14:09 +00:00
coins_changed = True
2019-07-24 18:57:31 +00:00
continue
2023-12-18 13:15:16 +00:00
if name in ( ' withoutcoin ' , ' withoutcoins ' ) :
2024-05-30 16:55:35 +00:00
for coin in [ s . strip ( ) . lower ( ) for s in s [ 1 ] . split ( ' , ' ) ] :
2023-10-09 14:43:09 +00:00
ensure_coin_valid ( coin , test_disabled = False )
2020-12-01 20:45:03 +00:00
with_coins . discard ( coin )
2022-12-09 16:14:09 +00:00
coins_changed = True
2019-07-24 18:57:31 +00:00
continue
if name == ' addcoin ' :
2024-05-30 16:55:35 +00:00
add_coin = s [ 1 ] . strip ( ) . lower ( )
2023-10-09 14:43:09 +00:00
ensure_coin_valid ( add_coin )
2022-08-08 23:29:51 +00:00
with_coins = { add_coin , }
2019-07-24 18:57:31 +00:00
continue
2019-07-25 18:30:01 +00:00
if name == ' disablecoin ' :
2024-05-30 16:55:35 +00:00
disable_coin = s [ 1 ] . strip ( ) . lower ( )
2023-10-09 14:43:09 +00:00
ensure_coin_valid ( disable_coin , test_disabled = False )
2019-07-25 18:30:01 +00:00
continue
2020-12-04 23:59:21 +00:00
if name == ' htmlhost ' :
htmlhost = s [ 1 ] . strip ( ' " ' )
continue
2022-07-31 17:33:01 +00:00
if name == ' wshost ' :
2024-02-08 08:53:10 +00:00
extra_opts [ ' wshost ' ] = s [ 1 ] . strip ( ' " ' )
2022-07-31 17:33:01 +00:00
continue
2020-12-04 23:59:21 +00:00
if name == ' xmrrestoreheight ' :
xmr_restore_height = int ( s [ 1 ] )
continue
2024-03-31 22:47:14 +00:00
if name == ' wowrestoreheight ' :
wow_restore_height = int ( s [ 1 ] )
continue
2022-07-17 20:34:39 +00:00
if name == ' keysdirpath ' :
extra_opts [ ' keysdirpath ' ] = os . path . expanduser ( s [ 1 ] . strip ( ' " ' ) )
continue
2024-02-07 20:48:34 +00:00
if name == ' trustremotenode ' :
extra_opts [ ' trust_remote_node ' ] = toBool ( s [ 1 ] )
continue
2019-07-21 18:50:32 +00:00
2019-07-24 18:57:31 +00:00
exitWithError ( ' Unknown argument {} ' . format ( v ) )
2019-07-21 18:50:32 +00:00
if data_dir is None :
2022-07-11 21:36:28 +00:00
data_dir = os . path . join ( os . path . expanduser ( cfg . BASICSWAP_DATADIR ) )
2019-08-15 19:14:28 +00:00
if bin_dir is None :
bin_dir = os . path . join ( data_dir , ' bin ' )
2022-11-22 08:28:02 +00:00
logger . info ( f ' BasicSwap prepare script { __version__ } \n ' )
2023-10-17 12:42:52 +00:00
logger . info ( f ' Python version: { platform . python_version ( ) } ' )
2022-11-22 08:28:02 +00:00
logger . info ( f ' Data dir: { data_dir } ' )
logger . info ( f ' Bin dir: { bin_dir } ' )
logger . info ( f ' Chain: { chain } ' )
logger . info ( ' WALLET_ENCRYPTION_PWD is {} set ' . format ( ' not ' if WALLET_ENCRYPTION_PWD == ' ' else ' ' ) )
2019-08-15 19:14:28 +00:00
if port_offset is None :
port_offset = 300 if chain == ' testnet ' else 0
2019-07-21 18:50:32 +00:00
if not os . path . exists ( data_dir ) :
os . makedirs ( data_dir )
2020-02-01 18:57:20 +00:00
config_path = os . path . join ( data_dir , cfg . CONFIG_FILENAME )
2019-07-24 18:57:31 +00:00
2024-02-05 12:16:34 +00:00
if use_tor_proxy and extra_opts . get ( ' no_tor_proxy ' , False ) :
exitWithError ( ' Can \' t use --usetorproxy and --notorproxy together ' )
2024-05-25 09:22:12 +00:00
# Automatically enable usetorproxy for certain commands if it's set in basicswap config
2024-02-08 20:58:56 +00:00
if not ( initwalletsonly or enable_tor or disable_tor or disable_coin ) and \
not use_tor_proxy and os . path . exists ( config_path ) :
2024-02-05 12:16:34 +00:00
settings = load_config ( config_path )
settings_use_tor = settings . get ( ' use_tor ' , False )
if settings_use_tor :
logger . info ( ' use_tor is set in the config ' )
if extra_opts . get ( ' no_tor_proxy ' , False ) :
use_tor_proxy = False
logger . warning ( ' Not automatically setting --usetorproxy as --notorproxy is set ' )
else :
use_tor_proxy = True
2024-02-05 15:17:44 +00:00
logger . info ( ' Automatically setting --usetorproxy ' )
2024-02-05 12:16:34 +00:00
setConnectionParameters ( allow_set_tor = False )
if use_tor_proxy and TEST_TOR_PROXY :
testTorConnection ( )
if use_tor_proxy and TEST_ONION_LINK :
testOnionLink ( )
2023-09-28 22:06:45 +00:00
should_download_btc_fastsync = False
2022-12-13 22:19:38 +00:00
if extra_opts . get ( ' use_btc_fastsync ' , False ) is True :
2023-09-28 22:06:45 +00:00
if ' bitcoin ' in with_coins or add_coin == ' bitcoin ' :
should_download_btc_fastsync = True
else :
logger . warning ( ' Ignoring usebtcfastsync option without Bitcoin selected. ' )
if should_download_btc_fastsync :
2022-12-13 22:19:38 +00:00
logger . info ( f ' Preparing BTC Fastsync file { BITCOIN_FASTSYNC_FILE } ' )
sync_file_path = os . path . join ( data_dir , BITCOIN_FASTSYNC_FILE )
sync_file_url = os . path . join ( BITCOIN_FASTSYNC_URL , BITCOIN_FASTSYNC_FILE )
try :
2023-03-28 13:47:29 +00:00
check_btc_fastsync = extra_opts . get ( ' check_btc_fastsync ' , True )
2022-12-13 22:19:38 +00:00
check_sig = False
if not os . path . exists ( sync_file_path ) :
downloadFile ( sync_file_url , sync_file_path , timeout = 50 )
2023-03-28 13:47:29 +00:00
check_sig = check_btc_fastsync
elif check_btc_fastsync :
2022-12-13 22:19:38 +00:00
file_size = os . stat ( sync_file_path ) . st_size
2023-03-28 13:47:29 +00:00
remote_file = urlopen ( sync_file_url )
2022-12-13 22:19:38 +00:00
if file_size < remote_file . length :
logger . warning ( f ' { BITCOIN_FASTSYNC_FILE } is an unexpected size, { file_size } < { remote_file . length } ' )
downloadFile ( sync_file_url , sync_file_path , timeout = 50 , resume_from = file_size )
check_sig = True
if check_sig :
check_btc_fastsync_data ( data_dir , sync_file_path )
except Exception as e :
2023-01-11 21:06:05 +00:00
logger . error ( f ' Failed to download BTC fastsync file: { e } \n Re-running the command should resume the download or try manually downloading from { sync_file_url } ' )
2022-12-13 22:19:38 +00:00
return 1
2019-07-27 17:26:06 +00:00
withchainclients = { }
2019-07-24 18:57:31 +00:00
chainclients = {
' particl ' : {
' connection_type ' : ' rpc ' ,
2021-01-11 21:48:46 +00:00
' manage_daemon ' : True if ( ' particl ' in with_coins and PART_RPC_HOST == ' 127.0.0.1 ' ) else False ,
2020-12-27 19:39:10 +00:00
' rpchost ' : PART_RPC_HOST ,
2021-01-16 08:21:59 +00:00
' rpcport ' : PART_RPC_PORT + port_offset ,
2022-03-23 22:00:35 +00:00
' onionport ' : PART_ONION_PORT + port_offset ,
2020-12-27 19:39:10 +00:00
' datadir ' : os . getenv ( ' PART_DATA_DIR ' , os . path . join ( data_dir , ' particl ' ) ) ,
2019-08-15 19:14:28 +00:00
' bindir ' : os . path . join ( bin_dir , ' particl ' ) ,
2019-07-24 18:57:31 +00:00
' blocks_confirmed ' : 2 ,
' override_feerate ' : 0.002 ,
2019-07-26 21:03:56 +00:00
' conf_target ' : 2 ,
2022-07-15 14:38:05 +00:00
' core_version_group ' : 21 ,
2024-04-09 21:33:44 +00:00
} ,
' 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 ,
2019-07-24 18:57:31 +00:00
} ,
' litecoin ' : {
' connection_type ' : ' rpc ' if ' litecoin ' in with_coins else ' none ' ,
2021-01-11 21:48:46 +00:00
' manage_daemon ' : True if ( ' litecoin ' in with_coins and LTC_RPC_HOST == ' 127.0.0.1 ' ) else False ,
2020-12-27 19:39:10 +00:00
' rpchost ' : LTC_RPC_HOST ,
2021-01-16 08:21:59 +00:00
' rpcport ' : LTC_RPC_PORT + port_offset ,
2022-03-23 22:00:35 +00:00
' onionport ' : LTC_ONION_PORT + port_offset ,
2020-12-27 19:39:10 +00:00
' datadir ' : os . getenv ( ' LTC_DATA_DIR ' , os . path . join ( data_dir , ' litecoin ' ) ) ,
2019-08-15 19:14:28 +00:00
' bindir ' : os . path . join ( bin_dir , ' litecoin ' ) ,
2019-07-24 18:57:31 +00:00
' use_segwit ' : True ,
2019-07-26 21:03:56 +00:00
' blocks_confirmed ' : 2 ,
' conf_target ' : 2 ,
2022-07-15 14:38:05 +00:00
' core_version_group ' : 21 ,
2024-01-31 15:25:22 +00:00
' min_relay_fee ' : 0.00001 ,
2019-07-24 18:57:31 +00:00
} ,
2024-04-09 21:33:44 +00:00
' 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 ,
2024-05-20 14:29:14 +00:00
' manage_wallet_daemon ' : True if ( ' decred ' in with_coins and DCR_WALLET_RPC_HOST == ' 127.0.0.1 ' ) else False ,
2024-05-22 07:59:57 +00:00
' wallet_pwd ' : DCR_WALLET_PWD if WALLET_ENCRYPTION_PWD == ' ' else ' ' ,
2024-04-09 21:33:44 +00:00
' rpchost ' : DCR_RPC_HOST ,
' rpcport ' : DCR_RPC_PORT + port_offset ,
2024-05-20 14:29:14 +00:00
' walletrpchost ' : DCR_WALLET_RPC_HOST ,
' walletrpcport ' : DCR_WALLET_RPC_PORT + port_offset ,
' rpcuser ' : DCR_RPC_USER ,
' rpcpassword ' : DCR_RPC_PWD ,
2024-04-09 21:33:44 +00:00
' datadir ' : os . getenv ( ' DCR_DATA_DIR ' , os . path . join ( data_dir , ' decred ' ) ) ,
' bindir ' : os . path . join ( bin_dir , ' decred ' ) ,
2024-05-20 14:29:14 +00:00
' use_csv ' : True ,
2019-07-25 18:09:46 +00:00
' use_segwit ' : True ,
2024-04-09 21:33:44 +00:00
' blocks_confirmed ' : 2 ,
2019-07-26 21:03:56 +00:00
' conf_target ' : 2 ,
2024-04-09 21:33:44 +00:00
' core_type_group ' : ' dcr ' ,
' min_relay_fee ' : 0.00001 ,
2019-07-24 18:57:31 +00:00
} ,
' namecoin ' : {
' connection_type ' : ' rpc ' if ' namecoin ' in with_coins else ' none ' ,
2021-01-11 21:48:46 +00:00
' manage_daemon ' : True if ( ' namecoin ' in with_coins and NMC_RPC_HOST == ' 127.0.0.1 ' ) else False ,
2020-12-27 19:39:10 +00:00
' rpchost ' : NMC_RPC_HOST ,
2021-01-16 08:21:59 +00:00
' rpcport ' : NMC_RPC_PORT + port_offset ,
2020-12-27 19:39:10 +00:00
' datadir ' : os . getenv ( ' NMC_DATA_DIR ' , os . path . join ( data_dir , ' namecoin ' ) ) ,
2019-08-15 19:14:28 +00:00
' bindir ' : os . path . join ( bin_dir , ' namecoin ' ) ,
2019-07-24 18:57:31 +00:00
' use_segwit ' : False ,
2019-07-24 22:59:40 +00:00
' use_csv ' : False ,
2019-07-26 21:03:56 +00:00
' blocks_confirmed ' : 1 ,
' conf_target ' : 2 ,
2019-07-31 16:53:44 +00:00
' core_version_group ' : 18 ,
2019-08-05 22:04:40 +00:00
' chain_lookups ' : ' local ' ,
2020-11-30 17:07:55 +00:00
} ,
' monero ' : {
' connection_type ' : ' rpc ' if ' monero ' in with_coins else ' none ' ,
2021-01-11 21:48:46 +00:00
' manage_daemon ' : True if ( ' monero ' in with_coins and XMR_RPC_HOST == ' 127.0.0.1 ' ) else False ,
' manage_wallet_daemon ' : True if ( ' monero ' in with_coins and XMR_WALLET_RPC_HOST == ' 127.0.0.1 ' ) else False ,
2020-12-03 23:46:01 +00:00
' rpcport ' : BASE_XMR_RPC_PORT + port_offset ,
' zmqport ' : BASE_XMR_ZMQ_PORT + port_offset ,
' walletrpcport ' : BASE_XMR_WALLET_PORT + port_offset ,
' rpchost ' : XMR_RPC_HOST ,
2024-02-08 08:43:02 +00:00
' trusted_daemon ' : extra_opts . get ( ' trust_remote_node ' , ' auto ' ) ,
2020-12-27 19:39:10 +00:00
' walletrpchost ' : XMR_WALLET_RPC_HOST ,
2020-12-03 23:46:01 +00:00
' walletrpcuser ' : XMR_WALLET_RPC_USER ,
' walletrpcpassword ' : XMR_WALLET_RPC_PWD ,
' walletfile ' : ' swap_wallet ' ,
2020-12-27 19:39:10 +00:00
' datadir ' : os . getenv ( ' XMR_DATA_DIR ' , os . path . join ( data_dir , ' monero ' ) ) ,
2020-11-30 17:07:55 +00:00
' bindir ' : os . path . join ( bin_dir , ' monero ' ) ,
2020-12-04 23:59:21 +00:00
' restore_height ' : xmr_restore_height ,
2024-02-01 23:05:19 +00:00
' blocks_confirmed ' : 3 ,
2024-02-05 15:17:44 +00:00
' rpctimeout ' : 60 ,
' walletrpctimeout ' : 120 ,
' walletrpctimeoutlong ' : 600 ,
2024-04-09 21:33:44 +00:00
' core_type_group ' : ' xmr ' ,
2022-08-10 22:02:36 +00:00
} ,
' pivx ' : {
' connection_type ' : ' rpc ' if ' pivx ' in with_coins else ' none ' ,
' manage_daemon ' : True if ( ' pivx ' in with_coins and PIVX_RPC_HOST == ' 127.0.0.1 ' ) else False ,
' rpchost ' : PIVX_RPC_HOST ,
' rpcport ' : PIVX_RPC_PORT + port_offset ,
' onionport ' : PIVX_ONION_PORT + port_offset ,
' datadir ' : os . getenv ( ' PIVX_DATA_DIR ' , os . path . join ( data_dir , ' pivx ' ) ) ,
' bindir ' : os . path . join ( bin_dir , ' pivx ' ) ,
' use_segwit ' : False ,
' use_csv ' : False ,
' blocks_confirmed ' : 1 ,
' conf_target ' : 2 ,
2023-09-28 22:59:32 +00:00
' core_version_group ' : 17 ,
2022-10-20 20:23:25 +00:00
} ,
' dash ' : {
' connection_type ' : ' rpc ' if ' dash ' in with_coins else ' none ' ,
2022-11-07 20:31:10 +00:00
' manage_daemon ' : True if ( ' dash ' in with_coins and DASH_RPC_HOST == ' 127.0.0.1 ' ) else False ,
2022-10-20 20:23:25 +00:00
' rpchost ' : DASH_RPC_HOST ,
' rpcport ' : DASH_RPC_PORT + port_offset ,
' onionport ' : DASH_ONION_PORT + port_offset ,
' datadir ' : os . getenv ( ' DASH_DATA_DIR ' , os . path . join ( data_dir , ' dash ' ) ) ,
' bindir ' : os . path . join ( bin_dir , ' dash ' ) ,
' use_segwit ' : False ,
' use_csv ' : True ,
' blocks_confirmed ' : 1 ,
' conf_target ' : 2 ,
' core_version_group ' : 18 ,
2022-11-07 20:31:10 +00:00
} ,
' firo ' : {
' connection_type ' : ' rpc ' if ' firo ' in with_coins else ' none ' ,
' manage_daemon ' : True if ( ' firo ' in with_coins and FIRO_RPC_HOST == ' 127.0.0.1 ' ) else False ,
' rpchost ' : FIRO_RPC_HOST ,
' rpcport ' : FIRO_RPC_PORT + port_offset ,
' onionport ' : FIRO_ONION_PORT + port_offset ,
' datadir ' : os . getenv ( ' FIRO_DATA_DIR ' , os . path . join ( data_dir , ' firo ' ) ) ,
' bindir ' : os . path . join ( bin_dir , ' firo ' ) ,
' use_segwit ' : False ,
2023-11-24 19:44:48 +00:00
' use_csv ' : False ,
2022-11-07 20:31:10 +00:00
' blocks_confirmed ' : 1 ,
' conf_target ' : 2 ,
2023-11-28 15:38:30 +00:00
' core_version_group ' : 14 ,
2023-12-01 17:16:28 +00:00
' min_relay_fee ' : 0.00001 ,
2023-08-29 21:08:28 +00:00
} ,
' navcoin ' : {
' connection_type ' : ' rpc ' if ' navcoin ' in with_coins else ' none ' ,
' manage_daemon ' : True if ( ' navcoin ' in with_coins and NAV_RPC_HOST == ' 127.0.0.1 ' ) else False ,
' rpchost ' : NAV_RPC_HOST ,
' rpcport ' : NAV_RPC_PORT + port_offset ,
' onionport ' : NAV_ONION_PORT + port_offset ,
' datadir ' : os . getenv ( ' NAV_DATA_DIR ' , os . path . join ( data_dir , ' navcoin ' ) ) ,
' bindir ' : os . path . join ( bin_dir , ' navcoin ' ) ,
' use_segwit ' : True ,
' use_csv ' : True ,
' blocks_confirmed ' : 1 ,
' conf_target ' : 2 ,
' core_version_group ' : 18 ,
' chain_lookups ' : ' local ' ,
2023-09-02 12:28:08 +00:00
' startup_tries ' : 40 ,
2024-03-31 22:47:14 +00:00
} ,
' wownero ' : {
' connection_type ' : ' rpc ' if ' wownero ' in with_coins else ' none ' ,
' manage_daemon ' : True if ( ' wownero ' in with_coins and WOW_RPC_HOST == ' 127.0.0.1 ' ) else False ,
' manage_wallet_daemon ' : True if ( ' wownero ' in with_coins and WOW_WALLET_RPC_HOST == ' 127.0.0.1 ' ) else False ,
' rpcport ' : BASE_WOW_RPC_PORT + port_offset ,
' zmqport ' : BASE_WOW_ZMQ_PORT + port_offset ,
' walletrpcport ' : BASE_WOW_WALLET_PORT + port_offset ,
' rpchost ' : WOW_RPC_HOST ,
' trusted_daemon ' : extra_opts . get ( ' trust_remote_node ' , ' auto ' ) ,
' walletrpchost ' : WOW_WALLET_RPC_HOST ,
' walletrpcuser ' : WOW_WALLET_RPC_USER ,
' walletrpcpassword ' : WOW_WALLET_RPC_PWD ,
' walletfile ' : ' swap_wallet ' ,
' datadir ' : os . getenv ( ' WOW_DATA_DIR ' , os . path . join ( data_dir , ' wownero ' ) ) ,
' bindir ' : os . path . join ( bin_dir , ' wownero ' ) ,
' restore_height ' : wow_restore_height ,
' blocks_confirmed ' : 2 ,
' rpctimeout ' : 60 ,
' walletrpctimeout ' : 120 ,
' walletrpctimeoutlong ' : 300 ,
' core_type_group ' : ' xmr ' ,
2019-07-24 18:57:31 +00:00
}
}
2021-06-28 21:56:45 +00:00
if PART_RPC_USER != ' ' :
chainclients [ ' particl ' ] [ ' rpcuser ' ] = PART_RPC_USER
chainclients [ ' particl ' ] [ ' rpcpassword ' ] = PART_RPC_PWD
if LTC_RPC_USER != ' ' :
chainclients [ ' litecoin ' ] [ ' rpcuser ' ] = LTC_RPC_USER
chainclients [ ' litecoin ' ] [ ' rpcpassword ' ] = LTC_RPC_PWD
if BTC_RPC_USER != ' ' :
chainclients [ ' bitcoin ' ] [ ' rpcuser ' ] = BTC_RPC_USER
chainclients [ ' bitcoin ' ] [ ' rpcpassword ' ] = BTC_RPC_PWD
2022-11-28 17:54:41 +00:00
if XMR_RPC_USER != ' ' :
chainclients [ ' monero ' ] [ ' rpcuser ' ] = XMR_RPC_USER
chainclients [ ' monero ' ] [ ' rpcpassword ' ] = XMR_RPC_PWD
2024-03-31 22:47:14 +00:00
if WOW_RPC_USER != ' ' :
chainclients [ ' wownero ' ] [ ' rpcuser ' ] = WOW_RPC_USER
chainclients [ ' wownero ' ] [ ' rpcpassword ' ] = WOW_RPC_PWD
2022-08-10 22:02:36 +00:00
if PIVX_RPC_USER != ' ' :
chainclients [ ' pivx ' ] [ ' rpcuser ' ] = PIVX_RPC_USER
chainclients [ ' pivx ' ] [ ' rpcpassword ' ] = PIVX_RPC_PWD
2022-10-20 20:23:25 +00:00
if DASH_RPC_USER != ' ' :
chainclients [ ' dash ' ] [ ' rpcuser ' ] = DASH_RPC_USER
chainclients [ ' dash ' ] [ ' rpcpassword ' ] = DASH_RPC_PWD
2022-11-07 20:31:10 +00:00
if FIRO_RPC_USER != ' ' :
chainclients [ ' firo ' ] [ ' rpcuser ' ] = FIRO_RPC_USER
chainclients [ ' firo ' ] [ ' rpcpassword ' ] = FIRO_RPC_PWD
2023-08-29 21:08:28 +00:00
if NAV_RPC_USER != ' ' :
chainclients [ ' nav ' ] [ ' rpcuser ' ] = NAV_RPC_USER
chainclients [ ' nav ' ] [ ' rpcpassword ' ] = NAV_RPC_PWD
2021-06-28 21:56:45 +00:00
chainclients [ ' monero ' ] [ ' walletsdir ' ] = os . getenv ( ' XMR_WALLETS_DIR ' , chainclients [ ' monero ' ] [ ' datadir ' ] )
2024-03-31 22:47:14 +00:00
chainclients [ ' wownero ' ] [ ' walletsdir ' ] = os . getenv ( ' WOW_WALLETS_DIR ' , chainclients [ ' wownero ' ] [ ' datadir ' ] )
2021-06-28 21:56:45 +00:00
2022-07-11 21:36:28 +00:00
if initwalletsonly :
logger . info ( ' Initialising wallets ' )
settings = load_config ( config_path )
init_coins = settings [ ' chainclients ' ] . keys ( )
logger . info ( ' Active coins: %s ' , ' , ' . join ( init_coins ) )
2022-12-09 16:14:09 +00:00
if coins_changed :
init_coins = with_coins
logger . info ( ' Initialising coins: %s ' , ' , ' . join ( init_coins ) )
2022-07-11 21:36:28 +00:00
initialise_wallets ( particl_wallet_mnemonic , init_coins , data_dir , settings , chain , use_tor_proxy )
print ( ' Done. ' )
return 0
2022-03-23 22:00:35 +00:00
if enable_tor :
logger . info ( ' Enabling TOR ' )
2022-07-11 21:36:28 +00:00
settings = load_config ( config_path )
2022-03-23 22:00:35 +00:00
tor_control_password = settings . get ( ' tor_control_password ' , None )
if tor_control_password is None :
tor_control_password = generate_salt ( 24 )
settings [ ' tor_control_password ' ] = tor_control_password
write_torrc ( data_dir , tor_control_password )
addTorSettings ( settings , tor_control_password )
for coin in settings [ ' chainclients ' ] :
2024-02-07 20:48:34 +00:00
modify_tor_config ( settings , coin , tor_control_password , enable = True , extra_opts = extra_opts )
2022-03-23 22:00:35 +00:00
with open ( config_path , ' w ' ) as fp :
json . dump ( settings , fp , indent = 4 )
logger . info ( ' Done. ' )
return 0
if disable_tor :
logger . info ( ' Disabling TOR ' )
2022-07-11 21:36:28 +00:00
settings = load_config ( config_path )
2022-03-23 22:00:35 +00:00
settings [ ' use_tor ' ] = False
for coin in settings [ ' chainclients ' ] :
2024-02-07 20:48:34 +00:00
modify_tor_config ( settings , coin , tor_control_password = None , enable = False , extra_opts = extra_opts )
2022-03-23 22:00:35 +00:00
with open ( config_path , ' w ' ) as fp :
json . dump ( settings , fp , indent = 4 )
logger . info ( ' Done. ' )
return 0
2019-07-25 18:30:01 +00:00
if disable_coin != ' ' :
logger . info ( ' Disabling coin: %s ' , disable_coin )
2022-07-11 21:36:28 +00:00
settings = load_config ( config_path )
2019-07-25 18:30:01 +00:00
if disable_coin not in settings [ ' chainclients ' ] :
2023-10-09 14:43:09 +00:00
exitWithError ( f ' { disable_coin } not configured ' )
coin_settings = settings [ ' chainclients ' ] [ disable_coin ]
if coin_settings [ ' connection_type ' ] == ' none ' and coin_settings [ ' manage_daemon ' ] is False :
exitWithError ( f ' { disable_coin } is already disabled ' )
coin_settings [ ' connection_type ' ] = ' none '
coin_settings [ ' manage_daemon ' ] = False
2019-07-25 18:30:01 +00:00
with open ( config_path , ' w ' ) as fp :
json . dump ( settings , fp , indent = 4 )
logger . info ( ' Done. ' )
return 0
2022-07-17 20:34:39 +00:00
extra_opts [ ' data_dir ' ] = data_dir
extra_opts [ ' tor_control_password ' ] = tor_control_password
2022-06-04 20:41:24 +00:00
2019-07-24 18:57:31 +00:00
if add_coin != ' ' :
logger . info ( ' Adding coin: %s ' , add_coin )
2022-07-11 21:36:28 +00:00
settings = load_config ( config_path )
2024-05-25 09:22:12 +00:00
if tor_control_password is None and settings . get ( ' use_tor ' , False ) :
extra_opts [ ' tor_control_password ' ] = settings . get ( ' tor_control_password ' , None )
2019-07-24 18:57:31 +00:00
2022-12-09 16:14:09 +00:00
if particl_wallet_mnemonic != ' none ' :
# Ensure Particl wallet is unencrypted or correct password is supplied
test_particl_encryption ( data_dir , settings , chain , use_tor_proxy )
2022-11-16 22:36:13 +00:00
2019-07-24 18:57:31 +00:00
if add_coin in settings [ ' chainclients ' ] :
2019-07-25 18:30:01 +00:00
coin_settings = settings [ ' chainclients ' ] [ add_coin ]
if coin_settings [ ' connection_type ' ] == ' none ' and coin_settings [ ' manage_daemon ' ] is False :
logger . info ( ' Enabling coin: %s ' , add_coin )
coin_settings [ ' connection_type ' ] = ' rpc '
coin_settings [ ' manage_daemon ' ] = True
with open ( config_path , ' w ' ) as fp :
json . dump ( settings , fp , indent = 4 )
logger . info ( ' Done. ' )
return 0
2019-07-24 18:57:31 +00:00
exitWithError ( ' {} is already in the settings file ' . format ( add_coin ) )
settings [ ' chainclients ' ] [ add_coin ] = chainclients [ add_coin ]
2022-03-23 22:00:35 +00:00
settings [ ' use_tor_proxy ' ] = use_tor_proxy
2019-07-24 18:57:31 +00:00
2020-12-27 19:39:10 +00:00
if not no_cores :
2022-06-04 20:41:24 +00:00
prepareCore ( add_coin , known_coins [ add_coin ] , settings , data_dir , extra_opts )
2019-07-24 18:57:31 +00:00
2019-07-25 12:30:47 +00:00
if not prepare_bin_only :
2022-06-04 20:41:24 +00:00
prepareDataDir ( add_coin , settings , chain , particl_wallet_mnemonic , extra_opts )
2022-07-11 21:36:28 +00:00
2022-12-09 16:14:09 +00:00
if particl_wallet_mnemonic != ' none ' :
2022-08-17 22:21:32 +00:00
initialise_wallets ( None , { add_coin , } , data_dir , settings , chain , use_tor_proxy )
2022-06-18 17:28:40 +00:00
2019-07-25 12:30:47 +00:00
with open ( config_path , ' w ' ) as fp :
json . dump ( settings , fp , indent = 4 )
2019-07-24 18:57:31 +00:00
2022-10-25 19:44:01 +00:00
logger . info ( f ' Done. Coin { add_coin } successfully added. ' )
2019-07-24 18:57:31 +00:00
return 0
logger . info ( ' With coins: %s ' , ' , ' . join ( with_coins ) )
2019-08-18 18:49:47 +00:00
if os . path . exists ( config_path ) :
if not prepare_bin_only :
exitWithError ( ' {} exists ' . format ( config_path ) )
else :
with open ( config_path ) as fs :
settings = json . load ( fs )
2022-11-20 18:58:10 +00:00
# Add temporary default config for any coins that have not been added
for c in with_coins :
if c not in settings [ ' chainclients ' ] :
settings [ ' chainclients ' ] [ c ] = chainclients [ c ]
2019-08-18 18:49:47 +00:00
else :
for c in with_coins :
withchainclients [ c ] = chainclients [ c ]
settings = {
' debug ' : True ,
2022-07-11 21:36:28 +00:00
' zmqhost ' : f ' tcp:// { PART_RPC_HOST } ' ,
2021-01-16 08:21:59 +00:00
' zmqport ' : PART_ZMQ_PORT + port_offset ,
2020-12-04 23:59:21 +00:00
' htmlhost ' : htmlhost ,
2021-01-16 08:21:59 +00:00
' htmlport ' : UI_HTML_PORT + port_offset ,
2019-08-18 18:49:47 +00:00
' network_key ' : ' 7sW2UEcHXvuqEjkpE5mD584zRaQYs6WXYohue4jLFZPTvMSxwvgs ' ,
' network_pubkey ' : ' 035758c4a22d7dd59165db02a56156e790224361eb3191f02197addcb3bde903d2 ' ,
' chainclients ' : withchainclients ,
2020-12-02 21:19:10 +00:00
' min_delay_event ' : 5 , # Min delay in seconds before reacting to an event
' max_delay_event ' : 50 , # Max delay in seconds before reacting to an event
2019-08-18 18:49:47 +00:00
' check_progress_seconds ' : 60 ,
' check_watched_seconds ' : 60 ,
2024-02-05 15:17:44 +00:00
' check_expired_seconds ' : 60 ,
' wallet_update_timeout ' : 10 , # Seconds to wait for wallet page update
2019-08-18 18:49:47 +00:00
}
2019-07-21 18:50:32 +00:00
2024-02-08 08:53:10 +00:00
wshost : str = extra_opts . get ( ' wshost ' , htmlhost )
2022-07-31 17:33:01 +00:00
if wshost != ' none ' :
settings [ ' wshost ' ] = wshost
settings [ ' wsport ' ] = UI_WS_PORT + port_offset
2022-03-23 22:00:35 +00:00
if use_tor_proxy :
tor_control_password = generate_salt ( 24 )
addTorSettings ( settings , tor_control_password )
2020-12-27 19:39:10 +00:00
if not no_cores :
for c in with_coins :
2022-06-04 20:41:24 +00:00
prepareCore ( c , known_coins [ c ] , settings , data_dir , extra_opts )
2019-07-25 12:06:58 +00:00
if prepare_bin_only :
logger . info ( ' Done. ' )
return 0
2019-07-25 12:30:47 +00:00
for c in with_coins :
2022-06-04 20:41:24 +00:00
prepareDataDir ( c , settings , chain , particl_wallet_mnemonic , extra_opts )
2019-07-24 18:57:31 +00:00
2019-07-21 18:50:32 +00:00
with open ( config_path , ' w ' ) as fp :
json . dump ( settings , fp , indent = 4 )
2022-12-09 16:14:09 +00:00
if particl_wallet_mnemonic == ' none ' :
2019-07-25 11:41:33 +00:00
logger . info ( ' Done. ' )
return 0
2022-07-11 21:36:28 +00:00
initialise_wallets ( particl_wallet_mnemonic , with_coins , data_dir , settings , chain , use_tor_proxy )
2022-07-08 16:41:01 +00:00
print ( ' Done. ' )
2019-07-21 18:50:32 +00:00
if __name__ == ' __main__ ' :
main ( )