From bd07a917828cc0deb9da124fb5aa923ef6d54d91 Mon Sep 17 00:00:00 2001 From: ZmnSCPxj Date: Sat, 24 Feb 2018 14:59:39 +0000 Subject: [PATCH] jsonrpc: Let Base58 '2..' address work on both regtest and testnet. --- lightningd/invoice.c | 17 ++++++++++++----- lightningd/jsonrpc.c | 40 ++++++++++++++++++++++++++++++---------- lightningd/jsonrpc.h | 20 ++++++++++++++++---- wallet/walletrpc.c | 15 ++++++++------- 4 files changed, 66 insertions(+), 26 deletions(-) diff --git a/lightningd/invoice.c b/lightningd/invoice.c index 02d37a70c..c84161d4c 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -107,7 +107,7 @@ static void json_invoice(struct command *cmd, u64 *msatoshi_val; const char *label_val; const char *desc_val; - const char *bip173; + enum address_parse_result fallback_parse; struct json_result *response = new_json_result(cmd); struct wallet *wallet = cmd->ld->wallet; struct bolt11 *b11; @@ -174,10 +174,17 @@ static void json_invoice(struct command *cmd, /* fallback address */ if (fallback) { - bip173 = json_tok_address_scriptpubkey(cmd, buffer, fallback, &fallback_script); - if (!streq(get_chainparams(cmd->ld)->bip173_name, bip173)) { - command_fail(cmd, "Invalid fallback address for %s does not match network %s", - get_chainparams(cmd->ld)->network_name, bip173); + fallback_parse + = json_tok_address_scriptpubkey(cmd, + get_chainparams(cmd->ld), + buffer, fallback, + &fallback_script); + if (fallback_parse == ADDRESS_PARSE_UNRECOGNIZED) { + command_fail(cmd, "Fallback address not valid"); + return; + } else if (fallback_parse == ADDRESS_PARSE_WRONG_NETWORK) { + command_fail(cmd, "Fallback address does not match our network %s", + get_chainparams(cmd->ld)->network_name); return; } } diff --git a/lightningd/jsonrpc.c b/lightningd/jsonrpc.c index 3b2aa40e9..492e081f6 100644 --- a/lightningd/jsonrpc.c +++ b/lightningd/jsonrpc.c @@ -831,8 +831,11 @@ static const char* segwit_addr_net_decode(int *witness_version, return NULL; } -const char *json_tok_address_scriptpubkey(const tal_t *cxt, const char *buffer, - const jsmntok_t *tok, const u8 **scriptpubkey) +enum address_parse_result +json_tok_address_scriptpubkey(const tal_t *cxt, + const struct chainparams *chainparams, + const char *buffer, + const jsmntok_t *tok, const u8 **scriptpubkey) { struct bitcoin_address p2pkh_destination; struct ripemd160 p2sh_destination; @@ -846,21 +849,31 @@ const char *json_tok_address_scriptpubkey(const tal_t *cxt, const char *buffer, char *addrz; const char *bip173; + + bool parsed; + bool right_network; bool testnet; - bip173 = NULL; + parsed = false; if (bitcoin_from_base58(&testnet, &p2pkh_destination, buffer + tok->start, tok->end - tok->start)) { *scriptpubkey = scriptpubkey_p2pkh(cxt, &p2pkh_destination); - bip173 = chainparams_for_network(testnet ? "testnet" : "bitcoin")->bip173_name; + parsed = true; + right_network = (testnet == chainparams->testnet); } else if (p2sh_from_base58(&testnet, &p2sh_destination, buffer + tok->start, tok->end - tok->start)) { *scriptpubkey = scriptpubkey_p2sh_hash(cxt, &p2sh_destination); - bip173 = chainparams_for_network(testnet ? "testnet" : "bitcoin")->bip173_name; + parsed = true; + right_network = (testnet == chainparams->testnet); } /* Insert other parsers that accept pointer+len here. */ - if (bip173) return bip173; + if (parsed) { + if (right_network) + return ADDRESS_PARSE_SUCCESS; + else + return ADDRESS_PARSE_WRONG_NETWORK; + } /* Generate null-terminated address. */ addrz = tal_dup_arr(cxt, char, buffer + tok->start, tok->end - tok->start, 1); @@ -880,13 +893,20 @@ const char *json_tok_address_scriptpubkey(const tal_t *cxt, const char *buffer, if (witness_ok) { *scriptpubkey = scriptpubkey_witness_raw(cxt, witness_version, witness_program, witness_program_len); - } - else { - bip173 = NULL; + parsed = true; + right_network = streq(bip173, chainparams->bip173_name); } } /* Insert other parsers that accept null-terminated string here. */ tal_free(addrz); - return bip173; + + if (parsed) { + if (right_network) + return ADDRESS_PARSE_SUCCESS; + else + return ADDRESS_PARSE_WRONG_NETWORK; + } + + return ADDRESS_PARSE_UNRECOGNIZED; } diff --git a/lightningd/jsonrpc.h b/lightningd/jsonrpc.h index f9f6dd62c..ebdf02b68 100644 --- a/lightningd/jsonrpc.h +++ b/lightningd/jsonrpc.h @@ -1,6 +1,7 @@ #ifndef LIGHTNING_LIGHTNINGD_JSONRPC_H #define LIGHTNING_LIGHTNINGD_JSONRPC_H #include "config.h" +#include #include #include #include @@ -109,11 +110,22 @@ void json_add_address(struct json_result *response, const char *fieldname, /* For initialization */ void setup_jsonrpc(struct lightningd *ld, const char *rpc_filename); -/* Returns NULL, or bip173 network name and fills in *scriptpubkey - * allocated off ctx +enum address_parse_result { + /* Not recognized as an onchain address */ + ADDRESS_PARSE_UNRECOGNIZED, + /* Recognized as an onchain address, but targets wrong network */ + ADDRESS_PARSE_WRONG_NETWORK, + /* Recognized and succeeds */ + ADDRESS_PARSE_SUCCESS, +}; +/* Return result of address parsing and fills in *scriptpubkey + * allocated off ctx if ADDRESS_PARSE_SUCCESS */ -const char *json_tok_address_scriptpubkey(const tal_t *ctx, const char *buffer, - const jsmntok_t *tok, const u8 **scriptpubkey); +enum address_parse_result +json_tok_address_scriptpubkey(const tal_t *ctx, + const struct chainparams *chainparams, + const char *buffer, + const jsmntok_t *tok, const u8 **scriptpubkey); AUTODATA_TYPE(json_command, struct json_command); #endif /* LIGHTNING_LIGHTNINGD_JSONRPC_H */ diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index 966739379..e3b231ba8 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -91,7 +91,7 @@ static void json_withdraw(struct command *cmd, u64 fee_estimate; struct bitcoin_tx *tx; bool withdraw_all = false; - const char *bip173 = NULL; + enum address_parse_result addr_parse; if (!json_get_params(cmd, buffer, params, "destination", &desttok, @@ -111,20 +111,21 @@ static void json_withdraw(struct command *cmd, } /* Parse address. */ - bip173 = json_tok_address_scriptpubkey(cmd, buffer, - desttok, (const u8**)(&withdraw->destination)); + addr_parse = json_tok_address_scriptpubkey(cmd, + get_chainparams(cmd->ld), + buffer, desttok, + (const u8**)(&withdraw->destination)); /* Check that destination address could be understood. */ - if (!bip173) { + if (addr_parse == ADDRESS_PARSE_UNRECOGNIZED) { command_fail(cmd, "Could not parse destination address"); return; } /* Check address given is compatible with the chain we are on. */ - if (!streq(bip173, get_chainparams(cmd->ld)->bip173_name)) { + if (addr_parse == ADDRESS_PARSE_WRONG_NETWORK) { command_fail(cmd, - "Use of %s address on %s", - chainparams_by_bip173(bip173)->network_name, + "Destination address is not on network %s", get_chainparams(cmd->ld)->network_name); return; }