Browse Source

newaddr: support getting both bech32 and p2sh addresses.

Higher layers consume less addresses this way.

Fixes: #2390
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
pr-2391
Rusty Russell 6 years ago
committed by Christian Decker
parent
commit
d9b6abbe31
No known key found for this signature in database GPG Key ID: 1416D83DC4F0E86D
  1. 2
      CHANGELOG.md
  2. 8
      doc/lightning-newaddr.7
  3. 7
      doc/lightning-newaddr.7.txt
  4. 13
      tests/test_misc.py
  5. 57
      wallet/walletrpc.c

2
CHANGELOG.md

@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- JSON API: `newaddr` outputs `bech32` or `p2sh-segwit`, or both with new `all` parameter (#2390)#
### Changed ### Changed
### Deprecated ### Deprecated

8
doc/lightning-newaddr.7

@ -2,12 +2,12 @@
.\" Title: lightning-newaddr .\" Title: lightning-newaddr
.\" Author: [see the "AUTHOR" section] .\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/> .\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" Date: 07/23/2018 .\" Date: 02/23/2019
.\" Manual: \ \& .\" Manual: \ \&
.\" Source: \ \& .\" Source: \ \&
.\" Language: English .\" Language: English
.\" .\"
.TH "LIGHTNING\-NEWADDR" "7" "07/23/2018" "\ \&" "\ \&" .TH "LIGHTNING\-NEWADDR" "7" "02/23/2019" "\ \&" "\ \&"
.\" ----------------------------------------------------------------- .\" -----------------------------------------------------------------
.\" * Define some portability stuff .\" * Define some portability stuff
.\" ----------------------------------------------------------------- .\" -----------------------------------------------------------------
@ -38,12 +38,12 @@ The \fBnewaddr\fR RPC command generates a new address which can subsequently be
.sp .sp
The funding transaction needs to be confirmed before funds can be used\&. The funding transaction needs to be confirmed before funds can be used\&.
.sp .sp
\fIaddresstype\fR specifies the type of address wanted; i\&.e\&. p2sh\-segwit (e\&.g\&. 2MxaozoqWwiUcuD9KKgUSrLFDafLqimT9Ta on bitcoin testnet or 3MZxzq3jBSKNQ2e7dzneo9hy4FvNzmMmt3 on bitcoin mainnet) or bech32 (e\&.g\&. tb1qu9j4lg5f9rgjyfhvfd905vw46eg39czmktxqgg on bitcoin testnet or bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej on bitcoin mainnet)\&. \fIaddresstype\fR specifies the type of address wanted; i\&.e\&. \fIp2sh\-segwit\fR (e\&.g\&. 2MxaozoqWwiUcuD9KKgUSrLFDafLqimT9Ta on bitcoin testnet or 3MZxzq3jBSKNQ2e7dzneo9hy4FvNzmMmt3 on bitcoin mainnet) or \fIbech32 \*(Aq (e\&.g\&. tb1qu9j4lg5f9rgjyfhvfd905vw46eg39czmktxqgg on bitcoin testnet or bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej on bitcoin mainnet)\&. The special value \*(Aqall\fR generates both address types for the same underlying key\&.
.sp .sp
If not specified the address generated is bech32\&. If not specified the address generated is bech32\&.
.SH "RETURN VALUE" .SH "RETURN VALUE"
.sp .sp
On success, a new address will be returned\&. On success, a \fIbech32\fR address and/or a \fIp2sh\-segwit\fR address will be returned\&.
.SH "ERRORS" .SH "ERRORS"
.sp .sp
If an unrecognized address type is requested an error message will be returned\&. If an unrecognized address type is requested an error message will be returned\&.

7
doc/lightning-newaddr.7.txt

@ -19,16 +19,17 @@ subsequently be used to fund channels managed by the c-lightning node.
The funding transaction needs to be confirmed before funds can be used. The funding transaction needs to be confirmed before funds can be used.
'addresstype' specifies the type of address wanted; i.e. 'addresstype' specifies the type of address wanted; i.e.
p2sh-segwit (e.g. 2MxaozoqWwiUcuD9KKgUSrLFDafLqimT9Ta on bitcoin testnet 'p2sh-segwit' (e.g. 2MxaozoqWwiUcuD9KKgUSrLFDafLqimT9Ta on bitcoin testnet
or 3MZxzq3jBSKNQ2e7dzneo9hy4FvNzmMmt3 on bitcoin mainnet) or bech32 or 3MZxzq3jBSKNQ2e7dzneo9hy4FvNzmMmt3 on bitcoin mainnet) or 'bech32 '
(e.g. tb1qu9j4lg5f9rgjyfhvfd905vw46eg39czmktxqgg on bitcoin testnet or (e.g. tb1qu9j4lg5f9rgjyfhvfd905vw46eg39czmktxqgg on bitcoin testnet or
bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej on bitcoin mainnet). bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej on bitcoin mainnet).
The special value 'all' generates both address types for the same underlying key.
If not specified the address generated is bech32. If not specified the address generated is bech32.
RETURN VALUE RETURN VALUE
------------ ------------
On success, a new address will be returned. On success, a 'bech32' address and/or a 'p2sh-segwit' address will be returned.
ERRORS ERRORS
------ ------

13
tests/test_misc.py

@ -1232,3 +1232,16 @@ def test_bad_onion(node_factory, bitcoind):
assert err.value.error['data']['failcode'] == WIRE_INVALID_ONION_HMAC assert err.value.error['data']['failcode'] == WIRE_INVALID_ONION_HMAC
assert err.value.error['data']['erring_node'] == mangled_nodeid assert err.value.error['data']['erring_node'] == mangled_nodeid
assert err.value.error['data']['erring_channel'] == route[1]['channel'] assert err.value.error['data']['erring_channel'] == route[1]['channel']
def test_newaddr(node_factory):
l1 = node_factory.get_node()
p2sh = l1.rpc.newaddr('p2sh-segwit')
assert 'bech32' not in p2sh
assert p2sh['p2sh-segwit'].startswith('2')
bech32 = l1.rpc.newaddr('bech32')
assert 'p2sh-segwit' not in bech32
assert bech32['bech32'].startswith('bcrt1')
both = l1.rpc.newaddr('all')
assert both['p2sh-segwit'].startswith('2')
assert both['bech32'].startswith('bcrt1')

57
wallet/walletrpc.c

@ -266,25 +266,31 @@ encode_scriptpubkey_to_addr(const tal_t *ctx,
return out; return out;
} }
/* Extract a bool indicating "p2sh-segwit" or "bech32" */ enum addrtype {
ADDR_P2SH_SEGWIT = 1,
ADDR_BECH32 = 2,
ADDR_ALL = (ADDR_P2SH_SEGWIT + ADDR_BECH32)
};
/* Extract bool indicating "p2sh-segwit" or "bech32" */
static struct command_result *param_newaddr(struct command *cmd, static struct command_result *param_newaddr(struct command *cmd,
const char *name, const char *name,
const char *buffer, const char *buffer,
const jsmntok_t *tok, const jsmntok_t *tok,
bool **is_p2wpkh) enum addrtype **addrtype)
{ {
*is_p2wpkh = tal(cmd, bool); *addrtype = tal(cmd, enum addrtype);
if (json_tok_streq(buffer, tok, "p2sh-segwit")) { if (json_tok_streq(buffer, tok, "p2sh-segwit"))
**is_p2wpkh = false; **addrtype = ADDR_P2SH_SEGWIT;
return NULL; else if (json_tok_streq(buffer, tok, "bech32"))
} **addrtype = ADDR_BECH32;
if (json_tok_streq(buffer, tok, "bech32")) { else if (json_tok_streq(buffer, tok, "all"))
**is_p2wpkh = true; **addrtype = ADDR_ALL;
return NULL; else
} return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
return command_fail(cmd, JSONRPC2_INVALID_PARAMS, "'%s' should be 'bech32', 'p2sh-segwit' or 'all', not '%.*s'",
"'%s' should be 'bech32' or 'p2sh-segwit', not '%.*s'", name, tok->end - tok->start, buffer + tok->start);
name, tok->end - tok->start, buffer + tok->start); return NULL;
} }
static struct command_result *json_newaddr(struct command *cmd, static struct command_result *json_newaddr(struct command *cmd,
@ -295,12 +301,12 @@ static struct command_result *json_newaddr(struct command *cmd,
struct json_stream *response; struct json_stream *response;
struct ext_key ext; struct ext_key ext;
struct pubkey pubkey; struct pubkey pubkey;
bool *is_p2wpkh; enum addrtype *addrtype;
s64 keyidx; s64 keyidx;
char *out; char *p2sh, *bech32;
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_opt_def("addresstype", param_newaddr, &is_p2wpkh, true), p_opt_def("addresstype", param_newaddr, &addrtype, ADDR_BECH32),
NULL)) NULL))
return command_param_failed(); return command_param_failed();
@ -321,17 +327,20 @@ static struct command_result *json_newaddr(struct command *cmd,
txfilter_add_derkey(cmd->ld->owned_txfilter, ext.pub_key); txfilter_add_derkey(cmd->ld->owned_txfilter, ext.pub_key);
out = encode_pubkey_to_addr(cmd, cmd->ld, p2sh = encode_pubkey_to_addr(cmd, cmd->ld, &pubkey, true, NULL);
&pubkey, !*is_p2wpkh, bech32 = encode_pubkey_to_addr(cmd, cmd->ld, &pubkey, false, NULL);
NULL); if (!p2sh || !bech32) {
if (!out) {
return command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"p2wpkh address encoding failure."); "p2wpkh address encoding failure.");
} }
response = json_stream_success(cmd); response = json_stream_success(cmd);
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_string(response, "address", out); json_add_string(response, "address", bech32 ? bech32 : p2sh);
if (*addrtype & ADDR_BECH32)
json_add_string(response, "bech32", bech32);
if (*addrtype & ADDR_P2SH_SEGWIT)
json_add_string(response, "p2sh-segwit", p2sh);
json_object_end(response); json_object_end(response);
return command_success(cmd, response); return command_success(cmd, response);
} }
@ -339,8 +348,8 @@ static struct command_result *json_newaddr(struct command *cmd,
static const struct json_command newaddr_command = { static const struct json_command newaddr_command = {
"newaddr", "newaddr",
json_newaddr, json_newaddr,
"Get a new {bech32, p2sh-segwit} address to fund a channel (default is bech32)", false, "Get a new {bech32, p2sh-segwit} (or all) address to fund a channel (default is bech32)", false,
"Generates a new address that belongs to the internal wallet. Funds sent to these addresses will be managed by lightningd. Use `withdraw` to withdraw funds to an external wallet." "Generates a new address (or both) that belongs to the internal wallet. Funds sent to these addresses will be managed by lightningd. Use `withdraw` to withdraw funds to an external wallet."
}; };
AUTODATA(json_command, &newaddr_command); AUTODATA(json_command, &newaddr_command);

Loading…
Cancel
Save