wallet_db upgrade: do not use '/' in StoredDict keys
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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())]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
Reference in New Issue
Block a user