mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 21:35:11 +01:00
BOLT7: broadcast htlc_maximum_msat
in `channel_update s
Have c-lightning nodes send out the largest value for `htlc_maximum_msat` that makes sense, ie the lesser of the peer's max_inflight_htlc value or the total channel capacity minus the total channel reserve.
This commit is contained in:
parent
e904fcc00c
commit
0ae1d03513
@ -60,6 +60,7 @@
|
||||
#define PEER_FD 3
|
||||
#define GOSSIP_FD 4
|
||||
#define HSM_FD 5
|
||||
#define min(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
struct commit_sigs {
|
||||
struct peer *peer;
|
||||
@ -227,6 +228,25 @@ static const u8 *hsm_req(const tal_t *ctx, const u8 *req TAKES)
|
||||
return msg;
|
||||
}
|
||||
|
||||
/*
|
||||
* The maximum msat that this node will accept for an htlc.
|
||||
* It's flagged as an optional field in `channel_update`.
|
||||
*
|
||||
* We advertise the maximum value possible, defined as the smaller
|
||||
* of the remote's maximum in-flight HTLC or the total channel
|
||||
* capacity minus the cumulative reserve.
|
||||
* FIXME: does this need fuzz?
|
||||
*/
|
||||
static const u64 advertised_htlc_max(const u64 funding_msat,
|
||||
const struct channel_config *our_config,
|
||||
const struct channel_config *remote_config)
|
||||
{
|
||||
u64 cumulative_reserve_msat = (our_config->channel_reserve_satoshis +
|
||||
remote_config->channel_reserve_satoshis) * 1000;
|
||||
return min(remote_config->max_htlc_value_in_flight_msat,
|
||||
funding_msat - cumulative_reserve_msat);
|
||||
}
|
||||
|
||||
/* Create and send channel_update to gossipd (and maybe peer) */
|
||||
static void send_channel_update(struct peer *peer, int disable_flag)
|
||||
{
|
||||
@ -247,7 +267,11 @@ static void send_channel_update(struct peer *peer, int disable_flag)
|
||||
peer->cltv_delta,
|
||||
peer->conf[REMOTE].htlc_minimum_msat,
|
||||
peer->fee_base,
|
||||
peer->fee_per_satoshi);
|
||||
peer->fee_per_satoshi,
|
||||
advertised_htlc_max(
|
||||
peer->channel->funding_msat,
|
||||
&peer->conf[LOCAL],
|
||||
&peer->conf[REMOTE]));
|
||||
wire_sync_write(GOSSIP_FD, take(msg));
|
||||
}
|
||||
|
||||
@ -2306,7 +2330,6 @@ static void handle_offer_htlc(struct peer *peer, const u8 *inmsg)
|
||||
|
||||
/* FIXME: Fuzz the boundaries a bit to avoid probing? */
|
||||
case CHANNEL_ERR_MAX_HTLC_VALUE_EXCEEDED:
|
||||
/* FIXME: We should advertise this? */
|
||||
failcode = WIRE_TEMPORARY_CHANNEL_FAILURE;
|
||||
failmsg = tal_fmt(inmsg, "Maximum value exceeded");
|
||||
goto failed;
|
||||
|
@ -130,6 +130,7 @@ gossip_local_channel_update,,cltv_expiry_delta,u16
|
||||
gossip_local_channel_update,,htlc_minimum_msat,u64
|
||||
gossip_local_channel_update,,fee_base_msat,u32
|
||||
gossip_local_channel_update,,fee_proportional_millionths,u32
|
||||
gossip_local_channel_update,,htlc_maximum_msat,u64
|
||||
|
||||
gossip_local_channel_close,3027
|
||||
gossip_local_channel_close,,short_channel_id,struct short_channel_id
|
||||
|
|
@ -942,6 +942,7 @@ static void update_local_channel(struct daemon *daemon,
|
||||
u64 htlc_minimum_msat,
|
||||
u32 fee_base_msat,
|
||||
u32 fee_proportional_millionths,
|
||||
u64 htlc_maximum_msat,
|
||||
const char *caller)
|
||||
{
|
||||
secp256k1_ecdsa_signature dummy_sig;
|
||||
@ -949,10 +950,6 @@ static void update_local_channel(struct daemon *daemon,
|
||||
u32 timestamp = time_now().ts.tv_sec;
|
||||
u8 message_flags, channel_flags;
|
||||
|
||||
/* `message_flags` are optional.
|
||||
* Currently, not set by c-lightning */
|
||||
message_flags = 0;
|
||||
|
||||
/* So valgrind doesn't complain */
|
||||
memset(&dummy_sig, 0, sizeof(dummy_sig));
|
||||
|
||||
@ -965,7 +962,10 @@ static void update_local_channel(struct daemon *daemon,
|
||||
if (disable)
|
||||
channel_flags |= ROUTING_FLAGS_DISABLED;
|
||||
|
||||
update = towire_channel_update(tmpctx, &dummy_sig,
|
||||
// We set the htlc_maximum_msat value
|
||||
message_flags = 0 | ROUTING_OPT_HTLC_MAX_MSAT;
|
||||
|
||||
update = towire_channel_update_option_channel_htlc_max(tmpctx, &dummy_sig,
|
||||
&daemon->rstate->chain_hash,
|
||||
&chan->scid,
|
||||
timestamp,
|
||||
@ -973,7 +973,8 @@ static void update_local_channel(struct daemon *daemon,
|
||||
cltv_expiry_delta,
|
||||
htlc_minimum_msat,
|
||||
fee_base_msat,
|
||||
fee_proportional_millionths);
|
||||
fee_proportional_millionths,
|
||||
htlc_maximum_msat);
|
||||
|
||||
if (!wire_sync_write(HSM_FD,
|
||||
towire_hsm_cupdate_sig_req(tmpctx, update))) {
|
||||
@ -1026,6 +1027,7 @@ static void maybe_update_local_channel(struct daemon *daemon,
|
||||
hc->htlc_minimum_msat,
|
||||
hc->base_fee,
|
||||
hc->proportional_fee,
|
||||
hc->htlc_maximum_msat,
|
||||
__func__);
|
||||
}
|
||||
|
||||
@ -1093,7 +1095,8 @@ out:
|
||||
/* Return true if the information has changed. */
|
||||
static bool halfchan_new_info(const struct half_chan *hc,
|
||||
u16 cltv_delta, u64 htlc_minimum_msat,
|
||||
u32 fee_base_msat, u32 fee_proportional_millionths)
|
||||
u32 fee_base_msat, u32 fee_proportional_millionths,
|
||||
u64 htlc_maximum_msat)
|
||||
{
|
||||
if (!is_halfchan_defined(hc))
|
||||
return true;
|
||||
@ -1101,7 +1104,8 @@ static bool halfchan_new_info(const struct half_chan *hc,
|
||||
return hc->delay != cltv_delta
|
||||
|| hc->htlc_minimum_msat != htlc_minimum_msat
|
||||
|| hc->base_fee != fee_base_msat
|
||||
|| hc->proportional_fee != fee_proportional_millionths;
|
||||
|| hc->proportional_fee != fee_proportional_millionths
|
||||
|| hc->htlc_maximum_msat != htlc_maximum_msat;
|
||||
}
|
||||
|
||||
static void handle_local_channel_update(struct peer *peer, const u8 *msg)
|
||||
@ -1111,6 +1115,7 @@ static void handle_local_channel_update(struct peer *peer, const u8 *msg)
|
||||
bool disable;
|
||||
u16 cltv_expiry_delta;
|
||||
u64 htlc_minimum_msat;
|
||||
u64 htlc_maximum_msat;
|
||||
u32 fee_base_msat;
|
||||
u32 fee_proportional_millionths;
|
||||
int direction;
|
||||
@ -1121,7 +1126,8 @@ static void handle_local_channel_update(struct peer *peer, const u8 *msg)
|
||||
&cltv_expiry_delta,
|
||||
&htlc_minimum_msat,
|
||||
&fee_base_msat,
|
||||
&fee_proportional_millionths)) {
|
||||
&fee_proportional_millionths,
|
||||
&htlc_maximum_msat)) {
|
||||
status_broken("peer %s bad local_channel_update %s",
|
||||
type_to_string(tmpctx, struct pubkey, &peer->id),
|
||||
tal_hex(tmpctx, msg));
|
||||
@ -1151,7 +1157,8 @@ static void handle_local_channel_update(struct peer *peer, const u8 *msg)
|
||||
* Or, if it's an unannounced channel (only sending to peer). */
|
||||
if (halfchan_new_info(&chan->half[direction],
|
||||
cltv_expiry_delta, htlc_minimum_msat,
|
||||
fee_base_msat, fee_proportional_millionths)
|
||||
fee_base_msat, fee_proportional_millionths,
|
||||
htlc_maximum_msat)
|
||||
|| ((chan->half[direction].channel_flags & ROUTING_FLAGS_DISABLED)
|
||||
&& !disable)
|
||||
|| !is_chan_public(chan)) {
|
||||
@ -1161,6 +1168,7 @@ static void handle_local_channel_update(struct peer *peer, const u8 *msg)
|
||||
htlc_minimum_msat,
|
||||
fee_base_msat,
|
||||
fee_proportional_millionths,
|
||||
htlc_maximum_msat,
|
||||
__func__);
|
||||
}
|
||||
|
||||
@ -1748,6 +1756,7 @@ static void gossip_send_keepalive_update(struct daemon *daemon,
|
||||
hc->htlc_minimum_msat,
|
||||
hc->base_fee,
|
||||
hc->proportional_fee,
|
||||
hc->htlc_maximum_msat,
|
||||
__func__);
|
||||
}
|
||||
|
||||
|
15
hsmd/hsmd.c
15
hsmd/hsmd.c
@ -653,6 +653,7 @@ static struct io_plan *handle_channel_update_sig(struct io_conn *conn,
|
||||
struct short_channel_id scid;
|
||||
u32 timestamp, fee_base_msat, fee_proportional_mill;
|
||||
u64 htlc_minimum_msat;
|
||||
u64 htlc_maximum_msat;
|
||||
u8 message_flags, channel_flags;
|
||||
u16 cltv_expiry_delta;
|
||||
struct bitcoin_blkid chain_hash;
|
||||
@ -661,10 +662,11 @@ static struct io_plan *handle_channel_update_sig(struct io_conn *conn,
|
||||
if (!fromwire_hsm_cupdate_sig_req(tmpctx, msg_in, &cu))
|
||||
return bad_req(conn, c, msg_in);
|
||||
|
||||
if (!fromwire_channel_update(cu, &sig, &chain_hash,
|
||||
&scid, ×tamp, &message_flags, &channel_flags,
|
||||
&cltv_expiry_delta, &htlc_minimum_msat,
|
||||
&fee_base_msat, &fee_proportional_mill)) {
|
||||
if (!fromwire_channel_update_option_channel_htlc_max(cu, &sig,
|
||||
&chain_hash, &scid, ×tamp, &message_flags,
|
||||
&channel_flags, &cltv_expiry_delta,
|
||||
&htlc_minimum_msat, &fee_base_msat,
|
||||
&fee_proportional_mill, &htlc_maximum_msat)) {
|
||||
return bad_req_fmt(conn, c, msg_in, "Bad inner channel_update");
|
||||
}
|
||||
if (tal_count(cu) < offset)
|
||||
@ -676,10 +678,11 @@ static struct io_plan *handle_channel_update_sig(struct io_conn *conn,
|
||||
|
||||
sign_hash(&node_pkey, &hash, &sig);
|
||||
|
||||
cu = towire_channel_update(tmpctx, &sig, &chain_hash,
|
||||
cu = towire_channel_update_option_channel_htlc_max(tmpctx, &sig, &chain_hash,
|
||||
&scid, timestamp, message_flags, channel_flags,
|
||||
cltv_expiry_delta, htlc_minimum_msat,
|
||||
fee_base_msat, fee_proportional_mill);
|
||||
fee_base_msat, fee_proportional_mill,
|
||||
htlc_maximum_msat);
|
||||
return req_reply(conn, c, take(towire_hsm_cupdate_sig_reply(NULL, cu)));
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,7 @@ def test_pay_get_error_with_update(node_factory):
|
||||
# channel_update, and it should patch it to include a type prefix. The
|
||||
# prefix 0x0102 should be in the channel_update, but not in the
|
||||
# onionreply (negation of 0x0102 in the RE)
|
||||
l1.daemon.wait_for_log(r'Extracted channel_update 0102.*from onionreply 10070080(?!.*0102)')
|
||||
l1.daemon.wait_for_log(r'Extracted channel_update 0102.*from onionreply 10070088[0-9a-fA-F]{88}')
|
||||
|
||||
# And now monitor for l1 to apply the channel_update we just extracted
|
||||
l1.daemon.wait_for_log('Received channel_update for channel {}\(.\) now DISABLED was ACTIVE \(from error\)'.format(chanid2))
|
||||
|
Loading…
Reference in New Issue
Block a user