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 sys
|
||||||
import traceback
|
import traceback
|
||||||
from functools import partial
|
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 bitcoin
|
||||||
from . import keystore
|
from . import keystore
|
||||||
@ -56,6 +56,12 @@ class ScriptTypeNotSupported(Exception): pass
|
|||||||
class GoBack(Exception): pass
|
class GoBack(Exception): pass
|
||||||
|
|
||||||
|
|
||||||
|
class WizardStackItem(NamedTuple):
|
||||||
|
action: Any
|
||||||
|
args: Any
|
||||||
|
storage_data: dict
|
||||||
|
|
||||||
|
|
||||||
class BaseWizard(object):
|
class BaseWizard(object):
|
||||||
|
|
||||||
def __init__(self, config: SimpleConfig, plugins: Plugins, storage: WalletStorage):
|
def __init__(self, config: SimpleConfig, plugins: Plugins, storage: WalletStorage):
|
||||||
@ -64,7 +70,7 @@ class BaseWizard(object):
|
|||||||
self.plugins = plugins
|
self.plugins = plugins
|
||||||
self.storage = storage
|
self.storage = storage
|
||||||
self.wallet = None # type: Abstract_Wallet
|
self.wallet = None # type: Abstract_Wallet
|
||||||
self._stack = []
|
self._stack = [] # type: List[WizardStackItem]
|
||||||
self.plugin = None
|
self.plugin = None
|
||||||
self.keystores = []
|
self.keystores = []
|
||||||
self.is_kivy = config.get('gui') == 'kivy'
|
self.is_kivy = config.get('gui') == 'kivy'
|
||||||
@ -76,7 +82,8 @@ class BaseWizard(object):
|
|||||||
def run(self, *args):
|
def run(self, *args):
|
||||||
action = args[0]
|
action = args[0]
|
||||||
args = args[1:]
|
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:
|
if not action:
|
||||||
return
|
return
|
||||||
if type(action) is tuple:
|
if type(action) is tuple:
|
||||||
@ -96,9 +103,15 @@ class BaseWizard(object):
|
|||||||
def go_back(self):
|
def go_back(self):
|
||||||
if not self.can_go_back():
|
if not self.can_go_back():
|
||||||
return
|
return
|
||||||
|
# pop 'current' frame
|
||||||
self._stack.pop()
|
self._stack.pop()
|
||||||
action, args = self._stack.pop()
|
# pop 'previous' frame
|
||||||
self.run(action, *args)
|
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):
|
def reset_stack(self):
|
||||||
self._stack = []
|
self._stack = []
|
||||||
@ -154,8 +167,8 @@ class BaseWizard(object):
|
|||||||
|
|
||||||
def choose_multisig(self):
|
def choose_multisig(self):
|
||||||
def on_multisig(m, n):
|
def on_multisig(m, n):
|
||||||
self.multisig_type = "%dof%d"%(m, n)
|
multisig_type = "%dof%d" % (m, n)
|
||||||
self.storage.put('wallet_type', self.multisig_type)
|
self.storage.put('wallet_type', multisig_type)
|
||||||
self.n = n
|
self.n = n
|
||||||
self.run('choose_keystore')
|
self.run('choose_keystore')
|
||||||
self.multisig_dialog(run_next=on_multisig)
|
self.multisig_dialog(run_next=on_multisig)
|
||||||
|
|||||||
@ -101,6 +101,20 @@ class JsonDB(PrintError):
|
|||||||
self.modified = True
|
self.modified = True
|
||||||
self.data.pop(key)
|
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
|
@profiler
|
||||||
def write(self):
|
def write(self):
|
||||||
with self.db_lock:
|
with self.db_lock:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user