psbt: follow-ups: fix digital bitbox

This commit is contained in:
SomberNight 2019-11-05 22:06:46 +01:00
parent 9e86352022
commit dd14a3fde5
No known key found for this signature in database
GPG key ID: B33B5F232C6271E9
4 changed files with 28 additions and 4 deletions

View file

@ -372,6 +372,18 @@ def normalize_bip32_derivation(s: Optional[str]) -> Optional[str]:
return convert_bip32_intpath_to_strpath(ints) return convert_bip32_intpath_to_strpath(ints)
def is_all_public_derivation(path: Union[str, Iterable[int]]) -> bool:
"""Returns whether all levels in path use non-hardened derivation."""
if isinstance(path, str):
path = convert_bip32_path_to_list_of_uint32(path)
for child_index in path:
if child_index < 0:
raise ValueError('the bip32 index needs to be non-negative')
if child_index & BIP32_PRIME:
return False
return True
def root_fp_and_der_prefix_from_xkey(xkey: str) -> Tuple[Optional[str], Optional[str]]: def root_fp_and_der_prefix_from_xkey(xkey: str) -> Tuple[Optional[str], Optional[str]]:
"""Returns the root bip32 fingerprint and the derivation path from the """Returns the root bip32 fingerprint and the derivation path from the
root to the given xkey, if they can be determined. Otherwise (None, None). root to the given xkey, if they can be determined. Otherwise (None, None).

View file

@ -707,8 +707,10 @@ class Hardware_KeyStore(KeyStore, Xpub):
def opportunistically_fill_in_missing_info_from_device(self, client): def opportunistically_fill_in_missing_info_from_device(self, client):
assert client is not None assert client is not None
if self._root_fingerprint is None: if self._root_fingerprint is None:
root_xpub = client.get_xpub('m', xtype='standard') # digitalbitbox (at least) does not reveal xpubs corresponding to unhardened paths
root_fingerprint = BIP32Node.from_xkey(root_xpub).calc_fingerprint_of_this_node().hex().lower() # so ask for a direct child, and read out fingerprint from that:
child_of_root_xpub = client.get_xpub("m/0'", xtype='standard')
root_fingerprint = BIP32Node.from_xkey(child_of_root_xpub).fingerprint.hex().lower()
self._root_fingerprint = root_fingerprint self._root_fingerprint = root_fingerprint
self.is_requesting_to_be_rewritten_to_wallet_file = True self.is_requesting_to_be_rewritten_to_wallet_file = True

View file

@ -19,7 +19,7 @@ import copy
from electrum.crypto import sha256d, EncodeAES_base64, EncodeAES_bytes, DecodeAES_bytes, hmac_oneshot from electrum.crypto import sha256d, EncodeAES_base64, EncodeAES_bytes, DecodeAES_bytes, hmac_oneshot
from electrum.bitcoin import (TYPE_ADDRESS, push_script, var_int, public_key_to_p2pkh, from electrum.bitcoin import (TYPE_ADDRESS, push_script, var_int, public_key_to_p2pkh,
is_address) is_address)
from electrum.bip32 import BIP32Node, convert_bip32_intpath_to_strpath from electrum.bip32 import BIP32Node, convert_bip32_intpath_to_strpath, is_all_public_derivation
from electrum import ecc from electrum import ecc
from electrum.ecc import msg_magic from electrum.ecc import msg_magic
from electrum.wallet import Standard_Wallet from electrum.wallet import Standard_Wallet
@ -741,6 +741,8 @@ class DigitalBitboxPlugin(HW_PluginBase):
def get_xpub(self, device_id, derivation, xtype, wizard): def get_xpub(self, device_id, derivation, xtype, wizard):
if xtype not in self.SUPPORTED_XTYPES: if xtype not in self.SUPPORTED_XTYPES:
raise ScriptTypeNotSupported(_('This type of script is not supported with {}.').format(self.device)) raise ScriptTypeNotSupported(_('This type of script is not supported with {}.').format(self.device))
if is_all_public_derivation(derivation):
raise Exception(f"The {self.device} does not reveal xpubs corresponding to non-hardened paths. (path: {derivation})")
devmgr = self.device_manager() devmgr = self.device_manager()
client = devmgr.client_by_id(device_id) client = devmgr.client_by_id(device_id)
client.handler = self.create_handler(wizard) client.handler = self.create_handler(wizard)

View file

@ -12,7 +12,7 @@ from electrum.bitcoin import (public_key_to_p2pkh, address_from_private_key,
from electrum.bip32 import (BIP32Node, convert_bip32_intpath_to_strpath, from electrum.bip32 import (BIP32Node, convert_bip32_intpath_to_strpath,
xpub_from_xprv, xpub_type, is_xprv, is_bip32_derivation, xpub_from_xprv, xpub_type, is_xprv, is_bip32_derivation,
is_xpub, convert_bip32_path_to_list_of_uint32, is_xpub, convert_bip32_path_to_list_of_uint32,
normalize_bip32_derivation) normalize_bip32_derivation, is_all_public_derivation)
from electrum.crypto import sha256d, SUPPORTED_PW_HASH_VERSIONS from electrum.crypto import sha256d, SUPPORTED_PW_HASH_VERSIONS
from electrum import ecc, crypto, constants from electrum import ecc, crypto, constants
from electrum.ecc import number_to_string, string_to_number from electrum.ecc import number_to_string, string_to_number
@ -494,6 +494,14 @@ class Test_xprv_xpub(ElectrumTestCase):
self.assertEqual("m/0/2/1'", normalize_bip32_derivation("m/0/2/-1/")) self.assertEqual("m/0/2/1'", normalize_bip32_derivation("m/0/2/-1/"))
self.assertEqual("m/0/1'/1'/5'", normalize_bip32_derivation("m/0//-1/1'///5h")) self.assertEqual("m/0/1'/1'/5'", normalize_bip32_derivation("m/0//-1/1'///5h"))
def test_is_all_public_derivation(self):
self.assertFalse(is_all_public_derivation("m/0/1'/1'"))
self.assertFalse(is_all_public_derivation("m/0/2/1'"))
self.assertFalse(is_all_public_derivation("m/0/1'/1'/5"))
self.assertTrue(is_all_public_derivation("m"))
self.assertTrue(is_all_public_derivation("m/0"))
self.assertTrue(is_all_public_derivation("m/75/22/3"))
def test_xtype_from_derivation(self): def test_xtype_from_derivation(self):
self.assertEqual('standard', xtype_from_derivation("m/44'")) self.assertEqual('standard', xtype_from_derivation("m/44'"))
self.assertEqual('standard', xtype_from_derivation("m/44'/")) self.assertEqual('standard', xtype_from_derivation("m/44'/"))