Browse Source

payalgo: Add maximum delay.

Fixes: #1086
ppa-0.6.1
ZmnSCPxj 7 years ago
committed by Rusty Russell
parent
commit
26f7014813
  1. 18
      doc/lightning-pay.7
  2. 16
      doc/lightning-pay.7.txt
  3. 58
      lightningd/payalgo.c

18
doc/lightning-pay.7

@ -2,12 +2,12 @@
.\" Title: lightning-pay
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" Date: 03/16/2018
.\" Date: 03/21/2018
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "LIGHTNING\-PAY" "7" "03/16/2018" "\ \&" "\ \&"
.TH "LIGHTNING\-PAY" "7" "03/21/2018" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@ -31,12 +31,12 @@
lightning-pay \- Protocol for sending a payment to a BOLT11 invoice
.SH "SYNOPSIS"
.sp
\fBpay\fR \fIbolt11\fR [\fImsatoshi\fR] [\fIdescription\fR] [\fIriskfactor\fR] [\fImaxfeepercent\fR] [\fIretry_for\fR]
\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\&.
.sp
The \fBpay\fR RPC command will randomize routes slightly, as long as the route achieves the targeted \fImaxfeepercent\fR\&.
The \fBpay\fR RPC command will randomize routes slightly, as long as the route achieves the targeted \fImaxfeepercent\fR and \fImaxdelay\fR\&.
.sp
The response will occur when the payment fails or succeeds\&. Once a payment has succeeded, calls to \fBpay\fR with the same \fIbolt11\fR will succeed immediately\&.
.sp
@ -122,13 +122,19 @@ field of the error will be routing failure object\&.
.sp -1
.IP \(bu 2.3
.\}
206\&. Route too expensive\&. The
206\&. Route too expensive\&. Either the fee or the needed total locktime for the route exceeds your
\fImaxfeepercent\fR
or
\fImaxdelay\fR
settings, respectively\&. The
\fIdata\fR
field of the error will indicate the actual
\fIfee\fR
as well as the
\fIfeepercent\fR
percentage that the fee has of the destination payment amount\&.
percentage that the fee has of the destination payment amount\&. It will also indicate the actual
\fIdelay\fR
along the route\&.
.RE
.sp
.RS 4

16
doc/lightning-pay.7.txt

