Browse Source

pay: Let `sendpay` modify the recorded `msatoshi` of payments.

ppa-0.6.1
ZmnSCPxj 7 years ago
committed by Christian Decker
parent
commit
bc5fc692d1
  1. 10
      doc/lightning-sendpay.7
  2. 17
      doc/lightning-sendpay.7.txt
  3. 36
      lightningd/pay.c
  4. 5
      lightningd/pay.h
  5. 1
      lightningd/payalgo.c

10
doc/lightning-sendpay.7

@ -2,12 +2,12 @@
.\" Title: lightning-sendpay .\" Title: lightning-sendpay
.\" 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: 03/14/2018 .\" Date: 03/22/2018
.\" Manual: \ \& .\" Manual: \ \&
.\" Source: \ \& .\" Source: \ \&
.\" Language: English .\" Language: English
.\" .\"
.TH "LIGHTNING\-SENDPAY" "7" "03/14/2018" "\ \&" "\ \&" .TH "LIGHTNING\-SENDPAY" "7" "03/22/2018" "\ \&" "\ \&"
.\" ----------------------------------------------------------------- .\" -----------------------------------------------------------------
.\" * Define some portability stuff .\" * Define some portability stuff
.\" ----------------------------------------------------------------- .\" -----------------------------------------------------------------
@ -31,7 +31,7 @@
lightning-sendpay \- Protocol for sending a payment via a route\&. lightning-sendpay \- Protocol for sending a payment via a route\&.
.SH "SYNOPSIS" .SH "SYNOPSIS"
.sp .sp
\fBsendpay\fR \fIroute\fR \fIhash\fR \fBsendpay\fR \fIroute\fR \fIhash\fR [\fImsatoshi\fR]
.SH "DESCRIPTION" .SH "DESCRIPTION"
.sp .sp
The \fBsendpay\fR RPC command attempts to send funds associated with the given \fIhash\fR, along a route to the final destination in the route\&. The \fBsendpay\fR RPC command attempts to send funds associated with the given \fIhash\fR, along a route to the final destination in the route\&.
@ -40,7 +40,9 @@ Generally, a client would call getroute(7) to resolve a route, then use \fBsendp
.sp .sp
The response will occur when the payment is on its way to the destination\&. The \fBsendpay\fR RPC command does not wait for definite success or definite failure of the payment\&. Instead, use the \fBwaitsendpay\fR RPC command to poll or wait for definite success or definite failure\&. The response will occur when the payment is on its way to the destination\&. The \fBsendpay\fR RPC command does not wait for definite success or definite failure of the payment\&. Instead, use the \fBwaitsendpay\fR RPC command to poll or wait for definite success or definite failure\&.
.sp .sp
Once a payment has succeeded, calls to \fBsendpay\fR with the same \fIhash\fR but a different amount or destination will fail; this prevents accidental multiple payments\&. Calls to \fBsendpay\fR with the same \fIhash\fR, amount, and destination as a previous successful payment (even if a different route) will return immediately with success\&. The \fImsatoshi\fR amount, if provided, is the amount that will be recorded as the target payment value\&. If not specified, it will be the final amount to the destination\&. If specified, then the final amount at the destination must be from the specified \fImsatoshi\fR to twice the specified \fImsatoshi\fR, inclusive\&. This is intended to obscure payments by overpaying slightly at the destination; the actual target payment is what should be specified as the \fImsatoshi\fR argument\&.
.sp
Once a payment has succeeded, calls to \fBsendpay\fR with the same \fIhash\fR but a different \fImsatoshi\fR or destination will fail; this prevents accidental multiple payments\&. Calls to \fBsendpay\fR with the same \fIhash\fR, \fImsatoshi\fR, and destination as a previous successful payment (even if a different route) will return immediately with success\&.
.SH "RETURN VALUE" .SH "RETURN VALUE"
.sp .sp
On success, an object similar to the output of \fBlistpayments\fR will be returned\&. This object will have a \fIstatus\fR field that is typically the string \fI"pending"\fR, but may be \fI"complete"\fR if the payment was already performed successfully\&. On success, an object similar to the output of \fBlistpayments\fR will be returned\&. This object will have a \fIstatus\fR field that is typically the string \fI"pending"\fR, but may be \fI"complete"\fR if the payment was already performed successfully\&.

