Skip to content

Commit

Permalink
master keys: accept/show optional key origin info
Browse files Browse the repository at this point in the history
  • Loading branch information
SomberNight committed Oct 30, 2019
1 parent 6c8ca0e commit 14e4932
Show file tree
Hide file tree
Showing 12 changed files with 230 additions and 70 deletions.
4 changes: 2 additions & 2 deletions electrum/base_wizard.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ def derivation_and_script_type_dialog(self, f):
# For segwit, a custom path is used, as there is no standard at all.
default_choice_idx = 2
choices = [
('standard', 'legacy multisig (p2sh)', "m/45'/0"),
('standard', 'legacy multisig (p2sh)', normalize_bip32_derivation("m/45'/0")),
('p2wsh-p2sh', 'p2sh-segwit multisig (p2wsh-p2sh)', purpose48_derivation(0, xtype='p2wsh-p2sh')),
('p2wsh', 'native segwit multisig (p2wsh)', purpose48_derivation(0, xtype='p2wsh')),
]
Expand Down Expand Up @@ -520,7 +520,7 @@ def on_keystore(self, k):
return
self.keystores.append(k)
if len(self.keystores) == 1:
xpub = k.get_master_public_key()
xpub = k.get_master_public_key_with_origin_info()
self.reset_stack()
self.run('show_xpub_and_add_cosigners', xpub)
elif len(self.keystores) < self.n:
Expand Down
4 changes: 2 additions & 2 deletions electrum/bip32.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# file LICENCE or http://www.opensource.org/licenses/mit-license.php

import hashlib
from typing import List, Tuple, NamedTuple, Union, Iterable
from typing import List, Tuple, NamedTuple, Union, Iterable, Sequence

from .util import bfh, bh2u, BitcoinException
from . import constants
Expand Down Expand Up @@ -335,7 +335,7 @@ def convert_bip32_path_to_list_of_uint32(n: str) -> List[int]:
return path


def convert_bip32_intpath_to_strpath(path: List[int]) -> str:
def convert_bip32_intpath_to_strpath(path: Sequence[int]) -> str:
s = "m/"
for child_index in path:
if not isinstance(child_index, int):
Expand Down
2 changes: 1 addition & 1 deletion electrum/gui/kivy/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,7 @@ def popup_dialog(self, name):
elif name == 'status':
popup = Builder.load_file('electrum/gui/kivy/uix/ui_screens/'+name+'.kv')
master_public_keys_layout = popup.ids.master_public_keys
for xpub in self.wallet.get_master_public_keys()[1:]:
for xpub in self.wallet.get_master_public_keys_with_origin_info()[1:]:
master_public_keys_layout.add_widget(TopLabel(text=_('Master Public Key')))
ref = RefLabel()
ref.name = _('Master Public Key')
Expand Down
2 changes: 1 addition & 1 deletion electrum/gui/kivy/uix/ui_screens/status.kv
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Popup:
TopLabel:
text: _('Master Public Key')
RefLabel:
data: app.wallet.get_master_public_key() or 'None'
data: app.wallet.get_master_public_key_with_origin_info() or 'None'
name: _('Master Public Key')
TopLabel:
text: _('This wallet is watching-only') if root.watching_only else _('Seed')
Expand Down
2 changes: 1 addition & 1 deletion electrum/gui/qt/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -2414,7 +2414,7 @@ def enable_lightning(self):
def show_wallet_info(self):
dialog = WindowModalDialog(self, _("Wallet Information"))
dialog.setMinimumSize(500, 100)
mpk_list = self.wallet.get_master_public_keys()
mpk_list = self.wallet.get_master_public_keys_with_origin_info()
vbox = QVBoxLayout()
wallet_type = self.wallet.storage.get('wallet_type', '')
if self.wallet.is_watching_only():
Expand Down
28 changes: 21 additions & 7 deletions electrum/json_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -450,24 +450,38 @@ def _convert_version_20(self):
if not self._is_upgrade_method_needed(19, 19):
return

from .bip32 import BIP32Node
from .bip32 import BIP32Node, convert_bip32_intpath_to_strpath
for ks_name in ('keystore', *['x{}/'.format(i) for i in range(1, 16)]):
ks = self.get(ks_name, None)
if ks is None: continue
xpub = ks.get('xpub', None)
if xpub is None: continue
bip32node = BIP32Node.from_xkey(xpub)
# derivation prefix
derivation_prefix = ks.get('derivation', 'm')
ks['derivation'] = derivation_prefix
derivation_prefix = ks.get('derivation', None)
if derivation_prefix is None:
assert bip32node.depth >= 0, bip32node.depth
if bip32node.depth == 0:
derivation_prefix = 'm'
else:
child_number_int = int.from_bytes(bip32node.child_number, 'big')
path_ints = [0xffff_ffff] * (bip32node.depth - 1) + [child_number_int]
if bip32node.depth > 1:
ks['is_fake_derivation'] = True
derivation_prefix = convert_bip32_intpath_to_strpath(path_ints)
ks['derivation'] = derivation_prefix
# root fingerprint
root_fingerprint = ks.get('ckcc_xfp', None)
if root_fingerprint is not None:
root_fingerprint = root_fingerprint.to_bytes(4, byteorder="little", signed=False).hex().lower()
if root_fingerprint is None:
# if we don't have prior data, we set it to the fp of the xpub
# EVEN IF there was already a derivation prefix saved different than 'm'
node = BIP32Node.from_xkey(xpub)
root_fingerprint = node.calc_fingerprint_of_this_node().hex().lower()
if bip32node.depth == 0:
root_fingerprint = bip32node.calc_fingerprint_of_this_node().hex().lower()
elif bip32node.depth == 1:
root_fingerprint = bip32node.fingerprint.hex()
else:
root_fingerprint = bip32node.calc_fingerprint_of_this_node().hex().lower()
ks['is_fake_root_fingerprint'] = True
ks['root_fingerprint'] = root_fingerprint
ks.pop('ckcc_xfp', None)
self.put(ks_name, ks)
Expand Down
Loading

0 comments on commit 14e4932

Please sign in to comment.