@ -8,7 +8,7 @@ lightning-pay - Protocol for sending a payment to a BOLT11 invoice
SYNOPSIS
--------
*pay* 'bolt11' ['msatoshi'] ['description'] ['riskfactor'] ['maxfeepercent'] ['retry_for']
*pay* 'bolt11' ['msatoshi'] ['description'] ['riskfactor'] ['maxfeepercent'] ['retry_for'] ['maxdelay']
DESCRIPTION
-----------
@ -24,7 +24,7 @@ The `maxfeepercent' is a percentage of the amount that is to be
paid.
The *pay* RPC command will randomize routes slightly, as long as the
route achieves the targeted 'maxfeepercent'.
route achieves the targeted 'maxfeepercent' and 'maxdelay'.
The response will occur when the payment fails or succeeds. Once a
payment has succeeded, calls to *pay* with the same 'bolt11' will
@ -65,10 +65,14 @@ The following error codes may occur:
* 203. Permanent failure at destination. The 'data' field of
the error will be routing failure object.
* 205. Unable to find a route.
* 206. Route too expensive. The 'data' field of the error will
indicate the actual 'fee' as well as the 'feepercent'
percentage that the fee has of the destination payment
amount.
* 206. Route too expensive.
Either the fee or the needed total locktime for the route
exceeds your 'maxfeepercent' or 'maxdelay' settings,
respectively.
The 'data' field of the error will indicate the actual 'fee'
as well as the 'feepercent' percentage that the fee has of the
destination payment amount.
It will also indicate the actual 'delay' along the route.
* 207. Invoice expired. Payment took too long before expiration,
or already expired at the time you initiated payment.
The 'data' field of the error indicates 'now' (the current time)

58
lightningd/payalgo.c

@ -104,6 +104,7 @@ struct pay {
u64 msatoshi;
double riskfactor;
double maxfeepercent;
u32 maxdelay;
/* Number of getroute and sendpay tries */
unsigned int getroute_tries;
@ -407,7 +408,9 @@ static void json_pay_getroute_reply(struct subd *gossip UNUSED,
u64 fee;
double feepercent;
bool fee_too_high;
bool delay_too_high;
struct json_result *data;
char const *err;
fromwire_gossip_getroute_reply(reply, reply, &route);
@ -434,30 +437,48 @@ static void json_pay_getroute_reply(struct subd *gossip UNUSED,
* payments are limited to 4294967295 msatoshi. */
feepercent = ((double) fee) * 100.0 / ((double) pay->msatoshi);
fee_too_high = (feepercent > pay->maxfeepercent);
delay_too_high = (route[0].delay > pay->maxdelay);
/* compare fuzz to range */
if (fee_too_high && pay->fuzz < 0.01) {
if ((fee_too_high || delay_too_high) && pay->fuzz < 0.01) {
data = new_json_result(pay);
json_object_start(data, NULL);
json_add_u64(data, "msatoshi", pay->msatoshi);
json_add_u64(data, "fee", fee);
json_add_double(data, "feepercent", feepercent);
json_add_u64(data, "msatoshi", pay->msatoshi);
json_add_double(data, "maxfeepercent", pay->maxfeepercent);
json_add_u64(data, "delay", (u64) route[0].delay);
json_add_num(data, "maxdelay", pay->maxdelay);
json_add_num(data, "getroute_tries", pay->getroute_tries);
json_add_num(data, "sendpay_tries", pay->sendpay_tries);
json_add_route(data, "route",
route, tal_count(route));
json_add_failures(data, "failures", &pay->pay_failures);
json_object_end(data);
command_fail_detailed(pay->cmd, PAY_ROUTE_TOO_EXPENSIVE,
data,
err = "";
if (fee_too_high)
err = tal_fmt(pay,
"Fee %"PRIu64" is %f%% "
"of payment %"PRIu64"; "
"max fee requested is %f%%",
"max fee requested is %f%%.",
fee, feepercent,
pay->msatoshi,
pay->maxfeepercent);
if (fee_too_high && delay_too_high)
err = tal_fmt(pay, "%s ", err);
if (delay_too_high)
err = tal_fmt(pay,
"%s"
"Delay (locktime) is %"PRIu32" blocks; "
"max delay requested is %u.",
err, route[0].delay, pay->maxdelay);
command_fail_detailed(pay->cmd, PAY_ROUTE_TOO_EXPENSIVE,
data, "%s", err);
return;
}
if (fee_too_high) {
if (fee_too_high || delay_too_high) {
/* Retry with lower fuzz */
pay->fuzz -= 0.15;
if (pay->fuzz <= 0.0)
@ -575,6 +596,7 @@ static void json_pay(struct command *cmd,
{
jsmntok_t *bolt11tok, *msatoshitok, *desctok, *riskfactortok, *maxfeetok;
jsmntok_t *retryfortok;
jsmntok_t *maxdelaytok;
double riskfactor = 1.0;
double maxfeepercent = 0.5;
u64 msatoshi;
@ -582,6 +604,7 @@ static void json_pay(struct command *cmd,
struct bolt11 *b11;
char *fail, *b11str, *desc;
unsigned int retryfor = 60;
unsigned int maxdelay = 500;
if (!json_get_params(cmd, buffer, params,
"bolt11", &bolt11tok,
@ -590,6 +613,7 @@ static void json_pay(struct command *cmd,
"?riskfactor", &riskfactortok,
"?maxfeepercent", &maxfeetok,
"?retry_for", &retryfortok,
"?maxdelay", &maxdelaytok,
NULL)) {
return;
}
@ -672,14 +696,32 @@ static void json_pay(struct command *cmd,
}
pay->maxfeepercent = maxfeepercent;
if (maxdelaytok
&& !json_tok_number(buffer, maxdelaytok, &maxdelay)) {
command_fail(cmd, "'%.*s' is not a valid double",
maxdelaytok->end - maxdelaytok->start,
buffer + maxdelaytok->start);
return;
}
if (maxdelay < pay->min_final_cltv_expiry) {
command_fail(cmd,
"maxdelay (%u) must be greater than "
"min_final_cltv_expiry (%"PRIu32") of "
"invoice",
maxdelay, pay->min_final_cltv_expiry);
return;
}
pay->maxdelay = maxdelay;
pay->getroute_tries = 0;
pay->sendpay_tries = 0;
/* Higher fuzz increases the potential fees we will pay, since
* higher fuzz makes it more likely that high-fee paths get
* selected. We start with very high fuzz, but if the
* returned route is too expensive for the given
* `maxfeepercent` we reduce the fuzz. Starting with high
* fuzz means, if the user allows high fee, we can take
* `maxfeepercent` or `maxdelay` we reduce the fuzz.
* Starting with high
* fuzz means, if the user allows high fee/locktime, we can take
* advantage of that to increase randomization and
* improve privacy somewhat. */
pay->fuzz = 0.75;

Loading…
Cancel
Save