17
doc/lightning-sendpay.7.txt

@ -8,7 +8,7 @@ lightning-sendpay - Protocol for sending a payment via a route.
SYNOPSIS SYNOPSIS
-------- --------
*sendpay* 'route' 'hash' *sendpay* 'route' 'hash' ['msatoshi']
DESCRIPTION DESCRIPTION
----------- -----------
@ -27,10 +27,21 @@ definite failure of the payment.
Instead, use the *waitsendpay* RPC command to poll or wait for Instead, use the *waitsendpay* RPC command to poll or wait for
definite success or definite failure. definite success or definite failure.
The 'msatoshi' amount, if provided, is the amount that will be
recorded as the target payment value.
If not specified, it will be the final amount to the destination.
If specified, then the final amount at the destination must be
from the specified 'msatoshi' to twice the specified 'msatoshi',
inclusive.
This is intended to obscure payments by overpaying slightly at
the destination;
the actual target payment is what should be specified as the
'msatoshi' argument.
Once a payment has succeeded, calls to *sendpay* with the same 'hash' Once a payment has succeeded, calls to *sendpay* with the same 'hash'
but a different amount or destination will fail; this prevents but a different 'msatoshi' or destination will fail; this prevents
accidental multiple payments. accidental multiple payments.
Calls to *sendpay* with the same 'hash', amount, and destination as a Calls to *sendpay* with the same 'hash', 'msatoshi', and destination as a
previous successful payment (even if a different route) will return previous successful payment (even if a different route) will return
immediately with success. immediately with success.

36
lightningd/pay.c

