From 252203de1fa3f08e1555986133400ae9f39ab578 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Fri, 27 Jul 2018 14:33:44 +0200 Subject: [PATCH 1/3] pay: Exempt a fee from the maxfeepercent rule it is still tiny Several users have noticed that they cannot pay satoshis.place or similar places that have tiny payment amounts if they are not directly connected. This is due to the forwarding fee dominating the transferred amount. This commit adds a new option, exempting tiny fees (up to 5 satoshis by default) from having to pass the maxfeepercent flag. While we could have told users to tweak maxfeepercent I think it is usefull to have a default exemption. --- doc/lightning-pay.7.txt | 4 ++++ lightningd/payalgo.c | 10 +++++++++- wallet/invoices.h | 6 +++--- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/doc/lightning-pay.7.txt b/doc/lightning-pay.7.txt index fa80a2cce4c8..ae56b2a44eda 100644 --- a/doc/lightning-pay.7.txt +++ b/doc/lightning-pay.7.txt @@ -22,6 +22,10 @@ in lightning-getroute(7), and defaults to 1.0. The 'maxfeepercent' limits the money paid in fees, and defaults to 0.5. The `maxfeepercent' is a percentage of the amount that is to be paid. +The `exemptfee` option can be used for tiny payments which would be dominated by +the fee leveraged by forwarding nodes. Setting `exemptfee` allows the +`maxfeepercent` check to be skipped on fees that are smaller than `exemptfee` +(default: 5000 millsatoshi). The *pay* RPC command will randomize routes slightly, as long as the route achieves the targeted 'maxfeepercent' and 'maxdelay'. diff --git a/lightningd/payalgo.c b/lightningd/payalgo.c index 8b7ca115fdab..eb870fb15c5c 100644 --- a/lightningd/payalgo.c +++ b/lightningd/payalgo.c @@ -128,6 +128,11 @@ struct pay { /* Whether we are attempting payment or not. */ bool in_sendpay; + + /* Maximum fee that is exempted from the maxfeepercent computation. This + * is mainly useful for tiny transfers for which the leveraged fee would + * be dominated by the forwarding fee. */ + u64 exemptfee; }; static struct routing_failure * @@ -435,7 +440,7 @@ static void json_pay_getroute_reply(struct subd *gossip UNUSED, * That loss will not be representable in double. So, it's Okay to * cast u64 to double for feepercent calculation. */ feepercent = ((double) fee) * 100.0 / ((double) pay->msatoshi); - fee_too_high = (feepercent > pay->maxfeepercent); + fee_too_high = (fee > pay->exemptfee && feepercent > pay->maxfeepercent); delay_too_high = (route[0].delay > pay->maxdelay); /* compare fuzz to range */ if ((fee_too_high || delay_too_high) && pay->fuzz < 0.01) { @@ -602,6 +607,7 @@ static void json_pay(struct command *cmd, char *fail, *b11str, *desc; unsigned int retryfor; unsigned int maxdelay; + unsigned int exemptfee; if (!param(cmd, buffer, params, p_req("bolt11", json_tok_tok, &bolt11tok), @@ -612,6 +618,7 @@ static void json_pay(struct command *cmd, p_opt_def("retry_for", json_tok_number, &retryfor, 60), p_opt_def("maxdelay", json_tok_number, &maxdelay, cmd->ld->config.locktime_max), + p_opt_def("exemptfee", json_tok_number, &exemptfee, 5000), NULL)) return; @@ -636,6 +643,7 @@ static void json_pay(struct command *cmd, memset(&pay->expiry, 0, sizeof(pay->expiry)); pay->expiry.ts.tv_sec = b11->timestamp + b11->expiry; pay->min_final_cltv_expiry = b11->min_final_cltv_expiry; + pay->exemptfee = exemptfee; if (b11->msatoshi) { if (msatoshi) { diff --git a/wallet/invoices.h b/wallet/invoices.h index 6677834d9404..4ac70a0425e8 100644 --- a/wallet/invoices.h +++ b/wallet/invoices.h @@ -65,9 +65,9 @@ bool invoices_create(struct invoices *invoices, /** * invoices_find_by_label - Search for an invoice by label * - * @invoices - the invoice handler. - * @pinvoice - pointer to location to load found invoice in. - * @label - the label to search for. + * @param invoices - the invoice handler. + * @param pinvoice - pointer to location to load found invoice in. + * @param label - the label to search for. * * Returns false if no invoice with that label exists. * Returns true if found. From 96881f8e2981441562500a99a8ac893d01525bf6 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Sat, 28 Jul 2018 14:09:24 +0200 Subject: [PATCH 2/3] doc: Update the compiled version of doc/lightning-pay.7 --- doc/lightning-pay.7 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/lightning-pay.7 b/doc/lightning-pay.7 index eb48cf619126..b603040c8493 100644 --- a/doc/lightning-pay.7 +++ b/doc/lightning-pay.7 @@ -2,12 +2,12 @@ .\" Title: lightning-pay .\" Author: [see the "AUTHOR" section] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 04/26/2018 +.\" Date: 07/28/2018 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" -.TH "LIGHTNING\-PAY" "7" "04/26/2018" "\ \&" "\ \&" +.TH "LIGHTNING\-PAY" "7" "07/28/2018" "\ \&" "\ \&" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -34,7 +34,7 @@ lightning-pay \- Command for sending a payment to a BOLT11 invoice \fBpay\fR \fIbolt11\fR [\fImsatoshi\fR] [\fIdescription\fR] [\fIriskfactor\fR] [\fImaxfeepercent\fR] [\fIretry_for\fR] [\fImaxdelay\fR] .SH "DESCRIPTION" .sp -The \fBpay\fR RPC command attempts to find a route to the given destination, and send the funds it asks for\&. If the \fIbolt11\fR does not contain an amount, \fImsatoshi\fR is required, otherwise if it is specified it must be \fInull\fR\&. If \fIbolt11\fR contains a description hash (\fIh\fR field) \fIdescription\fR is required, otherwise it is unused\&. The \fIriskfactor\fR is described in detail in lightning\-getroute(7), and defaults to 1\&.0\&. The \fImaxfeepercent\fR limits the money paid in fees, and defaults to 0\&.5\&. The \(oqmaxfeepercent\(cq is a percentage of the amount that is to be paid\&. +The \fBpay\fR RPC command attempts to find a route to the given destination, and send the funds it asks for\&. If the \fIbolt11\fR does not contain an amount, \fImsatoshi\fR is required, otherwise if it is specified it must be \fInull\fR\&. If \fIbolt11\fR contains a description hash (\fIh\fR field) \fIdescription\fR is required, otherwise it is unused\&. The \fIriskfactor\fR is described in detail in lightning\-getroute(7), and defaults to 1\&.0\&. The \fImaxfeepercent\fR limits the money paid in fees, and defaults to 0\&.5\&. The maxfeepercent\*(Aq is a percentage of the amount that is to be paid\&. The `exemptfee option can be used for tiny payments which would be dominated by the fee leveraged by forwarding nodes\&. Setting exemptfee allows the maxfeepercent check to be skipped on fees that are smaller than exemptfee (default: 5000 millsatoshi)\&. .sp The \fBpay\fR RPC command will randomize routes slightly, as long as the route achieves the targeted \fImaxfeepercent\fR and \fImaxdelay\fR\&. .sp From dddf5caf9278b7af49ecf2964ae2a1327a49ea5d Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Sat, 28 Jul 2018 14:11:11 +0200 Subject: [PATCH 3/3] json-rpc: Update the help text for `pay` to include exemptfee --- lightningd/payalgo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lightningd/payalgo.c b/lightningd/payalgo.c index eb870fb15c5c..c89ede199af1 100644 --- a/lightningd/payalgo.c +++ b/lightningd/payalgo.c @@ -711,6 +711,7 @@ static const struct json_command pay_command = { "{description} (required if {bolt11} uses description hash), " "{riskfactor} (default 1.0), " "{maxfeepercent} (default 0.5) the maximum acceptable fee as a percentage (e.g. 0.5 => 0.5%), " + "{exemptfee} (default 5000 msat) disables the maxfeepercent check for fees below the threshold, " "{retry_for} (default 60) the integer number of seconds before we stop retrying, and " "{maxdelay} (default 500) the maximum number of blocks we allow the funds to possibly get locked" };