Browse Source

wallet_db upgrade: do not use '/' in StoredDict keys

master
ThomasV 6 years ago
parent
commit
56e80c20d7
  1. 12
      electrum/gui/qt/__init__.py
  2. 6
      electrum/plugins/trustedcoin/qt.py
  3. 26
      electrum/plugins/trustedcoin/trustedcoin.py
  4. 14
      electrum/tests/test_wallet_vertical.py
  5. 6
      electrum/wallet.py
  6. 14
      electrum/wallet_db.py
  7. 18
      electrum/wizard.py

12
electrum/gui/qt/__init__.py

@ -420,7 +420,7 @@ class ElectrumGui(BaseElectrumGui, Logger):
if not d['wallet_exists']:
self.logger.info('about to create wallet')
wizard.create_storage()
if d['wallet_type'] == '2fa' and 'x3/' not in d:
if d['wallet_type'] == '2fa' and 'x3' not in d:
return
wallet_file = wizard.path
else:
@ -441,16 +441,16 @@ class ElectrumGui(BaseElectrumGui, Logger):
if action := db.get_action():
# wallet creation is not complete, 2fa online phase
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']:
xprv = k1.get_master_private_key(d['password'])
else:
xprv = db.get('x1/')['xprv']
xprv = db.get('x1')['xprv']
data = {
'wallet_name': os.path.basename(wallet_file),
'xprv1': xprv,
'xpub1': db.get('x1/')['xpub'],
'xpub2': db.get('x2/')['xpub'],
'xpub1': db.get('x1')['xpub'],
'xpub2': db.get('x2')['xpub'],
}
wizard = QENewWalletWizard(self.config, self.app, self.plugins, self.daemon, path,
start_viewstate=WizardViewState('trustedcoin_tos_email', data, {}))
@ -458,7 +458,7 @@ class ElectrumGui(BaseElectrumGui, Logger):
if result == QENewWalletWizard.Rejected:
self.logger.info('ok bye bye')
return
db.put('x3/', wizard.get_wizard_data()['x3/'])
db.put('x3', wizard.get_wizard_data()['x3'])
db.write()
wallet = Wallet(db, config=self.config)

6
electrum/plugins/trustedcoin/qt.py

@ -75,7 +75,7 @@ class HandlerTwoFactor(QObject, Logger):
return
if wallet.can_sign_without_server():
return
if not wallet.keystores['x3/'].can_sign(tx, ignore_watching_only=True):
if not wallet.keystores['x3'].can_sign(tx, ignore_watching_only=True):
self.logger.info("twofactor: xpub3 not needed")
return
window = self.window.top_level_window()
@ -414,8 +414,8 @@ class Plugin(TrustedCoinPlugin):
k1 = keystore.from_xprv(xprv1)
k2 = keystore.from_xpub(xpub2)
wizard_data['x1/'] = k1.dump()
wizard_data['x2/'] = k2.dump()
wizard_data['x1'] = k1.dump()
wizard_data['x2'] = k2.dump()
class WCDisclaimer(WizardComponent):

26
electrum/plugins/trustedcoin/trustedcoin.py

