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.

[Squashed --RR]
This commit is contained in:
Christian Decker 2018-07-30 03:05:43 +02:00 committed by Rusty Russell
parent a235c1fa67
commit 55d450ff00
4 changed files with 20 additions and 7 deletions

View File

@ -2,12 +2,12 @@
.\" Title: lightning-pay
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" 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

View File

@ -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'.

View File

@ -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) {
@ -703,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"
};

View File

@ -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.