Skip to content

Commit

Permalink
libplugin: conceptually separate "total due" from "amount we're paying".
Browse files Browse the repository at this point in the history
At the moment they're both the same, but we're about to change that.

Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell committed Mar 20, 2024
1 parent 9b83b8b commit bd5d2d1
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 45 deletions.
8 changes: 5 additions & 3 deletions plugins/keysend.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ static void check_preapprovekeysend_start(void *d UNUSED, struct payment *p)
&preapprovekeysend_rpc_failure, p);
json_add_node_id(req->js, "destination", p->destination);
json_add_sha256(req->js, "payment_hash", p->payment_hash);
json_add_amount_msat(req->js, "amount_msat", p->amount);
json_add_amount_msat(req->js, "amount_msat", p->our_amount);
(void) send_outreq(p->plugin, req);
}

Expand Down Expand Up @@ -278,7 +278,9 @@ static struct command_result *json_keysend(struct command *cmd, const char *buf,
p->payment_metadata = NULL;
p->blindedpath = NULL;
p->blindedpay = NULL;
p->amount = *msat;
/* FIXME: We could allow partial keysends, too, but we'd have to allow
* caller to provide keysend secret */
p->our_amount = p->final_amount = *msat;
p->routes = tal_steal(p, hints);
// 22 is the Rust-Lightning default and the highest minimum we know of.
p->min_final_cltv_expiry = 22;
Expand All @@ -297,7 +299,7 @@ static struct command_result *json_keysend(struct command *cmd, const char *buf,
"We are the destination. Keysend cannot be used to send funds to yourself");
}

