Skip to content

Commit

Permalink
Merge pull request #148 from edtubbs/0.1.3-dev-fix-header-add-bips
Browse files Browse the repository at this point in the history
Added bip and private key utilities
  • Loading branch information
xanimo authored Aug 2, 2023
2 parents e7812b9 + 4d53e4b commit ddd816b
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 10 deletions.
74 changes: 68 additions & 6 deletions contrib/examples/example.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,77 @@ int main() {
}
// END ===========================================

// BIP44 EXAMPLE
printf("\n\nBIP44 EXAMPLE:\n\n");

int result;
dogecoin_hdnode node;
dogecoin_hdnode bip44_key;
char keypath[BIP44_KEY_PATH_MAX_LENGTH + 1] = "";
size_t size;

dogecoin_hdnode_from_seed(utils_hex_to_uint8("000102030405060708090a0b0c0d0e0f"), 16, &node);
printf ("seed: 000102030405060708090a0b0c0d0e0f\n");

char master_key_str[112];

// Print the master key (MAINNET)
dogecoin_hdnode_serialize_public(&node, &dogecoin_chainparams_main, master_key_str, sizeof(master_key_str));
printf("BIP32 master pub key: %s\n", master_key_str);
dogecoin_hdnode_serialize_private(&node, &dogecoin_chainparams_main, master_key_str, sizeof(master_key_str));
printf("BIP32 master prv key: %s\n", master_key_str);

char* change_level = BIP44_CHANGE_EXTERNAL;

// Derive the BIP 44 extended key
result = derive_bip44_extended_private_key(&node, BIP44_FIRST_ACCOUNT_NODE, NULL, change_level, NULL, false, keypath, &bip44_key);

// Print the BIP 44 extended private key
char bip44_private_key[112];
dogecoin_hdnode_serialize_private(&bip44_key, &dogecoin_chainparams_main, bip44_private_key, sizeof(bip44_private_key));
printf("BIP44 extended private key: %s\n", bip44_private_key);

char str[112];

// Print the BIP 44 extended public key
char bip44_public_key[112];
dogecoin_hdnode_serialize_public(&bip44_key, &dogecoin_chainparams_main, bip44_public_key, sizeof(bip44_public_key));
printf("BIP44 extended public key: %s\n", bip44_public_key);

printf("%s", "Derived Addresses\n");

char wifstr[100];
size_t wiflen = 100;

for (uint32_t index = BIP44_FIRST_ACCOUNT_NODE; index < BIP44_ADDRESS_GAP_LIMIT; index++) {
// Derive the addresses
result = derive_bip44_extended_private_key(&node, BIP44_FIRST_ACCOUNT_NODE, &index, change_level, NULL, false, keypath, &bip44_key);

// Print the private key
dogecoin_hdnode_serialize_private(&bip44_key, &dogecoin_chainparams_main, bip44_private_key, sizeof(bip44_private_key));
printf("private key (serialized): %s\n", bip44_private_key);

// Print the public key
dogecoin_hdnode_serialize_public(&bip44_key, &dogecoin_chainparams_main, bip44_public_key, sizeof(bip44_public_key));
printf("public key (serialized): %s\n", bip44_public_key);

// Print the wif private key
dogecoin_privkey_encode_wif((dogecoin_key*) bip44_key.private_key, &dogecoin_chainparams_main, wifstr, &wiflen);
printf("private key (wif): %s\n", wifstr);

// Print the p2pkh address
dogecoin_hdnode_get_p2pkh_address(&bip44_key, &dogecoin_chainparams_main, str, sizeof(str));
printf("Address: %s\n", str);
}

// BASIC TRANSACTION FORMATION EXAMPLE
printf("\n\nBEGIN TRANSACTION FORMATION AND SIGNING:\n\n");
// declare keys and previous hashes
char *external_p2pkh_addr = "nbGfXLskPh7eM1iG5zz5EfDkkNTo9TRmde";
char *myprivkey = "ci5prbqz7jXyFPVWKkHhPq4a9N8Dag3TpeRfuqqC2Nfr7gSqx1fy";
char *mypubkey = "noxKJyGPugPRN4wqvrwsrtYXuQCk7yQEsy";
char *myscriptpubkey = "76a914d8c43e6f68ca4ea1e9b93da2d1e3a95118fa4a7c88ac";
char *hash_2_doge = "b4455e7b7b7acb51fb6feba7a2702c42a5100f61f61abafa31851ed6ae076074";
char *hash_10_doge = "42113bdc65fc2943cf0359ea1a24ced0b6b0b5290db4c63a3329c6601c4616e2";
char myscriptpubkey [100];
dogecoin_p2pkh_address_to_pubkey_hash (str, myscriptpubkey);