@ -405,8 +405,8 @@ class Wallet_2fa(Multisig_Wallet):
def get_user_id(db):
def make_long_id(xpub_hot, xpub_cold):
return sha256(''.join(sorted([xpub_hot, xpub_cold])))
xpub1 = db.get('x1/')['xpub']
xpub2 = db.get('x2/')['xpub']
xpub1 = db.get('x1')['xpub']
xpub2 = db.get('x2')['xpub']
long_id = make_long_id(xpub1, xpub2)
short_id = hashlib.sha256(long_id).hexdigest()
return long_id, short_id
@ -468,7 +468,7 @@ class TrustedCoinPlugin(BasePlugin):
return
if wallet.can_sign_without_server():
return
if not wallet.keystores['x3/'].can_sign(tx, ignore_watching_only=True):
if not wallet.keystores['x3'].can_sign(tx, ignore_watching_only=True):
self.logger.info("twofactor: xpub3 not needed")
return
def wrapper(tx):
@ -587,11 +587,11 @@ class TrustedCoinPlugin(BasePlugin):
def get_action(self, db):
if db.get('wallet_type') != '2fa':
return
if not db.get('x1/'):
if not db.get('x1'):
return self, 'show_disclaimer'
if not db.get('x2/'):
if not db.get('x2'):
return self, 'show_disclaimer'
if not db.get('x3/'):
if not db.get('x3'):
return self, 'accept_terms_of_use'
# insert trustedcoin pages in new wallet wizard
@ -644,7 +644,7 @@ class TrustedCoinPlugin(BasePlugin):
else:
xprv1, xpub1, xprv2, xpub2 = self.xkeys_from_seed(wizard_data['seed'], wizard_data['seed_extra_words'])
data = {'x1/': {'xpub': xpub1}, 'x2/': {'xpub': xpub2}}
data = {'x1': {'xpub': xpub1}, 'x2': {'xpub': xpub2}}
# Generate third key deterministically.
long_user_id, short_id = get_user_id(data)
@ -660,9 +660,9 @@ class TrustedCoinPlugin(BasePlugin):
k2 = keystore.from_xpub(xpub2)
k3 = keystore.from_xpub(xpub3)
wizard_data['x1/'] = k1.dump()
wizard_data['x2/'] = k2.dump()
wizard_data['x3/'] = k3.dump()
wizard_data['x1'] = k1.dump()
wizard_data['x2'] = k2.dump()
wizard_data['x3'] = k3.dump()
def recovery_disable(self, wizard_data):
if wizard_data['trustedcoin_keepordisable'] != 'disable':
@ -674,7 +674,7 @@ class TrustedCoinPlugin(BasePlugin):
k2 = keystore.from_xprv(xprv2)
k3 = keystore.from_xpub(xpub3)
wizard_data['x1/'] = k1.dump()
wizard_data['x2/'] = k2.dump()
wizard_data['x3/'] = k3.dump()
wizard_data['x1'] = k1.dump()
wizard_data['x2'] = k2.dump()
wizard_data['x3'] = k3.dump()

14
electrum/tests/test_wallet_vertical.py

@ -74,7 +74,7 @@ class WalletIntegrityHelper:
db = storage.WalletDB('', storage=None, upgrade=False)
for i, ks in enumerate(keystores):
cosigner_index = i + 1
db.put('x%d/' % cosigner_index, ks.dump())
db.put('x%d' % cosigner_index, ks.dump())
db.put('wallet_type', multisig_type)
db.put('gap_limit', gap_limit or cls.gap_limit)
w = Multisig_Wallet(db, config=config)
@ -190,8 +190,8 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase):
self.assertEqual(ks2.xpub, xpub2)
long_user_id, short_id = trustedcoin.get_user_id(
{'x1/': {'xpub': xpub1},
'x2/': {'xpub': xpub2}})
{'x1': {'xpub': xpub1},
'x2': {'xpub': xpub2}})
xtype = bip32.xpub_type(xpub1)
xpub3 = trustedcoin.make_xpub(trustedcoin.get_signing_xpub(xtype), long_user_id)
ks3 = keystore.from_xpub(xpub3)
@ -225,8 +225,8 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase):
self.assertEqual(ks2.xpub, xpub2)
long_user_id, short_id = trustedcoin.get_user_id(
{'x1/': {'xpub': xpub1},
'x2/': {'xpub': xpub2}})
{'x1': {'xpub': xpub1},
'x2': {'xpub': xpub2}})
xtype = bip32.xpub_type(xpub1)
xpub3 = trustedcoin.make_xpub(trustedcoin.get_signing_xpub(xtype), long_user_id)
ks3 = keystore.from_xpub(xpub3)
@ -259,8 +259,8 @@ class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase):
self.assertEqual(ks2.xpub, xpub2)
long_user_id, short_id = trustedcoin.get_user_id(
{'x1/': {'xpub': xpub1},
'x2/': {'xpub': xpub2}})
{'x1': {'xpub': xpub1},
'x2': {'xpub': xpub2}})
xtype = bip32.xpub_type(xpub1)
xpub3 = trustedcoin.make_xpub(trustedcoin.get_signing_xpub(xtype), long_user_id)
ks3 = keystore.from_xpub(xpub3)

6
electrum/wallet.py

@ -3615,9 +3615,9 @@ class Multisig_Wallet(Deterministic_Wallet):
def load_keystore(self):
self.keystores = {}
for i in range(self.n):
name = 'x%d/'%(i+1)
name = 'x%d'%(i+1)
self.keystores[name] = load_keystore(self.db, name)
self.keystore = self.keystores['x1/']
self.keystore = self.keystores['x1']
xtype = bip32.xpub_type(self.keystore.xpub)
self.txin_type = 'p2sh' if xtype == 'standard' else xtype
@ -3626,7 +3626,7 @@ class Multisig_Wallet(Deterministic_Wallet):
self.db.put(name, k.dump())
def get_keystore(self):
return self.keystores.get('x1/')
return self.keystores.get('x1')
def get_keystores(self):
return [self.keystores[i] for i in sorted(self.keystores.keys())]

