mirror of
https://github.com/basicswap/basicswap.git
synced 2025-11-05 18:38:09 +01:00
Merge pull request #297 from tecnovert/wallet_encryption
Add workaround for btc seed changing after encrypting wallet.
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -8,6 +8,8 @@ __pycache__
|
|||||||
/*.eggs
|
/*.eggs
|
||||||
.tox
|
.tox
|
||||||
.eggs
|
.eggs
|
||||||
|
.ruff_cache
|
||||||
|
.pytest_cache
|
||||||
*~
|
*~
|
||||||
|
|
||||||
# geckodriver.log
|
# geckodriver.log
|
||||||
|
|||||||
@@ -1358,7 +1358,9 @@ class BasicSwap(BaseApp):
|
|||||||
legacy_root_hash = ci.getSeedHash(root_key, 20)
|
legacy_root_hash = ci.getSeedHash(root_key, 20)
|
||||||
self.setStringKV(key_str, legacy_root_hash.hex(), cursor)
|
self.setStringKV(key_str, legacy_root_hash.hex(), cursor)
|
||||||
|
|
||||||
def initialiseWallet(self, interface_type, raise_errors: bool = False) -> None:
|
def initialiseWallet(
|
||||||
|
self, interface_type, raise_errors: bool = False, restore_time: int = -1
|
||||||
|
) -> None:
|
||||||
if interface_type == Coins.PART:
|
if interface_type == Coins.PART:
|
||||||
return
|
return
|
||||||
ci = self.ci(interface_type)
|
ci = self.ci(interface_type)
|
||||||
@@ -1377,7 +1379,7 @@ class BasicSwap(BaseApp):
|
|||||||
|
|
||||||
root_key = self.getWalletKey(interface_type, 1)
|
root_key = self.getWalletKey(interface_type, 1)
|
||||||
try:
|
try:
|
||||||
ci.initialiseWallet(root_key)
|
ci.initialiseWallet(root_key, restore_time)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# < 0.21: sethdseed cannot set a new HD seed while still in Initial Block Download.
|
# < 0.21: sethdseed cannot set a new HD seed while still in Initial Block Download.
|
||||||
self.log.error(f"initialiseWallet failed: {e}")
|
self.log.error(f"initialiseWallet failed: {e}")
|
||||||
|
|||||||
@@ -182,6 +182,7 @@ BSX_UPDATE_UNMANAGED = toBool(
|
|||||||
UI_HTML_PORT = int(os.getenv("UI_HTML_PORT", 12700))
|
UI_HTML_PORT = int(os.getenv("UI_HTML_PORT", 12700))
|
||||||
UI_WS_PORT = int(os.getenv("UI_WS_PORT", 11700))
|
UI_WS_PORT = int(os.getenv("UI_WS_PORT", 11700))
|
||||||
COINS_RPCBIND_IP = os.getenv("COINS_RPCBIND_IP", "127.0.0.1")
|
COINS_RPCBIND_IP = os.getenv("COINS_RPCBIND_IP", "127.0.0.1")
|
||||||
|
DEFAULT_RESTORE_TIME = int(os.getenv("DEFAULT_RESTORE_TIME", 1577833261)) # 2020
|
||||||
|
|
||||||
PART_ZMQ_PORT = int(os.getenv("PART_ZMQ_PORT", 20792))
|
PART_ZMQ_PORT = int(os.getenv("PART_ZMQ_PORT", 20792))
|
||||||
PART_RPC_HOST = os.getenv("PART_RPC_HOST", "127.0.0.1")
|
PART_RPC_HOST = os.getenv("PART_RPC_HOST", "127.0.0.1")
|
||||||
@@ -1707,6 +1708,11 @@ def printHelp():
|
|||||||
DEFAULT_WOW_RESTORE_HEIGHT
|
DEFAULT_WOW_RESTORE_HEIGHT
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
print(
|
||||||
|
"--walletrestoretime=n Time to restore wallets from, default:{}, -1 for now.".format(
|
||||||
|
DEFAULT_RESTORE_TIME
|
||||||
|
)
|
||||||
|
)
|
||||||
print(
|
print(
|
||||||
"--trustremotenode Set trusted-daemon for XMR, defaults to auto: true when daemon rpchost value is a private ip address else false"
|
"--trustremotenode Set trusted-daemon for XMR, defaults to auto: true when daemon rpchost value is a private ip address else false"
|
||||||
)
|
)
|
||||||
@@ -1808,12 +1814,18 @@ def test_particl_encryption(data_dir, settings, chain, use_tor_proxy):
|
|||||||
|
|
||||||
def encrypt_wallet(swap_client, coin_type) -> None:
|
def encrypt_wallet(swap_client, coin_type) -> None:
|
||||||
ci = swap_client.ci(coin_type)
|
ci = swap_client.ci(coin_type)
|
||||||
ci.changeWalletPassword("", WALLET_ENCRYPTION_PWD)
|
ci.changeWalletPassword("", WALLET_ENCRYPTION_PWD, check_seed_if_encrypt=False)
|
||||||
ci.unlockWallet(WALLET_ENCRYPTION_PWD)
|
ci.unlockWallet(WALLET_ENCRYPTION_PWD)
|
||||||
|
|
||||||
|
|
||||||
def initialise_wallets(
|
def initialise_wallets(
|
||||||
particl_wallet_mnemonic, with_coins, data_dir, settings, chain, use_tor_proxy
|
particl_wallet_mnemonic,
|
||||||
|
with_coins,
|
||||||
|
data_dir,
|
||||||
|
settings,
|
||||||
|
chain,
|
||||||
|
use_tor_proxy,
|
||||||
|
extra_opts={},
|
||||||
):
|
):
|
||||||
swap_client = None
|
swap_client = None
|
||||||
daemons = []
|
daemons = []
|
||||||
@@ -1922,7 +1934,7 @@ def initialise_wallets(
|
|||||||
if WALLET_ENCRYPTION_PWD == ""
|
if WALLET_ENCRYPTION_PWD == ""
|
||||||
else WALLET_ENCRYPTION_PWD
|
else WALLET_ENCRYPTION_PWD
|
||||||
)
|
)
|
||||||
extra_opts = [
|
extra_args = [
|
||||||
'--appdata="{}"'.format(coin_settings["datadir"]),
|
'--appdata="{}"'.format(coin_settings["datadir"]),
|
||||||
"--pass={}".format(dcr_password),
|
"--pass={}".format(dcr_password),
|
||||||
]
|
]
|
||||||
@@ -1931,7 +1943,7 @@ def initialise_wallets(
|
|||||||
args = [
|
args = [
|
||||||
os.path.join(coin_settings["bindir"], filename),
|
os.path.join(coin_settings["bindir"], filename),
|
||||||
"--create",
|
"--create",
|
||||||
] + extra_opts
|
] + extra_args
|
||||||
hex_seed = swap_client.getWalletKey(Coins.DCR, 1).hex()
|
hex_seed = swap_client.getWalletKey(Coins.DCR, 1).hex()
|
||||||
createDCRWallet(args, hex_seed, logger, threading.Event())
|
createDCRWallet(args, hex_seed, logger, threading.Event())
|
||||||
continue
|
continue
|
||||||
@@ -2028,6 +2040,7 @@ def initialise_wallets(
|
|||||||
)
|
)
|
||||||
|
|
||||||
for coin_name in with_coins:
|
for coin_name in with_coins:
|
||||||
|
coin_settings = settings["chainclients"][coin_name]
|
||||||
c = swap_client.getCoinIdFromName(coin_name)
|
c = swap_client.getCoinIdFromName(coin_name)
|
||||||
if c in (Coins.PART,):
|
if c in (Coins.PART,):
|
||||||
continue
|
continue
|
||||||
@@ -2035,14 +2048,29 @@ def initialise_wallets(
|
|||||||
# initialiseWallet only sets main_wallet_seedid_
|
# initialiseWallet only sets main_wallet_seedid_
|
||||||
swap_client.waitForDaemonRPC(c)
|
swap_client.waitForDaemonRPC(c)
|
||||||
try:
|
try:
|
||||||
swap_client.initialiseWallet(c, raise_errors=True)
|
default_restore_time = (
|
||||||
|
-1 if generated_mnemonic else DEFAULT_RESTORE_TIME
|
||||||
|
) # Set to -1 (now) if key is newly generated
|
||||||
|
restore_time: int = extra_opts.get(
|
||||||
|
"walletrestoretime", default_restore_time
|
||||||
|
)
|
||||||
|
|
||||||
|
swap_client.initialiseWallet(
|
||||||
|
c, raise_errors=True, restore_time=restore_time
|
||||||
|
)
|
||||||
|
if c not in (Coins.XMR, Coins.WOW):
|
||||||
|
if restore_time == -1:
|
||||||
|
restore_time = int(time.time())
|
||||||
|
coin_settings["restore_time"] = restore_time
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
coins_failed_to_initialise.append((c, e))
|
coins_failed_to_initialise.append((c, e))
|
||||||
if WALLET_ENCRYPTION_PWD != "" and (
|
if WALLET_ENCRYPTION_PWD != "" and (
|
||||||
c not in coins_to_create_wallets_for or c in (Coins.DASH,)
|
c not in coins_to_create_wallets_for or c in (Coins.DASH,)
|
||||||
): # TODO: Remove DASH workaround
|
): # TODO: Remove DASH workaround
|
||||||
try:
|
try:
|
||||||
swap_client.ci(c).changeWalletPassword("", WALLET_ENCRYPTION_PWD)
|
swap_client.ci(c).changeWalletPassword(
|
||||||
|
"", WALLET_ENCRYPTION_PWD, check_seed_if_encrypt=False
|
||||||
|
)
|
||||||
except Exception as e: # noqa: F841
|
except Exception as e: # noqa: F841
|
||||||
logger.warning(f"changeWalletPassword failed for {coin_name}.")
|
logger.warning(f"changeWalletPassword failed for {coin_name}.")
|
||||||
|
|
||||||
@@ -2363,6 +2391,9 @@ def main():
|
|||||||
if name == "wowrestoreheight":
|
if name == "wowrestoreheight":
|
||||||
wow_restore_height = int(s[1])
|
wow_restore_height = int(s[1])
|
||||||
continue
|
continue
|
||||||
|
if name == "walletrestoretime":
|
||||||
|
extra_opts["walletrestoretime"] = int(s[1])
|
||||||
|
continue
|
||||||
if name == "keysdirpath":
|
if name == "keysdirpath":
|
||||||
extra_opts["keysdirpath"] = os.path.expanduser(s[1].strip('"'))
|
extra_opts["keysdirpath"] = os.path.expanduser(s[1].strip('"'))
|
||||||
continue
|
continue
|
||||||
@@ -2823,6 +2854,7 @@ def main():
|
|||||||
settings,
|
settings,
|
||||||
chain,
|
chain,
|
||||||
use_tor_proxy,
|
use_tor_proxy,
|
||||||
|
extra_opts=extra_opts,
|
||||||
)
|
)
|
||||||
|
|
||||||
print("Done.")
|
print("Done.")
|
||||||
@@ -2944,6 +2976,7 @@ def main():
|
|||||||
settings,
|
settings,
|
||||||
chain,
|
chain,
|
||||||
use_tor_proxy,
|
use_tor_proxy,
|
||||||
|
extra_opts=extra_opts,
|
||||||
)
|
)
|
||||||
|
|
||||||
save_config(config_path, settings)
|
save_config(config_path, settings)
|
||||||
@@ -3082,15 +3115,21 @@ def main():
|
|||||||
for c in with_coins:
|
for c in with_coins:
|
||||||
prepareDataDir(c, settings, chain, particl_wallet_mnemonic, extra_opts)
|
prepareDataDir(c, settings, chain, particl_wallet_mnemonic, extra_opts)
|
||||||
|
|
||||||
save_config(config_path, settings)
|
|
||||||
|
|
||||||
if particl_wallet_mnemonic == "none":
|
if particl_wallet_mnemonic == "none":
|
||||||
|
save_config(config_path, settings)
|
||||||
logger.info("Done.")
|
logger.info("Done.")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
initialise_wallets(
|
initialise_wallets(
|
||||||
particl_wallet_mnemonic, with_coins, data_dir, settings, chain, use_tor_proxy
|
particl_wallet_mnemonic,
|
||||||
|
with_coins,
|
||||||
|
data_dir,
|
||||||
|
settings,
|
||||||
|
chain,
|
||||||
|
use_tor_proxy,
|
||||||
|
extra_opts=extra_opts,
|
||||||
)
|
)
|
||||||
|
save_config(config_path, settings)
|
||||||
print("Done.")
|
print("Done.")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -106,6 +106,31 @@ class BCHInterface(BTCInterface):
|
|||||||
) + self.make_int(u["amount"], r=1)
|
) + self.make_int(u["amount"], r=1)
|
||||||
return unspent_addr
|
return unspent_addr
|
||||||
|
|
||||||
|
def createWallet(self, wallet_name: str, password: str = ""):
|
||||||
|
self.rpc("createwallet", [wallet_name, False])
|
||||||
|
if password != "":
|
||||||
|
self.rpc(
|
||||||
|
"encryptwallet",
|
||||||
|
[
|
||||||
|
password,
|
||||||
|
],
|
||||||
|
override_wallet=wallet_name,
|
||||||
|
)
|
||||||
|
|
||||||
|
def newKeypool(self) -> None:
|
||||||
|
self._log.debug("Refreshing keypool.")
|
||||||
|
|
||||||
|
# Use up current keypool
|
||||||
|
wi = self.rpc_wallet("getwalletinfo")
|
||||||
|
keypool_size: int = wi["keypoolsize"]
|
||||||
|
for i in range(keypool_size):
|
||||||
|
_ = self.rpc_wallet("getnewaddress")
|
||||||
|
keypoolsize_hd_internal: int = wi["keypoolsize_hd_internal"]
|
||||||
|
for i in range(keypoolsize_hd_internal):
|
||||||
|
_ = self.rpc_wallet("getrawchangeaddress")
|
||||||
|
|
||||||
|
self.rpc_wallet("keypoolrefill")
|
||||||
|
|
||||||
# returns pkh
|
# returns pkh
|
||||||
def decodeAddress(self, address: str) -> bytes:
|
def decodeAddress(self, address: str) -> bytes:
|
||||||
return bytes(Address.from_string(address).payload)
|
return bytes(Address.from_string(address).payload)
|
||||||
|
|||||||
@@ -10,8 +10,13 @@ import base64
|
|||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import mmap
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import sqlite3
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from basicswap.basicswap_util import (
|
from basicswap.basicswap_util import (
|
||||||
@@ -377,7 +382,7 @@ class BTCInterface(Secp256k1Interface):
|
|||||||
last_block_header = prev_block_header
|
last_block_header = prev_block_header
|
||||||
raise ValueError(f"Block header not found at time: {time}")
|
raise ValueError(f"Block header not found at time: {time}")
|
||||||
|
|
||||||
def initialiseWallet(self, key_bytes: bytes) -> None:
|
def initialiseWallet(self, key_bytes: bytes, restore_time: int = -1) -> None:
|
||||||
assert len(key_bytes) == 32
|
assert len(key_bytes) == 32
|
||||||
self._have_checked_seed = False
|
self._have_checked_seed = False
|
||||||
if self._use_descriptors:
|
if self._use_descriptors:
|
||||||
@@ -387,6 +392,7 @@ class BTCInterface(Secp256k1Interface):
|
|||||||
ek_encoded: str = self.encode_secret_extkey(ek.encode_v())
|
ek_encoded: str = self.encode_secret_extkey(ek.encode_v())
|
||||||
desc_external = descsum_create(f"wpkh({ek_encoded}/0h/0h/*h)")
|
desc_external = descsum_create(f"wpkh({ek_encoded}/0h/0h/*h)")
|
||||||
desc_internal = descsum_create(f"wpkh({ek_encoded}/0h/1h/*h)")
|
desc_internal = descsum_create(f"wpkh({ek_encoded}/0h/1h/*h)")
|
||||||
|
|
||||||
rv = self.rpc_wallet(
|
rv = self.rpc_wallet(
|
||||||
"importdescriptors",
|
"importdescriptors",
|
||||||
[
|
[
|
||||||
@@ -394,7 +400,7 @@ class BTCInterface(Secp256k1Interface):
|
|||||||
{"desc": desc_external, "timestamp": "now", "active": True},
|
{"desc": desc_external, "timestamp": "now", "active": True},
|
||||||
{
|
{
|
||||||
"desc": desc_internal,
|
"desc": desc_internal,
|
||||||
"timestamp": "now",
|
"timestamp": "now" if restore_time == -1 else restore_time,
|
||||||
"active": True,
|
"active": True,
|
||||||
"internal": True,
|
"internal": True,
|
||||||
},
|
},
|
||||||
@@ -411,7 +417,18 @@ class BTCInterface(Secp256k1Interface):
|
|||||||
raise ValueError("Failed to import descriptors.")
|
raise ValueError("Failed to import descriptors.")
|
||||||
else:
|
else:
|
||||||
key_wif = self.encodeKey(key_bytes)
|
key_wif = self.encodeKey(key_bytes)
|
||||||
self.rpc_wallet("sethdseed", [True, key_wif])
|
try:
|
||||||
|
self.rpc_wallet("sethdseed", [True, key_wif])
|
||||||
|
except Exception as e:
|
||||||
|
self._log.debug(f"sethdseed failed: {e}")
|
||||||
|
"""
|
||||||
|
# TODO: Find derived key counts
|
||||||
|
if "Already have this key" in str(e):
|
||||||
|
key_id: bytes = self.getSeedHash(key_bytes)
|
||||||
|
self.setActiveKeyChain(key_id)
|
||||||
|
else:
|
||||||
|
"""
|
||||||
|
raise (e)
|
||||||
|
|
||||||
def getWalletInfo(self):
|
def getWalletInfo(self):
|
||||||
rv = self.rpc_wallet("getwalletinfo")
|
rv = self.rpc_wallet("getwalletinfo")
|
||||||
@@ -455,10 +472,6 @@ class BTCInterface(Secp256k1Interface):
|
|||||||
self.close_rpc(rpc_conn)
|
self.close_rpc(rpc_conn)
|
||||||
raise ValueError(f"{self.coin_name()} wallet restore height not found.")
|
raise ValueError(f"{self.coin_name()} wallet restore height not found.")
|
||||||
|
|
||||||
def getWalletSeedID(self) -> str:
|
|
||||||
wi = self.rpc_wallet("getwalletinfo")
|
|
||||||
return "Not found" if "hdseedid" not in wi else wi["hdseedid"]
|
|
||||||
|
|
||||||
def getActiveDescriptor(self):
|
def getActiveDescriptor(self):
|
||||||
descriptors = self.rpc_wallet("listdescriptors")["descriptors"]
|
descriptors = self.rpc_wallet("listdescriptors")["descriptors"]
|
||||||
for descriptor in descriptors:
|
for descriptor in descriptors:
|
||||||
@@ -470,21 +483,24 @@ class BTCInterface(Secp256k1Interface):
|
|||||||
return descriptor
|
return descriptor
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def checkExpectedSeed(self, expect_seedid: str) -> bool:
|
def getWalletSeedID(self) -> str:
|
||||||
if self._use_descriptors:
|
if self._use_descriptors:
|
||||||
descriptor = self.getActiveDescriptor()
|
descriptor = self.getActiveDescriptor()
|
||||||
if descriptor is None:
|
if descriptor is None:
|
||||||
self._log.debug("Could not find active descriptor.")
|
self._log.debug("Could not find active descriptor.")
|
||||||
return False
|
return "Not found"
|
||||||
|
|
||||||
end = descriptor["desc"].find("/")
|
end = descriptor["desc"].find("/")
|
||||||
if end < 10:
|
if end < 10:
|
||||||
return False
|
return "Not found"
|
||||||
extkey = descriptor["desc"][5:end]
|
extkey = descriptor["desc"][5:end]
|
||||||
extkey_data = b58decode(extkey)[4:-4]
|
extkey_data = b58decode(extkey)[4:-4]
|
||||||
extkey_data_hash: bytes = hash160(extkey_data)
|
extkey_data_hash: bytes = hash160(extkey_data)
|
||||||
return True if extkey_data_hash.hex() == expect_seedid else False
|
return extkey_data_hash.hex()
|
||||||
|
|
||||||
|
wi = self.rpc_wallet("getwalletinfo")
|
||||||
|
return "Not found" if "hdseedid" not in wi else wi["hdseedid"]
|
||||||
|
|
||||||
|
def checkExpectedSeed(self, expect_seedid: str) -> bool:
|
||||||
wallet_seed_id = self.getWalletSeedID()
|
wallet_seed_id = self.getWalletSeedID()
|
||||||
self._expect_seedid_hex = expect_seedid
|
self._expect_seedid_hex = expect_seedid
|
||||||
self._have_checked_seed = True
|
self._have_checked_seed = True
|
||||||
@@ -1978,12 +1994,234 @@ class BTCInterface(Secp256k1Interface):
|
|||||||
locked = encrypted and wallet_info["unlocked_until"] <= 0
|
locked = encrypted and wallet_info["unlocked_until"] <= 0
|
||||||
return encrypted, locked
|
return encrypted, locked
|
||||||
|
|
||||||
def changeWalletPassword(self, old_password: str, new_password: str):
|
def createWallet(self, wallet_name: str, password: str = "") -> None:
|
||||||
|
self.rpc(
|
||||||
|
"createwallet",
|
||||||
|
[wallet_name, False, True, password, False, self._use_descriptors],
|
||||||
|
)
|
||||||
|
|
||||||
|
def setActiveWallet(self, wallet_name: str) -> None:
|
||||||
|
# For debugging
|
||||||
|
self.rpc_wallet = make_rpc_func(
|
||||||
|
self._rpcport, self._rpcauth, host=self._rpc_host, wallet=wallet_name
|
||||||
|
)
|
||||||
|
self._rpc_wallet = wallet_name
|
||||||
|
|
||||||
|
def newKeypool(self) -> None:
|
||||||
|
self._log.debug("Running newkeypool.")
|
||||||
|
self.rpc_wallet("newkeypool")
|
||||||
|
|
||||||
|
def encryptWallet(self, password: str, check_seed: bool = True):
|
||||||
|
# Watchonly wallets are not encrypted
|
||||||
|
# Workaround for https://github.com/bitcoin/bitcoin/issues/26607
|
||||||
|
seed_id_before: str = self.getWalletSeedID()
|
||||||
|
orig_active_descriptors = []
|
||||||
|
orig_hdchain_bytes = None
|
||||||
|
walletpath = None
|
||||||
|
max_hdchain_key_count: int = 4000000 # Arbitrary
|
||||||
|
|
||||||
|
chain_client_settings = self._sc.getChainClientSettings(
|
||||||
|
self.coin_type()
|
||||||
|
) # basicswap.json
|
||||||
|
if (
|
||||||
|
chain_client_settings.get("manage_daemon", False)
|
||||||
|
and check_seed is True
|
||||||
|
and seed_id_before != "Not found"
|
||||||
|
):
|
||||||
|
# Store active keys
|
||||||
|
self.rpc("unloadwallet", [self._rpc_wallet])
|
||||||
|
|
||||||
|
datadir = chain_client_settings["datadir"]
|
||||||
|
if self._network != "mainnet":
|
||||||
|
datadir = os.path.join(datadir, self._network)
|
||||||
|
try_wallet_path = os.path.join(datadir, self._rpc_wallet)
|
||||||
|
if os.path.exists(try_wallet_path):
|
||||||
|
walletpath = try_wallet_path
|
||||||
|
else:
|
||||||
|
try_wallet_path = os.path.join(datadir, "wallets", self._rpc_wallet)
|
||||||
|
if os.path.exists(try_wallet_path):
|
||||||
|
walletpath = try_wallet_path
|
||||||
|
|
||||||
|
walletfilepath = walletpath
|
||||||
|
if os.path.isdir(walletpath):
|
||||||
|
walletfilepath = os.path.join(walletpath, "wallet.dat")
|
||||||
|
|
||||||
|
if walletpath is None:
|
||||||
|
self._log.warning(f"Unable to find {self.ticker()} wallet path.")
|
||||||
|
else:
|
||||||
|
if self._use_descriptors:
|
||||||
|
orig_active_descriptors = []
|
||||||
|
with sqlite3.connect(walletfilepath) as conn:
|
||||||
|
c = conn.cursor()
|
||||||
|
rows = c.execute(
|
||||||
|
"SELECT * FROM main WHERE key in (:kext, :kint)",
|
||||||
|
{
|
||||||
|
"kext": bytes.fromhex(
|
||||||
|
"1161637469766565787465726e616c73706b02"
|
||||||
|
),
|
||||||
|
"kint": bytes.fromhex(
|
||||||
|
"11616374697665696e7465726e616c73706b02"
|
||||||
|
),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
for row in rows:
|
||||||
|
k, v = row
|
||||||
|
orig_active_descriptors.append({"k": k, "v": v})
|
||||||
|
else:
|
||||||
|
seedid_bytes: bytes = bytes.fromhex(seed_id_before)[::-1]
|
||||||
|
with open(walletfilepath, "rb") as fp:
|
||||||
|
with mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ) as mm:
|
||||||
|
pos = mm.find(seedid_bytes)
|
||||||
|
while pos != -1:
|
||||||
|
mm.seek(pos - 8)
|
||||||
|
hdchain_bytes = mm.read(12 + 20)
|
||||||
|
version = int.from_bytes(hdchain_bytes[:4], "little")
|
||||||
|
if version == 2:
|
||||||
|
external_counter = int.from_bytes(
|
||||||
|
hdchain_bytes[4:8], "little"
|
||||||
|
)
|
||||||
|
internal_counter = int.from_bytes(
|
||||||
|
hdchain_bytes[-4:], "little"
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
external_counter > 0
|
||||||
|
and external_counter <= max_hdchain_key_count
|
||||||
|
and internal_counter > 0
|
||||||
|
and internal_counter <= max_hdchain_key_count
|
||||||
|
):
|
||||||
|
orig_hdchain_bytes = hdchain_bytes
|
||||||
|
self._log.debug(
|
||||||
|
f"Found hdchain for: {seed_id_before} external_counter: {external_counter}, internal_counter: {internal_counter}."
|
||||||
|
)
|
||||||
|
break
|
||||||
|
pos = mm.find(seedid_bytes, pos + 1)
|
||||||
|
|
||||||
|
self.rpc("loadwallet", [self._rpc_wallet])
|
||||||
|
|
||||||
|
self.rpc_wallet("encryptwallet", [password])
|
||||||
|
|
||||||
|
if check_seed is False or seed_id_before == "Not found" or walletpath is None:
|
||||||
|
return
|
||||||
|
seed_id_after: str = self.getWalletSeedID()
|
||||||
|
|
||||||
|
if seed_id_before == seed_id_after:
|
||||||
|
return
|
||||||
|
self._log.warning(f"{self.ticker()} wallet seed changed after encryption.")
|
||||||
|
self._log.debug(
|
||||||
|
f"seed_id_before: {seed_id_before} seed_id_after: {seed_id_after}."
|
||||||
|
)
|
||||||
|
self.setWalletSeedWarning(True)
|
||||||
|
|
||||||
|
if chain_client_settings.get("manage_daemon", False) is False:
|
||||||
|
self._log.warning(
|
||||||
|
f"{self.ticker()} manage_daemon is false. Can't attempt to fix."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
if self._use_descriptors:
|
||||||
|
if len(orig_active_descriptors) < 2:
|
||||||
|
self._log.error(
|
||||||
|
"Could not find original active descriptors for wallet."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
self._log.info("Attempting to revert to last descriptors.")
|
||||||
|
else:
|
||||||
|
if orig_hdchain_bytes is None:
|
||||||
|
self._log.error("Could not find hdchain for wallet.")
|
||||||
|
return
|
||||||
|
self._log.info("Attempting to revert to last hdchain.")
|
||||||
|
try:
|
||||||
|
# Make a copy of the encrypted wallet before modifying it
|
||||||
|
bkp_path = walletpath + ".bkp"
|
||||||
|
for i in range(100):
|
||||||
|
if not os.path.exists(bkp_path):
|
||||||
|
break
|
||||||
|
bkp_path = walletpath + f".bkp{i}"
|
||||||
|
|
||||||
|
if os.path.exists(bkp_path):
|
||||||
|
self._log.error("Could not find backup path for wallet.")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.rpc("unloadwallet", [self._rpc_wallet])
|
||||||
|
|
||||||
|
if os.path.isfile(walletpath):
|
||||||
|
shutil.copy(walletpath, bkp_path)
|
||||||
|
else:
|
||||||
|
shutil.copytree(walletpath, bkp_path)
|
||||||
|
|
||||||
|
hdchain_replaced: bool = False
|
||||||
|
if self._use_descriptors:
|
||||||
|
with sqlite3.connect(walletfilepath) as conn:
|
||||||
|
c = conn.cursor()
|
||||||
|
c.executemany(
|
||||||
|
"UPDATE main SET value = :v WHERE key = :k",
|
||||||
|
orig_active_descriptors,
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
else:
|
||||||
|
seedid_after_bytes: bytes = bytes.fromhex(seed_id_after)[::-1]
|
||||||
|
with open(walletfilepath, "r+b") as fp:
|
||||||
|
with mmap.mmap(fp.fileno(), 0) as mm:
|
||||||
|
pos = mm.find(seedid_after_bytes)
|
||||||
|
while pos != -1:
|
||||||
|
mm.seek(pos - 8)
|
||||||
|
hdchain_bytes = mm.read(12 + 20)
|
||||||
|
version = int.from_bytes(hdchain_bytes[:4], "little")
|
||||||
|
if version == 2:
|
||||||
|
external_counter = int.from_bytes(
|
||||||
|
hdchain_bytes[4:8], "little"
|
||||||
|
)
|
||||||
|
internal_counter = int.from_bytes(
|
||||||
|
hdchain_bytes[-4:], "little"
|
||||||
|
)
|
||||||
|
if (
|
||||||
|
external_counter > 0
|
||||||
|
and external_counter <= max_hdchain_key_count
|
||||||
|
and internal_counter > 0
|
||||||
|
and internal_counter <= max_hdchain_key_count
|
||||||
|
):
|
||||||
|
self._log.debug(
|
||||||
|
f"Replacing hdchain for: {seed_id_after} external_counter: {external_counter}, internal_counter: {internal_counter}."
|
||||||
|
)
|
||||||
|
offset: int = pos - 8
|
||||||
|
mm.seek(offset)
|
||||||
|
mm.write(orig_hdchain_bytes)
|
||||||
|
self._log.debug(
|
||||||
|
f"hdchain replaced at offset: {offset}."
|
||||||
|
)
|
||||||
|
hdchain_replaced = True
|
||||||
|
# Can appear multiple times in file, replace all.
|
||||||
|
pos = mm.find(seedid_after_bytes, pos + 1)
|
||||||
|
|
||||||
|
if hdchain_replaced is False:
|
||||||
|
self._log.error("Could not find new hdchain in wallet.")
|
||||||
|
|
||||||
|
self.rpc("loadwallet", [self._rpc_wallet])
|
||||||
|
|
||||||
|
if hdchain_replaced:
|
||||||
|
self.unlockWallet(password, check_seed=False)
|
||||||
|
seed_id_after_restore: str = self.getWalletSeedID()
|
||||||
|
if seed_id_after_restore == seed_id_before:
|
||||||
|
self.newKeypool()
|
||||||
|
else:
|
||||||
|
self._log.warning(
|
||||||
|
f"Expected seed id not found: {seed_id_before}, have {seed_id_after_restore}."
|
||||||
|
)
|
||||||
|
|
||||||
|
self.lockWallet()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self._log.error(f"{self.ticker()} recreating wallet failed: {e}.")
|
||||||
|
if self._sc.debug:
|
||||||
|
self._log.error(traceback.format_exc())
|
||||||
|
|
||||||
|
def changeWalletPassword(
|
||||||
|
self, old_password: str, new_password: str, check_seed_if_encrypt: bool = True
|
||||||
|
):
|
||||||
self._log.info("changeWalletPassword - {}".format(self.ticker()))
|
self._log.info("changeWalletPassword - {}".format(self.ticker()))
|
||||||
if old_password == "":
|
if old_password == "":
|
||||||
if self.isWalletEncrypted():
|
if self.isWalletEncrypted():
|
||||||
raise ValueError("Old password must be set")
|
raise ValueError("Old password must be set")
|
||||||
return self.rpc_wallet("encryptwallet", [new_password])
|
return self.encryptWallet(new_password, check_seed=check_seed_if_encrypt)
|
||||||
self.rpc_wallet("walletpassphrasechange", [old_password, new_password])
|
self.rpc_wallet("walletpassphrasechange", [old_password, new_password])
|
||||||
|
|
||||||
def unlockWallet(self, password: str, check_seed: bool = True) -> None:
|
def unlockWallet(self, password: str, check_seed: bool = True) -> None:
|
||||||
@@ -2001,9 +2239,16 @@ class BTCInterface(Secp256k1Interface):
|
|||||||
)
|
)
|
||||||
# wallet_name, disable_private_keys, blank, passphrase, avoid_reuse, descriptors
|
# wallet_name, disable_private_keys, blank, passphrase, avoid_reuse, descriptors
|
||||||
self.rpc(
|
self.rpc(
|
||||||
"createwallet", [self._rpc_wallet, False, True, "", False, False]
|
"createwallet",
|
||||||
|
[
|
||||||
|
self._rpc_wallet,
|
||||||
|
False,
|
||||||
|
True,
|
||||||
|
password,
|
||||||
|
False,
|
||||||
|
self._use_descriptors,
|
||||||
|
],
|
||||||
)
|
)
|
||||||
self.rpc_wallet("encryptwallet", [password])
|
|
||||||
|
|
||||||
# Max timeout value, ~3 years
|
# Max timeout value, ~3 years
|
||||||
self.rpc_wallet("walletpassphrase", [password, 100000000])
|
self.rpc_wallet("walletpassphrase", [password, 100000000])
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class DASHInterface(BTCInterface):
|
|||||||
def entropyToMnemonic(self, key: bytes) -> None:
|
def entropyToMnemonic(self, key: bytes) -> None:
|
||||||
return Mnemonic("english").to_mnemonic(key)
|
return Mnemonic("english").to_mnemonic(key)
|
||||||
|
|
||||||
def initialiseWallet(self, key_bytes: bytes) -> None:
|
def initialiseWallet(self, key_bytes: bytes, restore_time: int = -1) -> None:
|
||||||
self._have_checked_seed = False
|
self._have_checked_seed = False
|
||||||
if self._wallet_v20_compatible:
|
if self._wallet_v20_compatible:
|
||||||
self._log.warning("Generating wallet compatible with v20 seed.")
|
self._log.warning("Generating wallet compatible with v20 seed.")
|
||||||
@@ -66,7 +66,11 @@ class DASHInterface(BTCInterface):
|
|||||||
|
|
||||||
def checkExpectedSeed(self, expect_seedid: str) -> bool:
|
def checkExpectedSeed(self, expect_seedid: str) -> bool:
|
||||||
self._expect_seedid_hex = expect_seedid
|
self._expect_seedid_hex = expect_seedid
|
||||||
rv = self.rpc_wallet("dumphdinfo")
|
try:
|
||||||
|
rv = self.rpc_wallet("dumphdinfo")
|
||||||
|
except Exception as e:
|
||||||
|
self._log.debug(f"DASH dumphdinfo failed {e}.")
|
||||||
|
return False
|
||||||
if rv["mnemonic"] != "":
|
if rv["mnemonic"] != "":
|
||||||
entropy = Mnemonic("english").to_entropy(rv["mnemonic"].split(" "))
|
entropy = Mnemonic("english").to_entropy(rv["mnemonic"].split(" "))
|
||||||
entropy_hash = self.getAddressHashFromKey(entropy)[::-1].hex()
|
entropy_hash = self.getAddressHashFromKey(entropy)[::-1].hex()
|
||||||
@@ -120,3 +124,36 @@ class DASHInterface(BTCInterface):
|
|||||||
def lockWallet(self):
|
def lockWallet(self):
|
||||||
super().lockWallet()
|
super().lockWallet()
|
||||||
self._wallet_passphrase = ""
|
self._wallet_passphrase = ""
|
||||||
|
|
||||||
|
def encryptWallet(
|
||||||
|
self, old_password: str, new_password: str, check_seed: bool = True
|
||||||
|
):
|
||||||
|
if old_password != "":
|
||||||
|
self.unlockWallet(old_password, check_seed=False)
|
||||||
|
seed_id_before: str = self.getWalletSeedID()
|
||||||
|
|
||||||
|
self.rpc_wallet("encryptwallet", [new_password])
|
||||||
|
|
||||||
|
if check_seed is False or seed_id_before == "Not found":
|
||||||
|
return
|
||||||
|
self.unlockWallet(new_password, check_seed=False)
|
||||||
|
seed_id_after: str = self.getWalletSeedID()
|
||||||
|
|
||||||
|
self.lockWallet()
|
||||||
|
if seed_id_before == seed_id_after:
|
||||||
|
return
|
||||||
|
self._log.warning(f"{self.ticker()} wallet seed changed after encryption.")
|
||||||
|
self._log.debug(
|
||||||
|
f"seed_id_before: {seed_id_before} seed_id_after: {seed_id_after}."
|
||||||
|
)
|
||||||
|
self.setWalletSeedWarning(True)
|
||||||
|
|
||||||
|
def changeWalletPassword(
|
||||||
|
self, old_password: str, new_password: str, check_seed_if_encrypt: bool = True
|
||||||
|
):
|
||||||
|
self._log.info("changeWalletPassword - {}".format(self.ticker()))
|
||||||
|
if old_password == "":
|
||||||
|
if self.isWalletEncrypted():
|
||||||
|
raise ValueError("Old password must be set")
|
||||||
|
return self.encryptWallet(old_password, new_password, check_seed_if_encrypt)
|
||||||
|
self.rpc_wallet("walletpassphrasechange", [old_password, new_password])
|
||||||
|
|||||||
@@ -332,14 +332,14 @@ class DCRInterface(Secp256k1Interface):
|
|||||||
|
|
||||||
def testDaemonRPC(self, with_wallet=True) -> None:
|
def testDaemonRPC(self, with_wallet=True) -> None:
|
||||||
if with_wallet:
|
if with_wallet:
|
||||||
self.rpc_wallet("getinfo")
|
self.rpc_wallet("walletislocked")
|
||||||
else:
|
else:
|
||||||
self.rpc("getblockchaininfo")
|
self.rpc("getblockchaininfo")
|
||||||
|
|
||||||
def getChainHeight(self) -> int:
|
def getChainHeight(self) -> int:
|
||||||
return self.rpc("getblockcount")
|
return self.rpc("getblockcount")
|
||||||
|
|
||||||
def initialiseWallet(self, key: bytes) -> None:
|
def initialiseWallet(self, key: bytes, restore_time: int = -1) -> None:
|
||||||
# Load with --create
|
# Load with --create
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -354,7 +354,9 @@ class DCRInterface(Secp256k1Interface):
|
|||||||
walletislocked = self.rpc_wallet("walletislocked")
|
walletislocked = self.rpc_wallet("walletislocked")
|
||||||
return True, walletislocked
|
return True, walletislocked
|
||||||
|
|
||||||
def changeWalletPassword(self, old_password: str, new_password: str):
|
def changeWalletPassword(
|
||||||
|
self, old_password: str, new_password: str, check_seed_if_encrypt: bool = True
|
||||||
|
):
|
||||||
self._log.info("changeWalletPassword - {}".format(self.ticker()))
|
self._log.info("changeWalletPassword - {}".format(self.ticker()))
|
||||||
if old_password == "":
|
if old_password == "":
|
||||||
# Read initial pwd from settings
|
# Read initial pwd from settings
|
||||||
|
|||||||
@@ -51,13 +51,32 @@ class FIROInterface(BTCInterface):
|
|||||||
def getExchangeName(self, exchange_name: str) -> str:
|
def getExchangeName(self, exchange_name: str) -> str:
|
||||||
return "zcoin"
|
return "zcoin"
|
||||||
|
|
||||||
def initialiseWallet(self, key):
|
def initialiseWallet(self, key, restore_time: int = -1):
|
||||||
# load with -hdseed= parameter
|
# load with -hdseed= parameter
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def checkWallets(self) -> int:
|
def checkWallets(self) -> int:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
def encryptWallet(self, password: str, check_seed: bool = True):
|
||||||
|
# Watchonly wallets are not encrypted
|
||||||
|
# Firo shuts down after encryptwallet
|
||||||
|
seed_id_before: str = self.getWalletSeedID() if check_seed else "Not found"
|
||||||
|
|
||||||
|
self.rpc_wallet("encryptwallet", [password])
|
||||||
|
|
||||||
|
if check_seed is False or seed_id_before == "Not found":
|
||||||
|
return
|
||||||
|
seed_id_after: str = self.getWalletSeedID()
|
||||||
|
|
||||||
|
if seed_id_before == seed_id_after:
|
||||||
|
return
|
||||||
|
self._log.warning(f"{self.ticker()} wallet seed changed after encryption.")
|
||||||
|
self._log.debug(
|
||||||
|
f"seed_id_before: {seed_id_before} seed_id_after: {seed_id_after}."
|
||||||
|
)
|
||||||
|
self.setWalletSeedWarning(True)
|
||||||
|
|
||||||
def getNewAddress(self, use_segwit, label="swap_receive"):
|
def getNewAddress(self, use_segwit, label="swap_receive"):
|
||||||
return self.rpc("getnewaddress", [label])
|
return self.rpc("getnewaddress", [label])
|
||||||
# addr_plain = self.rpc('getnewaddress', [label])
|
# addr_plain = self.rpc('getnewaddress', [label])
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ class NAVInterface(BTCInterface):
|
|||||||
# p2sh-p2wsh
|
# p2sh-p2wsh
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def initialiseWallet(self, key):
|
def initialiseWallet(self, key, restore_time: int = -1):
|
||||||
# Load with -importmnemonic= parameter
|
# Load with -importmnemonic= parameter
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ class PARTInterface(BTCInterface):
|
|||||||
)
|
)
|
||||||
return index_info["spentindex"]
|
return index_info["spentindex"]
|
||||||
|
|
||||||
def initialiseWallet(self, key: bytes) -> None:
|
def initialiseWallet(self, key: bytes, restore_time: int = -1) -> None:
|
||||||
raise ValueError("TODO")
|
raise ValueError("TODO")
|
||||||
|
|
||||||
def withdrawCoin(self, value, addr_to, subfee):
|
def withdrawCoin(self, value, addr_to, subfee):
|
||||||
|
|||||||
@@ -34,6 +34,35 @@ class PIVXInterface(BTCInterface):
|
|||||||
self._rpcport, self._rpcauth, host=self._rpc_host
|
self._rpcport, self._rpcauth, host=self._rpc_host
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def encryptWallet(self, password: str, check_seed: bool = True):
|
||||||
|
# Watchonly wallets are not encrypted
|
||||||
|
|
||||||
|
seed_id_before: str = self.getWalletSeedID()
|
||||||
|
|
||||||
|
self.rpc_wallet("encryptwallet", [password])
|
||||||
|
|
||||||
|
if check_seed is False or seed_id_before == "Not found":
|
||||||
|
return
|
||||||
|
seed_id_after: str = self.getWalletSeedID()
|
||||||
|
|
||||||
|
if seed_id_before == seed_id_after:
|
||||||
|
return
|
||||||
|
self._log.warning(f"{self.ticker()} wallet seed changed after encryption.")
|
||||||
|
self._log.debug(
|
||||||
|
f"seed_id_before: {seed_id_before} seed_id_after: {seed_id_after}."
|
||||||
|
)
|
||||||
|
self.setWalletSeedWarning(True)
|
||||||
|
# Workaround for https://github.com/bitcoin/bitcoin/issues/26607
|
||||||
|
chain_client_settings = self._sc.getChainClientSettings(
|
||||||
|
self.coin_type()
|
||||||
|
) # basicswap.json
|
||||||
|
|
||||||
|
if chain_client_settings.get("manage_daemon", False) is False:
|
||||||
|
self._log.warning(
|
||||||
|
f"{self.ticker()} manage_daemon is false. Can't attempt to fix."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
def signTxWithWallet(self, tx):
|
def signTxWithWallet(self, tx):
|
||||||
rv = self.rpc("signrawtransaction", [tx.hex()])
|
rv = self.rpc("signrawtransaction", [tx.hex()])
|
||||||
return bytes.fromhex(rv["hex"])
|
return bytes.fromhex(rv["hex"])
|
||||||
|
|||||||
@@ -766,7 +766,9 @@ class XMRInterface(CoinInterface):
|
|||||||
balance_info = self.rpc_wallet("get_balance")
|
balance_info = self.rpc_wallet("get_balance")
|
||||||
return balance_info["unlocked_balance"]
|
return balance_info["unlocked_balance"]
|
||||||
|
|
||||||
def changeWalletPassword(self, old_password, new_password):
|
def changeWalletPassword(
|
||||||
|
self, old_password, new_password, check_seed_if_encrypt: bool = True
|
||||||
|
):
|
||||||
self._log.info("changeWalletPassword - {}".format(self.ticker()))
|
self._log.info("changeWalletPassword - {}".format(self.ticker()))
|
||||||
orig_password = self._wallet_password
|
orig_password = self._wallet_password
|
||||||
if old_password != "":
|
if old_password != "":
|
||||||
|
|||||||
@@ -850,7 +850,12 @@ def js_getcoinseed(self, url_split, post_string, is_json) -> bytes:
|
|||||||
swap_client.checkSystemStatus()
|
swap_client.checkSystemStatus()
|
||||||
post_data = getFormData(post_string, is_json)
|
post_data = getFormData(post_string, is_json)
|
||||||
|
|
||||||
coin = getCoinType(get_data_entry(post_data, "coin"))
|
coin_in = get_data_entry(post_data, "coin")
|
||||||
|
try:
|
||||||
|
coin = getCoinIdFromName(coin_in)
|
||||||
|
except Exception:
|
||||||
|
coin = getCoinType(coin_in)
|
||||||
|
|
||||||
if coin in (Coins.PART, Coins.PART_ANON, Coins.PART_BLIND):
|
if coin in (Coins.PART, Coins.PART_ANON, Coins.PART_BLIND):
|
||||||
raise ValueError("Particl wallet seed is set from the Basicswap mnemonic.")
|
raise ValueError("Particl wallet seed is set from the Basicswap mnemonic.")
|
||||||
|
|
||||||
@@ -878,12 +883,17 @@ def js_getcoinseed(self, url_split, post_string, is_json) -> bytes:
|
|||||||
expect_seedid = swap_client.getStringKV(
|
expect_seedid = swap_client.getStringKV(
|
||||||
"main_wallet_seedid_" + ci.coin_name().lower()
|
"main_wallet_seedid_" + ci.coin_name().lower()
|
||||||
)
|
)
|
||||||
|
try:
|
||||||
|
wallet_seed_id = ci.getWalletSeedID()
|
||||||
|
except Exception as e:
|
||||||
|
wallet_seed_id = f"Error: {e}"
|
||||||
|
|
||||||
rv.update(
|
rv.update(
|
||||||
{
|
{
|
||||||
"seed": seed_key.hex(),
|
"seed": seed_key.hex(),
|
||||||
"seed_id": seed_id.hex(),
|
"seed_id": seed_id.hex(),
|
||||||
"expected_seed_id": "Unset" if expect_seedid is None else expect_seedid,
|
"expected_seed_id": "Unset" if expect_seedid is None else expect_seedid,
|
||||||
|
"current_seed_id": wallet_seed_id,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Copyright (c) 2020-2024 tecnovert
|
# Copyright (c) 2020-2024 tecnovert
|
||||||
|
# Copyright (c) 2025 The Basicswap developers
|
||||||
# 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 json
|
import json
|
||||||
import shlex
|
|
||||||
import urllib
|
|
||||||
import traceback
|
import traceback
|
||||||
import subprocess
|
import urllib
|
||||||
from xmlrpc.client import (
|
from xmlrpc.client import (
|
||||||
Fault,
|
Fault,
|
||||||
Transport,
|
Transport,
|
||||||
@@ -104,7 +102,7 @@ def callrpc(rpc_port, auth, method, params=[], wallet=None, host="127.0.0.1"):
|
|||||||
r = json.loads(v.decode("utf-8"))
|
r = json.loads(v.decode("utf-8"))
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
raise ValueError("RPC server error " + str(ex) + ", method: " + method)
|
raise ValueError(f"RPC server error: {ex}, method: {method}")
|
||||||
|
|
||||||
if "error" in r and r["error"] is not None:
|
if "error" in r and r["error"] is not None:
|
||||||
raise ValueError("RPC error " + str(r["error"]))
|
raise ValueError("RPC error " + str(r["error"]))
|
||||||
@@ -120,36 +118,7 @@ def openrpc(rpc_port, auth, wallet=None, host="127.0.0.1"):
|
|||||||
return Jsonrpc(url)
|
return Jsonrpc(url)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
raise ValueError("RPC error " + str(ex))
|
raise ValueError(f"RPC error: {ex}")
|
||||||
|
|
||||||
|
|
||||||
def callrpc_cli(bindir, datadir, chain, cmd, cli_bin="particl-cli", wallet=None):
|
|
||||||
cli_bin = os.path.join(bindir, cli_bin)
|
|
||||||
|
|
||||||
args = [
|
|
||||||
cli_bin,
|
|
||||||
]
|
|
||||||
if chain != "mainnet":
|
|
||||||
args.append("-" + chain)
|
|
||||||
args.append("-datadir=" + datadir)
|
|
||||||
if wallet is not None:
|
|
||||||
args.append("-rpcwallet=" + wallet)
|
|
||||||
args += shlex.split(cmd)
|
|
||||||
|
|
||||||
p = subprocess.Popen(
|
|
||||||
args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
|
||||||
)
|
|
||||||
out = p.communicate()
|
|
||||||
|
|
||||||
if len(out[1]) > 0:
|
|
||||||
raise ValueError("RPC error " + str(out[1]))
|
|
||||||
|
|
||||||
r = out[0].decode("utf-8").strip()
|
|
||||||
try:
|
|
||||||
r = json.loads(r)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def make_rpc_func(port, auth, wallet=None, host="127.0.0.1"):
|
def make_rpc_func(port, auth, wallet=None, host="127.0.0.1"):
|
||||||
|
|||||||
@@ -6,10 +6,12 @@
|
|||||||
# Distributed under the MIT software license, see the accompanying
|
# Distributed under the MIT software license, see the accompanying
|
||||||
# file LICENSE.txt or http://www.opensource.org/licenses/mit-license.php.
|
# file LICENSE.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
import os
|
|
||||||
import json
|
import json
|
||||||
import signal
|
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
|
import shlex
|
||||||
|
import signal
|
||||||
|
import subprocess
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
from .util import read_json_api
|
from .util import read_json_api
|
||||||
@@ -133,11 +135,12 @@ def checkForks(ro):
|
|||||||
|
|
||||||
def stopDaemons(daemons):
|
def stopDaemons(daemons):
|
||||||
for d in daemons:
|
for d in daemons:
|
||||||
logging.info("Interrupting %d", d.handle.pid)
|
logging.info(f"Interrupting {d.handle.pid}")
|
||||||
|
signal_type = signal.SIGTERM if os.name == "nt" else signal.SIGINT
|
||||||
try:
|
try:
|
||||||
d.handle.send_signal(signal.SIGINT)
|
d.handle.send_signal(signal_type)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.info("Interrupting %d, error %s", d.handle.pid, str(e))
|
logging.info(f"Interrupting {d.handle.pid}, error: {e}")
|
||||||
for d in daemons:
|
for d in daemons:
|
||||||
try:
|
try:
|
||||||
d.handle.wait(timeout=20)
|
d.handle.wait(timeout=20)
|
||||||
@@ -145,7 +148,7 @@ def stopDaemons(daemons):
|
|||||||
if fp:
|
if fp:
|
||||||
fp.close()
|
fp.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.info("Closing %d, error %s", d.handle.pid, str(e))
|
logging.info(f"Closing {d.handle.pid}, error: {e}")
|
||||||
|
|
||||||
|
|
||||||
def wait_for_bid(
|
def wait_for_bid(
|
||||||
@@ -494,3 +497,38 @@ def compare_bid_states_unordered(states, expect_states, ignore_states=[]) -> boo
|
|||||||
logging.info("Have states: {}".format(json.dumps(states, indent=4)))
|
logging.info("Have states: {}".format(json.dumps(states, indent=4)))
|
||||||
raise e
|
raise e
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def callrpc_cli(
|
||||||
|
bindir,
|
||||||
|
datadir,
|
||||||
|
chain,
|
||||||
|
cmd,
|
||||||
|
cli_bin="particl-cli" + (".exe" if os.name == "nt" else ""),
|
||||||
|
wallet=None,
|
||||||
|
):
|
||||||
|
cli_bin = os.path.join(bindir, cli_bin)
|
||||||
|
args = [
|
||||||
|
cli_bin,
|
||||||
|
]
|
||||||
|
if chain != "mainnet":
|
||||||
|
args.append("-" + chain)
|
||||||
|
args.append("-datadir=" + datadir)
|
||||||
|
if wallet is not None:
|
||||||
|
args.append("-rpcwallet=" + wallet)
|
||||||
|
args += shlex.split(cmd)
|
||||||
|
|
||||||
|
p = subprocess.Popen(
|
||||||
|
args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||||
|
)
|
||||||
|
out = p.communicate()
|
||||||
|
|
||||||
|
if len(out[1]) > 0:
|
||||||
|
raise ValueError(f"RPC error: {out[1]}")
|
||||||
|
|
||||||
|
r = out[0].decode("utf-8").strip()
|
||||||
|
try:
|
||||||
|
r = json.loads(r)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return r
|
||||||
|
|||||||
@@ -557,12 +557,12 @@ def prepare_nodes(
|
|||||||
):
|
):
|
||||||
bins_path = os.path.join(TEST_PATH, "bin")
|
bins_path = os.path.join(TEST_PATH, "bin")
|
||||||
for i in range(num_nodes):
|
for i in range(num_nodes):
|
||||||
logging.info("Preparing node: %d.", i)
|
logging.info(f"Preparing node: {i}.")
|
||||||
client_path = os.path.join(TEST_PATH, "client{}".format(i))
|
client_path = os.path.join(TEST_PATH, f"client{i}")
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(client_path)
|
shutil.rmtree(client_path)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
logging.warning("setUpClass %s", str(ex))
|
logging.warning(f"setUpClass {ex}")
|
||||||
|
|
||||||
run_prepare(
|
run_prepare(
|
||||||
i,
|
i,
|
||||||
|
|||||||
@@ -40,9 +40,6 @@ from basicswap.basicswap_util import (
|
|||||||
from basicswap.util.address import (
|
from basicswap.util.address import (
|
||||||
toWIF,
|
toWIF,
|
||||||
)
|
)
|
||||||
from basicswap.rpc import (
|
|
||||||
callrpc_cli,
|
|
||||||
)
|
|
||||||
from basicswap.contrib.key import (
|
from basicswap.contrib.key import (
|
||||||
ECKey,
|
ECKey,
|
||||||
)
|
)
|
||||||
@@ -53,6 +50,7 @@ from tests.basicswap.util import (
|
|||||||
read_json_api,
|
read_json_api,
|
||||||
)
|
)
|
||||||
from tests.basicswap.common import (
|
from tests.basicswap.common import (
|
||||||
|
callrpc_cli,
|
||||||
checkForks,
|
checkForks,
|
||||||
stopDaemons,
|
stopDaemons,
|
||||||
wait_for_offer,
|
wait_for_offer,
|
||||||
|
|||||||
@@ -25,13 +25,11 @@ from basicswap.util import (
|
|||||||
make_int,
|
make_int,
|
||||||
format_amount,
|
format_amount,
|
||||||
)
|
)
|
||||||
from basicswap.rpc import (
|
|
||||||
callrpc_cli,
|
|
||||||
)
|
|
||||||
from tests.basicswap.util import (
|
from tests.basicswap.util import (
|
||||||
read_json_api,
|
read_json_api,
|
||||||
)
|
)
|
||||||
from tests.basicswap.common import (
|
from tests.basicswap.common import (
|
||||||
|
callrpc_cli,
|
||||||
stopDaemons,
|
stopDaemons,
|
||||||
wait_for_bid,
|
wait_for_bid,
|
||||||
make_rpc_func,
|
make_rpc_func,
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ from basicswap.util.address import (
|
|||||||
)
|
)
|
||||||
from basicswap.rpc import (
|
from basicswap.rpc import (
|
||||||
callrpc,
|
callrpc,
|
||||||
callrpc_cli,
|
|
||||||
)
|
)
|
||||||
from basicswap.contrib.key import (
|
from basicswap.contrib.key import (
|
||||||
ECKey,
|
ECKey,
|
||||||
@@ -44,19 +43,20 @@ from tests.basicswap.util import (
|
|||||||
read_json_api,
|
read_json_api,
|
||||||
)
|
)
|
||||||
from tests.basicswap.common import (
|
from tests.basicswap.common import (
|
||||||
prepareDataDir,
|
|
||||||
make_rpc_func,
|
|
||||||
checkForks,
|
|
||||||
stopDaemons,
|
|
||||||
delay_for,
|
|
||||||
TEST_HTTP_HOST,
|
|
||||||
TEST_HTTP_PORT,
|
|
||||||
BASE_P2P_PORT,
|
BASE_P2P_PORT,
|
||||||
BASE_RPC_PORT,
|
BASE_RPC_PORT,
|
||||||
BASE_ZMQ_PORT,
|
BASE_ZMQ_PORT,
|
||||||
BTC_BASE_PORT,
|
BTC_BASE_PORT,
|
||||||
BTC_BASE_RPC_PORT,
|
BTC_BASE_RPC_PORT,
|
||||||
|
callrpc_cli,
|
||||||
|
checkForks,
|
||||||
|
delay_for,
|
||||||
|
make_rpc_func,
|
||||||
PREFIX_SECRET_KEY_REGTEST,
|
PREFIX_SECRET_KEY_REGTEST,
|
||||||
|
prepareDataDir,
|
||||||
|
stopDaemons,
|
||||||
|
TEST_HTTP_HOST,
|
||||||
|
TEST_HTTP_PORT,
|
||||||
waitForRPC,
|
waitForRPC,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -40,9 +40,6 @@ from basicswap.basicswap_util import (
|
|||||||
from basicswap.util.address import (
|
from basicswap.util.address import (
|
||||||
toWIF,
|
toWIF,
|
||||||
)
|
)
|
||||||
from basicswap.rpc import (
|
|
||||||
callrpc_cli,
|
|
||||||
)
|
|
||||||
from basicswap.contrib.key import (
|
from basicswap.contrib.key import (
|
||||||
ECKey,
|
ECKey,
|
||||||
)
|
)
|
||||||
@@ -53,6 +50,7 @@ from tests.basicswap.util import (
|
|||||||
read_json_api,
|
read_json_api,
|
||||||
)
|
)
|
||||||
from tests.basicswap.common import (
|
from tests.basicswap.common import (
|
||||||
|
callrpc_cli,
|
||||||
checkForks,
|
checkForks,
|
||||||
stopDaemons,
|
stopDaemons,
|
||||||
wait_for_bid,
|
wait_for_bid,
|
||||||
|
|||||||
1278
tests/basicswap/extended/test_wallet_encryption.py
Normal file
1278
tests/basicswap/extended/test_wallet_encryption.py
Normal file
File diff suppressed because it is too large
Load Diff
@@ -174,7 +174,8 @@ class Test(BaseTest):
|
|||||||
"create_wallet",
|
"create_wallet",
|
||||||
{"filename": "testwallet", "language": "English"},
|
{"filename": "testwallet", "language": "English"},
|
||||||
)
|
)
|
||||||
cls.callwownodewallet(cls, i, "open_wallet", {"filename": "testwallet"})
|
else:
|
||||||
|
cls.callwownodewallet(cls, i, "open_wallet", {"filename": "testwallet"})
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def addPIDInfo(cls, sc, i):
|
def addPIDInfo(cls, sc, i):
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ from basicswap.bin.run import startDaemon
|
|||||||
from basicswap.util.crypto import sha256
|
from basicswap.util.crypto import sha256
|
||||||
from tests.basicswap.test_btc_xmr import BasicSwapTest
|
from tests.basicswap.test_btc_xmr import BasicSwapTest
|
||||||
from tests.basicswap.common import (
|
from tests.basicswap.common import (
|
||||||
|
callrpc_cli,
|
||||||
make_rpc_func,
|
make_rpc_func,
|
||||||
prepareDataDir,
|
prepareDataDir,
|
||||||
stopDaemons,
|
stopDaemons,
|
||||||
@@ -37,9 +38,6 @@ from basicswap.contrib.test_framework.script import (
|
|||||||
OP_CHECKSEQUENCEVERIFY,
|
OP_CHECKSEQUENCEVERIFY,
|
||||||
)
|
)
|
||||||
from basicswap.interface.bch import BCHInterface
|
from basicswap.interface.bch import BCHInterface
|
||||||
from basicswap.rpc import (
|
|
||||||
callrpc_cli,
|
|
||||||
)
|
|
||||||
from basicswap.util import ensure
|
from basicswap.util import ensure
|
||||||
from .test_xmr import test_delay_event, callnoderpc
|
from .test_xmr import test_delay_event, callnoderpc
|
||||||
|
|
||||||
@@ -134,14 +132,20 @@ class TestBCH(BasicSwapTest):
|
|||||||
if not line.startswith("findpeers"):
|
if not line.startswith("findpeers"):
|
||||||
fp.write(line)
|
fp.write(line)
|
||||||
|
|
||||||
if os.path.exists(os.path.join(BITCOINCASH_BINDIR, "bitcoin-wallet")):
|
bch_wallet_bin = "bitcoin-wallet" + (".exe" if os.name == "nt" else "")
|
||||||
|
if os.path.exists(
|
||||||
|
os.path.join(
|
||||||
|
BITCOINCASH_BINDIR,
|
||||||
|
bch_wallet_bin,
|
||||||
|
)
|
||||||
|
):
|
||||||
try:
|
try:
|
||||||
callrpc_cli(
|
callrpc_cli(
|
||||||
BITCOINCASH_BINDIR,
|
BITCOINCASH_BINDIR,
|
||||||
data_dir,
|
data_dir,
|
||||||
"regtest",
|
"regtest",
|
||||||
"-wallet=wallet.dat create",
|
"-wallet=wallet.dat create",
|
||||||
"bitcoin-wallet",
|
bch_wallet_bin,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.warning("bch: bitcoin-wallet create failed")
|
logging.warning("bch: bitcoin-wallet create failed")
|
||||||
|
|||||||
@@ -1740,6 +1740,74 @@ class BasicSwapTest(TestFunctions):
|
|||||||
self.callnoderpc("unloadwallet", [new_wallet_name])
|
self.callnoderpc("unloadwallet", [new_wallet_name])
|
||||||
self.callnoderpc("unloadwallet", [new_watch_wallet_name])
|
self.callnoderpc("unloadwallet", [new_watch_wallet_name])
|
||||||
|
|
||||||
|
def test_014_encrypt_existing_wallet(self):
|
||||||
|
logging.info(
|
||||||
|
f"---------- Test {self.test_coin_from.name} encrypt existing wallet"
|
||||||
|
)
|
||||||
|
|
||||||
|
ci = self.swap_clients[0].ci(self.test_coin_from)
|
||||||
|
wallet_name = "encrypt_existing_wallet"
|
||||||
|
|
||||||
|
ci.createWallet(wallet_name)
|
||||||
|
ci.setActiveWallet(wallet_name)
|
||||||
|
chain_client_settings = self.swap_clients[0].getChainClientSettings(
|
||||||
|
self.test_coin_from
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
chain_client_settings["manage_daemon"] = True
|
||||||
|
ci.initialiseWallet(ci.getNewRandomKey())
|
||||||
|
|
||||||
|
original_seed_id = ci.getWalletSeedID()
|
||||||
|
|
||||||
|
addr1 = ci.getNewAddress(True)
|
||||||
|
addr1_info = ci.rpc_wallet(
|
||||||
|
"getaddressinfo",
|
||||||
|
[
|
||||||
|
addr1,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
addr_int1 = ci.rpc_wallet("getrawchangeaddress")
|
||||||
|
addr_int1_info = ci.rpc_wallet(
|
||||||
|
"getaddressinfo",
|
||||||
|
[
|
||||||
|
addr_int1,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
ci.encryptWallet("test.123")
|
||||||
|
|
||||||
|
after_seed_id = ci.getWalletSeedID()
|
||||||
|
|
||||||
|
addr2 = ci.getNewAddress(True)
|
||||||
|
addr2_info = ci.rpc_wallet(
|
||||||
|
"getaddressinfo",
|
||||||
|
[
|
||||||
|
addr2,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
addr_int2 = ci.rpc_wallet("getrawchangeaddress")
|
||||||
|
addr_int2_info = ci.rpc_wallet(
|
||||||
|
"getaddressinfo",
|
||||||
|
[
|
||||||
|
addr_int2,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
key_id_field: str = (
|
||||||
|
"hdmasterkeyid"
|
||||||
|
if "hdmasterkeyid" in addr1_info
|
||||||
|
else "hdmasterfingerprint"
|
||||||
|
)
|
||||||
|
assert addr1_info[key_id_field] == addr2_info[key_id_field]
|
||||||
|
assert addr_int1_info[key_id_field] == addr_int2_info[key_id_field]
|
||||||
|
assert addr1_info[key_id_field] == addr_int1_info[key_id_field]
|
||||||
|
assert original_seed_id == after_seed_id
|
||||||
|
finally:
|
||||||
|
ci.setActiveWallet("wallet.dat")
|
||||||
|
chain_client_settings["manage_daemon"] = False
|
||||||
|
|
||||||
def test_01_0_lock_bad_prevouts(self):
|
def test_01_0_lock_bad_prevouts(self):
|
||||||
logging.info(
|
logging.info(
|
||||||
"---------- Test {} lock_bad_prevouts".format(self.test_coin_from.name)
|
"---------- Test {} lock_bad_prevouts".format(self.test_coin_from.name)
|
||||||
|
|||||||
@@ -24,9 +24,6 @@ import threading
|
|||||||
import multiprocessing
|
import multiprocessing
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from basicswap.rpc import (
|
|
||||||
callrpc_cli,
|
|
||||||
)
|
|
||||||
from tests.basicswap.util import (
|
from tests.basicswap.util import (
|
||||||
read_json_api,
|
read_json_api,
|
||||||
post_json_api,
|
post_json_api,
|
||||||
@@ -38,6 +35,7 @@ from tests.basicswap.common import (
|
|||||||
waitForNumSwapping,
|
waitForNumSwapping,
|
||||||
)
|
)
|
||||||
from tests.basicswap.common_xmr import (
|
from tests.basicswap.common_xmr import (
|
||||||
|
callrpc_cli,
|
||||||
prepare_nodes,
|
prepare_nodes,
|
||||||
)
|
)
|
||||||
import basicswap.bin.run as runSystem
|
import basicswap.bin.run as runSystem
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ from basicswap.util.address import (
|
|||||||
)
|
)
|
||||||
from basicswap.rpc import (
|
from basicswap.rpc import (
|
||||||
callrpc,
|
callrpc,
|
||||||
callrpc_cli,
|
|
||||||
)
|
)
|
||||||
from basicswap.rpc_xmr import (
|
from basicswap.rpc_xmr import (
|
||||||
callrpc_xmr,
|
callrpc_xmr,
|
||||||
@@ -61,6 +60,7 @@ from tests.basicswap.util import (
|
|||||||
read_json_api,
|
read_json_api,
|
||||||
)
|
)
|
||||||
from tests.basicswap.common import (
|
from tests.basicswap.common import (
|
||||||
|
callrpc_cli,
|
||||||
prepareDataDir,
|
prepareDataDir,
|
||||||
make_rpc_func,
|
make_rpc_func,
|
||||||
checkForks,
|
checkForks,
|
||||||
@@ -376,7 +376,7 @@ class BaseTest(unittest.TestCase):
|
|||||||
|
|
||||||
if os.path.isdir(TEST_DIR):
|
if os.path.isdir(TEST_DIR):
|
||||||
if RESET_TEST:
|
if RESET_TEST:
|
||||||
logging.info("Removing " + TEST_DIR)
|
logging.info("Removing test dir " + TEST_DIR)
|
||||||
for name in os.listdir(TEST_DIR):
|
for name in os.listdir(TEST_DIR):
|
||||||
if name == "pivx-params":
|
if name == "pivx-params":
|
||||||
continue
|
continue
|
||||||
@@ -388,6 +388,8 @@ class BaseTest(unittest.TestCase):
|
|||||||
else:
|
else:
|
||||||
logging.info("Restoring instance from " + TEST_DIR)
|
logging.info("Restoring instance from " + TEST_DIR)
|
||||||
cls.restore_instance = True
|
cls.restore_instance = True
|
||||||
|
else:
|
||||||
|
logging.info("Creating test dir " + TEST_DIR)
|
||||||
if not os.path.exists(TEST_DIR):
|
if not os.path.exists(TEST_DIR):
|
||||||
os.makedirs(TEST_DIR)
|
os.makedirs(TEST_DIR)
|
||||||
|
|
||||||
@@ -399,19 +401,25 @@ class BaseTest(unittest.TestCase):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
logging.info("Preparing coin nodes.")
|
logging.info("Preparing coin nodes.")
|
||||||
|
part_wallet_bin = "particl-wallet" + (".exe" if os.name == "nt" else "")
|
||||||
for i in range(NUM_NODES):
|
for i in range(NUM_NODES):
|
||||||
if not cls.restore_instance:
|
if not cls.restore_instance:
|
||||||
data_dir = prepareDataDir(TEST_DIR, i, "particl.conf", "part_")
|
data_dir = prepareDataDir(TEST_DIR, i, "particl.conf", "part_")
|
||||||
if os.path.exists(
|
if not os.path.exists(
|
||||||
os.path.join(cfg.PARTICL_BINDIR, "particl-wallet")
|
os.path.join(
|
||||||
|
cfg.PARTICL_BINDIR,
|
||||||
|
part_wallet_bin,
|
||||||
|
)
|
||||||
):
|
):
|
||||||
|
logging.warning(f"{part_wallet_bin} not found.")
|
||||||
|
else:
|
||||||
try:
|
try:
|
||||||
callrpc_cli(
|
callrpc_cli(
|
||||||
cfg.PARTICL_BINDIR,
|
cfg.PARTICL_BINDIR,
|
||||||
data_dir,
|
data_dir,
|
||||||
"regtest",
|
"regtest",
|
||||||
"-wallet=wallet.dat -legacy create",
|
"-wallet=wallet.dat -legacy create",
|
||||||
"particl-wallet",
|
part_wallet_bin,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.warning(
|
logging.warning(
|
||||||
@@ -422,7 +430,7 @@ class BaseTest(unittest.TestCase):
|
|||||||
data_dir,
|
data_dir,
|
||||||
"regtest",
|
"regtest",
|
||||||
"-wallet=wallet.dat create",
|
"-wallet=wallet.dat create",
|
||||||
"particl-wallet",
|
part_wallet_bin,
|
||||||
)
|
)
|
||||||
|
|
||||||
cls.part_daemons.append(
|
cls.part_daemons.append(
|
||||||
@@ -471,6 +479,7 @@ class BaseTest(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
rpc("reservebalance", [False])
|
rpc("reservebalance", [False])
|
||||||
|
|
||||||
|
btc_wallet_bin = "bitcoin-wallet" + (".exe" if os.name == "nt" else "")
|
||||||
for i in range(NUM_BTC_NODES):
|
for i in range(NUM_BTC_NODES):
|
||||||
if not cls.restore_instance:
|
if not cls.restore_instance:
|
||||||
data_dir = prepareDataDir(
|
data_dir = prepareDataDir(
|
||||||
@@ -481,9 +490,14 @@ class BaseTest(unittest.TestCase):
|
|||||||
base_p2p_port=BTC_BASE_PORT,
|
base_p2p_port=BTC_BASE_PORT,
|
||||||
base_rpc_port=BTC_BASE_RPC_PORT,
|
base_rpc_port=BTC_BASE_RPC_PORT,
|
||||||
)
|
)
|
||||||
if os.path.exists(
|
if not os.path.exists(
|
||||||
os.path.join(cfg.BITCOIN_BINDIR, "bitcoin-wallet")
|
os.path.join(
|
||||||
|
cfg.BITCOIN_BINDIR,
|
||||||
|
btc_wallet_bin,
|
||||||
|
)
|
||||||
):
|
):
|
||||||
|
logging.warning(f"{btc_wallet_bin} not found.")
|
||||||
|
else:
|
||||||
if BTC_USE_DESCRIPTORS:
|
if BTC_USE_DESCRIPTORS:
|
||||||
# How to set blank and disable_private_keys with wallet util?
|
# How to set blank and disable_private_keys with wallet util?
|
||||||
pass
|
pass
|
||||||
@@ -494,7 +508,7 @@ class BaseTest(unittest.TestCase):
|
|||||||
data_dir,
|
data_dir,
|
||||||
"regtest",
|
"regtest",
|
||||||
"-wallet=wallet.dat -legacy create",
|
"-wallet=wallet.dat -legacy create",
|
||||||
"bitcoin-wallet",
|
btc_wallet_bin,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.warning(
|
logging.warning(
|
||||||
@@ -505,7 +519,7 @@ class BaseTest(unittest.TestCase):
|
|||||||
data_dir,
|
data_dir,
|
||||||
"regtest",
|
"regtest",
|
||||||
"-wallet=wallet.dat create",
|
"-wallet=wallet.dat create",
|
||||||
"bitcoin-wallet",
|
btc_wallet_bin,
|
||||||
)
|
)
|
||||||
|
|
||||||
cls.btc_daemons.append(
|
cls.btc_daemons.append(
|
||||||
@@ -536,6 +550,7 @@ class BaseTest(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if cls.start_ltc_nodes:
|
if cls.start_ltc_nodes:
|
||||||
|
ltc_wallet_bin = "litecoin-wallet" + (".exe" if os.name == "nt" else "")
|
||||||
for i in range(NUM_LTC_NODES):
|
for i in range(NUM_LTC_NODES):
|
||||||
if not cls.restore_instance:
|
if not cls.restore_instance:
|
||||||
data_dir = prepareDataDir(
|
data_dir = prepareDataDir(
|
||||||
@@ -547,14 +562,16 @@ class BaseTest(unittest.TestCase):
|
|||||||
base_rpc_port=LTC_BASE_RPC_PORT,
|
base_rpc_port=LTC_BASE_RPC_PORT,
|
||||||
)
|
)
|
||||||
if os.path.exists(
|
if os.path.exists(
|
||||||
os.path.join(cfg.LITECOIN_BINDIR, "litecoin-wallet")
|
os.path.join(cfg.LITECOIN_BINDIR, ltc_wallet_bin)
|
||||||
):
|
):
|
||||||
|
logging.warning(f"{ltc_wallet_bin} not found.")
|
||||||
|
else:
|
||||||
callrpc_cli(
|
callrpc_cli(
|
||||||
cfg.LITECOIN_BINDIR,
|
cfg.LITECOIN_BINDIR,
|
||||||
data_dir,
|
data_dir,
|
||||||
"regtest",
|
"regtest",
|
||||||
"-wallet=wallet.dat create",
|
"-wallet=wallet.dat create",
|
||||||
"litecoin-wallet",
|
ltc_wallet_bin,
|
||||||
)
|
)
|
||||||
|
|
||||||
cls.ltc_daemons.append(
|
cls.ltc_daemons.append(
|
||||||
@@ -620,9 +637,10 @@ class BaseTest(unittest.TestCase):
|
|||||||
"create_wallet",
|
"create_wallet",
|
||||||
{"filename": "testwallet", "language": "English"},
|
{"filename": "testwallet", "language": "English"},
|
||||||
)
|
)
|
||||||
cls.callxmrnodewallet(
|
else:
|
||||||
cls, i, "open_wallet", {"filename": "testwallet"}
|
cls.callxmrnodewallet(
|
||||||
)
|
cls, i, "open_wallet", {"filename": "testwallet"}
|
||||||
|
)
|
||||||
|
|
||||||
for i in range(NUM_NODES):
|
for i in range(NUM_NODES):
|
||||||
# Hook for descendant classes
|
# Hook for descendant classes
|
||||||
|
|||||||
Reference in New Issue
Block a user