@ -628,6 +628,7 @@ send_payment(const tal_t *ctx,
struct lightningd* ld, struct lightningd* ld,
const struct sha256 *rhash, const struct sha256 *rhash,
const struct route_hop *route, const struct route_hop *route,
u64 msatoshi,
void (*cb)(const struct sendpay_result *, void*), void (*cb)(const struct sendpay_result *, void*),
void *cbarg) void *cbarg)
{ {
@ -685,7 +686,7 @@ send_payment(const tal_t *ctx,
if (payment->status == PAYMENT_COMPLETE) { if (payment->status == PAYMENT_COMPLETE) {
log_add(ld->log, "... succeeded"); log_add(ld->log, "... succeeded");
/* Must match successful payment parameters. */ /* Must match successful payment parameters. */
if (payment->msatoshi != hop_data[n_hops-1].amt_forward) { if (payment->msatoshi != msatoshi) {
char *msg = tal_fmt(tmpctx, char *msg = tal_fmt(tmpctx,
"Already succeeded " "Already succeeded "
"with amount %"PRIu64, "with amount %"PRIu64,
@ -740,8 +741,8 @@ send_payment(const tal_t *ctx,
sizeof(struct sha256), &path_secrets); sizeof(struct sha256), &path_secrets);
onion = serialize_onionpacket(tmpctx, packet); onion = serialize_onionpacket(tmpctx, packet);
log_info(ld->log, "Sending %u over %zu hops to deliver %u", log_info(ld->log, "Sending %u over %zu hops to deliver %"PRIu64"",
route[0].amount, n_hops, route[n_hops-1].amount); route[0].amount, n_hops, msatoshi);
failcode = send_htlc_out(channel, route[0].amount, failcode = send_htlc_out(channel, route[0].amount,
base_expiry + route[0].delay, base_expiry + route[0].delay,
@ -781,7 +782,7 @@ send_payment(const tal_t *ctx,
payment->payment_hash = *rhash; payment->payment_hash = *rhash;
payment->destination = ids[n_hops - 1]; payment->destination = ids[n_hops - 1];
payment->status = PAYMENT_PENDING; payment->status = PAYMENT_PENDING;
payment->msatoshi = route[n_hops-1].amount; payment->msatoshi = msatoshi;
payment->msatoshi_sent = route[0].amount; payment->msatoshi_sent = route[0].amount;
payment->timestamp = time_now().ts.tv_sec; payment->timestamp = time_now().ts.tv_sec;
payment->payment_preimage = NULL; payment->payment_preimage = NULL;
@ -912,14 +913,17 @@ static void json_sendpay(struct command *cmd,
const char *buffer, const jsmntok_t *params) const char *buffer, const jsmntok_t *params)
{ {
jsmntok_t *routetok, *rhashtok; jsmntok_t *routetok, *rhashtok;
jsmntok_t *msatoshitok;
const jsmntok_t *t, *end; const jsmntok_t *t, *end;
size_t n_hops; size_t n_hops;
struct sha256 rhash; struct sha256 rhash;
struct route_hop *route; struct route_hop *route;
u64 msatoshi;
if (!json_get_params(cmd, buffer, params, if (!json_get_params(cmd, buffer, params,
"route", &routetok, "route", &routetok,
"payment_hash", &rhashtok, "payment_hash", &rhashtok,
"?msatoshi", &msatoshitok,
NULL)) { NULL)) {
return; return;
} }
@ -994,7 +998,29 @@ static void json_sendpay(struct command *cmd,
return; return;
} }
if (send_payment(cmd, cmd->ld, &rhash, route, if (msatoshitok) {
if (!json_tok_u64(buffer, msatoshitok, &msatoshi)) {
command_fail(cmd, "'%.*s' is not a number",
msatoshitok->end - msatoshitok->start,
buffer + msatoshitok->start);
return;
}
/* The given msatoshi is the actual payment that
* the payee is requesting. The final hop amount, is
* what we actually give, which can be from the
* msatoshi to twice msatoshi. */
/* if not: msatoshi <= finalhop.amount <= 2 * msatoshi,
* fail. */
if (!(msatoshi <= route[n_hops-1].amount &&
route[n_hops-1].amount <= 2 * msatoshi)) {
command_fail(cmd, "msatoshi %"PRIu64" out of range",
msatoshi);
return;
}
} else
msatoshi = route[n_hops-1].amount;
if (send_payment(cmd, cmd->ld, &rhash, route, msatoshi,
&json_sendpay_on_resolve, cmd)) &json_sendpay_on_resolve, cmd))
command_still_pending(cmd); command_still_pending(cmd);
} }

5
lightningd/pay.h

@ -57,11 +57,14 @@ struct sendpay_result {
* sendpay_result indicating an error code of PAY_IN_PROGRESS. * sendpay_result indicating an error code of PAY_IN_PROGRESS.
* It will only call the callback with successful sendpay_result * It will only call the callback with successful sendpay_result
* if the payment has already completed with the same amount * if the payment has already completed with the same amount
* and destination before. */ * and destination before.
*
* The msatoshi given is what is recorded in the payment. */
bool send_payment(const tal_t *ctx, bool send_payment(const tal_t *ctx,
struct lightningd* ld, struct lightningd* ld,
const struct sha256 *rhash, const struct sha256 *rhash,
const struct route_hop *route, const struct route_hop *route,
u64 msatoshi,
void (*cb)(const struct sendpay_result *, void*), void (*cb)(const struct sendpay_result *, void*),
void *cbarg); void *cbarg);
/* Wait for a previous send_payment to complete in definite /* Wait for a previous send_payment to complete in definite

1
lightningd/payalgo.c

@ -475,6 +475,7 @@ static void json_pay_getroute_reply(struct subd *gossip UNUSED,
pay->in_sendpay = true; pay->in_sendpay = true;
send_payment(pay->try_parent, send_payment(pay->try_parent,
pay->cmd->ld, &pay->payment_hash, route, pay->cmd->ld, &pay->payment_hash, route,
pay->msatoshi,
&json_pay_sendpay_resume, pay); &json_pay_sendpay_resume, pay);
} }

Loading…
Cancel
Save