14
electrum/wallet_db.py

@ -59,7 +59,7 @@ class WalletRequiresSplit(WalletFileException):
OLD_SEED_VERSION = 4 # electrum versions < 2.0
NEW_SEED_VERSION = 11 # electrum versions >= 2.0
FINAL_SEED_VERSION = 54 # electrum >= 2.7 will set this to prevent
FINAL_SEED_VERSION = 55 # electrum >= 2.7 will set this to prevent
# old versions from overwriting new format
@ -217,6 +217,7 @@ class WalletDBUpgrader(Logger):
self._convert_version_52()
self._convert_version_53()
self._convert_version_54()
self._convert_version_55()
self.put('seed_version', FINAL_SEED_VERSION) # just to be sure
def _convert_wallet_type(self):
@ -1065,6 +1066,15 @@ class WalletDBUpgrader(Logger):
del d[key]
self.data['seed_version'] = 54
def _convert_version_55(self):
if not self._is_upgrade_method_needed(54, 54):
return
# do not use '/' in dict keys
for key in list(self.data.keys()):
if key.endswith('/'):
self.data[key[:-1]] = self.data.pop(key)
self.data['seed_version'] = 55
def _convert_imported(self):
if not self._is_upgrade_method_needed(0, 13):
return
@ -1619,7 +1629,7 @@ class WalletDB(JsonDB):
def _should_convert_to_stored_dict(self, key) -> bool:
if key == 'keystore':
return False
multisig_keystore_names = [('x%d/' % i) for i in range(1, 16)]
multisig_keystore_names = [('x%d' % i) for i in range(1, 16)]
if key in multisig_keystore_names:
return False
return True

18
electrum/wizard.py

@ -547,7 +547,7 @@ class NewWalletWizard(AbstractWizard):
k = keystore.from_bip43_rootseed(root_seed, derivation, xtype=script)
elif is_any_2fa_seed_type(data['seed_type']):
self._logger.debug('creating keystore from 2fa seed')
k = keystore.from_xprv(data['x1/']['xprv'])
k = keystore.from_xprv(data['x1']['xprv'])
else:
raise Exception('unsupported/unknown seed_type %s' % data['seed_type'])
elif data['keystore_type'] == 'masterkey':
@ -597,23 +597,23 @@ class NewWalletWizard(AbstractWizard):
if data['wallet_type'] == 'standard':
db.put('keystore', k.dump())
elif data['wallet_type'] == '2fa':
db.put('x1/', k.dump())
db.put('x1', k.dump())
if 'trustedcoin_keepordisable' in data and data['trustedcoin_keepordisable'] == 'disable':
k2 = keystore.from_xprv(data['x2/']['xprv'])
k2 = keystore.from_xprv(data['x2']['xprv'])
if data['encrypt'] and k2.may_have_password():
k2.update_password(None, data['password'])
db.put('x2/', k2.dump())
db.put('x2', k2.dump())
else:
db.put('x2/', data['x2/'])
if 'x3/' in data:
db.put('x3/', data['x3/'])
db.put('x2', data['x2'])
if 'x3' in data:
db.put('x3', data['x3'])
db.put('use_trustedcoin', True)
elif data['wallet_type'] == 'multisig':
if not isinstance(k, keystore.Xpub):
raise Exception(f'unexpected keystore(main) type={type(k)} in multisig. not bip32.')
k_xpub_type = xpub_type(k.xpub)
db.put('wallet_type', '%dof%d' % (data['multisig_signatures'], data['multisig_participants']))
db.put('x1/', k.dump())
db.put('x1', k.dump())
for cosigner in data['multisig_cosigner_data']:
cosigner_keystore = self.keystore_from_data('multisig', data['multisig_cosigner_data'][cosigner])
if not isinstance(cosigner_keystore, keystore.Xpub):
@ -622,7 +622,7 @@ class NewWalletWizard(AbstractWizard):
raise Exception('multisig wallet needs to have homogeneous xpub types')
if data['encrypt'] and cosigner_keystore.may_have_password():
cosigner_keystore.update_password(None, data['password'])
db.put(f'x{cosigner}/', cosigner_keystore.dump())
db.put(f'x{cosigner}', cosigner_keystore.dump())
elif data['wallet_type'] == 'imported':
if k:
db.put('keystore', k.dump())

Loading…
Cancel
Save