wizard: copy/restore storage when stepping through the wizard
When interacting with wizard, there is a single shared storage instance. If you go down the tree of dialogs, press "back" a couple times, go down another branch of dialogs, etc, there are side-effects on storage, which are never undone. fixes #5057 fixes #4496
This commit is contained in:
parent
9013f6d59e
commit
8412b53ed5
@ -27,7 +27,7 @@ import os
|
||||
import sys
|
||||
import traceback
|
||||
from functools import partial
|
||||
from typing import List, TYPE_CHECKING, Tuple
|
||||
from typing import List, TYPE_CHECKING, Tuple, NamedTuple, Any
|
||||
|
||||
from . import bitcoin
|
||||
from . import keystore
|
||||
@ -56,6 +56,12 @@ class ScriptTypeNotSupported(Exception): pass
|
||||
class GoBack(Exception): pass
|
||||
|
||||
|
||||
class WizardStackItem(NamedTuple):
|
||||
action: Any
|
||||
args: Any
|
||||
storage_data: dict
|
||||
|
||||
|
||||
class BaseWizard(object):
|
||||
|
||||
def __init__(self, config: SimpleConfig, plugins: Plugins, storage: WalletStorage):
|
||||
@ -64,7 +70,7 @@ class BaseWizard(object):
|
||||
self.plugins = plugins
|
||||
self.storage = storage
|
||||
self.wallet = None # type: Abstract_Wallet
|
||||
self._stack = []
|
||||
self._stack = [] # type: List[WizardStackItem]
|
||||
self.plugin = None
|
||||
self.keystores = []
|
||||
self.is_kivy = config.get('gui') == 'kivy'
|
||||
@ -76,7 +82,8 @@ class BaseWizard(object):
|
||||
def run(self, *args):
|
||||
action = args[0]
|
||||
args = args[1:]
|
||||
self._stack.append((action, args))
|
||||
storage_data = self.storage.get_all_data()
|
||||
self._stack.append(WizardStackItem(action, args, storage_data))
|
||||
if not action:
|
||||
return
|
||||
if type(action) is tuple:
|
||||
@ -96,9 +103,15 @@ class BaseWizard(object):
|
||||
def go_back(self):
|
||||
if not self.can_go_back():
|
||||
return
|
||||
# pop 'current' frame
|
||||
self._stack.pop()
|
||||
action, args = self._stack.pop()
|
||||
self.run(action, *args)
|
||||
# pop 'previous' frame
|
||||
stack_item = self._stack.pop()
|
||||
# try to undo side effects since we last entered 'previous' frame
|
||||
# FIXME only self.storage is properly restored
|
||||
self.storage.overwrite_all_data(stack_item.storage_data)
|
||||
# rerun 'previous' frame
|
||||
self.run(stack_item.action, *stack_item.args)
|
||||
|
||||
def reset_stack(self):
|
||||
self._stack = []
|
||||
@ -154,8 +167,8 @@ class BaseWizard(object):
|
||||
|
||||
def choose_multisig(self):
|
||||
def on_multisig(m, n):
|
||||
self.multisig_type = "%dof%d"%(m, n)
|
||||
self.storage.put('wallet_type', self.multisig_type)
|
||||
multisig_type = "%dof%d" % (m, n)
|
||||
self.storage.put('wallet_type', multisig_type)
|
||||
self.n = n
|
||||
self.run('choose_keystore')
|
||||
self.multisig_dialog(run_next=on_multisig)
|
||||
|
||||
@ -101,6 +101,20 @@ class JsonDB(PrintError):
|
||||
self.modified = True
|
||||
self.data.pop(key)
|
||||
|
||||
def get_all_data(self) -> dict:
|
||||
with self.db_lock:
|
||||
return copy.deepcopy(self.data)
|
||||
|
||||
def overwrite_all_data(self, data: dict) -> None:
|
||||
try:
|
||||
json.dumps(data, cls=util.MyEncoder)
|
||||
except:
|
||||
self.print_error(f"json error: cannot save {repr(data)}")
|
||||
return
|
||||
with self.db_lock:
|
||||
self.modified = True
|
||||
self.data = copy.deepcopy(data)
|
||||
|
||||
@profiler
|
||||
def write(self):
|
||||
with self.db_lock:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user