mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-30 17:01:34 +00:00
keystore: cache BIP32Node.from_xkey(self.xpub)
This results in significant performance improvements for keystore.can_sign() and wallet._add_txinout_derivation_info()
This commit is contained in:
parent
f73b6b5d23
commit
59c5efb090
2 changed files with 16 additions and 7 deletions
|
@ -273,6 +273,7 @@ class BIP32Node(NamedTuple):
|
||||||
"""Returns the fingerprint of this node.
|
"""Returns the fingerprint of this node.
|
||||||
Note that self.fingerprint is of the *parent*.
|
Note that self.fingerprint is of the *parent*.
|
||||||
"""
|
"""
|
||||||
|
# TODO cache this
|
||||||
return hash_160(self.eckey.get_public_key_bytes(compressed=True))[0:4]
|
return hash_160(self.eckey.get_public_key_bytes(compressed=True))[0:4]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -143,8 +143,8 @@ class KeyStore(Logger):
|
||||||
if not test_der_suffix_against_pubkey(der_suffix, pubkey):
|
if not test_der_suffix_against_pubkey(der_suffix, pubkey):
|
||||||
der_suffix = None
|
der_suffix = None
|
||||||
# try fp against our intermediate fingerprint
|
# try fp against our intermediate fingerprint
|
||||||
if (der_suffix is None and hasattr(self, 'xpub') and
|
if (der_suffix is None and hasattr(self, 'get_bip32_node_for_xpub') and
|
||||||
fp_found == BIP32Node.from_xkey(self.xpub).calc_fingerprint_of_this_node()):
|
fp_found == self.get_bip32_node_for_xpub().calc_fingerprint_of_this_node()):
|
||||||
der_suffix = path_found
|
der_suffix = path_found
|
||||||
if not test_der_suffix_against_pubkey(der_suffix, pubkey):
|
if not test_der_suffix_against_pubkey(der_suffix, pubkey):
|
||||||
der_suffix = None
|
der_suffix = None
|
||||||
|
@ -331,6 +331,7 @@ class Xpub:
|
||||||
self.xpub = None
|
self.xpub = None
|
||||||
self.xpub_receive = None
|
self.xpub_receive = None
|
||||||
self.xpub_change = None
|
self.xpub_change = None
|
||||||
|
self._xpub_bip32_node = None # type: Optional[BIP32Node]
|
||||||
|
|
||||||
# "key origin" info (subclass should persist these):
|
# "key origin" info (subclass should persist these):
|
||||||
self._derivation_prefix = derivation_prefix # type: Optional[str]
|
self._derivation_prefix = derivation_prefix # type: Optional[str]
|
||||||
|
@ -339,6 +340,13 @@ class Xpub:
|
||||||
def get_master_public_key(self):
|
def get_master_public_key(self):
|
||||||
return self.xpub
|
return self.xpub
|
||||||
|
|
||||||
|
def get_bip32_node_for_xpub(self) -> Optional[BIP32Node]:
|
||||||
|
if self._xpub_bip32_node is None:
|
||||||
|
if self.xpub is None:
|
||||||
|
return None
|
||||||
|
self._xpub_bip32_node = BIP32Node.from_xkey(self.xpub)
|
||||||
|
return self._xpub_bip32_node
|
||||||
|
|
||||||
def get_derivation_prefix(self) -> Optional[str]:
|
def get_derivation_prefix(self) -> Optional[str]:
|
||||||
"""Returns to bip32 path from some root node to self.xpub
|
"""Returns to bip32 path from some root node to self.xpub
|
||||||
Note that the return value might be None; if it is unknown.
|
Note that the return value might be None; if it is unknown.
|
||||||
|
@ -367,7 +375,7 @@ class Xpub:
|
||||||
der_prefix_ints = convert_bip32_path_to_list_of_uint32(der_prefix_str)
|
der_prefix_ints = convert_bip32_path_to_list_of_uint32(der_prefix_str)
|
||||||
else:
|
else:
|
||||||
# use intermediate fp, and claim der suffix is the full path
|
# use intermediate fp, and claim der suffix is the full path
|
||||||
fingerprint_bytes = BIP32Node.from_xkey(self.xpub).calc_fingerprint_of_this_node()
|
fingerprint_bytes = self.get_bip32_node_for_xpub().calc_fingerprint_of_this_node()
|
||||||
der_prefix_ints = convert_bip32_path_to_list_of_uint32('m')
|
der_prefix_ints = convert_bip32_path_to_list_of_uint32('m')
|
||||||
der_full = der_prefix_ints + list(der_suffix)
|
der_full = der_prefix_ints + list(der_suffix)
|
||||||
return fingerprint_bytes, der_full
|
return fingerprint_bytes, der_full
|
||||||
|
@ -376,7 +384,7 @@ class Xpub:
|
||||||
assert self.xpub
|
assert self.xpub
|
||||||
fp_bytes, der_full = self.get_fp_and_derivation_to_be_used_in_partial_tx(der_suffix=[],
|
fp_bytes, der_full = self.get_fp_and_derivation_to_be_used_in_partial_tx(der_suffix=[],
|
||||||
only_der_suffix=only_der_suffix)
|
only_der_suffix=only_der_suffix)
|
||||||
bip32node = BIP32Node.from_xkey(self.xpub)
|
bip32node = self.get_bip32_node_for_xpub()
|
||||||
depth = len(der_full)
|
depth = len(der_full)
|
||||||
child_number_int = der_full[-1] if len(der_full) >= 1 else 0
|
child_number_int = der_full[-1] if len(der_full) >= 1 else 0
|
||||||
child_number_bytes = child_number_int.to_bytes(length=4, byteorder="big")
|
child_number_bytes = child_number_int.to_bytes(length=4, byteorder="big")
|
||||||
|
@ -391,7 +399,7 @@ class Xpub:
|
||||||
# try to derive ourselves from what we were given
|
# try to derive ourselves from what we were given
|
||||||
child_node1 = root_node.subkey_at_private_derivation(derivation_prefix)
|
child_node1 = root_node.subkey_at_private_derivation(derivation_prefix)
|
||||||
child_pubkey_bytes1 = child_node1.eckey.get_public_key_bytes(compressed=True)
|
child_pubkey_bytes1 = child_node1.eckey.get_public_key_bytes(compressed=True)
|
||||||
child_node2 = BIP32Node.from_xkey(self.xpub)
|
child_node2 = self.get_bip32_node_for_xpub()
|
||||||
child_pubkey_bytes2 = child_node2.eckey.get_public_key_bytes(compressed=True)
|
child_pubkey_bytes2 = child_node2.eckey.get_public_key_bytes(compressed=True)
|
||||||
if child_pubkey_bytes1 != child_pubkey_bytes2:
|
if child_pubkey_bytes1 != child_pubkey_bytes2:
|
||||||
raise Exception("(xpub, derivation_prefix, root_node) inconsistency")
|
raise Exception("(xpub, derivation_prefix, root_node) inconsistency")
|
||||||
|
@ -408,7 +416,7 @@ class Xpub:
|
||||||
assert for_change in (0, 1)
|
assert for_change in (0, 1)
|
||||||
xpub = self.xpub_change if for_change else self.xpub_receive
|
xpub = self.xpub_change if for_change else self.xpub_receive
|
||||||
if xpub is None:
|
if xpub is None:
|
||||||
rootnode = BIP32Node.from_xkey(self.xpub)
|
rootnode = self.get_bip32_node_for_xpub()
|
||||||
xpub = rootnode.subkey_at_public_derivation((for_change,)).to_xpub()
|
xpub = rootnode.subkey_at_public_derivation((for_change,)).to_xpub()
|
||||||
if for_change:
|
if for_change:
|
||||||
self.xpub_change = xpub
|
self.xpub_change = xpub
|
||||||
|
@ -453,7 +461,7 @@ class BIP32_KeyStore(Deterministic_KeyStore, Xpub):
|
||||||
|
|
||||||
def check_password(self, password):
|
def check_password(self, password):
|
||||||
xprv = pw_decode(self.xprv, password, version=self.pw_hash_version)
|
xprv = pw_decode(self.xprv, password, version=self.pw_hash_version)
|
||||||
if BIP32Node.from_xkey(xprv).chaincode != BIP32Node.from_xkey(self.xpub).chaincode:
|
if BIP32Node.from_xkey(xprv).chaincode != self.get_bip32_node_for_xpub().chaincode:
|
||||||
raise InvalidPassword()
|
raise InvalidPassword()
|
||||||
|
|
||||||
def update_password(self, old_password, new_password):
|
def update_password(self, old_password, new_password):
|
||||||
|
|
Loading…
Add table
Reference in a new issue