def gait_paths_from_seed(seed): """Get the paths for deriving the GreenAddress xpubs from a hex seed, rather than mnemonic This is an alternative derivation path used with hardware wallets where the mnemonic may not be available. It is based on a hardened public key derived from the backed up hw wallet seed. Returns two possible paths corresponding to two different client implementations. """ assert len(seed) == wally.BIP39_SEED_LEN_512 # Passing version=BIP32_VER_MAIN_PRIVATE here although it may be either MAIN or TEST # This version indicator only matters if you serialize the key version = wally.BIP32_VER_MAIN_PRIVATE root_key = wally.bip32_key_from_seed(seed, version, wally.BIP32_FLAG_SKIP_HASH) # path = m/18241' # 18241 = 0x4741 = 'GA' flags = wally.BIP32_FLAG_KEY_PUBLIC | wally.BIP32_FLAG_SKIP_HASH path = [gaconstants.HARDENED | 18241] derived_public_key = wally.bip32_key_from_parent_path(root_key, path, flags) chain_code = wally.bip32_key_get_chain_code(derived_public_key) pub_key = wally.bip32_key_get_pub_key(derived_public_key) # For historic reasons some old clients use a hexlified input path here - generate both path_input = chain_code + pub_key path_input_hex = bytearray(wally.hex_from_bytes(chain_code + pub_key), 'ascii') return [get_gait_path(path_input) for path_input in [path_input, path_input_hex]]
def _private_key_can_spend_output(self, tx, private_key): pubkey = wally.bip32_key_get_pub_key(private_key) spk_from_key = wally.scriptpubkey_p2pkh_from_bytes( pubkey, wally.WALLY_SCRIPT_HASH160) assert wally.tx_get_num_outputs(tx) == 1 spk_from_tx = wally.tx_get_output_script(tx, 0) return spk_from_key == spk_from_tx
def __init__(self, pointer): logging.debug('Derive keys for subaccount={}, pointer={}'.format( subaccount, pointer)) self.subaccount = subaccount self.pointer = pointer # Derive the GreenAddress public key for this pointer value ga_key = gacommon.derive_hd_key(ga_xpub, [pointer], wally.BIP32_FLAG_KEY_PUBLIC) self.ga_key = wally.bip32_key_get_pub_key(ga_key) logging.debug("ga_key = {}".format( wally.hex_from_bytes(self.ga_key))) # Derive the user private keys for this pointer value flags = wally.BIP32_FLAG_KEY_PRIVATE user_key_paths = [(key, [pointer]) for key in user_keys] private_keys = [ gacommon.derive_hd_key(*path, flags=flags) for path in user_key_paths ] self.private_keys = [ wally.bip32_key_get_priv_key(k) for k in private_keys ] # Derive the user public keys from the private keys user_public_keys = [ wally.ec_public_key_from_private_key(k) for k in self.private_keys ] public_keys = [self.ga_key] + user_public_keys # Script could be segwit or not - generate both segwit and non-segwit addresses self.witnesses = { cls.type_: cls(public_keys, network) for cls in (P2SH, P2WSH) } logging.debug('p2sh address: {}'.format( self.witnesses['p2sh'].address)) logging.debug('p2wsh address: {}'.format( self.witnesses['p2wsh'].address))
def get_pubkey_for_pointer_hex(xpub): """Return hex encoded public key derived from xpub for pointer""" xpub = gacommon.derive_hd_key(xpub, [pointer], wally.BIP32_FLAG_KEY_PUBLIC) return wally.hex_from_bytes(wally.bip32_key_get_pub_key(xpub))
def pub(self): return wally.bip32_key_get_pub_key(self.extkey)
def pubkey(self) -> bytes: return PublicKey(wally.bip32_key_get_pub_key(self.extkey))
try: # Desktop: make test vectors from hashlib import sha256 import wallycore as w with open('test_hdnode_gen.py', 'wt') as fd: print("import gc, ngu # auto-gen", file=fd) print("HDNode = ngu.hdnode.HDNode", file=fd) print("for i in range(3):", file=fd) ms = b'1' * 32 for i in range(10): ms = sha256(ms).digest() node = w.bip32_key_from_seed(ms, 0x488ade4, 0) pub = w.bip32_key_get_pub_key(node) priv = w.bip32_key_get_priv_key(node) fp = bytearray(4) w.bip32_key_get_fingerprint(node, fp) cc = w.bip32_key_get_chain_code(node) xprv = w.base58check_from_bytes(w.bip32_key_serialize(node, 0)) xpub = w.base58check_from_bytes( w.bip32_key_serialize(node, w.BIP32_FLAG_KEY_PUBLIC)) addr = w.bip32_key_to_address(node, w.WALLY_ADDRESS_TYPE_P2PKH, 0) print(" a = HDNode(); a.from_master(%r)" % ms, file=fd) print(" assert a.pubkey() == %r" % pub, file=fd) print(" assert a.privkey() == %r" % priv, file=fd) print(" assert a.my_fp() == 0x%s" % fp.hex(), file=fd) print(" assert a.chain_code() == %r" % bytes(cc), file=fd) print(" assert a.serialize(0x488ade4, 1) == %r" % xprv, file=fd)