From 56ac5eebef5977c8c8052febf318befcada0f594 Mon Sep 17 00:00:00 2001 From: Lagrang3 Date: Mon, 18 Mar 2024 08:31:42 +0100 Subject: [PATCH] add more fields to gossmods_listpeerchannels Add spendable/receivable and is_local fields to the callback function used in gossmods_from_listpeerchannels. This allows to do more fine grained use of the listpeerchannels call. The first use case is renepay, for which we need to ignore the htlc_max of the local channels only. --- common/gossmods_listpeerchannels.c | 33 +++++++++++++++--------------- common/gossmods_listpeerchannels.h | 14 +++++++++---- plugins/renepay/pay.c | 30 ++++++++++++++++++++++----- plugins/test/run-route-calc.c | 12 +++++++---- plugins/test/run-route-overlong.c | 12 +++++++---- plugins/topology.c | 6 ++++-- tests/test_renepay.py | 11 ++++++++++ 7 files changed, 83 insertions(+), 35 deletions(-) diff --git a/common/gossmods_listpeerchannels.c b/common/gossmods_listpeerchannels.c index 731c63ae7..36a24bd6b 100644 --- a/common/gossmods_listpeerchannels.c +++ b/common/gossmods_listpeerchannels.c @@ -9,16 +9,23 @@ void gossmod_add_localchan(struct gossmap_localmods *mods, const struct node_id *self, const struct node_id *peer, const struct short_channel_id_dir *scidd, - struct amount_msat min, - struct amount_msat max, + struct amount_msat htlcmin, + struct amount_msat htlcmax, + struct amount_msat spendable, struct amount_msat fee_base, u32 fee_proportional, u32 cltv_delta, bool enabled, + bool is_local UNUSED, const char *buf UNUSED, const jsmntok_t *chantok UNUSED, void *cbarg UNUSED) { + struct amount_msat min = htlcmin, max = htlcmax; + + if (amount_msat_less(spendable, max)) + max = spendable; + /* FIXME: features? */ gossmap_local_addchan(mods, self, peer, scidd->scid, NULL); @@ -40,12 +47,14 @@ gossmods_from_listpeerchannels_(const tal_t *ctx, const struct node_id *self, const struct node_id *peer, const struct short_channel_id_dir *scidd, - struct amount_msat min, - struct amount_msat max, + struct amount_msat htlcmin, + struct amount_msat htlcmax, + struct amount_msat sr_able, struct amount_msat fee_base, u32 fee_proportional, u32 cltv_delta, bool enabled, + bool is_local, const char *buf, const jsmntok_t *chantok, void *cbarg), @@ -130,10 +139,6 @@ gossmods_from_listpeerchannels_(const tal_t *ctx, && !streq(state, "CHANNELD_AWAITING_SPLICE")) enabled = false; - /* Cut htlc max to spendable. */ - if (amount_msat_less(spendable, htlc_max[LOCAL])) - htlc_max[LOCAL] = spendable; - /* We route better if we know we won't charge * ourselves fees (though if fees are a signal on what * channel we prefer to use, this ignores that @@ -146,8 +151,8 @@ gossmods_from_listpeerchannels_(const tal_t *ctx, /* We add both directions */ cb(mods, self, &dst, &scidd, htlc_min[LOCAL], htlc_max[LOCAL], - fee_base[LOCAL], fee_proportional[LOCAL], cltv_delta[LOCAL], - enabled, buf, channel, cbarg); + spendable, fee_base[LOCAL], fee_proportional[LOCAL], + cltv_delta[LOCAL], enabled, true, buf, channel, cbarg); /* If we didn't have a remote update, it's not usable yet */ if (fee_proportional[REMOTE] == -1U) @@ -155,13 +160,9 @@ gossmods_from_listpeerchannels_(const tal_t *ctx, scidd.dir = !scidd.dir; - /* Cut htlc max to receivable. */ - if (amount_msat_less(receivable, htlc_max[REMOTE])) - htlc_max[REMOTE] = receivable; - cb(mods, self, &dst, &scidd, htlc_min[REMOTE], htlc_max[REMOTE], - fee_base[REMOTE], fee_proportional[REMOTE], cltv_delta[REMOTE], - enabled, buf, channel, cbarg); + receivable, fee_base[REMOTE], fee_proportional[REMOTE], + cltv_delta[REMOTE], enabled, false, buf, channel, cbarg); } return mods; diff --git a/common/gossmods_listpeerchannels.h b/common/gossmods_listpeerchannels.h index edabacc10..5b2a68b08 100644 --- a/common/gossmods_listpeerchannels.h +++ b/common/gossmods_listpeerchannels.h @@ -30,12 +30,14 @@ struct gossmap_localmods *gossmods_from_listpeerchannels_(const tal_t *ctx, const struct node_id *self_, const struct node_id *peer, const struct short_channel_id_dir *scidd, - struct amount_msat min, - struct amount_msat max, + struct amount_msat htlcmin, + struct amount_msat htlcmax, + struct amount_msat spendable, struct amount_msat fee_base, u32 fee_proportional, u32 cltv_delta, bool enabled, + bool is_local, const char *buf_, const jsmntok_t *chantok, void *cbarg_), @@ -51,9 +53,11 @@ struct gossmap_localmods *gossmods_from_listpeerchannels_(const tal_t *ctx, struct amount_msat, \ struct amount_msat, \ struct amount_msat, \ + struct amount_msat, \ u32, \ u32, \ bool, \ + bool, \ const char *, \ const jsmntok_t *), \ (cbarg)) @@ -63,12 +67,14 @@ void gossmod_add_localchan(struct gossmap_localmods *mods, const struct node_id *self, const struct node_id *peer, const struct short_channel_id_dir *scidd, - struct amount_msat min, - struct amount_msat max, + struct amount_msat htlcmin, + struct amount_msat htlcmax, + struct amount_msat spendable, struct amount_msat fee_base, u32 fee_proportional, u32 cltv_delta, bool enabled, + bool is_local, const char *buf UNUSED, const jsmntok_t *chantok UNUSED, void *cbarg UNUSED); diff --git a/plugins/renepay/pay.c b/plugins/renepay/pay.c index e20b3b0a8..3eb0ea4a1 100644 --- a/plugins/renepay/pay.c +++ b/plugins/renepay/pay.c @@ -458,19 +458,39 @@ static void gossmod_cb(struct gossmap_localmods *mods, const struct node_id *self, const struct node_id *peer, const struct short_channel_id_dir *scidd, - struct amount_msat min, - struct amount_msat max, + struct amount_msat htlcmin, + struct amount_msat htlcmax, + struct amount_msat spendable, struct amount_msat fee_base, u32 fee_proportional, u32 cltv_delta, bool enabled, + bool is_local, const char *buf, const jsmntok_t *chantok, struct payment *payment) { - /* Add to gossmap like normal */ - gossmod_add_localchan(mods, self, peer, scidd, min, max, - fee_base, fee_proportional, cltv_delta, enabled, buf, chantok, NULL); + struct amount_msat min, max; + + if (is_local) { + /* local channels can send up to what's spendable */ + min = AMOUNT_MSAT(0); + max = spendable; + } else { + /* remote channels can send up no more than spendable */ + min = htlcmin; + max = amount_msat_min(spendable, htlcmax); + } + + /* FIXME: features? */ + gossmap_local_addchan(mods, self, peer, &scidd->scid, NULL); + + gossmap_local_updatechan(mods, &scidd->scid, min, max, + fee_base.millisatoshis, /* Raw: gossmap */ + fee_proportional, + cltv_delta, + enabled, + scidd->dir); /* Also update uncertainty map */ uncertainty_network_update_from_listpeerchannels(payment, scidd, max, enabled, diff --git a/plugins/test/run-route-calc.c b/plugins/test/run-route-calc.c index a9d97c245..e4f8f710a 100644 --- a/plugins/test/run-route-calc.c +++ b/plugins/test/run-route-calc.c @@ -42,12 +42,14 @@ void gossmod_add_localchan(struct gossmap_localmods *mods UNNEEDED, const struct node_id *self UNNEEDED, const struct node_id *peer UNNEEDED, const struct short_channel_id_dir *scidd UNNEEDED, - struct amount_msat min UNNEEDED, - struct amount_msat max UNNEEDED, + struct amount_msat htlcmin UNNEEDED, + struct amount_msat htlcmax UNNEEDED, + struct amount_msat spendable UNNEEDED, struct amount_msat fee_base UNNEEDED, u32 fee_proportional UNNEEDED, u32 cltv_delta UNNEEDED, bool enabled UNNEEDED, + bool is_local UNNEEDED, const char *buf UNUSED UNNEEDED, const jsmntok_t *chantok UNUSED UNNEEDED, void *cbarg UNUSED UNNEEDED) @@ -62,12 +64,14 @@ struct gossmap_localmods *gossmods_from_listpeerchannels_(const tal_t *ctx UNNEE const struct node_id *self_ UNNEEDED, const struct node_id *peer UNNEEDED, const struct short_channel_id_dir *scidd UNNEEDED, - struct amount_msat min UNNEEDED, - struct amount_msat max UNNEEDED, + struct amount_msat htlcmin UNNEEDED, + struct amount_msat htlcmax UNNEEDED, + struct amount_msat spendable UNNEEDED, struct amount_msat fee_base UNNEEDED, u32 fee_proportional UNNEEDED, u32 cltv_delta UNNEEDED, bool enabled UNNEEDED, + bool is_local UNNEEDED, const char *buf_ UNNEEDED, const jsmntok_t *chantok UNNEEDED, void *cbarg_) UNNEEDED, diff --git a/plugins/test/run-route-overlong.c b/plugins/test/run-route-overlong.c index 39b743777..96d74ff43 100644 --- a/plugins/test/run-route-overlong.c +++ b/plugins/test/run-route-overlong.c @@ -39,12 +39,14 @@ void gossmod_add_localchan(struct gossmap_localmods *mods UNNEEDED, const struct node_id *self UNNEEDED, const struct node_id *peer UNNEEDED, const struct short_channel_id_dir *scidd UNNEEDED, - struct amount_msat min UNNEEDED, - struct amount_msat max UNNEEDED, + struct amount_msat htlcmin UNNEEDED, + struct amount_msat htlcmax UNNEEDED, + struct amount_msat spendable UNNEEDED, struct amount_msat fee_base UNNEEDED, u32 fee_proportional UNNEEDED, u32 cltv_delta UNNEEDED, bool enabled UNNEEDED, + bool is_local UNNEEDED, const char *buf UNUSED UNNEEDED, const jsmntok_t *chantok UNUSED UNNEEDED, void *cbarg UNUSED UNNEEDED) @@ -59,12 +61,14 @@ struct gossmap_localmods *gossmods_from_listpeerchannels_(const tal_t *ctx UNNEE const struct node_id *self_ UNNEEDED, const struct node_id *peer UNNEEDED, const struct short_channel_id_dir *scidd UNNEEDED, - struct amount_msat min UNNEEDED, - struct amount_msat max UNNEEDED, + struct amount_msat htlcmin UNNEEDED, + struct amount_msat htlcmax UNNEEDED, + struct amount_msat spendable UNNEEDED, struct amount_msat fee_base UNNEEDED, u32 fee_proportional UNNEEDED, u32 cltv_delta UNNEEDED, bool enabled UNNEEDED, + bool is_local UNNEEDED, const char *buf_ UNNEEDED, const jsmntok_t *chantok UNNEEDED, void *cbarg_) UNNEEDED, diff --git a/plugins/topology.c b/plugins/topology.c index f8593043e..14054324e 100644 --- a/plugins/topology.c +++ b/plugins/topology.c @@ -364,10 +364,12 @@ static void gossmod_add_unknown_localchan(struct gossmap_localmods *mods, const struct short_channel_id_dir *scidd, struct amount_msat min, struct amount_msat max, + struct amount_msat spendable, struct amount_msat fee_base, u32 fee_proportional, u32 cltv_delta, bool enabled, + bool is_local, const char *buf UNUSED, const jsmntok_t *chantok UNUSED, struct gossmap *gossmap) @@ -375,9 +377,9 @@ static void gossmod_add_unknown_localchan(struct gossmap_localmods *mods, if (gossmap_find_chan(gossmap, &scidd->scid)) return; - gossmod_add_localchan(mods, self, peer, scidd, min, max, + gossmod_add_localchan(mods, self, peer, scidd, min, max, spendable, fee_base, fee_proportional, cltv_delta, enabled, - buf, chantok, gossmap); + is_local, buf, chantok, gossmap); } /* FIXME: We don't need this listpeerchannels at all if not deprecated! */ diff --git a/tests/test_renepay.py b/tests/test_renepay.py index c5831885e..d223a039e 100644 --- a/tests/test_renepay.py +++ b/tests/test_renepay.py @@ -624,3 +624,14 @@ def test_fees(node_factory): source.rpc.call("renepay", {"invstring": invstr}) invoice = only_one(dest.rpc.listinvoices("inv2")["invoices"]) assert invoice["amount_received_msat"] == Millisatoshi("150000sat") + + +def test_local_htlcmax0(node_factory): + """Testing a simple pay route when local channels have htlcmax=0.""" + l1, l2, l3 = node_factory.line_graph(3, wait_for_announce=True) + l1.rpc.setchannel(l2.info["id"], htlcmax=0) + inv = l3.rpc.invoice(123000, "test_renepay", "description")["bolt11"] + details = l1.rpc.call("renepay", {"invstring": inv}) + assert details["status"] == "complete" + assert details["amount_msat"] == Millisatoshi(123000) + assert details["destination"] == l3.info["id"]