Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Annotate payments initiated using sendonion with the amount at the destination #3881

Merged
merged 5 commits into from
Jul 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion doc/lightning-sendonion.7

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion doc/lightning-sendonion.7.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ lightning-sendonion -- Send a payment with a custom onion packet
SYNOPSIS
--------

**sendonion** *onion* *first_hop* *payment_hash* \[*label*\] \[*shared_secrets*\] \[*partid*\] \[*bolt11*\]
**sendonion** *onion* *first_hop* *payment_hash* \[*label*\] \[*shared_secrets*\] \[*partid*\] \[*bolt11*\] \[*msatoshi*\]
ZmnSCPxj marked this conversation as resolved.
Show resolved Hide resolved

DESCRIPTION
-----------
Expand Down Expand Up @@ -78,6 +78,9 @@ partial payments with the same *payment_hash*.
The *bolt11* parameter, if provided, will be returned in
*waitsendpay* and *listsendpays* results.

The *msatoshi* parameter is used to annotate the payment, and is returned by
*waitsendpay* and *listsendpays*.

RETURN VALUE
------------

Expand Down
4 changes: 3 additions & 1 deletion lightningd/pay.c
Original file line number Diff line number Diff line change
Expand Up @@ -1179,6 +1179,7 @@ static struct command_result *json_sendonion(struct command *cmd,
struct lightningd *ld = cmd->ld;
const char *label, *b11str;
struct secret *path_secrets;
struct amount_msat *msat;
u64 *partid;

if (!param(cmd, buffer, params,
Expand All @@ -1189,6 +1190,7 @@ static struct command_result *json_sendonion(struct command *cmd,
p_opt("shared_secrets", param_secrets_array, &path_secrets),
p_opt_def("partid", param_u64, &partid, 0),
p_opt("bolt11", param_string, &b11str),
p_opt_def("msatoshi", param_msat, &msat, AMOUNT_MSAT(0)),
cdecker marked this conversation as resolved.
Show resolved Hide resolved
NULL))
return command_param_failed();

Expand All @@ -1201,7 +1203,7 @@ static struct command_result *json_sendonion(struct command *cmd,
failcode);

return send_payment_core(ld, cmd, payment_hash, *partid,
first_hop, AMOUNT_MSAT(0), AMOUNT_MSAT(0),
first_hop, *msat, AMOUNT_MSAT(0),
label, b11str, &packet, NULL, NULL, NULL,
path_secrets);
}
Expand Down
1 change: 1 addition & 0 deletions plugins/libplugin-pay.c
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,7 @@ static struct command_result *payment_createonion_success(struct command *cmd,
json_object_end(req->js);

json_add_sha256(req->js, "payment_hash", p->payment_hash);
json_add_amount_msat_only(req->js, "msatoshi", p->amount);

json_array_start(req->js, "shared_secrets");
secrets = p->createonion_response->shared_secrets;
Expand Down
53 changes: 45 additions & 8 deletions plugins/pay.c
Original file line number Diff line number Diff line change
Expand Up @@ -1661,6 +1661,11 @@ struct pay_mpp {
size_t num_nonfailed_parts;
/* Total amount sent ("complete" or "pending" only). */
struct amount_msat amount_sent;

/* Total amount received by the recipient ("complete" or "pending"
* only). Null if we have any part for which we didn't know the
* amount. */
struct amount_msat *amount;
};

static const struct sha256 *pay_mpp_key(const struct pay_mpp *pm)
Expand All @@ -1683,17 +1688,43 @@ HTABLE_DEFINE_TYPE(struct pay_mpp, pay_mpp_key, pay_mpp_hash, pay_mpp_eq,

static void add_amount_sent(struct plugin *p,
const char *b11,
struct amount_msat *total,
struct pay_mpp *mpp,
const char *buf,
const jsmntok_t *t)
{
struct amount_msat sent;
struct amount_msat sent, recv;
const jsmntok_t *msattok;


json_to_msat(buf, json_get_member(buf, t, "amount_sent_msat"), &sent);
if (!amount_msat_add(total, *total, sent))
if (!amount_msat_add(&mpp->amount_sent, mpp->amount_sent, sent))
plugin_log(p, LOG_BROKEN,
"Cannot add amount_sent_msat for %s: %s + %s",
b11,
type_to_string(tmpctx, struct amount_msat, total),
type_to_string(tmpctx, struct amount_msat, &mpp->amount_sent),
type_to_string(tmpctx, struct amount_msat, &sent));

msattok = json_get_member(buf, t, "amount_msat");

/* If this is an unannotated partial payment we drop out estimate for
* all parts. */
if (msattok == NULL) {
mpp->amount = tal_free(mpp->amount);
return;
}

/* If we had a part of this multi-part payment for which we don't know
* the amount, then this is NULL. No point in summing up if we don't
* have the exact value.*/
if (mpp->amount == NULL)
return;

json_to_msat(buf, msattok, &recv);
if (!amount_msat_add(mpp->amount, *mpp->amount, recv))
plugin_log(p, LOG_BROKEN,
"Cannot add amount_msat for %s: %s + %s",
b11,
type_to_string(tmpctx, struct amount_msat, mpp->amount),
type_to_string(tmpctx, struct amount_msat, &sent));
}

Expand All @@ -1708,6 +1739,13 @@ static void add_new_entry(struct json_stream *ret,
json_add_tok(ret, "label", pm->label, buf);
if (pm->preimage)
json_add_tok(ret, "preimage", pm->preimage, buf);

/* This is only tallied for pending and successful payments, not
* failures. */
if (pm->amount != NULL && pm->num_nonfailed_parts > 0)
json_add_string(ret, "amount_msat",
fmt_amount_msat(tmpctx, pm->amount));

json_add_string(ret, "amount_sent_msat",
fmt_amount_msat(tmpctx, &pm->amount_sent));

Expand Down Expand Up @@ -1759,22 +1797,21 @@ static struct command_result *listsendpays_done(struct command *cmd,
pm->label = json_get_member(buf, t, "label");
pm->preimage = NULL;
pm->amount_sent = AMOUNT_MSAT(0);
pm->amount = talz(pm, struct amount_msat);
pm->num_nonfailed_parts = 0;
pm->status = NULL;
pay_map_add(&pay_map, pm);
}

status = json_get_member(buf, t, "status");
if (json_tok_streq(buf, status, "complete")) {
add_amount_sent(cmd->plugin, pm->b11,
&pm->amount_sent, buf, t);
add_amount_sent(cmd->plugin, pm->b11, pm, buf, t);
pm->num_nonfailed_parts++;
pm->status = "complete";
pm->preimage
= json_get_member(buf, t, "payment_preimage");
} else if (json_tok_streq(buf, status, "pending")) {
add_amount_sent(cmd->plugin, pm->b11,
&pm->amount_sent, buf, t);
add_amount_sent(cmd->plugin, pm->b11, pm, buf, t);
pm->num_nonfailed_parts++;
/* Failed -> pending; don't downgrade success. */
if (!pm->status || !streq(pm->status, "complete"))
Expand Down
6 changes: 4 additions & 2 deletions tests/test_pay.py
Original file line number Diff line number Diff line change
Expand Up @@ -3211,8 +3211,10 @@ def test_bolt11_null_after_pay(node_factory, bitcoind):
bitcoind.generate_block(6)
sync_blockheight(bitcoind, [l1, l2])

invl1 = l1.rpc.invoice(Millisatoshi(amount_sat * 2 * 1000), 'j', 'j')['bolt11']
amt = Millisatoshi(amount_sat * 2 * 1000)
invl1 = l1.rpc.invoice(amt, 'j', 'j')['bolt11']
l2.rpc.pay(invl1)

pays = l2.rpc.listpays()["pays"]
assert pays[0]["bolt11"] == invl1
assert(pays[0]["bolt11"] == invl1)
assert('amount_msat' in pays[0] and pays[0]['amount_msat'] == amt)
12 changes: 10 additions & 2 deletions wallet/wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -2749,8 +2749,16 @@ static struct wallet_payment *wallet_stmt2payment(const tal_t *ctx,
else
payment->failonion = NULL;

db_column_amount_msat(stmt, 14, &payment->total_msat);
payment->partid = db_column_u64(stmt, 15);
if (!db_column_is_null(stmt, 14))
db_column_amount_msat(stmt, 14, &payment->total_msat);
else
payment->total_msat = AMOUNT_MSAT(0);

if (!db_column_is_null(stmt, 15))
payment->partid = db_column_u64(stmt, 15);
else
payment->partid = 0;

return payment;
}

Expand Down