setchannel: don't let them advertize htlc_maximum_msat larger than capacity.

And check for the obvious setting min > max.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2022-03-21 11:28:57 +10:30
parent 999c734bb5
commit 5704653d4c
5 changed files with 40 additions and 4 deletions

View file

@ -71,6 +71,7 @@ On success, an object containing **channels** is returned. It is an array of ob
- **short_channel_id** (short_channel_id, optional): the short_channel_id (if locked in) - **short_channel_id** (short_channel_id, optional): the short_channel_id (if locked in)
- the following warnings are possible: - the following warnings are possible:
- **warning_htlcmin_too_low**: The requested htlcmin was too low for this peer, so we set it to the minimum they will allow - **warning_htlcmin_too_low**: The requested htlcmin was too low for this peer, so we set it to the minimum they will allow
- **warning_htlcmax_too_high**: The requested htlcmax was greater than the channel capacity, so we set it to the channel capacity
[comment]: # (GENERATE-FROM-SCHEMA-END) [comment]: # (GENERATE-FROM-SCHEMA-END)
@ -100,4 +101,4 @@ RESOURCES
Main web site: <https://github.com/ElementsProject/lightning> Main web site: <https://github.com/ElementsProject/lightning>
[comment]: # ( SHA256STAMP:0f153e7dddce61bc921b3743472f11316c5984b9b1459cac1b201d6f51ec1be1) [comment]: # ( SHA256STAMP:a38b5ea12566d9e40eab07b95a90007bf66373ac1189f458d1678634522575b3)

View file

@ -54,6 +54,10 @@
"maximum_htlc_out_msat": { "maximum_htlc_out_msat": {
"type": "msat", "type": "msat",
"description": "The resulting htlcmax we will advertize (the BOLT #7 name is htlc_maximum_msat)" "description": "The resulting htlcmax we will advertize (the BOLT #7 name is htlc_maximum_msat)"
},
"warning_htlcmax_too_high": {
"type": "string",
"description": "The requested htlcmax was greater than the channel capacity, so we set it to the channel capacity"
} }
} }
} }

View file

@ -2019,7 +2019,7 @@ static void set_channel_config(struct command *cmd, struct channel *channel,
struct json_stream *response, struct json_stream *response,
bool add_details) bool add_details)
{ {
bool warn_cannot_set_min = false; bool warn_cannot_set_min = false, warn_cannot_set_max = false;
/* We only need to defer values if we *increase* fees (or drop /* We only need to defer values if we *increase* fees (or drop
* max, increase min); we always allow users to overpay fees. */ * max, increase min); we always allow users to overpay fees. */
@ -2053,8 +2053,17 @@ static void set_channel_config(struct command *cmd, struct channel *channel,
} else } else
channel->htlc_minimum_msat = *htlc_min; channel->htlc_minimum_msat = *htlc_min;
} }
if (htlc_max) if (htlc_max) {
channel->htlc_maximum_msat = *htlc_max; struct amount_msat actual_max;
/* Can't set it greater than actual capacity. */
actual_max = htlc_max_possible_send(channel);
if (amount_msat_greater(*htlc_max, actual_max)) {
warn_cannot_set_max = true;
channel->htlc_maximum_msat = actual_max;
} else
channel->htlc_maximum_msat = *htlc_max;
}
/* tell channeld to make a send_channel_update */ /* tell channeld to make a send_channel_update */
if (channel->owner && streq(channel->owner->name, "channeld")) if (channel->owner && streq(channel->owner->name, "channeld"))
@ -2088,6 +2097,9 @@ static void set_channel_config(struct command *cmd, struct channel *channel,
json_add_amount_msat_only(response, json_add_amount_msat_only(response,
"maximum_htlc_out_msat", "maximum_htlc_out_msat",
channel->htlc_maximum_msat); channel->htlc_maximum_msat);
if (warn_cannot_set_max)
json_add_string(response, "warning_htlcmax_too_high",
"Set maximum_htlc_out_msat to maximum possible in channel");
} }
json_object_end(response); json_object_end(response);
} }
@ -2188,6 +2200,13 @@ static struct command_result *json_setchannel(struct command *cmd,
NULL)) NULL))
return command_param_failed(); return command_param_failed();
/* Prevent obviously incorrect things! */
if (htlc_min && htlc_max
&& amount_msat_less(*htlc_max, *htlc_min)) {
return command_fail(cmd, LIGHTNINGD,
"htlcmax cannot be less than htlcmin");
}
if (channel if (channel
&& channel->state != CHANNELD_NORMAL && channel->state != CHANNELD_NORMAL
&& channel->state != CHANNELD_AWAITING_LOCKIN && channel->state != CHANNELD_AWAITING_LOCKIN

View file

@ -247,6 +247,9 @@ bool htlc_is_trimmed(enum side htlc_owner UNNEEDED,
enum side side UNNEEDED, enum side side UNNEEDED,
bool option_anchor_outputs UNNEEDED) bool option_anchor_outputs UNNEEDED)
{ fprintf(stderr, "htlc_is_trimmed called!\n"); abort(); } { fprintf(stderr, "htlc_is_trimmed called!\n"); abort(); }
/* Generated stub for htlc_max_possible_send */
struct amount_msat htlc_max_possible_send(const struct channel *channel UNNEEDED)
{ fprintf(stderr, "htlc_max_possible_send called!\n"); abort(); }
/* Generated stub for htlc_set_fail */ /* Generated stub for htlc_set_fail */
void htlc_set_fail(struct htlc_set *set UNNEEDED, const u8 *failmsg TAKES UNNEEDED) void htlc_set_fail(struct htlc_set *set UNNEEDED, const u8 *failmsg TAKES UNNEEDED)
{ fprintf(stderr, "htlc_set_fail called!\n"); abort(); } { fprintf(stderr, "htlc_set_fail called!\n"); abort(); }

View file

@ -2213,6 +2213,7 @@ def test_setchannel_zero(node_factory, bitcoind):
# - payment can be done using zero fees # - payment can be done using zero fees
DEF_BASE = 1 DEF_BASE = 1
DEF_PPM = 10 DEF_PPM = 10
MAX_HTLC = Millisatoshi(int(FUNDAMOUNT * 1000 * 0.99))
l1, l2, l3 = node_factory.line_graph( l1, l2, l3 = node_factory.line_graph(
3, announce_channels=True, wait_for_announce=True, 3, announce_channels=True, wait_for_announce=True,
@ -2242,6 +2243,14 @@ def test_setchannel_zero(node_factory, bitcoind):
assert result['status'] == 'complete' assert result['status'] == 'complete'
assert result['msatoshi_sent'] == 4999999 assert result['msatoshi_sent'] == 4999999
# FIXME: hack something up to advertize min_htlc > 0, then test mintoolow.
with pytest.raises(RpcError, match="htlcmax cannot be less than htlcmin"):
l2.rpc.setchannel(scid, htlcmin=100000, htlcmax=99999)
ret = l2.rpc.setchannel(scid, htlcmax=FUNDAMOUNT * 1000)
assert 'warning_htlcmax_too_high' in only_one(ret['channels'])
assert only_one(ret['channels'])['maximum_htlc_out_msat'] == MAX_HTLC
@pytest.mark.developer("gossip without DEVELOPER=1 is slow") @pytest.mark.developer("gossip without DEVELOPER=1 is slow")
def test_setchannel_restart(node_factory, bitcoind): def test_setchannel_restart(node_factory, bitcoind):