diff --git a/doc/lightningd-config.5.md b/doc/lightningd-config.5.md index aaa3e8fb8bc7..ba69bae4ee2b 100644 --- a/doc/lightningd-config.5.md +++ b/doc/lightningd-config.5.md @@ -415,9 +415,21 @@ RPC call lightning-setchannel(7). * **htlc-maximum-msat**=*MILLISATOSHI* - Default: unset (no limit). Sets the maximum allowed HTLC value for newly created -channels. If you want to change the `htlc_maximum_msat` for existing channels, -use the RPC call lightning-setchannel(7). + Sets the maximum allowed HTLC value for newly created channels. If unset +(the default), public channels advertise 25% of the channel capacity: a +maximum well below the publicly-known capacity makes it harder to probe for +where payments are flowing. Private channels, whose capacity is not public, +advertise the full amount they can send. Either way this is capped at what we +can actually send, and an explicit value here overrides the default (up to +that cap). If you want to change the `htlc_maximum_msat` for existing +channels, use the RPC call lightning-setchannel(7), for example: + + lightning-cli listpeerchannels | \ + jq -r '.channels[] | select(.private == false and .short_channel_id) | + "\(.short_channel_id) \((.total_msat // 0) / 4 | floor)"' | \ + while read scid max; do + lightning-cli setchannel "$scid" htlcmax="${max}msat" + done * **announce-addr-discovered**=*BOOL* diff --git a/lightningd/channel.c b/lightningd/channel.c index 1cd40871ed2d..e2868fd4a588 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -489,6 +489,34 @@ struct amount_msat htlc_max_possible_send(const struct channel *channel) return lower_bound_msat; } +struct amount_msat channel_htlc_maximum_default(const struct channel *channel, + struct amount_msat configured_max) +{ + struct amount_msat cap = htlc_max_possible_send(channel); + struct amount_msat deflt; + + /* If the operator set --htlc-maximum-msat, honour it (the sentinel + * AMOUNT_MSAT(-1ULL) means "unset"). Otherwise pick a default. */ + if (!amount_msat_eq(configured_max, AMOUNT_MSAT(-1ULL))) + deflt = configured_max; + else if (channel->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL) { + /* Oakland privacy proposal (Lightning Dev Summit): probing for + * where payments went is much harder if the htlc maximum is + * well below the channel capacity. For public channels the + * capacity is known from the funding output, so default to 25% + * of it. The spec only requires htlc_maximum_msat <= capacity. */ + if (!amount_sat_to_msat(&deflt, channel->funding_sats)) + return cap; + deflt = amount_msat_div(deflt, 4); + } else + /* Private channels have no publicly-known capacity to correlate + * against, so we advertise the full amount we can send. */ + deflt = cap; + + /* Never advertise more than we could actually send. */ + return amount_msat_min(deflt, cap); +} + struct channel *new_channel(struct peer *peer, u64 dbid, /* NULL or stolen */ struct wallet_shachain *their_shachain, @@ -567,7 +595,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, bool withheld) { struct channel *channel = tal(peer->ld, struct channel); - struct amount_msat htlc_min, htlc_max; + struct amount_msat htlc_min; bool anysegwit = !chainparams->is_elements && feature_negotiated(peer->ld->our_features, peer->their_features, @@ -694,11 +722,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid, channel->htlc_minimum_msat = htlc_min; else channel->htlc_minimum_msat = htlc_minimum_msat; - htlc_max = htlc_max_possible_send(channel); - if (amount_msat_less(htlc_max, htlc_maximum_msat)) - channel->htlc_maximum_msat = htlc_max; - else - channel->htlc_maximum_msat = htlc_maximum_msat; + channel->htlc_maximum_msat = channel_htlc_maximum_default(channel, + htlc_maximum_msat); list_add_tail(&peer->channels, &channel->list); channel->rr_number = peer->ld->rr_counter++; @@ -1338,4 +1363,3 @@ const u8 *channel_update_for_error(const tal_t *ctx, return channel_gossip_update_for_error(ctx, channel); } - diff --git a/lightningd/channel.h b/lightningd/channel.h index 46add63f51a4..9ad927907451 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -972,6 +972,13 @@ const u8 *channel_update_for_error(const tal_t *ctx, struct amount_msat htlc_max_possible_send(const struct channel *channel); +/* Default htlc_maximum_msat to advertise for a new channel, given the + * configured --htlc-maximum-msat (AMOUNT_MSAT(-1ULL) if unset). Public + * channels default to 25% of capacity for privacy; private channels and an + * explicit setting use the full amount, all capped at what we can send. */ +struct amount_msat channel_htlc_maximum_default(const struct channel *channel, + struct amount_msat configured_max); + /* Given features, what channel_type do we want? */ struct channel_type *desired_channel_type(const tal_t *ctx, const struct feature_set *our_features, diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c index 7c440e59098b..cf3c0b81c81d 100644 --- a/lightningd/dual_open_control.c +++ b/lightningd/dual_open_control.c @@ -1255,7 +1255,8 @@ wallet_update_channel(struct lightningd *ld, channel->msat_to_us_max = our_msat; channel->lease_expiry = lease_expiry; channel->htlc_minimum_msat = channel->channel_info.their_config.htlc_minimum; - channel->htlc_maximum_msat = htlc_max_possible_send(channel); + channel->htlc_maximum_msat = channel_htlc_maximum_default(channel, + ld->config.htlc_maximum_msat); tal_free(channel->lease_commit_sig); channel->lease_commit_sig = tal_steal(channel, lease_commit_sig); @@ -1486,7 +1487,8 @@ wallet_commit_channel(struct lightningd *ld, channel->lease_chan_max_msat = lease_chan_max_msat; channel->lease_chan_max_ppt = lease_chan_max_ppt; channel->htlc_minimum_msat = channel_info->their_config.htlc_minimum; - channel->htlc_maximum_msat = htlc_max_possible_send(channel); + channel->htlc_maximum_msat = channel_htlc_maximum_default(channel, + ld->config.htlc_maximum_msat); /* Filled in when we have PSBT for inflight */ channel->funding_psbt = NULL; diff --git a/tests/test_pay.py b/tests/test_pay.py index 0f357547ae76..d47cb02a434b 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -2042,8 +2042,8 @@ def test_setchannel_usage(node_factory, bitcoind): DEF_BASE = 10 DEF_BASE_MSAT = Millisatoshi(DEF_BASE) DEF_PPM = 100 - # Minus reserve - MAX_HTLC = Millisatoshi(int(FUNDAMOUNT * 1000 * 0.99)) + # Public channels default htlc_maximum_msat to 25% of capacity. + MAX_HTLC = Millisatoshi(int(FUNDAMOUNT * 1000 * 0.25)) l1, l2, l3 = node_factory.get_nodes(3, opts={'fee-base': DEF_BASE, 'fee-per-satoshi': DEF_PPM}) @@ -2279,7 +2279,8 @@ def test_setchannel_routing(node_factory, bitcoind): # - htlc max is honored DEF_BASE = 1 DEF_PPM = 10 - MAX_HTLC = Millisatoshi(int(FUNDAMOUNT * 1000 * 0.99)) + # Public channels default htlc_maximum_msat to 25% of capacity. + MAX_HTLC = Millisatoshi(int(FUNDAMOUNT * 1000 * 0.25)) MIN_HTLC = Millisatoshi(0) l1, l2, l3 = node_factory.line_graph( @@ -2391,6 +2392,8 @@ def test_setchannel_zero(node_factory, bitcoind): # - payment can be done using zero fees DEF_BASE = 1 DEF_PPM = 10 + # This is the cap (capacity minus reserve) that setchannel clamps to, + # not the default: below we try to set htlcmax above it. MAX_HTLC = Millisatoshi(int(FUNDAMOUNT * 1000 * 0.99)) l1, l2, l3 = node_factory.line_graph( @@ -2442,7 +2445,8 @@ def test_setchannel_restart(node_factory, bitcoind): DEF_BASE = 1 DEF_PPM = 10 MIN_HTLC = Millisatoshi(0) - MAX_HTLC = Millisatoshi(int(FUNDAMOUNT * 1000 * 0.99)) + # Public channels default htlc_maximum_msat to 25% of capacity. + MAX_HTLC = Millisatoshi(int(FUNDAMOUNT * 1000 * 0.25)) OPTS = {'may_reconnect': True, 'fee-base': DEF_BASE, 'fee-per-satoshi': DEF_PPM} l1, l2, l3 = node_factory.line_graph(3, announce_channels=True, wait_for_announce=True, opts=OPTS)