Skip to content

Commit 8e98ad3

Browse files
authored
Merge branch 'ElementsProject:master' into add-testnet4-support
2 parents 48d797c + b5d1ace commit 8e98ad3

File tree

6 files changed

+85
-7
lines changed

6 files changed

+85
-7
lines changed

channeld/full_channel.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,13 +1658,13 @@ bool channel_force_htlcs(struct channel *channel,
16581658

16591659
const char *channel_add_err_name(enum channel_add_err e)
16601660
{
1661-
static char invalidbuf[sizeof("INVALID ") + STR_MAX_CHARS(e)];
1661+
static char invalidbuf[sizeof("UNKNOWN ") + STR_MAX_CHARS(e)];
16621662

16631663
for (size_t i = 0; enum_channel_add_err_names[i].name; i++) {
16641664
if (enum_channel_add_err_names[i].v == e)
16651665
return enum_channel_add_err_names[i].name;
16661666
}
1667-
snprintf(invalidbuf, sizeof(invalidbuf), "INVALID %i", e);
1667+
snprintf(invalidbuf, sizeof(invalidbuf), "UNKNOWN %i", e);
16681668
return invalidbuf;
16691669
}
16701670

lightningd/pay.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ json_add_routefail_info(struct json_stream *js,
219219
json_add_num(js, "erring_index", erring_index);
220220
json_add_num(js, "failcode", failcode);
221221
/* FIXME: Better way to detect this? */
222-
if (!strstarts(failcodename, "INVALID "))
222+
if (!strstarts(failcodename, "UNKNOWN "))
223223
json_add_string(js, "failcodename", failcodename);
224224

225225
if (erring_node != NULL)

lightningd/subd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,7 @@ void subd_send_msg(struct subd *sd, const u8 *msg_out)
839839
u16 type = fromwire_peektype(msg_out);
840840
/* FIXME: We should use unique upper bits for each daemon, then
841841
* have generate-wire.py add them, just assert here. */
842-
if (strstarts(sd->msgname(type), "INVALID"))
842+
if (strstarts(sd->msgname(type), "UNKNOWN"))
843843
fatal("Sending %s an invalid message %s", sd->name, tal_hex(tmpctx, msg_out));
844844
msg_enqueue(sd->outq, msg_out);
845845
}

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: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,3 +473,51 @@ def test_xpay_preapprove(node_factory):
473473

474474
with pytest.raises(RpcError, match=r"invoice was declined"):
475475
l1.rpc.xpay(inv)
476+
477+
478+
@unittest.skipIf(TEST_NETWORK != 'regtest', 'too dusty on elements')
479+
def test_xpay_maxfee(node_factory, bitcoind, chainparams):
480+
"""Test which shows that we don't excees maxfee"""
481+
outfile = tempfile.NamedTemporaryFile(prefix='gossip-store-')
482+
subprocess.check_output(['devtools/gossmap-compress',
483+
'decompress',
484+
'--node-map=3301=022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59',
485+
'tests/data/gossip-store-2024-09-22.compressed',
486+
outfile.name]).decode('utf-8').splitlines()
487+
AMOUNT = 100_000_000
488+
489+
# l2 will warn l1 about its invalid gossip: ignore.
490+
# We throttle l1's gossip to avoid massive log spam.
491+
l1, l2 = node_factory.line_graph(2,
492+
# This is in sats, so 1000x amount we send.
493+
fundamount=AMOUNT,
494+
opts=[{'gossip_store_file': outfile.name,
495+
'subdaemon': 'channeld:../tests/plugins/channeld_fakenet',
496+
'allow_warning': True,
497+
'dev-throttle-gossip': None},
498+
{'allow_bad_gossip': True}])
499+
500+
# l1 needs to know l2's shaseed for the channel so it can make revocations
501+
hsmfile = os.path.join(l2.daemon.lightning_dir, TEST_NETWORK, "hsm_secret")
502+
# Needs peer node id and channel dbid (1, it's the first channel), prints out:
503+
# "shaseed: xxxxxxx\n"
504+
shaseed = subprocess.check_output(["tools/hsmtool", "dumpcommitments", l1.info['id'], "1", "0", hsmfile]).decode('utf-8').strip().partition(": ")[2]
505+
l1.rpc.dev_peer_shachain(l2.info['id'], shaseed)
506+
507+
# This one triggers the bug!
508+
n = 59
509+
maxfee = 57966
510+
preimage_hex = bytes([n + 100]).hex() + '00' * 31
511+
hash_hex = sha256(bytes.fromhex(preimage_hex)).hexdigest()
512+
inv = subprocess.check_output(["devtools/bolt11-cli",
513+
"encode",
514+
n.to_bytes(length=8, byteorder=sys.byteorder).hex() + '01' * 24,
515+
f"currency={chainparams['bip173_prefix']}",
516+
f"p={hash_hex}",
517+
f"s={'00' * 32}",
518+
f"d=Paying node {n} with maxfee",
519+
f"amount={AMOUNT}msat"]).decode('utf-8').strip()
520+
521+
ret = l1.rpc.xpay(invstring=inv, maxfee=maxfee)
522+
fee = ret['amount_sent_msat'] - ret['amount_msat']
523+
assert fee <= maxfee

tools/gen/impl_template

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ ${i}
2424

2525
const char *${enum_set['name']}_name(int e)
2626
{
27-
static char invalidbuf[sizeof("INVALID ") + STR_MAX_CHARS(e)];
27+
static char invalidbuf[sizeof("UNKNOWN ") + STR_MAX_CHARS(e)];
2828

2929
switch ((enum ${enum_set['name']})e) {
3030
% for msg in enum_set['set']:
3131
case ${msg.enum_name()}: return "${msg.enum_name()}";
3232
% endfor
3333
}
3434

35-
snprintf(invalidbuf, sizeof(invalidbuf), "INVALID %i", e);
35+
snprintf(invalidbuf, sizeof(invalidbuf), "UNKNOWN %i", e);
3636
return invalidbuf;
3737
}
3838

0 commit comments

Comments
 (0)