mirror of
https://github.com/basicswap/basicswap.git
synced 2025-05-05 04:12:16 +00:00
commit
5270c7da0b
10 changed files with 313 additions and 276 deletions
basicswap
tests/basicswap
|
@ -5,17 +5,18 @@
|
||||||
# Distributed under the MIT software license, see the accompanying
|
# Distributed under the MIT software license, see the accompanying
|
||||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
import shlex
|
|
||||||
import socks
|
|
||||||
import random
|
|
||||||
import socket
|
|
||||||
import urllib
|
|
||||||
import logging
|
import logging
|
||||||
import threading
|
import os
|
||||||
import traceback
|
import random
|
||||||
|
import shlex
|
||||||
|
import socket
|
||||||
|
import socks
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
import traceback
|
||||||
|
import urllib
|
||||||
|
|
||||||
from sockshandler import SocksiPyHandler
|
from sockshandler import SocksiPyHandler
|
||||||
|
|
||||||
|
@ -42,9 +43,9 @@ def getaddrinfo_tor(*args):
|
||||||
|
|
||||||
|
|
||||||
class BaseApp(DBMethods):
|
class BaseApp(DBMethods):
|
||||||
def __init__(self, fp, data_dir, settings, chain, log_name="BasicSwap"):
|
def __init__(self, data_dir, settings, chain, log_name="BasicSwap"):
|
||||||
|
self.fp = None
|
||||||
self.log_name = log_name
|
self.log_name = log_name
|
||||||
self.fp = fp
|
|
||||||
self.fail_code = 0
|
self.fail_code = 0
|
||||||
self.mock_time_offset = 0
|
self.mock_time_offset = 0
|
||||||
|
|
||||||
|
@ -71,24 +72,33 @@ class BaseApp(DBMethods):
|
||||||
self.default_socket_timeout = socket.getdefaulttimeout()
|
self.default_socket_timeout = socket.getdefaulttimeout()
|
||||||
self.default_socket_getaddrinfo = socket.getaddrinfo
|
self.default_socket_getaddrinfo = socket.getaddrinfo
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
if self.fp:
|
||||||
|
self.fp.close()
|
||||||
|
|
||||||
def stopRunning(self, with_code=0):
|
def stopRunning(self, with_code=0):
|
||||||
self.fail_code = with_code
|
self.fail_code = with_code
|
||||||
with self.mxDB:
|
with self.mxDB:
|
||||||
self.chainstate_delay_event.set()
|
self.chainstate_delay_event.set()
|
||||||
self.delay_event.set()
|
self.delay_event.set()
|
||||||
|
|
||||||
|
def openLogFile(self):
|
||||||
|
self.fp = open(os.path.join(self.data_dir, "basicswap.log"), "a")
|
||||||
|
|
||||||
def prepareLogging(self):
|
def prepareLogging(self):
|
||||||
logging.setLoggerClass(BSXLogger)
|
logging.setLoggerClass(BSXLogger)
|
||||||
self.log = logging.getLogger(self.log_name)
|
self.log = logging.getLogger(self.log_name)
|
||||||
self.log.propagate = False
|
self.log.propagate = False
|
||||||
|
|
||||||
|
self.openLogFile()
|
||||||
|
|
||||||
# Remove any existing handlers
|
# Remove any existing handlers
|
||||||
self.log.handlers = []
|
self.log.handlers = []
|
||||||
|
|
||||||
formatter = logging.Formatter(
|
formatter = logging.Formatter(
|
||||||
"%(asctime)s %(levelname)s : %(message)s", "%Y-%m-%d %H:%M:%S"
|
"%(asctime)s %(levelname)s : %(message)s", "%Y-%m-%d %H:%M:%S"
|
||||||
)
|
)
|
||||||
stream_stdout = logging.StreamHandler()
|
stream_stdout = logging.StreamHandler(sys.stdout)
|
||||||
if self.log_name != "BasicSwap":
|
if self.log_name != "BasicSwap":
|
||||||
stream_stdout.setFormatter(
|
stream_stdout.setFormatter(
|
||||||
logging.Formatter(
|
logging.Formatter(
|
||||||
|
@ -98,6 +108,7 @@ class BaseApp(DBMethods):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
stream_stdout.setFormatter(formatter)
|
stream_stdout.setFormatter(formatter)
|
||||||
|
self.log_formatter = formatter
|
||||||
stream_fp = logging.StreamHandler(self.fp)
|
stream_fp = logging.StreamHandler(self.fp)
|
||||||
stream_fp.setFormatter(formatter)
|
stream_fp.setFormatter(formatter)
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import concurrent.futures
|
||||||
import copy
|
import copy
|
||||||
import datetime as dt
|
import datetime as dt
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import secrets
|
import secrets
|
||||||
|
@ -281,14 +282,13 @@ class BasicSwap(BaseApp):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
fp,
|
|
||||||
data_dir,
|
data_dir,
|
||||||
settings,
|
settings,
|
||||||
chain,
|
chain,
|
||||||
log_name="BasicSwap",
|
log_name="BasicSwap",
|
||||||
transient_instance=False,
|
transient_instance=False,
|
||||||
):
|
):
|
||||||
super().__init__(fp, data_dir, settings, chain, log_name)
|
super().__init__(data_dir, settings, chain, log_name)
|
||||||
|
|
||||||
v = __version__.split(".")
|
v = __version__.split(".")
|
||||||
self._version = struct.pack(">HHH", int(v[0]), int(v[1]), int(v[2]))
|
self._version = struct.pack(">HHH", int(v[0]), int(v[1]), int(v[2]))
|
||||||
|
@ -352,6 +352,13 @@ class BasicSwap(BaseApp):
|
||||||
self._expire_db_records_after = self.get_int_setting(
|
self._expire_db_records_after = self.get_int_setting(
|
||||||
"expire_db_records_after", 7 * 86400, 0, 31 * 86400
|
"expire_db_records_after", 7 * 86400, 0, 31 * 86400
|
||||||
) # Seconds
|
) # Seconds
|
||||||
|
self._max_logfile_bytes = self.settings.get(
|
||||||
|
"max_logfile_size", 100
|
||||||
|
) # In MB 0 to disable truncation
|
||||||
|
if self._max_logfile_bytes > 0:
|
||||||
|
self._max_logfile_bytes *= 1024 * 1024
|
||||||
|
self._max_logfiles = self.get_int_setting("max_logfiles", 10, 1, 100)
|
||||||
|
|
||||||
self._notifications_cache = {}
|
self._notifications_cache = {}
|
||||||
self._is_encrypted = None
|
self._is_encrypted = None
|
||||||
self._is_locked = None
|
self._is_locked = None
|
||||||
|
@ -9724,6 +9731,51 @@ class BasicSwap(BaseApp):
|
||||||
self.checkAcceptedBids()
|
self.checkAcceptedBids()
|
||||||
self._last_checked_expired = now
|
self._last_checked_expired = now
|
||||||
|
|
||||||
|
if self._max_logfile_bytes > 0:
|
||||||
|
logfile_size: int = self.fp.tell()
|
||||||
|
self.log.debug(f"Log file bytes: {logfile_size}.")
|
||||||
|
if logfile_size > self._max_logfile_bytes:
|
||||||
|
for i, log_handler in enumerate(self.log.handlers):
|
||||||
|
stream_name = getattr(log_handler.stream, "name", "")
|
||||||
|
if stream_name.endswith(".log"):
|
||||||
|
del self.log.handlers[i]
|
||||||
|
break
|
||||||
|
|
||||||
|
self.fp.close()
|
||||||
|
log_path = os.path.join(self.data_dir, "basicswap.log")
|
||||||
|
if self._max_logfiles == 1:
|
||||||
|
os.remove(log_path)
|
||||||
|
else:
|
||||||
|
last_log = os.path.join(
|
||||||
|
self.data_dir,
|
||||||
|
f"basicswap_{self._max_logfiles - 1:0>2}.log",
|
||||||
|
)
|
||||||
|
if os.path.exists(last_log):
|
||||||
|
os.remove(last_log)
|
||||||
|
|
||||||
|
for i in range(self._max_logfiles - 2, 0, -1):
|
||||||
|
path_from = os.path.join(
|
||||||
|
self.data_dir, f"basicswap_{i:0>2}.log"
|
||||||
|
)
|
||||||
|
path_to = os.path.join(
|
||||||
|
self.data_dir, f"basicswap_{i + 1:0>2}.log"
|
||||||
|
)
|
||||||
|
if os.path.exists(path_from):
|
||||||
|
os.rename(path_from, path_to)
|
||||||
|
|
||||||
|
log_path = os.path.join(self.data_dir, "basicswap.log")
|
||||||
|
os.rename(
|
||||||
|
log_path,
|
||||||
|
os.path.join(self.data_dir, "basicswap_01.log"),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.openLogFile()
|
||||||
|
|
||||||
|
stream_fp = logging.StreamHandler(self.fp)
|
||||||
|
stream_fp.setFormatter(self.log_formatter)
|
||||||
|
self.log.addHandler(stream_fp)
|
||||||
|
self.log.info("Log file rotated.")
|
||||||
|
|
||||||
if now - self._last_checked_actions >= self.check_actions_seconds:
|
if now - self._last_checked_actions >= self.check_actions_seconds:
|
||||||
self.checkQueuedActions()
|
self.checkQueuedActions()
|
||||||
self._last_checked_actions = now
|
self._last_checked_actions = now
|
||||||
|
|
|
@ -1733,48 +1733,45 @@ def test_particl_encryption(data_dir, settings, chain, use_tor_proxy):
|
||||||
swap_client = None
|
swap_client = None
|
||||||
daemons = []
|
daemons = []
|
||||||
daemon_args = ["-noconnect", "-nodnsseed", "-nofindpeers", "-nostaking"]
|
daemon_args = ["-noconnect", "-nodnsseed", "-nofindpeers", "-nostaking"]
|
||||||
with open(os.path.join(data_dir, "basicswap.log"), "a") as fp:
|
try:
|
||||||
try:
|
swap_client = BasicSwap(data_dir, settings, chain, transient_instance=True)
|
||||||
swap_client = BasicSwap(
|
if not swap_client.use_tor_proxy:
|
||||||
fp, data_dir, settings, chain, transient_instance=True
|
# Cannot set -bind or -whitebind together with -listen=0
|
||||||
)
|
daemon_args.append("-nolisten")
|
||||||
if not swap_client.use_tor_proxy:
|
c = Coins.PART
|
||||||
# Cannot set -bind or -whitebind together with -listen=0
|
coin_name = "particl"
|
||||||
daemon_args.append("-nolisten")
|
coin_settings = settings["chainclients"][coin_name]
|
||||||
c = Coins.PART
|
daemon_args += getCoreBinArgs(c, coin_settings, prepare=True)
|
||||||
coin_name = "particl"
|
extra_config = {"stdout_to_file": True}
|
||||||
coin_settings = settings["chainclients"][coin_name]
|
if coin_settings["manage_daemon"]:
|
||||||
daemon_args += getCoreBinArgs(c, coin_settings, prepare=True)
|
filename: str = getCoreBinName(c, coin_settings, coin_name + "d")
|
||||||
extra_config = {"stdout_to_file": True}
|
daemons.append(
|
||||||
if coin_settings["manage_daemon"]:
|
startDaemon(
|
||||||
filename: str = getCoreBinName(c, coin_settings, coin_name + "d")
|
coin_settings["datadir"],
|
||||||
daemons.append(
|
coin_settings["bindir"],
|
||||||
startDaemon(
|
filename,
|
||||||
coin_settings["datadir"],
|
daemon_args,
|
||||||
coin_settings["bindir"],
|
extra_config=extra_config,
|
||||||
filename,
|
|
||||||
daemon_args,
|
|
||||||
extra_config=extra_config,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
swap_client.setDaemonPID(c, daemons[-1].handle.pid)
|
)
|
||||||
swap_client.setCoinRunParams(c)
|
swap_client.setDaemonPID(c, daemons[-1].handle.pid)
|
||||||
swap_client.createCoinInterface(c)
|
swap_client.setCoinRunParams(c)
|
||||||
swap_client.waitForDaemonRPC(c, with_wallet=True)
|
swap_client.createCoinInterface(c)
|
||||||
|
swap_client.waitForDaemonRPC(c, with_wallet=True)
|
||||||
|
|
||||||
if swap_client.ci(c).isWalletEncrypted():
|
if swap_client.ci(c).isWalletEncrypted():
|
||||||
logger.info("Particl Wallet is encrypted")
|
logger.info("Particl Wallet is encrypted")
|
||||||
if WALLET_ENCRYPTION_PWD == "":
|
if WALLET_ENCRYPTION_PWD == "":
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Must set WALLET_ENCRYPTION_PWD to add coin when Particl wallet is encrypted"
|
"Must set WALLET_ENCRYPTION_PWD to add coin when Particl wallet is encrypted"
|
||||||
)
|
)
|
||||||
swap_client.ci(c).unlockWallet(WALLET_ENCRYPTION_PWD)
|
swap_client.ci(c).unlockWallet(WALLET_ENCRYPTION_PWD)
|
||||||
finally:
|
finally:
|
||||||
if swap_client:
|
if swap_client:
|
||||||
swap_client.finalise()
|
swap_client.finalise()
|
||||||
del swap_client
|
del swap_client
|
||||||
for d in daemons:
|
for d in daemons:
|
||||||
finalise_daemon(d)
|
finalise_daemon(d)
|
||||||
|
|
||||||
|
|
||||||
def encrypt_wallet(swap_client, coin_type) -> None:
|
def encrypt_wallet(swap_client, coin_type) -> None:
|
||||||
|
@ -1793,217 +1790,206 @@ def initialise_wallets(
|
||||||
|
|
||||||
coins_failed_to_initialise = []
|
coins_failed_to_initialise = []
|
||||||
|
|
||||||
with open(os.path.join(data_dir, "basicswap.log"), "a") as fp:
|
try:
|
||||||
try:
|
swap_client = BasicSwap(data_dir, settings, chain, transient_instance=True)
|
||||||
swap_client = BasicSwap(
|
if not swap_client.use_tor_proxy:
|
||||||
fp, data_dir, settings, chain, transient_instance=True
|
# Cannot set -bind or -whitebind together with -listen=0
|
||||||
)
|
daemon_args.append("-nolisten")
|
||||||
if not swap_client.use_tor_proxy:
|
coins_to_create_wallets_for = (
|
||||||
# Cannot set -bind or -whitebind together with -listen=0
|
Coins.PART,
|
||||||
daemon_args.append("-nolisten")
|
Coins.BTC,
|
||||||
coins_to_create_wallets_for = (
|
Coins.LTC,
|
||||||
Coins.PART,
|
Coins.DOGE,
|
||||||
Coins.BTC,
|
Coins.DCR,
|
||||||
Coins.LTC,
|
Coins.DASH,
|
||||||
Coins.DOGE,
|
)
|
||||||
Coins.DCR,
|
# Always start Particl, it must be running to initialise a wallet in addcoin mode
|
||||||
Coins.DASH,
|
# Particl must be loaded first as subsequent coins are initialised from the Particl mnemonic
|
||||||
)
|
start_daemons = [
|
||||||
# Always start Particl, it must be running to initialise a wallet in addcoin mode
|
"particl",
|
||||||
# Particl must be loaded first as subsequent coins are initialised from the Particl mnemonic
|
] + [c for c in with_coins if c != "particl"]
|
||||||
start_daemons = [
|
for coin_name in start_daemons:
|
||||||
"particl",
|
coin_settings = settings["chainclients"][coin_name]
|
||||||
] + [c for c in with_coins if c != "particl"]
|
wallet_name = coin_settings.get("wallet_name", "wallet.dat")
|
||||||
for coin_name in start_daemons:
|
c = swap_client.getCoinIdFromName(coin_name)
|
||||||
coin_settings = settings["chainclients"][coin_name]
|
|
||||||
wallet_name = coin_settings.get("wallet_name", "wallet.dat")
|
|
||||||
c = swap_client.getCoinIdFromName(coin_name)
|
|
||||||
|
|
||||||
if c == Coins.XMR:
|
if c == Coins.XMR:
|
||||||
if coin_settings["manage_wallet_daemon"]:
|
if coin_settings["manage_wallet_daemon"]:
|
||||||
filename = (
|
filename = (
|
||||||
coin_name
|
coin_name + "-wallet-rpc" + (".exe" if os.name == "nt" else "")
|
||||||
+ "-wallet-rpc"
|
)
|
||||||
+ (".exe" if os.name == "nt" else "")
|
filename: str = getWalletBinName(
|
||||||
|
c, coin_settings, coin_name + "-wallet-rpc"
|
||||||
|
)
|
||||||
|
daemons.append(
|
||||||
|
startXmrWalletDaemon(
|
||||||
|
coin_settings["datadir"],
|
||||||
|
coin_settings["bindir"],
|
||||||
|
filename,
|
||||||
)
|
)
|
||||||
filename: str = getWalletBinName(
|
)
|
||||||
c, coin_settings, coin_name + "-wallet-rpc"
|
elif c == Coins.WOW:
|
||||||
|
if coin_settings["manage_wallet_daemon"]:
|
||||||
|
filename: str = getWalletBinName(
|
||||||
|
c, coin_settings, coin_name + "-wallet-rpc"
|
||||||
|
)
|
||||||
|
daemons.append(
|
||||||
|
startXmrWalletDaemon(
|
||||||
|
coin_settings["datadir"],
|
||||||
|
coin_settings["bindir"],
|
||||||
|
filename,
|
||||||
)
|
)
|
||||||
daemons.append(
|
)
|
||||||
startXmrWalletDaemon(
|
elif c == Coins.DCR:
|
||||||
coin_settings["datadir"],
|
pass
|
||||||
coin_settings["bindir"],
|
else:
|
||||||
filename,
|
if coin_settings["manage_daemon"]:
|
||||||
|
filename: str = getCoreBinName(c, coin_settings, coin_name + "d")
|
||||||
|
coin_args = (
|
||||||
|
["-nofindpeers", "-nostaking"] if c == Coins.PART else []
|
||||||
|
)
|
||||||
|
coin_args += getCoreBinArgs(c, coin_settings, prepare=True)
|
||||||
|
|
||||||
|
if c == Coins.FIRO:
|
||||||
|
coin_args += [
|
||||||
|
"-hdseed={}".format(
|
||||||
|
swap_client.getWalletKey(Coins.FIRO, 1).hex()
|
||||||
)
|
)
|
||||||
)
|
|
||||||
elif c == Coins.WOW:
|
|
||||||
if coin_settings["manage_wallet_daemon"]:
|
|
||||||
filename: str = getWalletBinName(
|
|
||||||
c, coin_settings, coin_name + "-wallet-rpc"
|
|
||||||
)
|
|
||||||
daemons.append(
|
|
||||||
startXmrWalletDaemon(
|
|
||||||
coin_settings["datadir"],
|
|
||||||
coin_settings["bindir"],
|
|
||||||
filename,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
elif c == Coins.DCR:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if coin_settings["manage_daemon"]:
|
|
||||||
filename: str = getCoreBinName(
|
|
||||||
c, coin_settings, coin_name + "d"
|
|
||||||
)
|
|
||||||
coin_args = (
|
|
||||||
["-nofindpeers", "-nostaking"] if c == Coins.PART else []
|
|
||||||
)
|
|
||||||
coin_args += getCoreBinArgs(c, coin_settings, prepare=True)
|
|
||||||
|
|
||||||
if c == Coins.FIRO:
|
|
||||||
coin_args += [
|
|
||||||
"-hdseed={}".format(
|
|
||||||
swap_client.getWalletKey(Coins.FIRO, 1).hex()
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
extra_config = {"stdout_to_file": True}
|
|
||||||
daemons.append(
|
|
||||||
startDaemon(
|
|
||||||
coin_settings["datadir"],
|
|
||||||
coin_settings["bindir"],
|
|
||||||
filename,
|
|
||||||
daemon_args + coin_args,
|
|
||||||
extra_config=extra_config,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
swap_client.setDaemonPID(c, daemons[-1].handle.pid)
|
|
||||||
swap_client.setCoinRunParams(c)
|
|
||||||
swap_client.createCoinInterface(c)
|
|
||||||
|
|
||||||
if c in coins_to_create_wallets_for:
|
|
||||||
if c == Coins.DCR:
|
|
||||||
if coin_settings["manage_wallet_daemon"] is False:
|
|
||||||
continue
|
|
||||||
from basicswap.interface.dcr.util import createDCRWallet
|
|
||||||
|
|
||||||
dcr_password = (
|
|
||||||
coin_settings["wallet_pwd"]
|
|
||||||
if WALLET_ENCRYPTION_PWD == ""
|
|
||||||
else WALLET_ENCRYPTION_PWD
|
|
||||||
)
|
|
||||||
extra_opts = [
|
|
||||||
'--appdata="{}"'.format(coin_settings["datadir"]),
|
|
||||||
"--pass={}".format(dcr_password),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
filename: str = getWalletBinName(c, coin_settings, "dcrwallet")
|
extra_config = {"stdout_to_file": True}
|
||||||
args = [
|
daemons.append(
|
||||||
os.path.join(coin_settings["bindir"], filename),
|
startDaemon(
|
||||||
"--create",
|
coin_settings["datadir"],
|
||||||
] + extra_opts
|
coin_settings["bindir"],
|
||||||
hex_seed = swap_client.getWalletKey(Coins.DCR, 1).hex()
|
filename,
|
||||||
createDCRWallet(args, hex_seed, logger, threading.Event())
|
daemon_args + coin_args,
|
||||||
continue
|
extra_config=extra_config,
|
||||||
swap_client.waitForDaemonRPC(c, with_wallet=False)
|
|
||||||
# Create wallet if it doesn't exist yet
|
|
||||||
wallets = swap_client.callcoinrpc(c, "listwallets")
|
|
||||||
if wallet_name not in wallets:
|
|
||||||
logger.info(
|
|
||||||
f'Creating wallet "{wallet_name}" for {getCoinName(c)}.'
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
swap_client.setDaemonPID(c, daemons[-1].handle.pid)
|
||||||
|
swap_client.setCoinRunParams(c)
|
||||||
|
swap_client.createCoinInterface(c)
|
||||||
|
|
||||||
if c in (Coins.BTC, Coins.LTC, Coins.DOGE, Coins.DASH):
|
if c in coins_to_create_wallets_for:
|
||||||
# wallet_name, disable_private_keys, blank, passphrase, avoid_reuse, descriptors
|
if c == Coins.DCR:
|
||||||
|
if coin_settings["manage_wallet_daemon"] is False:
|
||||||
|
continue
|
||||||
|
from basicswap.interface.dcr.util import createDCRWallet
|
||||||
|
|
||||||
use_descriptors = coin_settings.get(
|
dcr_password = (
|
||||||
"use_descriptors", False
|
coin_settings["wallet_pwd"]
|
||||||
)
|
if WALLET_ENCRYPTION_PWD == ""
|
||||||
|
else WALLET_ENCRYPTION_PWD
|
||||||
|
)
|
||||||
|
extra_opts = [
|
||||||
|
'--appdata="{}"'.format(coin_settings["datadir"]),
|
||||||
|
"--pass={}".format(dcr_password),
|
||||||
|
]
|
||||||
|
|
||||||
|
filename: str = getWalletBinName(c, coin_settings, "dcrwallet")
|
||||||
|
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())
|
||||||
|
continue
|
||||||
|
swap_client.waitForDaemonRPC(c, with_wallet=False)
|
||||||
|
# Create wallet if it doesn't exist yet
|
||||||
|
wallets = swap_client.callcoinrpc(c, "listwallets")
|
||||||
|
if wallet_name not in wallets:
|
||||||
|
logger.info(
|
||||||
|
f'Creating wallet "{wallet_name}" for {getCoinName(c)}.'
|
||||||
|
)
|
||||||
|
|
||||||
|
if c in (Coins.BTC, Coins.LTC, Coins.DOGE, Coins.DASH):
|
||||||
|
# wallet_name, disable_private_keys, blank, passphrase, avoid_reuse, descriptors
|
||||||
|
|
||||||
|
use_descriptors = coin_settings.get("use_descriptors", False)
|
||||||
|
swap_client.callcoinrpc(
|
||||||
|
c,
|
||||||
|
"createwallet",
|
||||||
|
[
|
||||||
|
wallet_name,
|
||||||
|
False,
|
||||||
|
True,
|
||||||
|
WALLET_ENCRYPTION_PWD,
|
||||||
|
False,
|
||||||
|
use_descriptors,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
if use_descriptors:
|
||||||
swap_client.callcoinrpc(
|
swap_client.callcoinrpc(
|
||||||
c,
|
c,
|
||||||
"createwallet",
|
"createwallet",
|
||||||
[
|
[
|
||||||
wallet_name,
|
coin_settings["watch_wallet_name"],
|
||||||
False,
|
|
||||||
True,
|
True,
|
||||||
WALLET_ENCRYPTION_PWD,
|
True,
|
||||||
|
"",
|
||||||
False,
|
False,
|
||||||
use_descriptors,
|
use_descriptors,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
if use_descriptors:
|
|
||||||
swap_client.callcoinrpc(
|
|
||||||
c,
|
|
||||||
"createwallet",
|
|
||||||
[
|
|
||||||
coin_settings["watch_wallet_name"],
|
|
||||||
True,
|
|
||||||
True,
|
|
||||||
"",
|
|
||||||
False,
|
|
||||||
use_descriptors,
|
|
||||||
],
|
|
||||||
)
|
|
||||||
swap_client.ci(c).unlockWallet(WALLET_ENCRYPTION_PWD)
|
|
||||||
else:
|
|
||||||
swap_client.callcoinrpc(
|
|
||||||
c,
|
|
||||||
"createwallet",
|
|
||||||
[
|
|
||||||
wallet_name,
|
|
||||||
],
|
|
||||||
)
|
|
||||||
if WALLET_ENCRYPTION_PWD != "":
|
|
||||||
encrypt_wallet(swap_client, c)
|
|
||||||
|
|
||||||
if c == Coins.LTC:
|
|
||||||
password = (
|
|
||||||
WALLET_ENCRYPTION_PWD
|
|
||||||
if WALLET_ENCRYPTION_PWD != ""
|
|
||||||
else None
|
|
||||||
)
|
|
||||||
swap_client.ci(Coins.LTC_MWEB).init_wallet(password)
|
|
||||||
|
|
||||||
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"]
|
|
||||||
generated_mnemonic = True
|
|
||||||
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)
|
swap_client.ci(c).unlockWallet(WALLET_ENCRYPTION_PWD)
|
||||||
|
else:
|
||||||
for coin_name in with_coins:
|
swap_client.callcoinrpc(
|
||||||
c = swap_client.getCoinIdFromName(coin_name)
|
c,
|
||||||
if c in (Coins.PART,):
|
"createwallet",
|
||||||
continue
|
[
|
||||||
if c not in (Coins.DCR,):
|
wallet_name,
|
||||||
# initialiseWallet only sets main_wallet_seedid_
|
],
|
||||||
swap_client.waitForDaemonRPC(c)
|
|
||||||
try:
|
|
||||||
swap_client.initialiseWallet(c, raise_errors=True)
|
|
||||||
except Exception as e:
|
|
||||||
coins_failed_to_initialise.append((c, e))
|
|
||||||
if WALLET_ENCRYPTION_PWD != "" and c not in coins_to_create_wallets_for:
|
|
||||||
try:
|
|
||||||
swap_client.ci(c).changeWalletPassword(
|
|
||||||
"", WALLET_ENCRYPTION_PWD
|
|
||||||
)
|
)
|
||||||
except Exception as e: # noqa: F841
|
if WALLET_ENCRYPTION_PWD != "":
|
||||||
logger.warning(f"changeWalletPassword failed for {coin_name}.")
|
encrypt_wallet(swap_client, c)
|
||||||
|
|
||||||
finally:
|
if c == Coins.LTC:
|
||||||
if swap_client:
|
password = (
|
||||||
swap_client.finalise()
|
WALLET_ENCRYPTION_PWD
|
||||||
del swap_client
|
if WALLET_ENCRYPTION_PWD != ""
|
||||||
for d in daemons:
|
else None
|
||||||
finalise_daemon(d)
|
)
|
||||||
|
swap_client.ci(Coins.LTC_MWEB).init_wallet(password)
|
||||||
|
|
||||||
|
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"]
|
||||||
|
generated_mnemonic = True
|
||||||
|
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)
|
||||||
|
|
||||||
|
for coin_name in with_coins:
|
||||||
|
c = swap_client.getCoinIdFromName(coin_name)
|
||||||
|
if c in (Coins.PART,):
|
||||||
|
continue
|
||||||
|
if c not in (Coins.DCR,):
|
||||||
|
# initialiseWallet only sets main_wallet_seedid_
|
||||||
|
swap_client.waitForDaemonRPC(c)
|
||||||
|
try:
|
||||||
|
swap_client.initialiseWallet(c, raise_errors=True)
|
||||||
|
except Exception as e:
|
||||||
|
coins_failed_to_initialise.append((c, e))
|
||||||
|
if WALLET_ENCRYPTION_PWD != "" and c not in coins_to_create_wallets_for:
|
||||||
|
try:
|
||||||
|
swap_client.ci(c).changeWalletPassword("", WALLET_ENCRYPTION_PWD)
|
||||||
|
except Exception as e: # noqa: F841
|
||||||
|
logger.warning(f"changeWalletPassword failed for {coin_name}.")
|
||||||
|
|
||||||
|
finally:
|
||||||
|
if swap_client:
|
||||||
|
swap_client.finalise()
|
||||||
|
del swap_client
|
||||||
|
for d in daemons:
|
||||||
|
finalise_daemon(d)
|
||||||
|
|
||||||
print("")
|
print("")
|
||||||
for pair in coins_failed_to_initialise:
|
for pair in coins_failed_to_initialise:
|
||||||
|
|
|
@ -272,8 +272,8 @@ def getCoreBinArgs(coin_id: int, coin_settings, prepare=False, use_tor_proxy=Fal
|
||||||
|
|
||||||
|
|
||||||
def runClient(
|
def runClient(
|
||||||
fp, data_dir: str, chain: str, start_only_coins: bool, log_prefix: str = "BasicSwap"
|
data_dir: str, chain: str, start_only_coins: bool, log_prefix: str = "BasicSwap"
|
||||||
):
|
) -> int:
|
||||||
global swap_client, logger
|
global swap_client, logger
|
||||||
daemons = []
|
daemons = []
|
||||||
pids = []
|
pids = []
|
||||||
|
@ -298,7 +298,7 @@ def runClient(
|
||||||
with open(settings_path) as fs:
|
with open(settings_path) as fs:
|
||||||
settings = json.load(fs)
|
settings = json.load(fs)
|
||||||
|
|
||||||
swap_client = BasicSwap(fp, data_dir, settings, chain, log_name=log_prefix)
|
swap_client = BasicSwap(data_dir, settings, chain, log_name=log_prefix)
|
||||||
logger = swap_client.log
|
logger = swap_client.log
|
||||||
|
|
||||||
if os.path.exists(pids_path):
|
if os.path.exists(pids_path):
|
||||||
|
@ -482,7 +482,6 @@ def runClient(
|
||||||
else cfg.DEFAULT_ALLOW_CORS
|
else cfg.DEFAULT_ALLOW_CORS
|
||||||
)
|
)
|
||||||
thread_http = HttpThread(
|
thread_http = HttpThread(
|
||||||
fp,
|
|
||||||
settings["htmlhost"],
|
settings["htmlhost"],
|
||||||
settings["htmlport"],
|
settings["htmlport"],
|
||||||
allow_cors,
|
allow_cors,
|
||||||
|
@ -548,6 +547,9 @@ def runClient(
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
swap_client.log.error(f"Error: {e}")
|
swap_client.log.error(f"Error: {e}")
|
||||||
|
|
||||||
|
fail_code: int = swap_client.fail_code
|
||||||
|
del swap_client
|
||||||
|
|
||||||
if os.path.exists(pids_path):
|
if os.path.exists(pids_path):
|
||||||
with open(pids_path) as fd:
|
with open(pids_path) as fd:
|
||||||
lines = fd.read().split("\n")
|
lines = fd.read().split("\n")
|
||||||
|
@ -561,6 +563,8 @@ def runClient(
|
||||||
with open(pids_path, "w") as fd:
|
with open(pids_path, "w") as fd:
|
||||||
fd.write(still_running)
|
fd.write(still_running)
|
||||||
|
|
||||||
|
return fail_code
|
||||||
|
|
||||||
|
|
||||||
def printVersion():
|
def printVersion():
|
||||||
logger.info(
|
logger.info(
|
||||||
|
@ -642,14 +646,11 @@ def main():
|
||||||
if not os.path.exists(data_dir):
|
if not os.path.exists(data_dir):
|
||||||
os.makedirs(data_dir)
|
os.makedirs(data_dir)
|
||||||
|
|
||||||
with open(os.path.join(data_dir, "basicswap.log"), "a") as fp:
|
logger.info(os.path.basename(sys.argv[0]) + ", version: " + __version__ + "\n\n")
|
||||||
logger.info(
|
fail_code = runClient(data_dir, chain, start_only_coins, log_prefix)
|
||||||
os.path.basename(sys.argv[0]) + ", version: " + __version__ + "\n\n"
|
|
||||||
)
|
|
||||||
runClient(fp, data_dir, chain, start_only_coins, log_prefix)
|
|
||||||
|
|
||||||
print("Done.")
|
print("Done.")
|
||||||
return swap_client.fail_code if swap_client is not None else 0
|
return fail_code
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -637,11 +637,10 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||||
|
|
||||||
|
|
||||||
class HttpThread(threading.Thread, HTTPServer):
|
class HttpThread(threading.Thread, HTTPServer):
|
||||||
def __init__(self, fp, host_name, port_no, allow_cors, swap_client):
|
def __init__(self, host_name, port_no, allow_cors, swap_client):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
|
|
||||||
self.stop_event = threading.Event()
|
self.stop_event = threading.Event()
|
||||||
self.fp = fp
|
|
||||||
self.host_name = host_name
|
self.host_name = host_name
|
||||||
self.port_no = port_no
|
self.port_no = port_no
|
||||||
self.allow_cors = allow_cors
|
self.allow_cors = allow_cors
|
||||||
|
|
|
@ -408,9 +408,8 @@ class Test(unittest.TestCase):
|
||||||
settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
|
settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
|
||||||
with open(settings_path) as fs:
|
with open(settings_path) as fs:
|
||||||
settings = json.load(fs)
|
settings = json.load(fs)
|
||||||
fp = open(os.path.join(basicswap_dir, "basicswap.log"), "w")
|
|
||||||
sc = BasicSwap(
|
sc = BasicSwap(
|
||||||
fp, basicswap_dir, settings, "regtest", log_name="BasicSwap{}".format(i)
|
basicswap_dir, settings, "regtest", log_name="BasicSwap{}".format(i)
|
||||||
)
|
)
|
||||||
cls.swap_clients.append(sc)
|
cls.swap_clients.append(sc)
|
||||||
sc.setDaemonPID(Coins.BTC, cls.daemons[0].handle.pid)
|
sc.setDaemonPID(Coins.BTC, cls.daemons[0].handle.pid)
|
||||||
|
@ -423,7 +422,7 @@ class Test(unittest.TestCase):
|
||||||
|
|
||||||
sc.start()
|
sc.start()
|
||||||
|
|
||||||
t = HttpThread(sc.fp, TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, sc)
|
t = HttpThread(TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, sc)
|
||||||
cls.http_threads.append(t)
|
cls.http_threads.append(t)
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
|
@ -484,7 +483,6 @@ class Test(unittest.TestCase):
|
||||||
t.join()
|
t.join()
|
||||||
for c in cls.swap_clients:
|
for c in cls.swap_clients:
|
||||||
c.finalise()
|
c.finalise()
|
||||||
c.fp.close()
|
|
||||||
|
|
||||||
stopDaemons(cls.daemons)
|
stopDaemons(cls.daemons)
|
||||||
|
|
||||||
|
|
|
@ -325,9 +325,7 @@ class Test(unittest.TestCase):
|
||||||
settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
|
settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
|
||||||
with open(settings_path) as fs:
|
with open(settings_path) as fs:
|
||||||
settings = json.load(fs)
|
settings = json.load(fs)
|
||||||
fp = open(os.path.join(basicswap_dir, "basicswap.log"), "w")
|
|
||||||
sc = BasicSwap(
|
sc = BasicSwap(
|
||||||
fp,
|
|
||||||
basicswap_dir,
|
basicswap_dir,
|
||||||
settings,
|
settings,
|
||||||
"regtest",
|
"regtest",
|
||||||
|
@ -338,7 +336,7 @@ class Test(unittest.TestCase):
|
||||||
sc.setDaemonPID(Coins.PART, cls.part_daemons[i].handle.pid)
|
sc.setDaemonPID(Coins.PART, cls.part_daemons[i].handle.pid)
|
||||||
sc.start()
|
sc.start()
|
||||||
|
|
||||||
t = HttpThread(sc.fp, TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, sc)
|
t = HttpThread(TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, sc)
|
||||||
cls.http_threads.append(t)
|
cls.http_threads.append(t)
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
|
@ -397,7 +395,6 @@ class Test(unittest.TestCase):
|
||||||
t.join()
|
t.join()
|
||||||
for c in cls.swap_clients:
|
for c in cls.swap_clients:
|
||||||
c.finalise()
|
c.finalise()
|
||||||
c.fp.close()
|
|
||||||
|
|
||||||
stopDaemons(cls.part_daemons)
|
stopDaemons(cls.part_daemons)
|
||||||
stopDaemons(cls.btc_daemons)
|
stopDaemons(cls.btc_daemons)
|
||||||
|
|
|
@ -365,9 +365,8 @@ class Test(unittest.TestCase):
|
||||||
settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
|
settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
|
||||||
with open(settings_path) as fs:
|
with open(settings_path) as fs:
|
||||||
settings = json.load(fs)
|
settings = json.load(fs)
|
||||||
fp = open(os.path.join(basicswap_dir, "basicswap.log"), "w")
|
|
||||||
sc = BasicSwap(
|
sc = BasicSwap(
|
||||||
fp, basicswap_dir, settings, "regtest", log_name="BasicSwap{}".format(i)
|
basicswap_dir, settings, "regtest", log_name="BasicSwap{}".format(i)
|
||||||
)
|
)
|
||||||
cls.swap_clients.append(sc)
|
cls.swap_clients.append(sc)
|
||||||
|
|
||||||
|
@ -376,7 +375,7 @@ class Test(unittest.TestCase):
|
||||||
sc.setDaemonPID(Coins.PART, cls.daemons[2 + i].handle.pid)
|
sc.setDaemonPID(Coins.PART, cls.daemons[2 + i].handle.pid)
|
||||||
sc.start()
|
sc.start()
|
||||||
|
|
||||||
t = HttpThread(sc.fp, TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, sc)
|
t = HttpThread(TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, sc)
|
||||||
cls.http_threads.append(t)
|
cls.http_threads.append(t)
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
|
@ -437,7 +436,6 @@ class Test(unittest.TestCase):
|
||||||
t.join()
|
t.join()
|
||||||
for c in cls.swap_clients:
|
for c in cls.swap_clients:
|
||||||
c.finalise()
|
c.finalise()
|
||||||
c.fp.close()
|
|
||||||
|
|
||||||
stopDaemons(cls.daemons)
|
stopDaemons(cls.daemons)
|
||||||
cls.http_threads.clear()
|
cls.http_threads.clear()
|
||||||
|
|
|
@ -414,9 +414,8 @@ class Test(unittest.TestCase):
|
||||||
settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
|
settings_path = os.path.join(basicswap_dir, cfg.CONFIG_FILENAME)
|
||||||
with open(settings_path) as fs:
|
with open(settings_path) as fs:
|
||||||
settings = json.load(fs)
|
settings = json.load(fs)
|
||||||
fp = open(os.path.join(basicswap_dir, "basicswap.log"), "w")
|
|
||||||
sc = BasicSwap(
|
sc = BasicSwap(
|
||||||
fp, basicswap_dir, settings, "regtest", log_name="BasicSwap{}".format(i)
|
basicswap_dir, settings, "regtest", log_name="BasicSwap{}".format(i)
|
||||||
)
|
)
|
||||||
cls.swap_clients.append(sc)
|
cls.swap_clients.append(sc)
|
||||||
sc.setDaemonPID(Coins.BTC, cls.daemons[0].handle.pid)
|
sc.setDaemonPID(Coins.BTC, cls.daemons[0].handle.pid)
|
||||||
|
@ -424,7 +423,7 @@ class Test(unittest.TestCase):
|
||||||
sc.setDaemonPID(Coins.PART, cls.daemons[2 + i].handle.pid)
|
sc.setDaemonPID(Coins.PART, cls.daemons[2 + i].handle.pid)
|
||||||
sc.start()
|
sc.start()
|
||||||
|
|
||||||
t = HttpThread(sc.fp, TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, sc)
|
t = HttpThread(TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, sc)
|
||||||
cls.http_threads.append(t)
|
cls.http_threads.append(t)
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
|
@ -482,7 +481,6 @@ class Test(unittest.TestCase):
|
||||||
t.join()
|
t.join()
|
||||||
for c in cls.swap_clients:
|
for c in cls.swap_clients:
|
||||||
c.finalise()
|
c.finalise()
|
||||||
c.fp.close()
|
|
||||||
|
|
||||||
stopDaemons(cls.daemons)
|
stopDaemons(cls.daemons)
|
||||||
cls.http_threads.clear()
|
cls.http_threads.clear()
|
||||||
|
|
|
@ -654,9 +654,7 @@ class BaseTest(unittest.TestCase):
|
||||||
if cls.restore_instance and i == 1:
|
if cls.restore_instance and i == 1:
|
||||||
cls.network_key = settings["network_key"]
|
cls.network_key = settings["network_key"]
|
||||||
cls.network_pubkey = settings["network_pubkey"]
|
cls.network_pubkey = settings["network_pubkey"]
|
||||||
fp = open(os.path.join(basicswap_dir, "basicswap.log"), "w")
|
|
||||||
sc = BasicSwap(
|
sc = BasicSwap(
|
||||||
fp,
|
|
||||||
basicswap_dir,
|
basicswap_dir,
|
||||||
settings,
|
settings,
|
||||||
"regtest",
|
"regtest",
|
||||||
|
@ -684,7 +682,7 @@ class BaseTest(unittest.TestCase):
|
||||||
# Import a random seed to keep the existing test behaviour. BTC core rescans even with timestamp: now.
|
# Import a random seed to keep the existing test behaviour. BTC core rescans even with timestamp: now.
|
||||||
sc.ci(Coins.BTC).initialiseWallet(random.randbytes(32))
|
sc.ci(Coins.BTC).initialiseWallet(random.randbytes(32))
|
||||||
|
|
||||||
t = HttpThread(sc.fp, TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, sc)
|
t = HttpThread(TEST_HTTP_HOST, TEST_HTTP_PORT + i, False, sc)
|
||||||
cls.http_threads.append(t)
|
cls.http_threads.append(t)
|
||||||
t.start()
|
t.start()
|
||||||
# Set future block rewards to nowhere (a random address), so wallet amounts stay constant
|
# Set future block rewards to nowhere (a random address), so wallet amounts stay constant
|
||||||
|
@ -952,7 +950,6 @@ class BaseTest(unittest.TestCase):
|
||||||
logging.info("Stopping swap clients")
|
logging.info("Stopping swap clients")
|
||||||
for c in cls.swap_clients:
|
for c in cls.swap_clients:
|
||||||
c.finalise()
|
c.finalise()
|
||||||
c.fp.close()
|
|
||||||
|
|
||||||
logging.info("Stopping coin nodes")
|
logging.info("Stopping coin nodes")
|
||||||
stopDaemons(cls.xmr_daemons)
|
stopDaemons(cls.xmr_daemons)
|
||||||
|
|
Loading…
Reference in a new issue