diff --git a/contrib/pylightning/lightning/lightning.py b/contrib/pylightning/lightning/lightning.py index d90c2b3e2..da820b3a0 100644 --- a/contrib/pylightning/lightning/lightning.py +++ b/contrib/pylightning/lightning/lightning.py @@ -331,15 +331,14 @@ class LightningRpc(UnixDomainSocketRpc): } return self.call("listpeers", payload) - def fundchannel(self, node_id, satoshi, feerate=None, feeratestyle=None): + def fundchannel(self, node_id, satoshi, feerate=None): """ Fund channel with {id} using {satoshi} satoshis" """ payload = { "id": node_id, "satoshi": satoshi, - "feerate": feerate, - "feeratestyle": feeratestyle + "feerate": feerate } return self.call("fundchannel", payload) @@ -406,7 +405,7 @@ class LightningRpc(UnixDomainSocketRpc): """ return self.call("dev-memleak") - def withdraw(self, destination, satoshi, feerate=None, feeratestyle=None): + def withdraw(self, destination, satoshi, feerate=None): """ Send to {destination} address {satoshi} (or "all") amount via Bitcoin transaction @@ -414,8 +413,7 @@ class LightningRpc(UnixDomainSocketRpc): payload = { "destination": destination, "satoshi": satoshi, - "feerate": feerate, - "feeratestyle": feeratestyle + "feerate": feerate } return self.call("withdraw", payload) diff --git a/doc/lightning-fundchannel.7 b/doc/lightning-fundchannel.7 index ee90583c4..08f6c7396 100644 --- a/doc/lightning-fundchannel.7 +++ b/doc/lightning-fundchannel.7 @@ -2,12 +2,12 @@ .\" Title: lightning-fundchannel .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 08/27/2018 +.\" Date: 08/29/2018 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" -.TH "LIGHTNING\-FUNDCHANN" "7" "08/27/2018" "\ \&" "\ \&" +.TH "LIGHTNING\-FUNDCHANN" "7" "08/29/2018" "\ \&" "\ \&" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -31,7 +31,7 @@ lightning-fundchannel \- Command for establishing a lightning channel\&. .SH "SYNOPSIS" .sp -\fBfundchannel\fR \fIid\fR \fIsatoshi\fR [\fIfeerate\fR \fIfeeratestyle\fR] +\fBfundchannel\fR \fIid\fR \fIsatoshi\fR [\fIfeerate\fR] .SH "DESCRIPTION" .sp The \fBfundchannel\fR RPC command opens a payment channel with a peer by commiting a funding transaction to the blockchain as defined in BOLT #2\&. \fBfundchannel\fR by itself does not attempt to open a connection\&. A connection must first be established using \fBconnect\fR\&. Once the transaction is confirmed, normal channel operations may begin\&. Readiness is indicated by \fBlistpeers\fR reporting a \fIstate\fR of CHANNELD_NORMAL for the channel\&. @@ -40,7 +40,7 @@ The \fBfundchannel\fR RPC command opens a payment channel with a peer by commiti .sp \fIsatoshi\fR is the amount in satoshis taken from the internal wallet to fund the channel\&. The string \fIall\fR can be used to specify all available funds (or 16777215 satoshi if more is available)\&. The value cannot be less than the dust limit, currently set to 546, nor more than 16777215 satoshi\&. .sp -\fIfeerate\fR is an optional feerate to use, overriding lightningd\(cqs internal estimate\&. If specified, \fIfeeratestyle\fR must be either \fI"perkw"\fR for if \fIfeerate\fR is in satoshi\-per\-kilosipa (weight), or \fI"perkb"\fR for if \fIfeerate\fR is in bitcoind\-style satoshi\-per\-kilobyte\&. +\fIfeerate\fR is an optional feerate to use, overriding lightningd\(cqs internal estimate\&. \fIfeerate\fR is a number, with an optional suffix: \fIperkw\fR means the number is interpreted as satoshi\-per\-kilosipa (weight), and \fIperkb\fR means it is interpreted bitcoind\-style as satoshi\-per\-kilobyte\&. Omitting the suffix is equivalent to \fIperkb\fR\&. .SH "RETURN VALUE" .sp On success, the \fItx\fR and \fItxid\fR of the transaction is returned, as well as the \fIchannel_id\fR of the newly created channel\&. On failure, an error is reported and the channel is not funded\&. diff --git a/doc/lightning-fundchannel.7.txt b/doc/lightning-fundchannel.7.txt index 1df784a8d..faeedebda 100644 --- a/doc/lightning-fundchannel.7.txt +++ b/doc/lightning-fundchannel.7.txt @@ -8,7 +8,7 @@ lightning-fundchannel - Command for establishing a lightning channel. SYNOPSIS -------- -*fundchannel* 'id' 'satoshi' ['feerate' 'feeratestyle'] +*fundchannel* 'id' 'satoshi' ['feerate'] DESCRIPTION ----------- @@ -28,9 +28,10 @@ The value cannot be less than the dust limit, currently set to 546, nor more than 16777215 satoshi. 'feerate' is an optional feerate to use, overriding lightningd's -internal estimate. If specified, 'feeratestyle' must be either -'"perkw"' for if 'feerate' is in satoshi-per-kilosipa (weight), -or '"perkb"' for if 'feerate' is in bitcoind-style satoshi-per-kilobyte. +internal estimate. 'feerate' is a number, with an optional suffix: +'perkw' means the number is interpreted as satoshi-per-kilosipa +(weight), and 'perkb' means it is interpreted bitcoind-style as +satoshi-per-kilobyte. Omitting the suffix is equivalent to 'perkb'. RETURN VALUE ------------ diff --git a/doc/lightning-withdraw.7 b/doc/lightning-withdraw.7 index 34736e486..b2338aa67 100644 --- a/doc/lightning-withdraw.7 +++ b/doc/lightning-withdraw.7 @@ -2,12 +2,12 @@ .\" Title: lightning-withdraw .\" Author: [see the "AUTHOR" section] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 08/27/2018 +.\" Date: 08/29/2018 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" -.TH "LIGHTNING\-WITHDRAW" "7" "08/27/2018" "\ \&" "\ \&" +.TH "LIGHTNING\-WITHDRAW" "7" "08/29/2018" "\ \&" "\ \&" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -31,7 +31,7 @@ lightning-withdraw \- Command for withdrawing funds from the internal wallet\&. .SH "SYNOPSIS" .sp -\fBwithdraw\fR \fIdestination\fR \fIsatoshi\fR [\fIfeerate\fR \fIfeeratestyle\fR] +\fBwithdraw\fR \fIdestination\fR \fIsatoshi\fR [\fIfeerate\fR] .SH "DESCRIPTION" .sp The \fBwithdraw\fR RPC command sends funds from c\-lightning\(cqs internal wallet to the address specified in \fIdestination\fR\&. @@ -40,7 +40,7 @@ The address can be of any Bitcoin accepted type, including bech32\&. .sp \fIsatoshi\fR is the amount to be withdrawn from the internal wallet (expressed, as name suggests, in satoshi)\&. The string \fIall\fR can be used to specify withdrawal of all available funds\&. .sp -\fIfeerate\fR is an optional feerate to use, overriding lightningd\(cqs internal estimate\&. If specified, \fIfeeratestyle\fR must be either \fI"perkw"\fR for if \fIfeerate\fR is in satoshi\-per\-kilosipa (weight), or \fI"perkb"\fR for if \fIfeerate\fR is in bitcoind\-style satoshi\-per\-kilobyte\&. +\fIfeerate\fR is an optional feerate to use, overriding lightningd\(cqs internal estimate\&. \fIfeerate\fR is a number, with an optional suffix: \fIperkw\fR means the number is interpreted as satoshi\-per\-kilosipa (weight), and \fIperkb\fR means it is interpreted bitcoind\-style as satoshi\-per\-kilobyte\&. Omitting the suffix is equivalent to \fIperkb\fR\&. .SH "RETURN VALUE" .sp On success, an object with attributes \fItx\fR and \fItxid\fR will be returned\&. diff --git a/doc/lightning-withdraw.7.txt b/doc/lightning-withdraw.7.txt index 87ba84d79..45c40bbb0 100644 --- a/doc/lightning-withdraw.7.txt +++ b/doc/lightning-withdraw.7.txt @@ -9,7 +9,7 @@ internal wallet. SYNOPSIS -------- -*withdraw* 'destination' 'satoshi' ['feerate' 'feeratestyle'] +*withdraw* 'destination' 'satoshi' ['feerate'] DESCRIPTION ----------- @@ -25,9 +25,10 @@ The string 'all' can be used to specify withdrawal of all available funds. 'feerate' is an optional feerate to use, overriding lightningd's -internal estimate. If specified, 'feeratestyle' must be either -'"perkw"' for if 'feerate' is in satoshi-per-kilosipa (weight), -or '"perkb"' for if 'feerate' is in bitcoind-style satoshi-per-kilobyte. +internal estimate. 'feerate' is a number, with an optional suffix: +'perkw' means the number is interpreted as satoshi-per-kilosipa +(weight), and 'perkb' means it is interpreted bitcoind-style as +satoshi-per-kilobyte. Omitting the suffix is equivalent to 'perkb'. RETURN VALUE ------------ diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index 1c5957fd4..60f83e8bc 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -447,36 +447,6 @@ u32 feerate_to_style(u32 feerate_perkw, enum feerate_style style) abort(); } -/* If we have both feerate and style, use that, otherwise use inbuilt if avail. - * Return false if we failed command, otherwise fills in feerate_perkw. */ -bool json_feerate_and_style(struct command *cmd, - const u32 *feerate, enum feerate_style *style, - u32 fallback_feerate_per_kw, - u32 *feerate_per_kw) -{ - if (feerate) { - if (!style) { - command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "'feerate' requires 'feeratestyle'"); - return false; - } - *feerate_per_kw = feerate_from_style(*feerate, *style); - return true; - } else { - if (style) { - command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "'feeratestyle' requires 'feerate'"); - return false; - } - *feerate_per_kw = fallback_feerate_per_kw; - if (!*feerate_per_kw) { - command_fail(cmd, LIGHTNINGD, "Cannot estimate fees"); - return false; - } - return true; - } -} - static void json_feerates(struct command *cmd, const char *buffer, const jsmntok_t *params) { diff --git a/lightningd/chaintopology.h b/lightningd/chaintopology.h index c785dd528..ced494752 100644 --- a/lightningd/chaintopology.h +++ b/lightningd/chaintopology.h @@ -150,14 +150,6 @@ u32 unilateral_feerate(struct chain_topology *topo); u32 feerate_from_style(u32 feerate, enum feerate_style style); u32 feerate_to_style(u32 feerate_perkw, enum feerate_style style); -/* If we have both feerate and style, use that, otherwise use fallback - * if nonzero. Return false if we failed command, otherwise fills in - * feerate_per_kw. */ -bool json_feerate_and_style(struct command *cmd, - const u32 *feerate, enum feerate_style *style, - u32 fallback_feerate_per_kw, - u32 *feerate_per_kw); - /* Broadcast a single tx, and rebroadcast as reqd (copies tx). * If failed is non-NULL, call that and don't rebroadcast. */ void broadcast_tx(struct chain_topology *topo, diff --git a/lightningd/json.c b/lightningd/json.c index f4b3b6a3b..cd091b0ec 100644 --- a/lightningd/json.c +++ b/lightningd/json.c @@ -258,6 +258,50 @@ bool json_tok_feerate_style(struct command *cmd, const char *name, return false; } +bool json_tok_feerate(struct command *cmd, const char *name, + const char *buffer, const jsmntok_t *tok, + u32 **feerate) +{ + jsmntok_t base = *tok, suffix = *tok; + enum feerate_style style; + unsigned int num; + + /* We have to split the number and suffix. */ + suffix.start = suffix.end; + while (suffix.start > base.start && !isdigit(buffer[suffix.start-1])) { + suffix.start--; + base.end--; + } + + if (!json_to_number(buffer, &base, &num)) { + command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "'%s' prefix should be an integer, not '%.*s'", + name, base.end - base.start, buffer + base.start); + return false; + } + + if (json_tok_streq(buffer, &suffix, "") + || json_tok_streq(buffer, &suffix, + json_feerate_style_name(FEERATE_PER_KBYTE))) { + style = FEERATE_PER_KBYTE; + } else if (json_tok_streq(buffer, &suffix, + json_feerate_style_name(FEERATE_PER_KSIPA))) { + style = FEERATE_PER_KSIPA; + } else { + command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "'%s' suffix should be '%s' or '%s', not '%.*s'", + name, + json_feerate_style_name(FEERATE_PER_KSIPA), + json_feerate_style_name(FEERATE_PER_KBYTE), + suffix.end - suffix.start, buffer + suffix.start); + return false; + } + + *feerate = tal(cmd, u32); + **feerate = feerate_from_style(num, style); + return true; +} + bool json_tok_channel_id(const char *buffer, const jsmntok_t *tok, struct channel_id *cid) diff --git a/lightningd/json.h b/lightningd/json.h index 3b694a5e3..069042ddf 100644 --- a/lightningd/json.h +++ b/lightningd/json.h @@ -5,6 +5,7 @@ #ifndef LIGHTNING_LIGHTNINGD_JSON_H #define LIGHTNING_LIGHTNINGD_JSON_H #include "config.h" +#include #include #include #include @@ -95,6 +96,11 @@ bool json_tok_feerate_style(struct command *cmd, const char *name, const char *json_feerate_style_name(enum feerate_style style); +/* Extract a feerate with optional style suffix. */ +bool json_tok_feerate(struct command *cmd, const char *name, + const char *buffer, const jsmntok_t *tok, + u32 **feerate); + /* '"fieldname" : "1234:5:6"' */ void json_add_short_channel_id(struct json_result *response, const char *fieldname, diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 8a4b1344d..b03b9120d 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -764,9 +764,7 @@ static void json_fund_channel(struct command *cmd, struct pubkey *id; struct peer *peer; struct channel *channel; - unsigned int *feerate; - enum feerate_style *style; - u32 feerate_per_kw; + u32 *feerate_per_kw; u8 *msg; fc->cmd = cmd; @@ -775,18 +773,21 @@ static void json_fund_channel(struct command *cmd, if (!param(fc->cmd, buffer, params, p_req("id", json_tok_pubkey, &id), p_req("satoshi", json_tok_tok, &sattok), - p_opt("feerate", json_tok_number, &feerate), - p_opt("feeratestyle", json_tok_feerate_style, &style), + p_opt("feerate", json_tok_feerate, &feerate_per_kw), NULL)) return; if (!json_tok_wtx(&fc->wtx, buffer, sattok, MAX_FUNDING_SATOSHI)) return; - if (!json_feerate_and_style(cmd, feerate, style, - opening_feerate(cmd->ld->topology), - &feerate_per_kw)) - return; + if (!feerate_per_kw) { + feerate_per_kw = tal(cmd, u32); + *feerate_per_kw = opening_feerate(cmd->ld->topology); + if (!*feerate_per_kw) { + command_fail(cmd, LIGHTNINGD, "Cannot estimate fees"); + return; + } + } peer = peer_by_id(cmd->ld, id); if (!peer) { @@ -815,7 +816,7 @@ static void json_fund_channel(struct command *cmd, fc->push_msat = 0; fc->channel_flags = OUR_CHANNEL_FLAGS; - if (!wtx_select_utxos(&fc->wtx, feerate_per_kw, + if (!wtx_select_utxos(&fc->wtx, *feerate_per_kw, BITCOIN_SCRIPTPUBKEY_P2WSH_LEN)) return; @@ -827,7 +828,7 @@ static void json_fund_channel(struct command *cmd, msg = towire_opening_funder(NULL, fc->wtx.amount, fc->push_msat, - feerate_per_kw, + *feerate_per_kw, fc->wtx.change, fc->wtx.change_key_index, fc->channel_flags, diff --git a/lightningd/test/run-param.c b/lightningd/test/run-param.c index bd2756250..45871daca 100644 --- a/lightningd/test/run-param.c +++ b/lightningd/test/run-param.c @@ -45,6 +45,9 @@ void command_fail_detailed(struct command *cmd, int code, } /* AUTOGENERATED MOCKS START */ +/* Generated stub for feerate_from_style */ +u32 feerate_from_style(u32 feerate UNNEEDED, enum feerate_style style UNNEEDED) +{ fprintf(stderr, "feerate_from_style called!\n"); abort(); } /* Generated stub for fmt_wireaddr_without_port */ char *fmt_wireaddr_without_port(const tal_t *ctx UNNEEDED, const struct wireaddr *a UNNEEDED) { fprintf(stderr, "fmt_wireaddr_without_port called!\n"); abort(); } diff --git a/tests/test_connection.py b/tests/test_connection.py index 6061023a8..1238c4237 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -1125,8 +1125,8 @@ def test_no_fee_estimate(node_factory, bitcoind, executor): l1.rpc.withdraw(l2.rpc.newaddr()['address'], 'all') # Can with manual feerate. - l1.rpc.withdraw(l2.rpc.newaddr()['address'], 10000, 1500, 'perkb') - l1.rpc.fundchannel(l2.info['id'], 10**6, 2000, 'perkw') + l1.rpc.withdraw(l2.rpc.newaddr()['address'], 10000, '1500perkb') + l1.rpc.fundchannel(l2.info['id'], 10**6, '2000perkw') # Make sure we clean up cahnnel for later attempt. l1.daemon.wait_for_log('sendrawtx exit 0') diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 5752a33f2..392a1ab32 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -354,9 +354,6 @@ u8 *towire_errorfmt(const tal_t *ctx UNNEEDED, /* Generated stub for towire_hsm_sign_commitment_tx */ u8 *towire_hsm_sign_commitment_tx(const tal_t *ctx UNNEEDED, const struct pubkey *peer_id UNNEEDED, u64 channel_dbid UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, const struct pubkey *remote_funding_key UNNEEDED, u64 funding_amount UNNEEDED) { fprintf(stderr, "towire_hsm_sign_commitment_tx called!\n"); abort(); } -/* Generated stub for try_get_feerate */ -u32 try_get_feerate(const struct chain_topology *topo UNNEEDED, enum feerate feerate UNNEEDED) -{ fprintf(stderr, "try_get_feerate called!\n"); abort(); } /* Generated stub for watch_txid */ struct txwatch *watch_txid(const tal_t *ctx UNNEEDED, struct chain_topology *topo UNNEEDED, diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index 8dbeb3bdd..fbc1f3a20 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -89,9 +89,7 @@ static void json_withdraw(struct command *cmd, { const jsmntok_t *desttok, *sattok; struct withdrawal *withdraw = tal(cmd, struct withdrawal); - u32 feerate_per_kw; - unsigned int *feerate; - enum feerate_style *style; + u32 *feerate_per_kw; struct bitcoin_tx *tx; enum address_parse_result addr_parse; @@ -101,19 +99,22 @@ static void json_withdraw(struct command *cmd, if (!param(cmd, buffer, params, p_req("destination", json_tok_tok, &desttok), p_req("satoshi", json_tok_tok, &sattok), - p_opt("feerate", json_tok_number, &feerate), - p_opt("feeratestyle", json_tok_feerate_style, &style), + p_opt("feerate", json_tok_feerate, &feerate_per_kw), NULL)) return; if (!json_tok_wtx(&withdraw->wtx, buffer, sattok, -1ULL)) return; - if (!json_feerate_and_style(cmd, feerate, style, - try_get_feerate(cmd->ld->topology, - FEERATE_NORMAL), - &feerate_per_kw)) - return; + if (!feerate_per_kw) { + feerate_per_kw = tal(cmd, u32); + *feerate_per_kw + = try_get_feerate(cmd->ld->topology, FEERATE_NORMAL); + if (!*feerate_per_kw) { + command_fail(cmd, LIGHTNINGD, "Cannot estimate fees"); + return; + } + } /* Parse address. */ addr_parse = json_tok_address_scriptpubkey(cmd, @@ -135,7 +136,7 @@ static void json_withdraw(struct command *cmd, return; } - if (!wtx_select_utxos(&withdraw->wtx, feerate_per_kw, + if (!wtx_select_utxos(&withdraw->wtx, *feerate_per_kw, tal_count(withdraw->destination))) return;