pay: Let sendpay modify the recorded msatoshi of payments.

This commit is contained in:
ZmnSCPxj 2018-03-22 12:49:09 +00:00 committed by Christian Decker
parent 1fe79df867
commit bc5fc692d1
5 changed files with 56 additions and 13 deletions

View File

@ -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
.\" -----------------------------------------------------------------
@ -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\&.
@ -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\&.

View File

@ -8,7 +8,7 @@ lightning-sendpay - Protocol for sending a payment via a route.
SYNOPSIS
--------
*sendpay* 'route' 'hash'
*sendpay* 'route' 'hash' ['msatoshi']
DESCRIPTION
-----------
@ -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.

View File

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

View File

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

View File

@ -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);
}