Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bip32_ckd takes m/0H/0' notation #137

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 40 additions & 3 deletions bitcoin/deterministic.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,19 @@ def bip32_privtopub(data):
return bip32_serialize(raw_bip32_privtopub(bip32_deserialize(data)))


def bip32_ckd(data, i):
return bip32_serialize(raw_bip32_ckd(bip32_deserialize(data), i))
def bip32_ckd(key, *args, **kwargs):
"""CKD that takes bip32_path or ints, pubbkey derivation is "M/..", "m/0H.pub" or kwarg public=True"""
# use keyword public=True or end path in .pub for public child derivation
argz = map(str, args)
path = "/".join(argz) # no effect if "m/path/0"
if not path.startswith("m/") or not path.startswith("M/"):
path = "m/{0}".format(path)
is_public = path.startswith("M/") or path.endswith(".pub") or kwargs.get("public", False)
pathlist = parse_bip32_path(path)
for p in pathlist:
key = bip32_serialize(raw_bip32_ckd(bip32_deserialize(key), p))
return key if not is_public else bip32_privtopub(key)



def bip32_master_key(seed, vbytes=MAINNET_PRIVATE):
Expand Down Expand Up @@ -190,10 +201,36 @@ def coinvault_priv_to_bip32(*args):


def bip32_descend(*args):
"""Descend masterkey and return privkey"""
if len(args) == 2 and isinstance(args[1], list):
key, path = args
else:
elif len(args) == 2 and isinstance(args[1], string_types):
key = args[0]
path = map(int, str(args[1]).lstrip("mM/").split('/'))
elif len(args):
key, path = args[0], map(int, args[1:])
for p in path:
key = bip32_ckd(key, p)
return bip32_extract_key(key)





def parse_bip32_path(path):
"""Takes bip32 path, "m/0'/2H" or "m/0H/1/2H/2/1000000000.pub", returns list of ints """
path = path.lstrip("m/").rstrip(".pub")
if not path:
return []
elif path.endswith("/"):
path += "0"
patharr = []
for v in path.split('/'):
if not v:
continue
elif v[-1] in ("'H"): # hardened path
v = int(v[:-1]) | 0x80000000
else: # non-hardened path
v = int(v) & 0x7fffffff
patharr.append(v)
return patharr