diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index 0b896bbfc..722d0db8e 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -1409,6 +1409,24 @@ err_extracted: return daemon_conn_read_next(conn, daemon->master); } +static struct io_plan *handle_new_lease_rates(struct io_conn *conn, + struct daemon *daemon, + const u8 *msg) +{ + struct lease_rates *rates = tal(daemon, struct lease_rates); + + if (!fromwire_gossipd_new_lease_rates(msg, rates)) + master_badmsg(WIRE_GOSSIPD_NEW_LEASE_RATES, msg); + + tal_free(daemon->rates); + daemon->rates = rates; + + /* Send the update over to the peer */ + maybe_send_own_node_announce(daemon, false); + + return daemon_conn_read_next(conn, daemon->master); +} + /*~ This is where lightningd tells us that a channel's funding transaction has * been spent. */ static struct io_plan *handle_outpoint_spent(struct io_conn *conn, @@ -1496,6 +1514,9 @@ static struct io_plan *recv_req(struct io_conn *conn, case WIRE_GOSSIPD_ADDGOSSIP: return inject_gossip(conn, daemon, msg); + case WIRE_GOSSIPD_NEW_LEASE_RATES: + return handle_new_lease_rates(conn, daemon, msg); + #if DEVELOPER case WIRE_GOSSIPD_DEV_SET_MAX_SCIDS_ENCODE_SIZE: return dev_set_max_scids_encode_size(conn, daemon, msg); diff --git a/gossipd/gossipd_wire.csv b/gossipd/gossipd_wire.csv index 2dbd2b224..1f41189a5 100644 --- a/gossipd/gossipd_wire.csv +++ b/gossipd/gossipd_wire.csv @@ -1,6 +1,7 @@ #include #include #include +#include #include # Initialize the gossip daemon. @@ -118,3 +119,6 @@ msgdata,gossipd_addgossip,msg,u8,len msgtype,gossipd_addgossip_reply,3144 msgdata,gossipd_addgossip_reply,err,wirestring, +# Updated lease rates available +msgtype,gossipd_new_lease_rates,3046 +msgdata,gossipd_new_lease_rates,rates,lease_rates, diff --git a/gossipd/gossipd_wiregen.c b/gossipd/gossipd_wiregen.c index c54ac4b88..08d364955 100644 --- a/gossipd/gossipd_wiregen.c +++ b/gossipd/gossipd_wiregen.c @@ -43,6 +43,7 @@ const char *gossipd_wire_name(int e) case WIRE_GOSSIPD_SEND_ONIONMSG: return "WIRE_GOSSIPD_SEND_ONIONMSG"; case WIRE_GOSSIPD_ADDGOSSIP: return "WIRE_GOSSIPD_ADDGOSSIP"; case WIRE_GOSSIPD_ADDGOSSIP_REPLY: return "WIRE_GOSSIPD_ADDGOSSIP_REPLY"; + case WIRE_GOSSIPD_NEW_LEASE_RATES: return "WIRE_GOSSIPD_NEW_LEASE_RATES"; } snprintf(invalidbuf, sizeof(invalidbuf), "INVALID %i", e); @@ -75,6 +76,7 @@ bool gossipd_wire_is_defined(u16 type) case WIRE_GOSSIPD_SEND_ONIONMSG:; case WIRE_GOSSIPD_ADDGOSSIP:; case WIRE_GOSSIPD_ADDGOSSIP_REPLY:; + case WIRE_GOSSIPD_NEW_LEASE_RATES:; return true; } return false; @@ -753,4 +755,26 @@ bool fromwire_gossipd_addgossip_reply(const tal_t *ctx, const void *p, wirestrin *err = fromwire_wirestring(ctx, &cursor, &plen); return cursor != NULL; } -// SHA256STAMP:9b38d439d81bbd471c821163b275c5cf3106a665dbdea563113742476f18e386 + +/* WIRE: GOSSIPD_NEW_LEASE_RATES */ +/* Updated lease rates available */ +u8 *towire_gossipd_new_lease_rates(const tal_t *ctx, const struct lease_rates *rates) +{ + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_GOSSIPD_NEW_LEASE_RATES); + towire_lease_rates(&p, rates); + + return memcheck(p, tal_count(p)); +} +bool fromwire_gossipd_new_lease_rates(const void *p, struct lease_rates *rates) +{ + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_GOSSIPD_NEW_LEASE_RATES) + return false; + fromwire_lease_rates(&cursor, &plen, rates); + return cursor != NULL; +} +// SHA256STAMP:c511c2859bffa718708c4cceedd59807d0a43cd48060a59bf7cbabfa2f6515f9 diff --git a/gossipd/gossipd_wiregen.h b/gossipd/gossipd_wiregen.h index c393c1448..f1c39c19e 100644 --- a/gossipd/gossipd_wiregen.h +++ b/gossipd/gossipd_wiregen.h @@ -10,6 +10,7 @@ #include #include #include +#include #include enum gossipd_wire { @@ -54,6 +55,8 @@ enum gossipd_wire { WIRE_GOSSIPD_ADDGOSSIP = 3044, /* Empty string means no problem. */ WIRE_GOSSIPD_ADDGOSSIP_REPLY = 3144, + /* Updated lease rates available */ + WIRE_GOSSIPD_NEW_LEASE_RATES = 3046, }; const char *gossipd_wire_name(int e); @@ -178,6 +181,11 @@ bool fromwire_gossipd_addgossip(const tal_t *ctx, const void *p, u8 **msg); u8 *towire_gossipd_addgossip_reply(const tal_t *ctx, const wirestring *err); bool fromwire_gossipd_addgossip_reply(const tal_t *ctx, const void *p, wirestring **err); +/* WIRE: GOSSIPD_NEW_LEASE_RATES */ +/* Updated lease rates available */ +u8 *towire_gossipd_new_lease_rates(const tal_t *ctx, const struct lease_rates *rates); +bool fromwire_gossipd_new_lease_rates(const void *p, struct lease_rates *rates); + #endif /* LIGHTNING_GOSSIPD_GOSSIPD_WIREGEN_H */ -// SHA256STAMP:9b38d439d81bbd471c821163b275c5cf3106a665dbdea563113742476f18e386 +// SHA256STAMP:c511c2859bffa718708c4cceedd59807d0a43cd48060a59bf7cbabfa2f6515f9 diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 1b2fd6a70..acb0e851c 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -138,6 +138,7 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) case WIRE_GOSSIPD_GET_STRIPPED_CUPDATE: case WIRE_GOSSIPD_GET_TXOUT_REPLY: case WIRE_GOSSIPD_OUTPOINT_SPENT: + case WIRE_GOSSIPD_NEW_LEASE_RATES: case WIRE_GOSSIPD_DEV_SET_MAX_SCIDS_ENCODE_SIZE: case WIRE_GOSSIPD_DEV_SUPPRESS: case WIRE_GOSSIPD_LOCAL_CHANNEL_CLOSE: @@ -243,6 +244,74 @@ void gossipd_notify_spend(struct lightningd *ld, subd_send_msg(ld->gossip, msg); } +static struct command_result *json_setleaserates(struct command *cmd, + const char *buffer, + const jsmntok_t *obj UNNEEDED, + const jsmntok_t *params) +{ + struct json_stream *res; + struct lease_rates *rates; + struct amount_sat *lease_base_sat; + struct amount_msat *channel_fee_base_msat; + u32 *lease_basis, *channel_fee_max_ppt, *funding_weight; + + if (!param(cmd, buffer, params, + p_req("lease_fee_base_msat", param_sat, &lease_base_sat), + p_req("lease_fee_basis", param_number, &lease_basis), + p_req("funding_weight", param_number, &funding_weight), + p_req("channel_fee_max_base_msat", param_msat, + &channel_fee_base_msat), + p_req("channel_fee_max_proportional_thousandths", + param_number, &channel_fee_max_ppt), + NULL)) + return command_param_failed(); + + rates = tal(tmpctx, struct lease_rates); + rates->lease_fee_basis = *lease_basis; + rates->lease_fee_base_sat = lease_base_sat->satoshis; /* Raw: conversion */ + rates->channel_fee_max_base_msat = channel_fee_base_msat->millisatoshis; /* Raw: conversion */ + + rates->funding_weight = *funding_weight; + rates->channel_fee_max_proportional_thousandths + = *channel_fee_max_ppt; + + /* Gotta check that we didn't overflow */ + if (lease_base_sat->satoshis > rates->lease_fee_base_sat) /* Raw: comparison */ + return command_fail_badparam(cmd, "lease_fee_base_msat", + buffer, params, "Overflow"); + + if (channel_fee_base_msat->millisatoshis > rates->channel_fee_max_base_msat) /* Raw: comparison */ + return command_fail_badparam(cmd, "channel_fee_max_base_msat", + buffer, params, "Overflow"); + + /* Call gossipd, let them know we've got new rates */ + subd_send_msg(cmd->ld->gossip, + take(towire_gossipd_new_lease_rates(NULL, rates))); + + res = json_stream_success(cmd); + json_add_amount_sat_only(res, "lease_fee_base_msat", + amount_sat(rates->lease_fee_base_sat)); + json_add_num(res, "lease_fee_basis", rates->lease_fee_basis); + json_add_num(res, "funding_weight", rates->funding_weight); + json_add_amount_msat_only(res, "channel_fee_max_base_msat", + amount_msat(rates->channel_fee_max_base_msat)); + json_add_num(res, "channel_fee_max_proportional_thousandths", + rates->channel_fee_max_proportional_thousandths); + + return command_success(cmd, res); +} + +static const struct json_command setleaserates_command = { + "setleaserates", + "channels", + json_setleaserates, + "Called by plugin to set the node's present channel lease rates." + " Not to be set without having a plugin which can handle" + " `openchannel2` hooks.", +}; + +AUTODATA(json_command, &setleaserates_command); + /* Called upon receiving a addgossip_reply from `gossipd` */ static void json_addgossip_reply(struct subd *gossip UNUSED, const u8 *reply, const int *fds UNUSED, diff --git a/tests/test_gossip.py b/tests/test_gossip.py index d4bf19b20..37ffb42f6 100644 --- a/tests/test_gossip.py +++ b/tests/test_gossip.py @@ -1095,6 +1095,28 @@ def test_node_reannounce(node_factory, bitcoind, chainparams): # Won't have queued up another one, either. assert not l1.daemon.is_in_log('node_announcement: delaying') + # Try updating the lease rates ad + ad = l1.rpc.call('setleaserates', + {'lease_fee_base_msat': '1000sat', + 'lease_fee_basis': 20, + 'funding_weight': 150, + 'channel_fee_max_base_msat': '2000msat', + 'channel_fee_max_proportional_thousandths': 22}) + + assert ad['lease_fee_base_msat'] == Millisatoshi('1000000msat') + assert ad['lease_fee_basis'] == 20 + assert ad['funding_weight'] == 150 + assert ad['channel_fee_max_base_msat'] == Millisatoshi('2000msat') + assert ad['channel_fee_max_proportional_thousandths'] == 22 + + msgs2 = l1.query_gossip('gossip_timestamp_filter', + genesis_blockhash, + '0', '0xFFFFFFFF', + # Filter out gossip_timestamp_filter, + # channel_announcement and channel_updates. + filters=['0109', '0102', '0100']) + assert msgs != msgs2 + def test_gossipwith(node_factory): l1, l2 = node_factory.line_graph(2, wait_for_announce=True)