// build transaction
int idx = start_transaction();
Expand Down Expand Up @@ -199,17 +261,17 @@ int main() {

// save the finalized unsigned transaction to a new index in the hash table
// save the finalized unsigned transaction to a new index in the hash table
int idx2 = store_raw_transaction(finalize_transaction(idx, external_p2pkh_addr, "0.00226", "12", mypubkey));
int idx2 = store_raw_transaction(finalize_transaction(idx, external_p2pkh_addr, "0.00226", "12", str));
if (idx2 > 0) {
printf("Change returned to address %s and finalized unsigned transaction saved at index %d.\n", mypubkey, idx2);
printf("Change returned to address %s and finalized unsigned transaction saved at index %d.\n", str, idx2);
}
else {
printf("Error occurred.\n");
return -1;
}

// sign transaction
if (sign_transaction(idx, myscriptpubkey, myprivkey)) {
if (sign_transaction(idx, myscriptpubkey, wifstr)) {
printf("\nAll transaction inputs signed successfully. \nFinal transaction hex: %s\n.", get_raw_transaction(idx));
}
else {
Expand Down
91 changes: 87 additions & 4 deletions include/dogecoin/libdogecoin.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,93 @@ dogecoin_bool dogecoin_p2pkh_address_to_pubkey_hash(char* p2pkh, char* scripthas
char* dogecoin_address_to_pubkey_hash(char* p2pkh);
char* dogecoin_private_key_wif_to_pubkey_hash(char* private_key_wif);

/* privkey utilities */
typedef struct dogecoin_key_ {
uint8_t privkey[DOGECOIN_ECKEY_PKEY_LENGTH];
} dogecoin_key;

void dogecoin_privkey_encode_wif(const dogecoin_key* privkey, const dogecoin_chainparams* chain, char* privkey_wif, size_t* strsize_inout);
dogecoin_bool dogecoin_privkey_decode_wif(const char* privkey_wif, const dogecoin_chainparams* chain, dogecoin_key* privkey);

/* bip32 utilities */
#define DOGECOIN_BIP32_CHAINCODE_SIZE 32

typedef struct
{
uint32_t depth;
uint32_t fingerprint;
uint32_t child_num;
uint8_t chain_code[DOGECOIN_BIP32_CHAINCODE_SIZE];
uint8_t private_key[DOGECOIN_ECKEY_PKEY_LENGTH];
uint8_t public_key[DOGECOIN_ECKEY_COMPRESSED_LENGTH];
} dogecoin_hdnode;

dogecoin_hdnode* dogecoin_hdnode_new();
dogecoin_hdnode* dogecoin_hdnode_copy(const dogecoin_hdnode* hdnode);
void dogecoin_hdnode_free(dogecoin_hdnode* node);
dogecoin_bool dogecoin_hdnode_public_ckd(dogecoin_hdnode* inout, uint32_t i);
dogecoin_bool dogecoin_hdnode_from_seed(const uint8_t* seed, int seed_len, dogecoin_hdnode* out);
dogecoin_bool dogecoin_hdnode_private_ckd(dogecoin_hdnode* inout, uint32_t i);
void dogecoin_hdnode_fill_public_key(dogecoin_hdnode* node);
void dogecoin_hdnode_serialize_public(const dogecoin_hdnode* node, const dogecoin_chainparams* chain, char* str, size_t strsize);
void dogecoin_hdnode_serialize_private(const dogecoin_hdnode* node, const dogecoin_chainparams* chain, char* str, size_t strsize);

void dogecoin_hdnode_get_hash160(const dogecoin_hdnode* node, uint160 hash160_out);
void dogecoin_hdnode_get_p2pkh_address(const dogecoin_hdnode* node, const dogecoin_chainparams* chain, char* str, size_t strsize);
dogecoin_bool dogecoin_hdnode_get_pub_hex(const dogecoin_hdnode* node, char* str, size_t* strsize);
dogecoin_bool dogecoin_hdnode_deserialize(const char* str, const dogecoin_chainparams* chain, dogecoin_hdnode* node);

/* bip44 utilities */
#define BIP44_PURPOSE "44" /* Purpose for key derivation according to BIP 44 */
#define BIP44_COIN_TYPE "3" /* Coin type for Dogecoin (3, SLIP 44) */
#define BIP44_COIN_TYPE_TEST "1" /* Coin type for Testnet (1, SLIP44) */
#define BIP44_CHANGE_EXTERNAL "0" /* Change level for external addresses */
#define BIP44_CHANGE_INTERNAL "1" /* Change level for internal addresses */
#define BIP44_CHANGE_LEVEL_SIZE 1 + 1 /* Change level size with a null terminator */

/* BIP 44 literal constants */
#define BIP44_KEY_PATH_MAX_LENGTH 255 /* Maximum length of key path string */
#define BIP44_KEY_PATH_MAX_SIZE BIP44_KEY_PATH_MAX_LENGTH + 1 /* Key path size with a null terminator */
#define BIP44_ADDRESS_GAP_LIMIT 20 /* Maximum gap between unused addresses */
#define BIP44_FIRST_ACCOUNT_NODE 0 /* Index of the first account node */
#define BIP44_FIRST_ADDRESS_INDEX 0 /* Index of the first address */

/* A string representation of change level used to generate a BIP 44 key path */
/* The change level should be a string equal to "0" or "1" with a maximum size of BIP44_CHANGE_LEVEL_SIZE */
typedef char CHANGE_LEVEL [BIP44_CHANGE_LEVEL_SIZE];

/* A string representation of key path used to derive BIP 44 keys */
/* The key path should be a string with a maximum size of BIP44_KEY_PATH_MAX_SIZE */
typedef char KEY_PATH [BIP44_KEY_PATH_MAX_SIZE];

/* Derives a BIP 44 extended private key from a master private key. */
/* Master private key to derive from */
/* Account index (literal) */
/* Derived address index, set to NULL to get an extended key */
/* Change level ("0" for external or "1" for internal addresses */
/* Custom path string (optional, account and change_level ignored) */
/* Test net flag */
/* Key path string generated */
/* BIP 44 extended private key generated */
/* return 0 (success), -1 (fail) */
int derive_bip44_extended_private_key(const dogecoin_hdnode *master_key, const uint32_t account, const uint32_t* address_index, const CHANGE_LEVEL change_level, const KEY_PATH path, const dogecoin_bool is_testnet, KEY_PATH keypath, dogecoin_hdnode *bip44_key);

/* Derives a BIP 44 extended public key from a master public key. */
/* Master public key to derive from */
/* Account index (literal) */
/* Derived address index, set to NULL to get an extended key */
/* Change level ("0" for external or "1" for internal addresses */
/* Custom path string (optional, account and change_level ignored) */
/* Test net flag */
/* Key path string generated */
/* BIP 44 extended public key generated */
/* return 0 (success), -1 (fail) */
int derive_bip44_extended_public_key(const dogecoin_hdnode *master_key, const uint32_t account, const uint32_t* address_index, const CHANGE_LEVEL change_level, const KEY_PATH path, const dogecoin_bool is_testnet, KEY_PATH keypath, dogecoin_hdnode *bip44_key);

/* utilities */
uint8_t* utils_hex_to_uint8(const char* str);
char* utils_uint8_to_hex(const uint8_t* bin, size_t l);

/* Advanced API functions for mnemonic seedphrase generation
--------------------------------------------------------------------------
*/
Expand Down Expand Up @@ -251,10 +338,6 @@ void dogecoin_free(void* ptr);
--------------------------------------------------------------------------
*/

typedef struct dogecoin_key_ {
uint8_t privkey[DOGECOIN_ECKEY_PKEY_LENGTH];
} dogecoin_key;

typedef struct dogecoin_pubkey_ {
dogecoin_bool compressed;
uint8_t pubkey[DOGECOIN_ECKEY_UNCOMPRESSED_LENGTH];
Expand Down

0 comments on commit ddd816b

Please sign in to comment.