Skip to content

Commit

Permalink
pay: Let sendpay modify the recorded msatoshi of payments.
Browse files Browse the repository at this point in the history
  • Loading branch information
ZmnSCPxj authored and cdecker committed Mar 30, 2018
1 parent 1fe79df commit bc5fc69
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 13 deletions.
10 changes: 6 additions & 4 deletions doc/lightning-sendpay.7
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
.\" Title: lightning-sendpay
.\" Author: [see the "AUTHOR" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
.\" Date: 03/14/2018
.\" Date: 03/22/2018
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "LIGHTNING\-SENDPAY" "7" "03/14/2018" "\ \&" "\ \&"
.TH "LIGHTNING\-SENDPAY" "7" "03/22/2018" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
Expand All @@ -31,7 +31,7 @@
lightning-sendpay \- Protocol for sending a payment via a route\&.
.SH "SYNOPSIS"
.sp
\fBsendpay\fR \fIroute\fR \fIhash\fR
\fBsendpay\fR \fIroute\fR \fIhash\fR [\fImsatoshi\fR]
.SH "DESCRIPTION"
.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\&.
Expand All @@ -40,7 +40,9 @@ Generally, a client would call getroute(7) to resolve a route, then use \fBsendp
.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\&.
.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"
.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\&.
Expand Down
17 changes: 14 additions & 3 deletions doc/lightning-sendpay.7.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ lightning-sendpay - Protocol for sending a payment via a route.

SYNOPSIS
--------
*sendpay* 'route' 'hash'
*sendpay* 'route' 'hash' ['msatoshi']

DESCRIPTION
-----------
Expand All @@ -27,10 +27,21 @@ definite failure of the payment.
Instead, use the *waitsendpay* RPC command to poll or wait for
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'
but a different amount or destination will fail; this prevents
but a different 'msatoshi' or destination will fail; this prevents
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
immediately with success.

Expand Down
36 changes: 31 additions & 5 deletions lightningd/pay.c
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,7 @@ send_payment(const tal_t *ctx,
struct lightningd* ld,
const struct sha256 *rhash,
const struct route_hop *route,
u64 msatoshi,
void (*cb)(const struct sendpay_result *, void*),
void *cbarg)
{
Expand Down Expand Up @@ -685,7 +686,7 @@ send_payment(const tal_t *ctx,
if (payment->status == PAYMENT_COMPLETE) {
log_add(ld->log, "... succeeded");
/* Must match successful payment parameters. */
if (payment->msatoshi != hop_data[n_hops-1].amt_forward) {
if (payment->msatoshi != msatoshi) {
char *msg = tal_fmt(tmpctx,
"Already succeeded "
"with amount %"PRIu64,
Expand Down Expand Up @@ -740,8 +741,8 @@ send_payment(const tal_t *ctx,
sizeof(struct sha256), &path_secrets);
onion = serialize_onionpacket(tmpctx, packet);

log_info(ld->log, "Sending %u over %zu hops to deliver %u",
route[0].amount, n_hops, route[n_hops-1].amount);
log_info(ld->log, "Sending %u over %zu hops to deliver %"PRIu64"",
route[0].amount, n_hops, msatoshi);

failcode = send_htlc_out(channel, route[0].amount,
base_expiry + route[0].delay,
Expand Down Expand Up @@ -781,7 +782,7 @@ send_payment(const tal_t *ctx,
payment->payment_hash = *rhash;
payment->destination = ids[n_hops - 1];
payment->status = PAYMENT_PENDING;
payment->msatoshi = route[n_hops-1].amount;
payment->msatoshi = msatoshi;
payment->msatoshi_sent = route[0].amount;
payment->timestamp = time_now().ts.tv_sec;
payment->payment_preimage = NULL;
Expand Down Expand Up @@ -912,14 +913,17 @@ static void json_sendpay(struct command *cmd,
const char *buffer, const jsmntok_t *params)
{
jsmntok_t *routetok, *rhashtok;
jsmntok_t *msatoshitok;
const jsmntok_t *t, *end;
size_t n_hops;
struct sha256 rhash;
struct route_hop *route;
u64 msatoshi;

if (!json_get_params(cmd, buffer, params,
"route", &routetok,
"payment_hash", &rhashtok,
"?msatoshi", &msatoshitok,
NULL)) {
return;
}
Expand Down Expand Up @@ -994,7 +998,29 @@ static void json_sendpay(struct command *cmd,
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))
command_still_pending(cmd);
}
Expand Down
5 changes: 4 additions & 1 deletion lightningd/pay.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,14 @@ struct sendpay_result {
* sendpay_result indicating an error code of PAY_IN_PROGRESS.
* It will only call the callback with successful sendpay_result
* 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,
struct lightningd* ld,
const struct sha256 *rhash,
const struct route_hop *route,
u64 msatoshi,
void (*cb)(const struct sendpay_result *, void*),
void *cbarg);
/* Wait for a previous send_payment to complete in definite
Expand Down
1 change: 1 addition & 0 deletions lightningd/payalgo.c
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ static void json_pay_getroute_reply(struct subd *gossip UNUSED,
pay->in_sendpay = true;
send_payment(pay->try_parent,
pay->cmd->ld, &pay->payment_hash, route,
pay->msatoshi,
&json_pay_sendpay_resume, pay);
}

Expand Down

0 comments on commit bc5fc69

Please sign in to comment.