From 990ef729b0564a9829ae9450bb62ee625b314218 Mon Sep 17 00:00:00 2001 From: ZmnSCPxj Date: Sat, 21 Apr 2018 12:24:58 +0000 Subject: [PATCH] walletrpc: Refactor out encoding of pubkey to address. --- wallet/walletrpc.c | 133 +++++++++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 53 deletions(-) diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index 33154b97f..123a5d0a9 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -198,13 +198,63 @@ static const struct json_command withdraw_command = { }; AUTODATA(json_command, &withdraw_command); +/* May return NULL if encoding error occurs. */ +static char * +encode_pubkey_to_addr(const tal_t *ctx, + const struct lightningd *ld, + const struct pubkey *pubkey, + bool is_p2sh_p2wpkh, + /* Output: redeemscript to use to redeem outputs + * paying to the address. + * May be NULL if redeemscript is do not care. */ + u8 **out_redeemscript) +{ + char *out; + const char *hrp; + struct sha256 h; + struct ripemd160 h160; + u8 *redeemscript; + bool ok; + + if (is_p2sh_p2wpkh) { + redeemscript = bitcoin_redeem_p2sh_p2wpkh(ctx, pubkey); + sha256(&h, redeemscript, tal_count(redeemscript)); + ripemd160(&h160, h.u.u8, sizeof(h)); + out = p2sh_to_base58(ctx, + get_chainparams(ld)->testnet, + &h160); + } else { + hrp = get_chainparams(ld)->bip173_name; + + /* out buffer is 73 + strlen(human readable part), + * see common/bech32.h*/ + out = tal_arr(ctx, char, 73 + strlen(hrp)); + pubkey_to_hash160(pubkey, &h160); + /* I am uncertain why this is so for direct SegWit + * outputs, but this is how listaddrs worked prior to + * this code being refactored. */ + redeemscript = tal_dup_arr(ctx, u8, + (u8 *) &h160, sizeof(h160), + 0); + + ok = segwit_addr_encode(out, hrp, 0, h160.u.u8, sizeof(h160)); + if (!ok) + out = tal_free(out); + } + + if (out_redeemscript) + *out_redeemscript = redeemscript; + else + tal_free(redeemscript); + + return out; +} + static void json_newaddr(struct command *cmd, const char *buffer UNUSED, const jsmntok_t *params UNUSED) { struct json_result *response = new_json_result(cmd); struct ext_key ext; - struct sha256 h; - struct ripemd160 h160; struct pubkey pubkey; jsmntok_t *addrtype; bool is_p2wpkh; @@ -247,23 +297,12 @@ static void json_newaddr(struct command *cmd, const char *buffer UNUSED, txfilter_add_derkey(cmd->ld->owned_txfilter, ext.pub_key); - if (is_p2wpkh) { - const char *hrp = get_chainparams(cmd->ld)->bip173_name; - /* out buffer is 73 + strlen(human readable part). see bech32.h */ - out = tal_arr(cmd, char, 73 + strlen(hrp)); - pubkey_to_hash160(&pubkey, &h160); - bool ok = segwit_addr_encode(out, hrp, 0, h160.u.u8, sizeof(h160.u.u8)); - if (!ok) { - command_fail(cmd, "p2wpkh address encoding failure."); - return; - } - } - else { - u8 *redeemscript = bitcoin_redeem_p2sh_p2wpkh(cmd, &pubkey); - sha256(&h, redeemscript, tal_count(redeemscript)); - ripemd160(&h160, h.u.u8, sizeof(h)); - out = p2sh_to_base58(cmd, - get_chainparams(cmd->ld)->testnet, &h160); + out = encode_pubkey_to_addr(cmd, cmd->ld, + &pubkey, !is_p2wpkh, + NULL); + if (!out) { + command_fail(cmd, "p2wpkh address encoding failure."); + return; } json_object_start(response, NULL); @@ -285,8 +324,6 @@ static void json_listaddrs(struct command *cmd, { struct json_result *response = new_json_result(cmd); struct ext_key ext; - struct sha256 h; - struct ripemd160 h160; struct pubkey pubkey; jsmntok_t *bip32tok; u64 bip32_max_index; @@ -322,19 +359,19 @@ static void json_listaddrs(struct command *cmd, } // p2sh - u8 *redeemscript = bitcoin_redeem_p2sh_p2wpkh(cmd, &pubkey); - sha256(&h, redeemscript, tal_count(redeemscript)); - ripemd160(&h160, h.u.u8, sizeof(h)); - char *out_p2sh = p2sh_to_base58(cmd, - get_chainparams(cmd->ld)->testnet, &h160); + u8 *redeemscript_p2sh; + char *out_p2sh = encode_pubkey_to_addr(cmd, cmd->ld, + &pubkey, + true, + &redeemscript_p2sh); // bech32 : p2wpkh - const char *hrp = get_chainparams(cmd->ld)->bip173_name; - /* out buffer is 73 + strlen(human readable part). see bech32.h */ - char *out_p2wpkh = tal_arr(cmd, char, 73 + strlen(hrp)); - pubkey_to_hash160(&pubkey, &h160); - bool ok = segwit_addr_encode(out_p2wpkh, hrp, 0, h160.u.u8, sizeof(h160.u.u8)); - if (!ok) { + u8 *redeemscript_p2wpkh; + char *out_p2wpkh = encode_pubkey_to_addr(cmd, cmd->ld, + &pubkey, + false, + &redeemscript_p2wpkh); + if (!out_p2wpkh) { command_fail(cmd, "p2wpkh address encoding failure."); return; } @@ -344,9 +381,11 @@ static void json_listaddrs(struct command *cmd, json_add_u64(response, "keyidx", keyidx); json_add_pubkey(response, "pubkey", &pubkey); json_add_string(response, "p2sh", out_p2sh); - json_add_hex(response, "p2sh_redeemscript", redeemscript, tal_count(redeemscript)); + json_add_hex(response, "p2sh_redeemscript", + redeemscript_p2sh, tal_count(redeemscript_p2sh)); json_add_string(response, "bech32", out_p2wpkh); - json_add_hex(response, "bech32_redeemscript", &h160.u.u8, sizeof(struct ripemd160)); + json_add_hex(response, "bech32_redeemscript", + redeemscript_p2wpkh, tal_count(redeemscript_p2wpkh)); json_object_end(response); } json_array_end(response); @@ -371,8 +410,6 @@ static void json_listfunds(struct command *cmd, const char *buffer UNUSED, struct utxo **utxos = wallet_get_utxos(cmd, cmd->ld->wallet, output_state_available); char* out; - struct sha256 h; - struct ripemd160 h160; struct pubkey funding_pubkey; json_object_start(response, NULL); json_array_start(response, "outputs"); @@ -386,23 +423,13 @@ static void json_listfunds(struct command *cmd, const char *buffer UNUSED, if (utxos[i]->close_info == NULL) { bip32_pubkey(cmd->ld->wallet->bip32_base, &funding_pubkey, utxos[i]->keyindex); - if (utxos[i]->is_p2sh) { - u8 *redeemscript = bitcoin_redeem_p2sh_p2wpkh(cmd, &funding_pubkey); - sha256(&h, redeemscript, tal_count(redeemscript)); - ripemd160(&h160, h.u.u8, sizeof(h)); - out = p2sh_to_base58(cmd, - get_chainparams(cmd->ld)->testnet, - &h160); - } else { - const char *hrp = get_chainparams(cmd->ld)->bip173_name; - /* out buffer is 73 + strlen(human readable part). see bech32.h */ - out = tal_arr(cmd, char, 73 + strlen(hrp)); - pubkey_to_hash160(&funding_pubkey, &h160); - bool ok = segwit_addr_encode(out, hrp, 0, h160.u.u8, sizeof(h160.u.u8)); - if (!ok) { - command_fail(cmd, "p2wpkh address encoding failure."); - return; - } + out = encode_pubkey_to_addr(cmd, cmd->ld, + &funding_pubkey, + utxos[i]->is_p2sh, + NULL); + if (!out) { + command_fail(cmd, "p2wpkh address encoding failure."); + return; } json_add_string(response, "address", out); }