if (!amount_msat_fee(&p->constraints.fee_budget, p->amount, 0,
if (!amount_msat_fee(&p->constraints.fee_budget, p->our_amount, 0,
*maxfee_pct_millionths / 100)) {
return command_fail(
cmd, JSONRPC2_INVALID_PARAMS,
Expand Down
62 changes: 32 additions & 30 deletions plugins/libplugin-pay.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ struct payment *payment_new(tal_t *ctx, struct command *cmd,
assert(cmd == NULL);
tal_arr_expand(&parent->children, p);
p->destination = parent->destination;
p->amount = parent->amount;
p->final_amount = parent->final_amount;
p->our_amount = parent->our_amount;
p->label = parent->label;
p->payment_hash = parent->payment_hash;
p->partid = payment_root(p->parent)->next_partid++;
Expand Down Expand Up @@ -310,7 +311,7 @@ void payment_start_at_blockheight(struct payment *p, u32 blockheight)
p->getroute->destination = p->destination;
p->getroute->max_hops = ROUTING_MAX_HOPS;
p->getroute->cltv = root->min_final_cltv_expiry;
p->getroute->amount = p->amount;
p->getroute->amount = p->our_amount;

p->start_constraints = tal_dup(p, struct payment_constraints, &p->constraints);

Expand Down Expand Up @@ -458,15 +459,15 @@ static void payment_exclude_longest_delay(struct payment *p)
static struct amount_msat payment_route_fee(struct payment *p)
{
struct amount_msat fee;
if (!amount_msat_sub(&fee, p->route[0].amount, p->amount)) {
if (!amount_msat_sub(&fee, p->route[0].amount, p->our_amount)) {
paymod_log(
p,
LOG_BROKEN,
"gossipd returned a route with a negative fee: sending %s "
"to deliver %s",
type_to_string(tmpctx, struct amount_msat,
&p->route[0].amount),
type_to_string(tmpctx, struct amount_msat, &p->amount));
type_to_string(tmpctx, struct amount_msat, &p->our_amount));
abort();
}
return fee;
Expand Down Expand Up @@ -627,7 +628,7 @@ payment_get_excluded_channels(const tal_t *ctx, struct payment *p)
if (!hint->enabled)
tal_arr_expand(&res, hint->scid);

else if (amount_msat_greater(p->amount,
else if (amount_msat_greater(p->our_amount,
hint->estimated_capacity))
tal_arr_expand(&res, hint->scid);

Expand Down Expand Up @@ -1657,7 +1658,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(req->js, "amount_msat", p->amount);
json_add_amount_msat(req->js, "amount_msat", p->our_amount);

json_array_start(req->js, "shared_secrets");
secrets = p->createonion_response->shared_secrets;
Expand Down Expand Up @@ -1716,7 +1717,6 @@ static void payment_add_hop_onion_payload(struct payment *p,
u32 cltv = p->start_block + next->delay + 1;
u64 msat = next->amount.millisatoshis; /* Raw: TLV payload generation*/
struct tlv_field **fields;
struct payment *root = payment_root(p);

/* This is the information of the node processing this payload, while
* `next` are the instructions to include in the payload, which is
Expand All @@ -1739,7 +1739,7 @@ static void payment_add_hop_onion_payload(struct payment *p,
assert(final);
tlvstream_set_tlv_payload_data(
fields, payment_secret,
root->amount.millisatoshis); /* Raw: TLV payload generation*/
p->final_amount.millisatoshis); /* Raw: TLV payload generation*/
}
if (payment_metadata != NULL) {
assert(final);
Expand All @@ -1751,6 +1751,7 @@ static void payment_add_hop_onion_payload(struct payment *p,
static void payment_add_blindedpath(const tal_t *ctx,
struct createonion_hop *hops,
const struct blinded_path *bpath,
struct amount_msat our_amt,
struct amount_msat final_amt,
u32 final_cltv)
{
Expand Down Expand Up @@ -1824,6 +1825,7 @@ static void payment_compute_onion_payloads(struct payment *p)
if (root->blindedpath) {
payment_add_blindedpath(cr->hops, cr->hops + hopcount - 1,
root->blindedpath,
root->blindedouramount,
root->blindedfinalamount,
root->blindedfinalcltv);
tal_append_fmt(&routetxt, "%s -> blinded path (%zu hops)",
Expand Down Expand Up @@ -1971,7 +1973,7 @@ static void payment_add_attempt(struct json_stream *s, const char *fieldname, st
json_add_string(s, "failreason", p->failreason);

json_add_u64(s, "partid", p->partid);
json_add_amount_msat(s, "amount_msat", p->amount);
json_add_amount_msat(s, "amount_msat", p->our_amount);
if (p->parent != NULL)
json_add_u64(s, "parent_partid", p->parent->partid);

Expand Down Expand Up @@ -2025,11 +2027,11 @@ void json_add_payment_success(struct json_stream *js,
else
json_add_num(js, "parts", 1);

json_add_amount_msat(js, "amount_msat", p->amount);
json_add_amount_msat(js, "amount_msat", p->our_amount);
if (result)
json_add_amount_msat(js, "amount_sent_msat", result->sent);
else
json_add_amount_msat(js, "amount_sent_msat", p->amount);
json_add_amount_msat(js, "amount_sent_msat", p->our_amount);

if (result && result->leafstates != PAYMENT_STEP_SUCCESS)
json_add_string(js, "warning_partial_completion",
Expand Down Expand Up @@ -2155,7 +2157,7 @@ static void payment_finished(struct payment *p)
json_add_string(ret, "status", "failed");
}

json_add_amount_msat(ret, "amount_msat", p->amount);
json_add_amount_msat(ret, "amount_msat", p->our_amount);
json_add_amount_msat(ret, "amount_sent_msat",
result.sent);

Expand Down Expand Up @@ -2429,7 +2431,7 @@ static inline void retry_step_cb(struct retry_mod_data *rd,
"Retrying %s/%d (%s), new partid %d. %d attempts left\n",
type_to_string(tmpctx, struct sha256, p->payment_hash),
p->partid,
type_to_string(tmpctx, struct amount_msat, &p->amount),
type_to_string(tmpctx, struct amount_msat, &p->our_amount),
subpayment->partid,
rdata->retries - 1);
}
Expand Down Expand Up @@ -2665,7 +2667,7 @@ static bool routehint_excluded(struct payment *p,

/* Check our capacity fits. */
struct amount_msat needed_capacity;
if (!route_msatoshi(&needed_capacity, p->amount,
if (!route_msatoshi(&needed_capacity, p->our_amount,
r + 1, tal_count(routehint) - i - 1))
return true;
/* Why do we scan the hints again if
Expand Down Expand Up @@ -2797,7 +2799,7 @@ static void routehint_pre_getroute(struct routehints_data *d, struct payment *p)
p->temp_exclusion = tal_free(p->temp_exclusion);

if (d->current_routehint != NULL) {
if (!route_msatoshi(&p->getroute->amount, p->amount,
if (!route_msatoshi(&p->getroute->amount, p->our_amount,
d->current_routehint,
tal_count(d->current_routehint))) {
}
Expand Down Expand Up @@ -2953,7 +2955,7 @@ static void routehint_step_cb(struct routehints_data *d, struct payment *p)
struct route_hop *prev_hop;
for (ssize_t i = 0; i < tal_count(routehint); i++) {
prev_hop = &p->route[tal_count(p->route)-1];
if (!route_msatoshi(&dest_amount, p->amount,
if (!route_msatoshi(&dest_amount, p->our_amount,
routehint + i + 1,
tal_count(routehint) - i - 1)) {
/* Just let it fail, since we couldn't stitch
Expand Down Expand Up @@ -3182,14 +3184,14 @@ static struct command_result *shadow_route_listchannels(struct command *cmd,

/* If the capacity is insufficient to pass the amount
* it's not a plausible extension. */
if (amount_msat_greater_sat(p->amount, capacity))
if (amount_msat_greater_sat(p->our_amount, capacity))
continue;

if (curr.cltv_expiry_delta > cons->cltv_budget)
continue;

if (!amount_msat_fee(
&fee, p->amount, curr.fee_base_msat,
&fee, p->our_amount, curr.fee_base_msat,
curr.fee_proportional_millionths)) {
/* Fee computation failed... */
continue;
Expand Down Expand Up @@ -3328,10 +3330,10 @@ static void direct_pay_override(struct payment *p) {
}

if (hint && hint->enabled &&
amount_msat_greater(hint->estimated_capacity, p->amount)) {
amount_msat_greater(hint->estimated_capacity, p->our_amount)) {
/* Now build a route that consists only of this single hop */
p->route = tal_arr(p, struct route_hop, 1);
p->route[0].amount = p->amount;
p->route[0].amount = p->our_amount;
p->route[0].delay = p->getroute->cltv;
p->route[0].scid = hint->scid.scid;
p->route[0].direction = hint->scid.dir;
Expand Down Expand Up @@ -3638,13 +3640,13 @@ static void adaptive_splitter_cb(struct adaptive_split_mod_data *d, struct payme
struct tlv_field **fields = &hop->tlv_payload->fields;
tlvstream_set_tlv_payload_data(
fields, root->payment_secret,
root->amount.millisatoshis); /* Raw: onion payload */
root->final_amount.millisatoshis); /* Raw: onion payload */
} else if (p->step == PAYMENT_STEP_FAILED && !p->abort) {
if (amount_msat_greater(p->amount, MPP_ADAPTIVE_LOWER_LIMIT)) {
if (amount_msat_greater(p->our_amount, MPP_ADAPTIVE_LOWER_LIMIT)) {
struct payment *a, *b;
/* Random number in the range [90%, 110%] */
double rand = pseudorand_double() * 0.2 + 0.9;
u64 mid = p->amount.millisatoshis / 2 * rand; /* Raw: multiplication */
u64 mid = p->our_amount.millisatoshis / 2 * rand; /* Raw: multiplication */
bool ok;
/* Use the start constraints, not the ones updated by routes and shadow-routes. */
struct payment_constraints *pconstraints = p->start_constraints;
Expand All @@ -3663,11 +3665,11 @@ static void adaptive_splitter_cb(struct adaptive_split_mod_data *d, struct payme
a = payment_new(p, NULL, p, p->modifiers);
b = payment_new(p, NULL, p, p->modifiers);

a->amount.millisatoshis = mid; /* Raw: split. */
b->amount.millisatoshis -= mid; /* Raw: split. */
a->our_amount.millisatoshis = mid; /* Raw: split. */
b->our_amount.millisatoshis -= mid; /* Raw: split. */

double multiplier = amount_msat_ratio(a->amount,
p->amount);
double multiplier = amount_msat_ratio(a->our_amount,
p->our_amount);
assert(multiplier >= 0.4 && multiplier < 0.6);

/* Adjust constraints since we don't want to double our
Expand Down Expand Up @@ -3695,10 +3697,10 @@ static void adaptive_splitter_cb(struct adaptive_split_mod_data *d, struct payme
"new partid %"PRIu32" (%s)",
a->partid,
type_to_string(tmpctx, struct amount_msat,
&a->amount),
&a->our_amount),
b->partid,
type_to_string(tmpctx, struct amount_msat,
&b->amount));
&b->our_amount));

/* Take note that we now have an additional split that
* may end up using an HTLC. */
Expand All @@ -3708,7 +3710,7 @@ static void adaptive_splitter_cb(struct adaptive_split_mod_data *d, struct payme
"Lower limit of adaptive splitter reached "
"(%s < %s), not splitting further.",
type_to_string(tmpctx, struct amount_msat,
&p->amount),
&p->our_amount),
type_to_string(tmpctx, struct amount_msat,
&MPP_ADAPTIVE_LOWER_LIMIT));
}
Expand Down
5 changes: 4 additions & 1 deletion plugins/libplugin-pay.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ struct payment {
/* Blinded path (for bolt12) */
struct blinded_path *blindedpath;
struct blinded_payinfo *blindedpay;
struct amount_msat blindedouramount;
struct amount_msat blindedfinalamount;
u32 blindedfinalcltv;

Expand All @@ -211,7 +212,9 @@ struct payment {
struct createonion_response *createonion_response;

/* Target amount to be delivered at the destination */
struct amount_msat amount;
struct amount_msat final_amount;
/* Amount we are trying to deliver with this payment (usually the same) */
struct amount_msat our_amount;

/* tal_arr of route_hops we decoded from the `getroute` call. Exposed
* here so it can be amended by mixins. */
Expand Down
32 changes: 21 additions & 11 deletions plugins/pay.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ static struct command_result *json_paystatus(struct command *cmd,

if (p->invstring)
json_add_invstring(ret, p->invstring);
json_add_amount_msat(ret, "amount_msat", p->amount);
json_add_amount_msat(ret, "amount_msat", p->our_amount);

json_add_node_id(ret, "destination", p->destination);

Expand Down Expand Up @@ -625,7 +625,7 @@ static void on_payment_success(struct payment *payment)
json_add_timeabs(ret, "created_at", p->start_time);
json_add_num(ret, "parts", result.attempts);

json_add_amount_msat(ret, "amount_msat", p->amount);
json_add_amount_msat(ret, "amount_msat", p->our_amount);
json_add_amount_msat(ret, "amount_sent_msat", result.sent);

if (result.leafstates != PAYMENT_STEP_SUCCESS)
Expand Down Expand Up @@ -663,7 +663,7 @@ static void payment_add_attempt(struct json_stream *s, const char *fieldname, st
json_add_string(s, "failreason", p->failreason);

json_add_u64(s, "partid", p->partid);
json_add_amount_msat(s, "amount_msat", p->amount);
json_add_amount_msat(s, "amount_msat", p->our_amount);
if (p->parent != NULL)
json_add_u64(s, "parent_partid", p->parent->partid);

Expand Down Expand Up @@ -763,7 +763,7 @@ static void on_payment_failure(struct payment *payment)
json_add_string(ret, "status", "failed");
}

json_add_amount_msat(ret, "amount_msat", p->amount);
json_add_amount_msat(ret, "amount_msat", p->our_amount);

json_add_amount_msat(ret, "amount_sent_msat",
result.sent);
Expand Down Expand Up @@ -830,7 +830,9 @@ static struct command_result *selfpay(struct command *cmd, struct payment *p)
json_add_sha256(req->js, "payment_hash", p->payment_hash);
if (p->label)
json_add_string(req->js, "label", p->label);
json_add_amount_msat(req->js, "amount_msat", p->amount);
/* FIXME: This will fail if we try to do a partial amount to
* ourselves! */
json_add_amount_msat(req->js, "amount_msat", p->our_amount);
json_add_string(req->js, "bolt11", p->invstring);
if (p->payment_secret)
json_add_secret(req->js, "payment_secret", p->payment_secret);
Expand Down Expand Up @@ -1187,27 +1189,35 @@ static struct command_result *json_pay(struct command *cmd,
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"msatoshi parameter unnecessary");
}
p->amount = *invmsat;
p->final_amount = *invmsat;
tal_free(invmsat);
} else {
if (!msat) {
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"msatoshi parameter required");
}
p->amount = *msat;
p->final_amount = *msat;
}

/* FIXME: Allow partial payment! */
p->our_amount = p->final_amount;

/* We replace real final values if we're using a blinded path */
if (p->blindedpath) {
p->blindedfinalcltv = p->min_final_cltv_expiry;
p->blindedfinalamount = p->amount;
p->blindedouramount = p->our_amount;
p->blindedfinalamount = p->final_amount;

p->min_final_cltv_expiry += p->blindedpay->cltv_expiry_delta;
if (!amount_msat_add_fee(&p->amount,
if (!amount_msat_add_fee(&p->final_amount,
p->blindedpay->fee_base_msat,
p->blindedpay->fee_proportional_millionths))
p->blindedpay->fee_proportional_millionths)
|| !amount_msat_add_fee(&p->our_amount,
p->blindedpay->fee_base_msat,
p->blindedpay->fee_proportional_millionths)) {
return command_fail(cmd, PAY_ROUTE_TOO_EXPENSIVE,
"This payment blinded path fee overflows!");
}
}

p->local_id = &my_id;
Expand Down Expand Up @@ -1236,7 +1246,7 @@ static struct command_result *json_pay(struct command *cmd,
maxppm = *maxfee_pct_millionths / 100;
else
maxppm = 500000 / 100;
if (!amount_msat_fee(&p->constraints.fee_budget, p->amount, 0,
if (!amount_msat_fee(&p->constraints.fee_budget, p->our_amount, 0,
maxppm)) {
return command_fail(
cmd, JSONRPC2_INVALID_PARAMS,
Expand Down

0 comments on commit bd5d2d1

Please sign in to comment.