diff --git a/doc/address.md b/doc/address.md index 6df942322..6138397ef 100644 --- a/doc/address.md +++ b/doc/address.md @@ -12,7 +12,8 @@ - [Essential Address API](#essential-address-api) - [**generatePrivPubKeypair:**](#generateprivpubkeypair) - [**generateHDMasterPubKeypair:**](#generatehdmasterpubkeypair) - - [**generateDerivedHDPubKey:**](#generatederivedhdpubkey) + - [**convertHDKeyToP2PKH:**](#convertHDKeyToP2PKH) + - [**convertHDKeyToECPrivKey:**](#convertHDKeyToECPrivKey) - [**verifyPrivPubKeypair**](#verifyprivpubkeypair) - [**verifyHDMasterPubKeypair**](#verifyhdmasterpubkeypair) - [**verifyP2pkhAddress**](#verifyp2pkhaddress) @@ -144,14 +145,16 @@ int main() { --- -### **generateDerivedHDPubKey:** +### **convertHDKeyToP2PKH:** -`int generateDerivedHDPubkey(const char* wif_privkey_master, char* p2pkh_pubkey)` +`int convertHDKeyToP2PKH(const char* extended_key, char* out_p2pkh_pubkey)` -This function takes a given HD master private key (wif_privkey_master) and loads it into the provided pointer for the resulting derived public key (p2pkh_pubkey). This private key input should come from the result of generateHDMasterPubKeypair(). The function returns 1 on success and 0 on failure. - -This function also works with any extended HD public address (e.g. dgub, tpub) from getDerivedHDAddress -or getDerivedHDAddressByPath, to get the corresponding public P2PKH Address (Dogecoin Address) +* **extended_key** The HD masterkey or HD child address (public or private) +* **out_p2pkh_pubkey** char[] for the corresponding P2PKH public key, at least P2PKH_ADDR_STRINGLEN chars. + +This function takes an HD masterkey or HD child address (public or private) and converts its public key +to a P2PKH Address (Dogecoin Address.) The extended_key can come from generateHDMasterPubKeypair, +getDerivedHDAddress or getDerivedHDAddressByPath. The function returns 1 on success and 0 on failure. _C usage:_ @@ -160,36 +163,39 @@ _C usage:_ #include int main() { - int masterPrivkeyLen = 200; // enough cushion - int pubkeyLen = 35; - - char masterPrivKey[masterPrivkeyLen]; - char masterPubKey[pubkeyLen]; - char childPubKey[pubkeyLen]; + char masterPrivKey[HD_MASTERKEY_STRINGLEN]; + char masterPubKey[P2PKH_ADDR_STRINGLEN]; + char childHDPublic[HD_MASTERKEY_STRINGLEN]; + char childP2PKHAddress[P2PKH_ADDR_STRINGLEN]; dogecoin_ecc_start(); generateHDMasterPubKeypair(masterPrivKey, masterPubKey, false); - generateDerivedHDPubkey(masterPrivKey, childPubKey); + getDerivedHDAddress(masterPrivKey, 0, false, 1, childHDPublic, false); + convertHDKeyToP2PKH(childHDPublic, childP2PKHAddress); dogecoin_ecc_stop(); printf("master private key: %s\n", masterPrivKey); printf("master public key: %s\n", masterPubKey); - printf("derived child key: %s\n", childPubKey); + printf("derived child key: %s\n", childHDPublic); + printf("derived child address: %s\n", childP2PKHAddress); } ``` --- -### **generateDerivedHDPrivKeyWIF** +### **convertHDKeyToECPrivKey** + +`int convertHDKeyToECPrivKey(const char* extended_private, char* out_ec_privkey)` -`int generateDerivedHDPrivKeyWIF(const char* extended_private, char* out_privkey_wif)` +* **extended_private** The extended HD private key (e.g. dgpv, tprv) +* **out_ec_privkey** char[] for the WIF-encoded private EC key, at least WIF_UNCOMPRESSED_PRIVKEY_STRINGLEN chars. -This function converts an extended HD private address (e.g. dgpv, tprv) to a WIF-encoded private key. +This function converts an extended private key (e.g. dgpv, tprv) to an EC private key in WIF format. It works with any extended HD private address from getDerivedHDAddress or getDerivedHDAddressByPath, -to get the corresponding WIF-encoded private key for the child address. +to get the corresponding WIF-encoded EC private key for the child address. -You will need a WIF-encoded private key to sign transactions. +You will need a WIF-encoded EC private key to sign transactions. _C usage:_ @@ -201,18 +207,18 @@ int main() { char masterPrivKey[HD_MASTERKEY_STRINGLEN]; char masterPubKey[P2PKH_ADDR_STRINGLEN]; char childHDPrivate[HD_MASTERKEY_STRINGLEN]; - char privkeyWIF[WIF_UNCOMPRESSED_PRIVKEY_STRINGLEN]; + char ECprivkey[WIF_UNCOMPRESSED_PRIVKEY_STRINGLEN]; dogecoin_ecc_start(); generateHDMasterPubKeypair(masterPrivKey, masterPubKey, false); getDerivedHDAddress(masterPrivKey, 0, false, 1, childHDPrivate, true); - generateDerivedHDPrivKeyWIF(childHDPrivate, privkeyWIF); + convertHDKeyToECPrivKey(childHDPrivate, ECprivkey); dogecoin_ecc_stop(); printf("master private key: %s\n", masterPrivKey); printf("master public key: %s\n", masterPubKey); printf("derived child key: %s\n", childHDPrivate); - printf("derived privkey WIF: %s\n", privkeyWIF); + printf("derived privkey WIF: %s\n", ECprivkey); } ``` diff --git a/include/dogecoin/address.h b/include/dogecoin/address.h index 132da683e..bbd2e8073 100644 --- a/include/dogecoin/address.h +++ b/include/dogecoin/address.h @@ -39,11 +39,14 @@ LIBDOGECOIN_API int generatePrivPubKeypair(char* wif_privkey, char* p2pkh_pubkey /* generate HD master key and WIF public key */ LIBDOGECOIN_API int generateHDMasterPubKeypair(char* wif_privkey_master, char* p2pkh_pubkey_master, bool is_testnet); -/* generate an extended public key */ -LIBDOGECOIN_API int generateDerivedHDPubkey(const char* wif_privkey_master, char* p2pkh_pubkey); +/* converts an HD masterkey or HD child address (public or private) to P2PKH Dogecoin Address */ +LIBDOGECOIN_API int convertHDKeyToP2PKH(const char* extended_key, char* out_p2pkh_pubkey); + +/* converts an HD private key (e.g. dgpv, tprv) to a WIF-encoded EC private key. */ +LIBDOGECOIN_API int convertHDKeyToECPrivKey(const char* extended_private, char* out_ec_privkey); -/* converts an extended HD private address (dgpv, tprv) to a WIF-encoded private key */ -LIBDOGECOIN_API int generateDerivedHDPrivKeyWIF(const char* extended_private, char* out_privkey_wif); +/* deprecated: renamed to convertHDKeyToP2PKH */ +LIBDOGECOIN_API int generateDerivedHDPubkey(const char* wif_privkey_master, char* p2pkh_pubkey); /* verify private and public keys are valid and associated with each other*/ LIBDOGECOIN_API int verifyPrivPubKeypair(char* wif_privkey, char* p2pkh_pubkey, bool is_testnet); diff --git a/include/dogecoin/libdogecoin.h b/include/dogecoin/libdogecoin.h index 5ee150f1a..ecfc43f0d 100644 --- a/include/dogecoin/libdogecoin.h +++ b/include/dogecoin/libdogecoin.h @@ -85,17 +85,20 @@ void dogecoin_ecc_start(void); //!destroys the static ecc context void dogecoin_ecc_stop(void); -/* generates a private and public keypair (a wallet import format private key and a p2pkh ready-to-use corresponding dogecoin address)*/ +/* generates a private and public keypair (a wallet import format EC private key and a p2pkh ready-to-use corresponding dogecoin address)*/ int generatePrivPubKeypair(char* wif_privkey, char* p2pkh_pubkey, bool is_testnet); -/* generates a hybrid deterministic WIF master key and p2pkh ready-to-use corresponding dogecoin address. */ +/* generates a hybrid deterministic (HD) WIF master key and p2pkh ready-to-use corresponding dogecoin address. */ int generateHDMasterPubKeypair(char* wif_privkey_master, char* p2pkh_pubkey_master, bool is_testnet); -/* generates a new dogecoin address from a HD master key */ -int generateDerivedHDPubkey(const char* wif_privkey_master, char* p2pkh_pubkey); +/* converts an HD masterkey or HD child address (public or private) to P2PKH Dogecoin Address */ +int convertHDKeyToP2PKH(const char* extended_key, char* out_p2pkh_pubkey); + +/* converts an HD private key (e.g. dgpv, tprv) to a WIF-encoded EC private key. */ +int convertHDKeyToECPrivKey(const char* extended_private, char* out_ec_privkey); -/* converts an extended HD private address (dgpv, tprv) to a WIF-encoded private key */ -int generateDerivedHDPrivKeyWIF(const char* extended_private, char* out_privkey_wif); +/* deprecated: renamed to convertHDKeyToP2PKH */ +int generateDerivedHDPubkey(const char* wif_privkey_master, char* p2pkh_pubkey); /* verify that a private key and dogecoin address match */ int verifyPrivPubKeypair(char* wif_privkey, char* p2pkh_pubkey, bool is_testnet); diff --git a/src/address.c b/src/address.c index 445472478..d3f4f9cb7 100644 --- a/src/address.c +++ b/src/address.c @@ -146,7 +146,7 @@ int generateHDMasterPubKeypair(char* wif_privkey_master, char* p2pkh_pubkey_mast return false; } - if (!generateDerivedHDPubkey(hd_privkey_master, hd_pubkey_master)) { + if (!convertHDKeyToP2PKH(hd_privkey_master, hd_pubkey_master)) { return false; } @@ -161,61 +161,61 @@ int generateHDMasterPubKeypair(char* wif_privkey_master, char* p2pkh_pubkey_mast } /** - * @brief This function takes a wif-encoded HD master - * private key and derive a new HD public key from it - * on the specified network. This input should come from - * the result of generateHDMasterPubKeypair(). + * @brief This function takes an extended HD key and converts its + * public key to P2PKH format. The extended_key can come from + * generateHDMasterPubKeypair, getDerivedHDAddress or getDerivedHDAddressByPath. * - * @param wif_privkey_master The master private key to derive the child key from. - * @param p2pkh_pubkey The resulting child public key. + * @param extended_key The HD masterkey or HD child address (public or private) + * @param out_p2pkh_pubkey char[] for the corresponding P2PKH public key, + * at least P2PKH_ADDR_STRINGLEN chars * - * @return 1 if the child key was generated successfully, 0 otherwise. + * @return 1 if the P2PKH pubkey was generated successfully, 0 otherwise. */ -int generateDerivedHDPubkey(const char* wif_privkey_master, char* p2pkh_pubkey) +int convertHDKeyToP2PKH(const char* extended_key, char* out_p2pkh_pubkey) { - /* require master key */ - if (!wif_privkey_master) { + if (!extended_key) { return false; } /* determine address prefix for network chainparams */ - const dogecoin_chainparams* chain = chain_from_b58_prefix(wif_privkey_master); + const dogecoin_chainparams* chain = chain_from_b58_prefix(extended_key); char str[P2PKH_ADDR_STRINGLEN]; - /* if nothing is passed in use internal variables */ - if (p2pkh_pubkey) { - memcpy_safe(str, p2pkh_pubkey, sizeof(str)); + dogecoin_hdnode node; + if (!dogecoin_hdnode_deserialize(extended_key, chain, &node)) { + return false; } - dogecoin_hdnode* node = dogecoin_hdnode_new(); - dogecoin_hdnode_deserialize(wif_privkey_master, chain, node); - - dogecoin_hdnode_get_p2pkh_address(node, chain, str, sizeof(str)); + dogecoin_hdnode_get_p2pkh_address(&node, chain, str, sizeof(str)); /* pass back to external variable if exists */ - if (p2pkh_pubkey) { - memcpy_safe(p2pkh_pubkey, str, sizeof(str)); + if (out_p2pkh_pubkey) { + memcpy_safe(out_p2pkh_pubkey, str, sizeof(str)); } /* reset internal variables */ - dogecoin_hdnode_free(node); - dogecoin_mem_zero(str, strlen(str)); + dogecoin_hdnode_clear(&node); return true; } +/* for backwards compatiblity with existing library users */ +int generateDerivedHDPubkey(const char* extended_key, char* p2pkh_pubkey) { + return convertHDKeyToP2PKH(extended_key, p2pkh_pubkey); +} + /** * @brief This function converts an HD extended private address - * (e.g. dgpv, tprv) to a WIF-encoded private key. + * (e.g. dgpv, tprv) to a WIF-encoded private EC key. * * @param extended_private The extended HD private key (e.g. dgpv, tprv) - * @param out_privkey_wif output buffer for the WIF-encoded private key, - * at least WIF_UNCOMPRESSED_PRIVKEY_STRINGLEN chars + * @param out_ec_privkey char[] for the WIF-encoded private EC key, + * at least WIF_UNCOMPRESSED_PRIVKEY_STRINGLEN chars * * @return dogecoin_bool (uint8_t) */ -int generateDerivedHDPrivKeyWIF(const char* extended_private, char* out_privkey_wif) +int convertHDKeyToECPrivKey(const char* extended_private, char* out_ec_privkey) { const dogecoin_chainparams* chain = chain_from_bip32_prefix(extended_private); if (!chain) { @@ -228,7 +228,7 @@ int generateDerivedHDPrivKeyWIF(const char* extended_private, char* out_privkey_ size_t out_size = WIF_UNCOMPRESSED_PRIVKEY_STRINGLEN; dogecoin_key key; memcpy_safe(key.privkey, node.private_key, sizeof(key.privkey)); - dogecoin_privkey_encode_wif(&key, chain, out_privkey_wif, &out_size); + dogecoin_privkey_encode_wif(&key, chain, out_ec_privkey, &out_size); dogecoin_privkey_cleanse(&key); dogecoin_hdnode_clear(&node); return true; diff --git a/test/address_tests.c b/test/address_tests.c index 5dfa2558b..4a12927be 100644 --- a/test/address_tests.c +++ b/test/address_tests.c @@ -175,11 +175,16 @@ void test_address() u_assert_str_eq(p2pkh_pubkey_main, "DTdKu8YgcxoXyjFCDtCeKimaZzsK27rcwT"); #endif - /* generateDerivedHDPrivKeyWIF */ - const char* ext_hd_private = "tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK"; - char privkey_wif_out[WIF_UNCOMPRESSED_PRIVKEY_STRINGLEN]; - u_assert_int_eq(generateDerivedHDPrivKeyWIF(ext_hd_private, privkey_wif_out), true); - u_assert_str_eq(privkey_wif_out, "chq4gQqR1C5erpniafsiu581zFCrctDiUMPTHiMWD3h6H9WWrMzu"); + /* convertHDKeyToP2PKH */ + u_assert_int_eq(convertHDKeyToP2PKH("dgpv51eADS3spNJhA6LG5QycrFmQQtxg7ztFJQuamYiytZ4x4FUC7pG5B7fUTHBDB7g6oGaCVwuGF2i75r1DQKyFSauAHUGBAi89NaggpdUP3yK", str), true) + u_assert_str_eq("DEByFfUQ3AxcFFet9afr8wxxedQysRduWN", str); + u_assert_int_eq(convertHDKeyToP2PKH("dgub8uxGyZKCxRo2buadqKBPGR5MMDrbk8RABK8EcnBv5GrdS8u1Lw2ifRSifsT3wuVRsK45b9kugWkd2cREzkJLiGvwbY5txG2dKfsY3bndC93", str), true) + u_assert_str_eq("D91jVi3CVGhRmyt83fhMdL4UJWtDuiTZET", str); + + /* convertHDKeyToECPrivKey */ + char privkey[WIF_UNCOMPRESSED_PRIVKEY_STRINGLEN]; + u_assert_int_eq(convertHDKeyToECPrivKey("tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK", privkey), true); + u_assert_str_eq("chq4gQqR1C5erpniafsiu581zFCrctDiUMPTHiMWD3h6H9WWrMzu", privkey); /*free up VLAs*/ free(masterkey_main);