Skip to content

Commit 1131568

Browse files
committed
xpay: don't excees maxfee *overall*.
We were handing "maxfee" to every getroutes call, even if we had already used some of the fees. Reported-by: @daywalker90 Signed-off-by: Rusty Russell <[email protected]> Changelog-None: xpay is new this release.
1 parent d0b4706 commit 1131568

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

plugins/xpay/xpay.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,25 @@ static struct amount_msat total_being_sent(const struct payment *payment)
749749
return sum;
750750
}
751751

752+
static struct amount_msat total_fees_being_sent(const struct payment *payment)
753+
{
754+
struct attempt *attempt;
755+
struct amount_msat sum = AMOUNT_MSAT(0);
756+
757+
list_for_each(&payment->current_attempts, attempt, list) {
758+
struct amount_msat fee;
759+
if (tal_count(attempt->hops) == 0)
760+
continue;
761+
if (!amount_msat_sub(&fee,
762+
attempt->hops[0].amount_in,
763+
attempt->delivers))
764+
abort();
765+
if (!amount_msat_accumulate(&sum, fee))
766+
abort();
767+
}
768+
return sum;
769+
}
770+
752771
static struct command_result *injectpaymentonion_succeeded(struct command *aux_cmd,
753772
const char *method,
754773
const char *buf,
@@ -1075,6 +1094,9 @@ static struct command_result *getroutes_done_err(struct command *aux_cmd,
10751094
return command_still_pending(aux_cmd);
10761095
}
10771096

1097+
/* FIXME: If we fail due to exceeding maxfee, we *could* try waiting for
1098+
* any outstanding payments to fail and then try again? */
1099+
10781100
/* More elaborate explanation. */
10791101
if (amount_msat_eq(payment->amount_being_routed, payment->amount))
10801102
complaint = "Then routing failed";
@@ -1097,6 +1119,7 @@ static struct command_result *getroutes_for(struct command *aux_cmd,
10971119
struct xpay *xpay = xpay_of(aux_cmd->plugin);
10981120
struct out_req *req;
10991121
const struct pubkey *dst;
1122+
struct amount_msat maxfee;
11001123

11011124
/* If we get injectpaymentonion responses, they can wait */
11021125
payment->amount_being_routed = deliver;
@@ -1112,6 +1135,13 @@ static struct command_result *getroutes_for(struct command *aux_cmd,
11121135
return do_inject(aux_cmd, attempt);
11131136
}
11141137

1138+
if (!amount_msat_sub(&maxfee, payment->maxfee, total_fees_being_sent(payment))) {
1139+
payment_log(payment, LOG_BROKEN, "more fees (%s) in flight than allowed (%s)!",
1140+
fmt_amount_msat(tmpctx, total_fees_being_sent(payment)),
1141+
fmt_amount_msat(tmpctx, payment->maxfee));
1142+
maxfee = AMOUNT_MSAT(0);
1143+
}
1144+
11151145
req = jsonrpc_request_start(aux_cmd, "getroutes",
11161146
getroutes_done,
11171147
getroutes_done_err,
@@ -1139,7 +1169,7 @@ static struct command_result *getroutes_for(struct command *aux_cmd,
11391169
for (size_t i = 0; i < tal_count(payment->layers); i++)
11401170
json_add_string(req->js, NULL, payment->layers[i]);
11411171
json_array_end(req->js);
1142-
json_add_amount_msat(req->js, "maxfee_msat", payment->maxfee);
1172+
json_add_amount_msat(req->js, "maxfee_msat", maxfee);
11431173
json_add_u32(req->js, "final_cltv", payment->final_cltv);
11441174

11451175
return send_payment_req(aux_cmd, payment, req);

tests/test_xpay.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ def test_xpay_preapprove(node_factory):
475475
l1.rpc.xpay(inv)
476476

477477

478-
@pytest.mark.xfail(strict=True)
478+
@unittest.skipIf(TEST_NETWORK != 'regtest', 'too dusty on elements')
479479
def test_xpay_maxfee(node_factory, bitcoind, chainparams):
480480
"""Test which shows that we don't excees maxfee"""
481481
outfile = tempfile.NamedTemporaryFile(prefix='gossip-store-')

0 commit comments

Comments
 (0)