mirror of
https://github.com/cryptoadvance/specter-desktop.git
synced 2026-08-13 12:33:29 +02:00
Bugfixes: Various bugfixes (#1959)
* missing __init__.py * Add Device modules to hidden imports * make cli-arguments work in electron * Bugfix devices not shown * additional checks for wallet_import * Update src/cryptoadvance/specter/util/wallet_importer.py Co-authored-by: Manolis Mandrapilias <70536101+moneymanolis@users.noreply.github.com> * Update src/cryptoadvance/specter/util/wallet_importer.py Co-authored-by: Manolis Mandrapilias <70536101+moneymanolis@users.noreply.github.com> * Update src/cryptoadvance/specter/util/wallet_importer.py Co-authored-by: Manolis Mandrapilias <70536101+moneymanolis@users.noreply.github.com> Co-authored-by: k9ert <kim@swanbitcoin.com> Co-authored-by: Manolis Mandrapilias <70536101+moneymanolis@users.noreply.github.com>
This commit is contained in:
parent
1d2fea976a
commit
bef9cf69f8
11 changed files with 160 additions and 29 deletions
|
|
@ -157,6 +157,8 @@ release_electron_linux_windows:
|
|||
stage: releasing
|
||||
only:
|
||||
- tags
|
||||
dependencies:
|
||||
- release_binary_windows
|
||||
before_script:
|
||||
- python3 -V # Print out python version for debugging
|
||||
- apt update
|
||||
|
|
|
|||
|
|
@ -348,10 +348,8 @@ function startSpecterd(specterdPath) {
|
|||
if (specterdArgs == null) {
|
||||
specterdArgs = []
|
||||
}
|
||||
let specterdExtraArgs = appSettings.specterdCLIArgs.split('--')
|
||||
specterdExtraArgs = specterdExtraArgs.filter(Boolean)
|
||||
specterdExtraArgs.forEach((arg, index) => specterdExtraArgs[index] = '--' + arg.trim())
|
||||
|
||||
let specterdExtraArgs = appSettings.specterdCLIArgs.split(' ')
|
||||
specterdExtraArgs.forEach((arg, index) => specterdExtraArgs[index] = arg.trim())
|
||||
specterdArgs = specterdArgs.concat(specterdExtraArgs)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import requests
|
|||
from cryptoadvance.specter.specter_error import SpecterError
|
||||
from cryptoadvance.specter.util.common import str2bool
|
||||
|
||||
from ..helpers import is_testnet, normalize_address
|
||||
from ..helpers import normalize_address
|
||||
from ..util.descriptor import AddChecksum, Descriptor
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import psutil
|
|||
from pathlib import Path
|
||||
|
||||
|
||||
from .helpers import is_testnet
|
||||
from .specter_error import SpecterError, ExtProcTimeoutException
|
||||
from .rpc import (
|
||||
get_default_datadir,
|
||||
|
|
|
|||
|
|
@ -429,16 +429,37 @@ class ServiceManager:
|
|||
|
||||
@classmethod
|
||||
def get_service_packages(cls):
|
||||
"""returns a list of strings containing the service-classes (+ controller/config-classes)
|
||||
"""returns a list of strings containing the service-classes (+ controller +config-classes +devices)
|
||||
This is used for hiddenimports in pyinstaller
|
||||
"""
|
||||
arr = get_subclasses_for_clazz(Service)
|
||||
logger.info(f"initial arr: {arr}")
|
||||
arr.extend(
|
||||
get_classlist_of_type_clazz_from_modulelist(
|
||||
Service, ProductionConfig.EXTENSION_LIST
|
||||
)
|
||||
)
|
||||
logger.info(f"After extending: {arr}")
|
||||
# Before we transform the arr into an array of strings, we iterate through all services to discover
|
||||
# the devices which might be specified in there
|
||||
devices_arr = []
|
||||
for clazz in arr:
|
||||
if hasattr(clazz, "devices"):
|
||||
logger.debug("class {clazz} has devices: {clazz.devices}")
|
||||
for device in clazz.devices:
|
||||
try:
|
||||
import_module(device)
|
||||
devices_arr.append(device)
|
||||
except ModuleNotFoundError as e:
|
||||
pass
|
||||
|
||||
# Transform into array of strings
|
||||
arr = [clazz.__module__ for clazz in arr]
|
||||
|
||||
# Add the devices
|
||||
arr.extend(devices_arr)
|
||||
logger.debug(f"After transforming + devices: {arr}")
|
||||
|
||||
# Controller-Packagages from the services are not imported via the service but via the baseclass
|
||||
# Therefore hiddenimport don't find them. We have to do it here.
|
||||
cont_arr = [
|
||||
|
|
|
|||
|
|
@ -110,6 +110,10 @@ class AbstractNode(PersistentObject):
|
|||
def network_parameters(self):
|
||||
return get_network(self.chain)
|
||||
|
||||
@property
|
||||
def is_testnet(self):
|
||||
return is_testnet(self.chain)
|
||||
|
||||
@property
|
||||
def is_running(self):
|
||||
if self.network_info["version"] == 999999:
|
||||
|
|
@ -582,10 +586,6 @@ class Node(AbstractNode):
|
|||
def chain(self):
|
||||
return self.info["chain"]
|
||||
|
||||
@property
|
||||
def is_testnet(self):
|
||||
return is_testnet(self.chain)
|
||||
|
||||
@property
|
||||
def asset_labels(self):
|
||||
if not self.is_liquid:
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ from cryptoadvance.specter.services.service_encrypted_storage import (
|
|||
ServiceUnencryptedStorageManager,
|
||||
)
|
||||
|
||||
from .helpers import clean_psbt, deep_update, is_liquid, is_testnet, get_asset_label
|
||||
from .helpers import clean_psbt, deep_update, is_liquid, get_asset_label
|
||||
from .internal_node import InternalNode
|
||||
from .liquid.rpc import LiquidRPC
|
||||
from .managers.config_manager import ConfigManager
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ from embit.descriptor.arguments import AllowedDerivation
|
|||
from embit.liquid.descriptor import LDescriptor
|
||||
from flask_babel import lazy_gettext as _
|
||||
|
||||
from cryptoadvance.specter.device import Device
|
||||
|
||||
from ..key import Key
|
||||
from ..managers.wallet_manager import WalletManager
|
||||
from ..server_endpoints import flash
|
||||
|
|
@ -58,8 +60,36 @@ class WalletImporter:
|
|||
self.unknown_cosigners,
|
||||
self.unknown_cosigners_types,
|
||||
) = self.parse_signers(device_manager.devices, self.cosigners_types)
|
||||
try:
|
||||
self.check_chain(specter.node)
|
||||
except Exception as e:
|
||||
logger.exception(e)
|
||||
raise SpecterError(f"Invalid chain: {e}")
|
||||
self.wallet_type = "multisig" if self.descriptor.is_basic_multisig else "simple"
|
||||
|
||||
def check_chain(self, node):
|
||||
|
||||
cosigner: Device
|
||||
for cosigner in self.cosigners:
|
||||
|
||||
key_chain_list = [key.is_testnet for key in cosigner.keys]
|
||||
logger.debug(key_chain_list)
|
||||
if node.is_testnet not in key_chain_list:
|
||||
raise SpecterError(
|
||||
f"The device {cosigner} does not have any key for the chain {node.chain}!"
|
||||
)
|
||||
for key, label in self.unknown_cosigners:
|
||||
if key.is_testnet != node.is_testnet:
|
||||
raise SpecterError(
|
||||
f"The device {label} has at least one key for the chain {key.metadata['chain'] } whereas your node is on the chain: {node.chain}!"
|
||||
)
|
||||
key: Key
|
||||
for key in self.keys:
|
||||
if key.is_testnet != node.is_testnet:
|
||||
raise SpecterError(
|
||||
f"The key {key} belongs to the chain {key.metadata['chain'] } but your node is on the chain {node.chain}!"
|
||||
)
|
||||
|
||||
def check_descriptor(self):
|
||||
# Sparrow fix: if all keys have None as allowed derivation - set allowed derivation to [0, None]
|
||||
if all(
|
||||
|
|
@ -86,6 +116,15 @@ class WalletImporter:
|
|||
)
|
||||
|
||||
def parse_signers(self, devices, cosigners_types):
|
||||
"""returns:
|
||||
* keys:
|
||||
* keys which are already existing in the device_manager
|
||||
* keys:[<cryptoadvance.specter.key.Key object at 0x7fda8451e0e0>]
|
||||
# cosigners:
|
||||
* [<cryptoadvance.specter.devices.generic.GenericDevice object at 0x7fda8451fcd0>]
|
||||
# unknown_cosigners:[(<cryptoadvance.specter.key.Key object at 0x7fda8451e830>, 'Signer - K'), (<cryptoadvance.specter.key.Key object at 0x7fda94235570>, 'Signer - Tired no WP')]
|
||||
|
||||
"""
|
||||
keys = []
|
||||
cosigners = []
|
||||
unknown_cosigners = []
|
||||
|
|
@ -119,7 +158,11 @@ class WalletImporter:
|
|||
unknown_cosigners_types.append("other")
|
||||
else:
|
||||
unknown_cosigners_types.append(cosigners_types[i]["type"])
|
||||
|
||||
logger.debug("parse_signers returning:")
|
||||
logger.debug(f"keys:{keys}")
|
||||
logger.debug(f"cosigners:{cosigners}")
|
||||
logger.debug(f"unknown_cosigners:{unknown_cosigners}")
|
||||
logger.debug(f"unknown_cosigners_types:{unknown_cosigners_types}")
|
||||
return (keys, cosigners, unknown_cosigners, unknown_cosigners_types)
|
||||
|
||||
def create_nonexisting_signers(self, device_manager, request_form):
|
||||
|
|
|
|||
|
|
@ -56,9 +56,12 @@ def test_ServiceManager_get_service_x_dirs(caplog):
|
|||
os.chdir("../")
|
||||
|
||||
|
||||
def test_ServiceManager_get_service_packages():
|
||||
def test_ServiceManager_get_service_packages(caplog):
|
||||
caplog.set_level(logging.DEBUG)
|
||||
packages = ServiceManager.get_service_packages()
|
||||
assert "cryptoadvance.specterext.swan.service" in packages
|
||||
assert "cryptoadvance.specterext.electrum.service" in packages
|
||||
assert "cryptoadvance.specterext.electrum.devices.electrum" in packages
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
|
|||
|
|
@ -1,36 +1,89 @@
|
|||
import json
|
||||
import logging
|
||||
import pytest
|
||||
import time
|
||||
|
||||
from cryptoadvance.specter.key import Key
|
||||
from cryptoadvance.specter.managers.device_manager import DeviceManager
|
||||
from cryptoadvance.specter.specter_error import SpecterError
|
||||
from cryptoadvance.specter.user import User
|
||||
from cryptoadvance.specter.util.descriptor import Descriptor
|
||||
from cryptoadvance.specter.util.wallet_importer import WalletImporter
|
||||
from mock import MagicMock, call, patch
|
||||
|
||||
# coldcard, trezor import
|
||||
wallet_coldcardtrezor_json = """
|
||||
{"label": "MyTestMultisig",
|
||||
"blockheight": 0,
|
||||
"descriptor":
|
||||
"wsh(sortedmulti(1,[fb7c1f11/48h/1h/0h/2h]tpubDExnGppazLhZPNadP8Q5Vgee2QcvbyAf9GvGaEY7ALVJREaG2vdTqv1MHRoDtPaYP3y1DGVx7wrKKhsLhs26GY263uE6Wi3qNbi71AHZ6p7/0/*,[1ef4e492/48h/1h/0h/2h]tpubDFiVCZzdarbyk8kE65tjRhHCambEo8iTx4xkXL8b33BKZj66HWsDnUb3rg4GZz6Mwm6vTNyzRCjYtiScCQJ77ENedb2deDDtcoNQXiUouJQ/0/*))#s0jemlck",
|
||||
"devices":
|
||||
[
|
||||
{"type": "coldcard",
|
||||
"label": "MyColdcard"},
|
||||
{"type": "trezor",
|
||||
"label": "MyTestTrezor"}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
wallet_ledger_json = """
|
||||
{
|
||||
"address": "bcrt1q66f7yuxegnzpv9jv5pp6pqfy7smq4ydq643d4e",
|
||||
"address_index": 7,
|
||||
"address_type": "bech32",
|
||||
"alias": "myledger_2",
|
||||
"blockheight": 8244,
|
||||
"change_address": "bcrt1qk087hncum850z0ghpss2lm49kcfu6lppngdeem",
|
||||
"change_descriptor": "wpkh([309c1ac3/84h/1h/0h]tpubDCRGLu8Kjg9dKLUqrVCBZA9TSUkga56X3mnfqWqSVWrooavQdCdYzUdY7peGk7KW7H6gmdJobm5rXr1NQmoGhuPf4aqD3GhgtggYdwMwRom/1/*)#qqulrlpr",
|
||||
"change_index": 0,
|
||||
"change_keypool": 300,
|
||||
"description": "Single (Segwit)",
|
||||
"devices": [
|
||||
"myledger"
|
||||
],
|
||||
"keypool": 300,
|
||||
"keys": [
|
||||
{
|
||||
"derivation": "m/84h/1h/0h",
|
||||
"fingerprint": "309c1ac3",
|
||||
"original": "vpub5YP7DKxoj37DLwukjadqw4d5mRN8hScTfv9vvAzXPbM9x6dF3fTLbueRqNeKDo4RW6LAf6bp9LYi56HdaX81DzaAGJh4BvQUmGxr6peWDsP",
|
||||
"purpose": "#0 Single Sig (Segwit)",
|
||||
"type": "wpkh",
|
||||
"xpub": "tpubDCRGLu8Kjg9dKLUqrVCBZA9TSUkga56X3mnfqWqSVWrooavQdCdYzUdY7peGk7KW7H6gmdJobm5rXr1NQmoGhuPf4aqD3GhgtggYdwMwRom"
|
||||
}
|
||||
],
|
||||
"labels": {},
|
||||
"name": "MyLedger",
|
||||
"recv_descriptor": "wpkh([309c1ac3/84h/1h/0h]tpubDCRGLu8Kjg9dKLUqrVCBZA9TSUkga56X3mnfqWqSVWrooavQdCdYzUdY7peGk7KW7H6gmdJobm5rXr1NQmoGhuPf4aqD3GhgtggYdwMwRom/0/*)#35e7723m",
|
||||
"sigs_required": 1
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
def test_WalletImporter_parse_wallet_data_import():
|
||||
(
|
||||
wallet_name,
|
||||
recv_descriptor,
|
||||
cosigners_types,
|
||||
) = WalletImporter.parse_wallet_data_import(json.loads(wallet_coldcardtrezor_json))
|
||||
assert wallet_name == "MyTestMultisig"
|
||||
assert recv_descriptor.startswith("wsh(sortedmulti(1,[fb7c1")
|
||||
assert cosigners_types[0]["type"] == "coldcard"
|
||||
assert cosigners_types[0]["label"] == "MyColdcard"
|
||||
assert cosigners_types[1]["type"] == "trezor"
|
||||
assert cosigners_types[1]["label"] == "MyTestTrezor"
|
||||
|
||||
|
||||
@patch("cryptoadvance.specter.util.wallet_importer.flash", print)
|
||||
@patch("cryptoadvance.specter.util.wallet_importer._", lambda x: x)
|
||||
def test_WalletImporter_unit():
|
||||
specter_mock = MagicMock()
|
||||
specter_mock.chain = "regtest"
|
||||
specter_mock.node.chain = "regtest"
|
||||
specter_mock.node.is_testnet = True
|
||||
|
||||
# coldcard, trezor import
|
||||
wallet_json = """
|
||||
{"label": "MyTestMultisig",
|
||||
"blockheight": 0,
|
||||
"descriptor":
|
||||
"wsh(sortedmulti(1,[fb7c1f11/48h/1h/0h/2h]tpubDExnGppazLhZPNadP8Q5Vgee2QcvbyAf9GvGaEY7ALVJREaG2vdTqv1MHRoDtPaYP3y1DGVx7wrKKhsLhs26GY263uE6Wi3qNbi71AHZ6p7/0/*,[1ef4e492/48h/1h/0h/2h]tpubDFiVCZzdarbyk8kE65tjRhHCambEo8iTx4xkXL8b33BKZj66HWsDnUb3rg4GZz6Mwm6vTNyzRCjYtiScCQJ77ENedb2deDDtcoNQXiUouJQ/0/*))#s0jemlck",
|
||||
"devices":
|
||||
[
|
||||
{"type": "coldcard",
|
||||
"label": "MyColdcard"},
|
||||
{"type": "trezor",
|
||||
"label": "MyTestTrezor"}
|
||||
]
|
||||
}
|
||||
"""
|
||||
wallet_json = wallet_coldcardtrezor_json
|
||||
|
||||
wallet_importer = WalletImporter(wallet_json, specter_mock)
|
||||
assert wallet_importer.wallet_name == "MyTestMultisig"
|
||||
|
|
@ -136,6 +189,18 @@ def test_WalletImporter_unit():
|
|||
)
|
||||
|
||||
|
||||
@patch("cryptoadvance.specter.util.wallet_importer.flash", print)
|
||||
@patch("cryptoadvance.specter.util.wallet_importer._", lambda x: x)
|
||||
def test_WalletImporter_unit_fail(caplog):
|
||||
caplog.set_level(logging.DEBUG)
|
||||
specter_mock = MagicMock()
|
||||
specter_mock.node.chain = "main"
|
||||
|
||||
wallet_json = wallet_ledger_json
|
||||
with pytest.raises(SpecterError):
|
||||
wallet_importer = WalletImporter(wallet_json, specter_mock)
|
||||
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_WalletImporter_integration(specter_regtest_configured, bitcoin_regtest):
|
||||
"""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue