Browse Source

Merge pull request #8646 from accumulator/load_wallet_refactor

daemon: refactor load_wallet
master
ThomasV 2 years ago committed by GitHub
parent
commit
e882856d4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 21
      electrum/daemon.py
  2. 16
      electrum/gui/qml/components/LoadingWalletDialog.qml
  3. 5
      electrum/gui/qml/components/controls/ElDialog.qml
  4. 18
      electrum/gui/qml/components/main.qml
  5. 2
      electrum/gui/qml/qeapp.py
  6. 35
      electrum/gui/qml/qedaemon.py
  7. 176
      electrum/gui/qml/qewalletdb.py
  8. 28
      electrum/gui/qt/__init__.py
  9. 13
      electrum/gui/qt/wizard/wallet.py
  10. 2
      electrum/scripts/ln_features.py
  11. 2
      electrum/scripts/quick_start.py
  12. 14
      electrum/wallet_db.py

21
electrum/daemon.py

@ -24,6 +24,7 @@
# SOFTWARE. # SOFTWARE.
import asyncio import asyncio
import ast import ast
import errno
import os import os
import time import time
import traceback import traceback
@ -41,13 +42,13 @@ from aiorpcx import timeout_after, TaskTimeout, ignore_after
from . import util from . import util
from .network import Network from .network import Network
from .util import (json_decode, to_bytes, to_string, profiler, standardize_path, constant_time_compare) from .util import (json_decode, to_bytes, to_string, profiler, standardize_path, constant_time_compare, InvalidPassword)
from .invoices import PR_PAID, PR_EXPIRED from .invoices import PR_PAID, PR_EXPIRED
from .util import log_exceptions, ignore_exceptions, randrange, OldTaskGroup from .util import log_exceptions, ignore_exceptions, randrange, OldTaskGroup
from .util import EventListener, event_listener from .util import EventListener, event_listener
from .wallet import Wallet, Abstract_Wallet from .wallet import Wallet, Abstract_Wallet
from .storage import WalletStorage from .storage import WalletStorage
from .wallet_db import WalletDB, WalletRequiresSplit, WalletRequiresUpgrade from .wallet_db import WalletDB, WalletRequiresSplit, WalletRequiresUpgrade, WalletUnfinished
from .commands import known_commands, Commands from .commands import known_commands, Commands
from .simple_config import SimpleConfig from .simple_config import SimpleConfig
from .exchange_rate import FxThread from .exchange_rate import FxThread
@ -488,8 +489,6 @@ class Daemon(Logger):
if wallet := self._wallets.get(wallet_key): if wallet := self._wallets.get(wallet_key):
return wallet return wallet
wallet = self._load_wallet(path, password, upgrade=upgrade, config=self.config) wallet = self._load_wallet(path, password, upgrade=upgrade, config=self.config)
if wallet is None:
return
wallet.start_network(self.network) wallet.start_network(self.network)
self.add_wallet(wallet) self.add_wallet(wallet)
return wallet return wallet
@ -506,20 +505,15 @@ class Daemon(Logger):
path = standardize_path(path) path = standardize_path(path)
storage = WalletStorage(path) storage = WalletStorage(path)
if not storage.file_exists(): if not storage.file_exists():
return raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), path)
if storage.is_encrypted(): if storage.is_encrypted():
if not password: if not password:
return raise InvalidPassword('No password given')
storage.decrypt(password) storage.decrypt(password)
# read data, pass it to db # read data, pass it to db
try: db = WalletDB(storage.read(), storage=storage, upgrade=upgrade)
db = WalletDB(storage.read(), storage=storage, upgrade=upgrade)
except WalletRequiresSplit:
return
except WalletRequiresUpgrade:
return
if db.get_action(): if db.get_action():
return raise WalletUnfinished(db)
wallet = Wallet(db, config=config) wallet = Wallet(db, config=config)
return wallet return wallet
@ -659,7 +653,6 @@ class Daemon(Logger):
pass pass
except Exception: except Exception:
self.logger.exception(f'failed to load wallet at {path!r}:') self.logger.exception(f'failed to load wallet at {path!r}:')
pass
if wallet is None: if wallet is None:
failed.append(path) failed.append(path)
continue continue

16
electrum/gui/qml/components/LoadingWalletDialog.qml

@ -19,6 +19,10 @@ ElDialog {
y: Math.floor((parent.height - implicitHeight) / 2) y: Math.floor((parent.height - implicitHeight) / 2)
// anchors.centerIn: parent // this strangely pixelates the spinner // anchors.centerIn: parent // this strangely pixelates the spinner
function open() {
showTimer.start()
}
ColumnLayout { ColumnLayout {
width: parent.width width: parent.width
@ -32,8 +36,18 @@ ElDialog {
Connections { Connections {
target: Daemon target: Daemon
function onLoadingChanged() { function onLoadingChanged() {
if (!Daemon.loading) console.log('daemon loading ' + Daemon.loading)
if (!Daemon.loading) {
showTimer.stop()
dialog.close() dialog.close()
}
} }
} }
Timer {
id: showTimer
interval: 250
repeat: false
onTriggered: dialog.visible = true
}
} }

5
electrum/gui/qml/components/controls/ElDialog.qml

@ -11,6 +11,8 @@ Dialog {
property bool resizeWithKeyboard: true property bool resizeWithKeyboard: true
property bool _result: false property bool _result: false
// workaround: remember opened state, to inhibit closed -> closed event
property bool _wasOpened: false
// called to finally close dialog after checks by onClosing handler in main.qml // called to finally close dialog after checks by onClosing handler in main.qml
function doClose() { function doClose() {
@ -46,7 +48,10 @@ Dialog {
onOpenedChanged: { onOpenedChanged: {
if (opened) { if (opened) {
app.activeDialogs.push(abstractdialog) app.activeDialogs.push(abstractdialog)
_wasOpened = true
} else { } else {
if (!_wasOpened)
return
if (app.activeDialogs.indexOf(abstractdialog) < 0) { if (app.activeDialogs.indexOf(abstractdialog) < 0) {
console.log('dialog should exist in activeDialogs!') console.log('dialog should exist in activeDialogs!')
app.activeDialogs.pop() app.activeDialogs.pop()

18
electrum/gui/qml/components/main.qml

@ -498,17 +498,21 @@ ApplicationWindow
property var _opendialog: undefined property var _opendialog: undefined
function showOpenWalletDialog(name, path) {
if (_opendialog == undefined) {
_opendialog = openWalletDialog.createObject(app, { name: name, path: path })
_opendialog.closed.connect(function() {
_opendialog = undefined
})
_opendialog.open()
}
}
Connections { Connections {
target: Daemon target: Daemon
function onWalletRequiresPassword(name, path) { function onWalletRequiresPassword(name, path) {
console.log('wallet requires password') console.log('wallet requires password')
if (_opendialog == undefined) { showOpenWalletDialog(name, path)
_opendialog = openWalletDialog.createObject(app, { path: path, name: name })
_opendialog.closed.connect(function() {
_opendialog = undefined
})
_opendialog.open()
}
} }
function onWalletOpenError(error) { function onWalletOpenError(error) {
console.log('wallet open error') console.log('wallet open error')

2
electrum/gui/qml/qeapp.py

@ -25,7 +25,6 @@ from .qedaemon import QEDaemon
from .qenetwork import QENetwork from .qenetwork import QENetwork
from .qewallet import QEWallet from .qewallet import QEWallet
from .qeqr import QEQRParser, QEQRImageProvider, QEQRImageProviderHelper from .qeqr import QEQRParser, QEQRImageProvider, QEQRImageProviderHelper
from .qewalletdb import QEWalletDB
from .qebitcoin import QEBitcoin from .qebitcoin import QEBitcoin
from .qefx import QEFX from .qefx import QEFX
from .qetxfinalizer import QETxFinalizer, QETxRbfFeeBumper, QETxCpfpFeeBumper, QETxCanceller from .qetxfinalizer import QETxFinalizer, QETxRbfFeeBumper, QETxCpfpFeeBumper, QETxCanceller
@ -332,7 +331,6 @@ class ElectrumQmlApplication(QGuiApplication):
ElectrumQmlApplication._daemon = daemon ElectrumQmlApplication._daemon = daemon
qmlRegisterType(QEWallet, 'org.electrum', 1, 0, 'Wallet') qmlRegisterType(QEWallet, 'org.electrum', 1, 0, 'Wallet')
qmlRegisterType(QEWalletDB, 'org.electrum', 1, 0, 'WalletDB')
qmlRegisterType(QEBitcoin, 'org.electrum', 1, 0, 'Bitcoin') qmlRegisterType(QEBitcoin, 'org.electrum', 1, 0, 'Bitcoin')
qmlRegisterType(QEQRParser, 'org.electrum', 1, 0, 'QRParser') qmlRegisterType(QEQRParser, 'org.electrum', 1, 0, 'QRParser')
qmlRegisterType(QEFX, 'org.electrum', 1, 0, 'FX') qmlRegisterType(QEFX, 'org.electrum', 1, 0, 'FX')

35
electrum/gui/qml/qedaemon.py

@ -8,16 +8,16 @@ from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from electrum.i18n import _ from electrum.i18n import _
from electrum.logging import get_logger from electrum.logging import get_logger
from electrum.util import WalletFileException, standardize_path from electrum.util import WalletFileException, standardize_path, InvalidPassword, send_exception_to_crash_reporter
from electrum.plugin import run_hook from electrum.plugin import run_hook
from electrum.lnchannel import ChannelState from electrum.lnchannel import ChannelState
from electrum.bitcoin import is_address from electrum.bitcoin import is_address
from electrum.ecc import verify_message_with_address from electrum.ecc import verify_message_with_address
from electrum.storage import StorageReadWriteError
from .auth import AuthMixin, auth_protect from .auth import AuthMixin, auth_protect
from .qefx import QEFX from .qefx import QEFX
from .qewallet import QEWallet from .qewallet import QEWallet
from .qewalletdb import QEWalletDB
from .qewizard import QENewWalletWizard, QEServerConnectWizard from .qewizard import QENewWalletWizard, QEServerConnectWizard
if TYPE_CHECKING: if TYPE_CHECKING:
@ -152,10 +152,6 @@ class QEDaemon(AuthMixin, QObject):
self._backendWalletLoaded.connect(self._on_backend_wallet_loaded) self._backendWalletLoaded.connect(self._on_backend_wallet_loaded)
self._walletdb = QEWalletDB()
self._walletdb.validPasswordChanged.connect(self.passwordValidityCheck)
self._walletdb.walletOpenProblem.connect(self.onWalletOpenProblem)
@pyqtSlot() @pyqtSlot()
def passwordValidityCheck(self): def passwordValidityCheck(self):
if not self._walletdb._validPassword: if not self._walletdb._validPassword:
@ -192,25 +188,27 @@ class QEDaemon(AuthMixin, QObject):
wallet_already_open = self.daemon.get_wallet(self._path) is not None wallet_already_open = self.daemon.get_wallet(self._path) is not None
if not wallet_already_open:
# pre-checks, let walletdb trigger any necessary user interactions
self._walletdb.path = self._path
self._walletdb.password = password
self._walletdb.verify()
if not self._walletdb.ready:
return
def load_wallet_task(): def load_wallet_task():
self._loading = True self._loading = True
self.loadingChanged.emit() self.loadingChanged.emit()
try: try:
local_password = password # need this in local scope local_password = password # need this in local scope
wallet = self.daemon.load_wallet(self._path, local_password, upgrade=True) wallet = None
try:
wallet = self.daemon.load_wallet(self._path, local_password, upgrade=True)
except InvalidPassword:
self.walletRequiresPassword.emit(self._name, self._path)
except FileNotFoundError:
self.walletOpenError.emit(_('File not found'))
except StorageReadWriteError:
self.walletOpenError.emit(_('Could not read/write file'))
except WalletFileException as e:
self.walletOpenError.emit(_('Could not open wallet: {}').format(str(e)))
if e.should_report_crash:
send_exception_to_crash_reporter(e)
if wallet is None: if wallet is None:
self._logger.info('could not open wallet')
self.walletOpenError.emit('could not open wallet')
return return
if wallet_already_open: if wallet_already_open:
@ -231,9 +229,6 @@ class QEDaemon(AuthMixin, QObject):
run_hook('load_wallet', wallet) run_hook('load_wallet', wallet)
self._backendWalletLoaded.emit(local_password) self._backendWalletLoaded.emit(local_password)
except WalletFileException as e:
self._logger.error(f"load_wallet_task errored opening wallet: {e!r}")
self.walletOpenError.emit(str(e))
finally: finally:
self._loading = False self._loading = False
self.loadingChanged.emit() self.loadingChanged.emit()

176
electrum/gui/qml/qewalletdb.py

@ -1,176 +0,0 @@
from typing import TYPE_CHECKING
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from electrum.i18n import _
from electrum.logging import get_logger
from electrum.storage import WalletStorage
from electrum.wallet_db import WalletDB, WalletRequiresSplit
from electrum.wallet import Wallet
from electrum.util import InvalidPassword, WalletFileException, send_exception_to_crash_reporter
if TYPE_CHECKING:
from electrum.simple_config import SimpleConfig
class QEWalletDB(QObject):
_logger = get_logger(__name__)
fileNotFound = pyqtSignal()
walletOpenProblem = pyqtSignal([str], arguments=['error'])
pathChanged = pyqtSignal([bool], arguments=['ready'])
needsPasswordChanged = pyqtSignal()
needsHWDeviceChanged = pyqtSignal()
passwordChanged = pyqtSignal()
validPasswordChanged = pyqtSignal()
readyChanged = pyqtSignal()
invalidPassword = pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
from .qeapp import ElectrumQmlApplication
self.daemon = ElectrumQmlApplication._daemon
self._config = self.daemon.config # type: SimpleConfig
self.reset()
def reset(self):
self._path = None
self._needsPassword = False
self._needsHWDevice = False
self._password = ''
self._validPassword = True
self._storage = None
self._ready = False
@pyqtProperty('QString', notify=pathChanged)
def path(self):
return self._path
@path.setter
def path(self, wallet_path):
self._logger.debug('setting path: ' + wallet_path)
self.reset()
self._path = wallet_path
self.pathChanged.emit(self._ready)
@pyqtProperty(bool, notify=needsPasswordChanged)
def needsPassword(self):
return self._needsPassword
@needsPassword.setter
def needsPassword(self, wallet_needs_password):
if wallet_needs_password == self._needsPassword:
return
self._needsPassword = wallet_needs_password
self.needsPasswordChanged.emit()
@pyqtProperty(bool, notify=needsHWDeviceChanged)
def needsHWDevice(self):
return self._needsHWDevice
@needsHWDevice.setter
def needsHWDevice(self, wallet_needs_hw_device):
if wallet_needs_hw_device == self._needsHWDevice:
return
self._needsHWDevice = wallet_needs_hw_device
self.needsHWDeviceChanged.emit()
@pyqtProperty('QString', notify=passwordChanged)
def password(self):
return '' # no read access
@password.setter
def password(self, wallet_password):
if wallet_password == self._password:
return
self._password = wallet_password
self.passwordChanged.emit()
@pyqtProperty(bool, notify=validPasswordChanged)
def validPassword(self):
return self._validPassword
@validPassword.setter
def validPassword(self, validPassword):
if self._validPassword != validPassword:
self._validPassword = validPassword
self.validPasswordChanged.emit()
@pyqtProperty(bool, notify=readyChanged)
def ready(self):
return self._ready
@pyqtSlot()
def verify(self):
try:
self._load_storage()
if self._storage:
self._load_db()
except WalletFileException as e:
self._logger.error(f"verify errored: {repr(e)}")
self._storage = None
self.walletOpenProblem.emit(str(e))
if e.should_report_crash:
send_exception_to_crash_reporter(e)
def _load_storage(self):
"""can raise WalletFileException"""
self._storage = WalletStorage(self._path)
if not self._storage.file_exists():
self._logger.warning('file does not exist')
self.fileNotFound.emit()
self._storage = None
return
if self._storage.is_encrypted():
self.needsPassword = True
try:
self._storage.decrypt('' if not self._password else self._password)
self.validPassword = True
except InvalidPassword as e:
self.validPassword = False
self.invalidPassword.emit()
else: # storage not encrypted; but it might still have a keystore pw
# FIXME hack... load both db and full wallet, just to tell if it has keystore pw.
try:
db = WalletDB(self._storage.read(), storage=None, upgrade=True)
except WalletRequiresSplit as e:
raise WalletFileException(_('This wallet requires to be split. This is currently not supported on mobile'))
wallet = Wallet(db, config=self._config)
self.needsPassword = wallet.has_password()
if self.needsPassword:
try:
wallet.check_password('' if not self._password else self._password)
self.validPassword = True
except InvalidPassword as e:
self.validPassword = False
self._storage = None
self.invalidPassword.emit()
if self._storage:
if not self._storage.is_past_initial_decryption():
self._storage = None
def _load_db(self):
"""can raise WalletFileException"""
# needs storage accessible
try:
db = WalletDB(self._storage.read(), storage=None, upgrade=True)
except WalletRequiresSplit as e:
self._logger.warning('wallet requires split')
raise WalletFileException(_('This wallet needs splitting. This is not supported on mobile'))
if db.get_action():
self._logger.warning('action pending. QML version doesn\'t support continuation of wizard')
raise WalletFileException(_('This wallet has an action pending. This is currently not supported on mobile'))
self._ready = True
self.readyChanged.emit()

28
electrum/gui/qt/__init__.py

@ -54,9 +54,9 @@ except ImportError as e:
from electrum.i18n import _, set_language from electrum.i18n import _, set_language
from electrum.plugin import run_hook from electrum.plugin import run_hook
from electrum.util import (UserCancelled, profiler, send_exception_to_crash_reporter, from electrum.util import (UserCancelled, profiler, send_exception_to_crash_reporter,
WalletFileException, BitcoinException, get_new_wallet_name) WalletFileException, BitcoinException, get_new_wallet_name, InvalidPassword)
from electrum.wallet import Wallet, Abstract_Wallet from electrum.wallet import Wallet, Abstract_Wallet
from electrum.wallet_db import WalletDB, WalletRequiresSplit, WalletRequiresUpgrade from electrum.wallet_db import WalletDB, WalletRequiresSplit, WalletRequiresUpgrade, WalletUnfinished
from electrum.logging import Logger from electrum.logging import Logger
from electrum.gui import BaseElectrumGui from electrum.gui import BaseElectrumGui
from electrum.simple_config import SimpleConfig from electrum.simple_config import SimpleConfig
@ -343,6 +343,12 @@ class ElectrumGui(BaseElectrumGui, Logger):
if not force_wizard: if not force_wizard:
try: try:
wallet = self.daemon.load_wallet(path, None) wallet = self.daemon.load_wallet(path, None)
except InvalidPassword:
pass # open with wizard below
except WalletRequiresSplit:
pass # open with wizard below
except WalletRequiresUpgrade:
pass # open with wizard below
except Exception as e: except Exception as e:
self.logger.exception('') self.logger.exception('')
err_text = str(e) if isinstance(e, WalletFileException) else repr(e) err_text = str(e) if isinstance(e, WalletFileException) else repr(e)
@ -426,20 +432,16 @@ class ElectrumGui(BaseElectrumGui, Logger):
else: else:
wallet_file = d['wallet_name'] wallet_file = d['wallet_name']
storage = WalletStorage(wallet_file)
if storage.is_encrypted_with_user_pw() or storage.is_encrypted_with_hw_device():
storage.decrypt(d['password'])
try: try:
db = WalletDB(storage.read(), storage=storage, upgrade=True) wallet = self.daemon.load_wallet(wallet_file, d['password'], upgrade=True)
return wallet
except WalletRequiresSplit as e: except WalletRequiresSplit as e:
try: wizard.run_split(wallet_file, e._split_data)
wizard.run_split(storage, e._split_data) return
except UserCancelled: except WalletUnfinished as e:
return
if action := db.get_action():
# wallet creation is not complete, 2fa online phase # wallet creation is not complete, 2fa online phase
db = e._wallet_db
action = db.get_action()
assert action[1] == 'accept_terms_of_use', 'only support for resuming trustedcoin split setup' assert action[1] == 'accept_terms_of_use', 'only support for resuming trustedcoin split setup'
k1 = load_keystore(db, 'x1') k1 = load_keystore(db, 'x1')
if 'password' in d and d['password']: if 'password' in d and d['password']:

13
electrum/gui/qt/wizard/wallet.py

@ -162,20 +162,17 @@ class QENewWalletWizard(NewWalletWizard, QEAbstractWizard, MessageBoxMixin):
self._password = data['password'] self._password = data['password']
self.path = path self.path = path
def run_split(self, storage, split_data) -> None: def run_split(self, wallet_path, split_data) -> None:
root_path = storage.path
msg = _( msg = _(
"The wallet '{}' contains multiple accounts, which are no longer supported since Electrum 2.7.\n\n" "The wallet '{}' contains multiple accounts, which are no longer supported since Electrum 2.7.\n\n"
"Do you want to split your wallet into multiple files?").format(root_path) "Do you want to split your wallet into multiple files?").format(wallet_path)
if self.question(msg): if self.question(msg):
file_list = WalletDB.split_accounts(root_path, split_data) file_list = WalletDB.split_accounts(wallet_path, split_data)
msg = _('Your accounts have been moved to') + ':\n' + '\n'.join(file_list) + '\n\n' + _( msg = _('Your accounts have been moved to') + ':\n' + '\n'.join(file_list) + '\n\n' + _(
'Do you want to delete the old file') + ':\n' + root_path 'Do you want to delete the old file') + ':\n' + wallet_path
if self.question(msg): if self.question(msg):
os.remove(root_path) os.remove(wallet_path)
self.show_warning(_('The file was removed')) self.show_warning(_('The file was removed'))
# raise now, to avoid having the old storage opened
raise UserCancelled()
def is_finalized(self, wizard_data: dict) -> bool: def is_finalized(self, wizard_data: dict) -> bool:
# check decryption of existing wallet and keep wizard open if incorrect. # check decryption of existing wallet and keep wizard open if incorrect.

2
electrum/scripts/ln_features.py

@ -51,7 +51,7 @@ if not os.path.exists(wallet_path):
create_new_wallet(path=wallet_path, config=config) create_new_wallet(path=wallet_path, config=config)
# open wallet # open wallet
wallet = daemon.load_wallet(wallet_path, password=None, manual_upgrades=False) wallet = daemon.load_wallet(wallet_path, password=None, upgrade=True)
wallet.start_network(network) wallet.start_network(network)

2
electrum/scripts/quick_start.py

@ -28,7 +28,7 @@ if not os.path.exists(wallet_path):
create_new_wallet(path=wallet_path, config=config) create_new_wallet(path=wallet_path, config=config)
# open wallet # open wallet
wallet = daemon.load_wallet(wallet_path, password=None, manual_upgrades=False) wallet = daemon.load_wallet(wallet_path, password=None, upgrade=True)
wallet.start_network(network) wallet.start_network(network)
# you can use ~CLI commands by accessing command_runner # you can use ~CLI commands by accessing command_runner

14
electrum/wallet_db.py

@ -52,12 +52,19 @@ from .version import ELECTRUM_VERSION
class WalletRequiresUpgrade(WalletFileException): class WalletRequiresUpgrade(WalletFileException):
pass pass
class WalletRequiresSplit(WalletFileException): class WalletRequiresSplit(WalletFileException):
def __init__(self, split_data): def __init__(self, split_data):
self._split_data = split_data self._split_data = split_data
# seed_version is now used for the version of the wallet file
class WalletUnfinished(WalletFileException):
def __init__(self, wallet_db: 'WalletDB'):
self._wallet_db = wallet_db
# seed_version is now used for the version of the wallet file
OLD_SEED_VERSION = 4 # electrum versions < 2.0 OLD_SEED_VERSION = 4 # electrum versions < 2.0
NEW_SEED_VERSION = 11 # electrum versions >= 2.0 NEW_SEED_VERSION = 11 # electrum versions >= 2.0
FINAL_SEED_VERSION = 55 # electrum >= 2.7 will set this to prevent FINAL_SEED_VERSION = 55 # electrum >= 2.7 will set this to prevent
@ -91,6 +98,7 @@ class DBMetadata(StoredObject):
# separate tracking issues # separate tracking issues
class WalletFileExceptionVersion51(WalletFileException): pass class WalletFileExceptionVersion51(WalletFileException): pass
# register dicts that require value conversions not handled by constructor # register dicts that require value conversions not handled by constructor
json_db.register_dict('transactions', lambda x: tx_from_any(x, deserialize=False), None) json_db.register_dict('transactions', lambda x: tx_from_any(x, deserialize=False), None)
json_db.register_dict('prevouts_by_scripthash', lambda x: set(tuple(k) for k in x), None) json_db.register_dict('prevouts_by_scripthash', lambda x: set(tuple(k) for k in x), None)
@ -106,9 +114,7 @@ for key in ['locked_in', 'fails', 'settles']:
json_db.register_parent_key(key, lambda x: HTLCOwner(int(x))) json_db.register_parent_key(key, lambda x: HTLCOwner(int(x)))
class WalletDBUpgrader(Logger): class WalletDBUpgrader(Logger):
def __init__(self, data): def __init__(self, data):
Logger.__init__(self) Logger.__init__(self)
self.data = data self.data = data
@ -164,7 +170,7 @@ class WalletDBUpgrader(Logger):
new_data['suffix'] = k new_data['suffix'] = k
result.append(new_data) result.append(new_data)
else: else:
raise WalletFileException("This wallet has multiple accounts and must be split") raise WalletFileException(f'Unsupported wallet type for split: {wallet_type}')
return result return result
def requires_upgrade(self): def requires_upgrade(self):

Loading…
Cancel
Save