Skip to content

Commit

Permalink
topology: listincoming: remove dependence on private gossip_store data
Browse files Browse the repository at this point in the history
This allows the removal of private gossip from the gossip store, using
the channels db table instead to populate the listincoming private
channel entries.

Changelog-Changed: Note: Private channels in listincoming deprecated -removal in 24.08.
  • Loading branch information
endothermicdev committed Oct 12, 2023
1 parent cd39e2a commit 1cf8d43
Show file tree
Hide file tree
Showing 15 changed files with 918 additions and 89 deletions.
6 changes: 6 additions & 0 deletions contrib/pyln-testing/pyln/testing/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,9 @@ def has_funds_on_addr(addr):
if wait_for_active:
self.wait_local_channel_active(scid)
l2.wait_local_channel_active(scid)
wait_for(lambda: len(self.rpc.listprivateinbound()['private_channels']) > 0)
wait_for(lambda: any('short_channel_id' in c for c in self.rpc.listpeerchannels()['channels']))
wait_for(lambda: any('short_channel_id' in c for c in l2.rpc.listpeerchannels()['channels']))

return scid, res

Expand Down Expand Up @@ -1613,6 +1616,9 @@ def join_nodes(self, nodes, fundchannel=True, fundamount=FUNDAMOUNT, wait_for_an
for i, n in enumerate(scids):
nodes[i].wait_local_channel_active(scids[i])
nodes[i + 1].wait_local_channel_active(scids[i])
wait_for(lambda: len(nodes[i].rpc.listprivateinbound()['private_channels']) > 0)
wait_for(lambda: any('short_channel_id' in c for c in nodes[i].rpc.listpeerchannels()['channels']))
wait_for(lambda: any('short_channel_id' in c for c in nodes[i + 1].rpc.listpeerchannels()['channels']))

if not wait_for_announce:
return
Expand Down
2 changes: 2 additions & 0 deletions gossipd/gossipd_wire.csv
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ subtypedata,remote_priv_update,fee_ppm,u32,
subtypedata,remote_priv_update,cltv_delta,u16,
subtypedata,remote_priv_update,htlc_minimum_msat,amount_msat,
subtypedata,remote_priv_update,htlc_maximum_msat,amount_msat,
subtypedata,remote_priv_update,channel_flags,u8,
subtypedata,remote_priv_update,timestamp,u32,

# Tell lightningd we received channel update info for a local channel
msgtype,gossipd_remote_channel_update,3010
Expand Down
71 changes: 42 additions & 29 deletions gossipd/routing.c
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,32 @@ static void remove_channel_from_store(struct routing_state *rstate,
delete_chan_messages_from_store(rstate, chan);
}

static void tell_lightningd_private_update(struct routing_state *rstate,
const struct node_id *source_peer,
struct short_channel_id scid,
u32 fee_base_msat,
u32 fee_ppm,
u16 cltv_delta,
struct amount_msat htlc_minimum,
struct amount_msat htlc_maximum,
u8 channel_flags,
u32 timestamp)
{
struct remote_priv_update remote_update;
u8* msg;
remote_update.source_node = *source_peer;
remote_update.scid = scid;
remote_update.fee_base = fee_base_msat;
remote_update.fee_ppm = fee_ppm;
remote_update.cltv_delta = cltv_delta;
remote_update.htlc_minimum_msat = htlc_minimum;
remote_update.htlc_maximum_msat = htlc_maximum;
remote_update.channel_flags = channel_flags;
remote_update.timestamp = timestamp;
msg = towire_gossipd_remote_channel_update(NULL, &remote_update);
daemon_conn_send(rstate->daemon->master, take(msg));
}

bool routing_add_channel_announcement(struct routing_state *rstate,
const u8 *msg TAKES,
struct amount_sat sat,
Expand Down Expand Up @@ -1007,6 +1033,11 @@ bool routing_add_channel_announcement(struct routing_state *rstate,
delete_chan_messages_from_store(rstate, oldchan);
free_chans_from_node(rstate, oldchan);
tal_free(oldchan);
/* Effectively delete private update from db */
tell_lightningd_private_update(rstate, &node_id_1, scid,
0, 0, 0, amount_msat(0), amount_msat(0), 0, 0);
tell_lightningd_private_update(rstate, &node_id_2, scid,
0, 0, 0, amount_msat(0), amount_msat(0), 0, 0);
}

return true;
Expand Down Expand Up @@ -1348,28 +1379,6 @@ static bool is_chan_dying(struct routing_state *rstate,
return false;
}

static void tell_lightningd_private_update(struct routing_state *rstate,
const struct node_id *source_peer,
struct short_channel_id scid,
u32 fee_base_msat,
u32 fee_ppm,
u16 cltv_delta,
struct amount_msat htlc_minimum,
struct amount_msat htlc_maximum)
{
struct remote_priv_update remote_update;
u8* msg;
remote_update.source_node = *source_peer;
remote_update.scid = scid;
remote_update.fee_base = fee_base_msat;
remote_update.fee_ppm = fee_ppm;
remote_update.cltv_delta = cltv_delta;
remote_update.htlc_minimum_msat = htlc_minimum;
remote_update.htlc_maximum_msat = htlc_maximum;
msg = towire_gossipd_remote_channel_update(NULL, &remote_update);
daemon_conn_send(rstate->daemon->master, take(msg));
}

bool routing_add_channel_update(struct routing_state *rstate,
const u8 *update TAKES,
u32 index,
Expand Down Expand Up @@ -1428,7 +1437,8 @@ bool routing_add_channel_update(struct routing_state *rstate,
short_channel_id, fee_base_msat,
fee_proportional_millionths,
expiry, htlc_minimum,
htlc_maximum);
htlc_maximum,
channel_flags, timestamp);
return false;
}
sat = uc->sat;
Expand Down Expand Up @@ -1560,18 +1570,21 @@ bool routing_add_channel_update(struct routing_state *rstate,
/* No need to separately track spam for private
* channels. */
hc->rgraph.index = hc->bcast.index;
/* give lightningd the channel's inbound info to
* store to db */
/* FIXME: Validate this is peer's and not our own */
tell_lightningd_private_update(rstate, source_peer,
short_channel_id, fee_base_msat,
fee_proportional_millionths,
expiry, htlc_minimum,
htlc_maximum,
channel_flags, timestamp);
} else {
hc->bcast.index = index;
hc->rgraph.index = index;
}
if (!source_peer)
return true;
/* give lightningd the channel's inbound info to store to db */
tell_lightningd_private_update(rstate, source_peer,
short_channel_id, fee_base_msat,
fee_proportional_millionths,
expiry, htlc_minimum,
htlc_maximum);
return true;
}

Expand Down
5 changes: 4 additions & 1 deletion lightningd/channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ struct channel *new_unsaved_channel(struct peer *peer,
channel->shutdown_wrong_funding = NULL;
channel->closing_feerate_range = NULL;
channel->private_update = NULL;
channel->local_private_update = NULL;
channel->channel_update = NULL;
channel->alias[LOCAL] = channel->alias[REMOTE] = NULL;

Expand Down Expand Up @@ -408,7 +409,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid,
struct amount_msat htlc_maximum_msat,
bool ignore_fee_limits,
/* NULL or stolen */
struct remote_priv_update *private_update STEALS)
struct remote_priv_update *private_update STEALS,
struct remote_priv_update *local_private_update STEALS)
{
struct channel *channel = tal(peer->ld, struct channel);
struct amount_msat htlc_min, htlc_max;
Expand Down Expand Up @@ -534,6 +536,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid,
channel->lease_chan_max_msat = lease_chan_max_msat;
channel->lease_chan_max_ppt = lease_chan_max_ppt;
channel->private_update = tal_steal(channel, private_update);
channel->local_private_update = tal_steal(channel, local_private_update);
channel->blockheight_states = dup_height_states(channel, height_states);
channel->channel_update = NULL;

Expand Down
7 changes: 6 additions & 1 deletion lightningd/channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,10 @@ struct channel {
* peer. Used to generate route hints, blinded paths. */
struct remote_priv_update *private_update;

/* This information allows our local private channel update to
* be replicated by listchannels until deprectated. */
struct remote_priv_update *local_private_update;

/* Latest channel_update, for use in error messages. */
u8 *channel_update;

Expand Down Expand Up @@ -375,7 +379,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid,
struct amount_msat htlc_maximum_msat,
bool ignore_fee_limits,
/* NULL or stolen */
struct remote_priv_update *private_update STEALS);
struct remote_priv_update *private_update STEALS,
struct remote_priv_update *local_private_update STEALS);

/* new_inflight - Create a new channel_inflight for a channel */
struct channel_inflight *new_inflight(struct channel *channel,
Expand Down
81 changes: 70 additions & 11 deletions lightningd/gossip_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ static void set_channel_remote_update(struct lightningd *ld,
struct channel *channel,
struct remote_priv_update* update TAKES)
{
if (!node_id_eq(&update->source_node, &channel->peer->id)) {
if (!node_id_eq(&update->source_node, &channel->peer->id) &&
!node_id_eq(&update->source_node, &ld->id)) {
log_unusual(ld->log, "%s sent us a channel update for a "
"channel they don't own (%s)",
type_to_string(tmpctx, struct node_id,
Expand All @@ -192,16 +193,37 @@ static void set_channel_remote_update(struct lightningd *ld,
scid = channel->scid;
if (!scid)
scid = channel->alias[LOCAL];
log_debug(ld->log, "updating channel %s with private inbound settings",
type_to_string(tmpctx, struct short_channel_id, scid));
tal_free(channel->private_update);
channel->private_update = tal_dup(channel,
struct remote_priv_update, update);
log_debug(ld->log, "updating channel %s with private %s settings "
"source node: %s",
type_to_string(tmpctx, struct short_channel_id, scid),
node_id_eq(&update->source_node, &ld->id) ? "outbound" : "inbound",
type_to_string(tmpctx, struct node_id, &update->source_node));
if (node_id_eq(&update->source_node, &channel->peer->id)) {
channel->private_update = tal_free(channel->private_update);
if (update->cltv_delta != 0)
channel->private_update = tal_dup(channel,
struct remote_priv_update, update);
} else {
channel->local_private_update = tal_free(channel->local_private_update);
if (update->cltv_delta != 0)
channel->local_private_update = tal_dup(channel,
struct remote_priv_update, update);
}
if (taken(update))
tal_free(update);
wallet_channel_save(ld->wallet, channel);
}

static struct channel *find_channel_by_remote_alias(struct lightningd *ld,
struct short_channel_id *alias,
struct node_id *id)
{
struct peer *channel_peer = peer_by_id(ld, id);
if (!channel_peer)
return NULL;
return find_channel_by_alias(channel_peer, alias, REMOTE);
}

static void handle_private_update_data(struct lightningd *ld, const u8 *msg)
{
struct channel *channel;
Expand All @@ -212,9 +234,16 @@ static void handle_private_update_data(struct lightningd *ld, const u8 *msg)
fatal("Gossip gave bad GOSSIPD_REMOTE_CHANNEL_UPDATE %s",
tal_hex(msg, msg));
channel = any_channel_by_scid(ld, &update->scid, true);
/* 0conf channels can pass the peer's channel alias */
if (!channel) {
channel = find_channel_by_remote_alias(ld, &update->scid,
&update->source_node);
}
if (!channel) {
log_unusual(ld->log, "could not find channel for peer's "
"private channel update");
log_unusual(ld->log, "could not find channel for the "
"private channel update: %s",
type_to_string(tmpctx, struct short_channel_id,
&update->scid));
return;
}

Expand Down Expand Up @@ -618,13 +647,15 @@ static struct command_result *json_listprivateinbound(struct command *cmd,
c->state != CHANNELD_AWAITING_SPLICE)
continue;

if (!c->private_update && !c->local_private_update)
continue;
json_object_start(response, NULL);
if (c->private_update) {
json_object_start(response, NULL);
json_add_node_id(response, "id", &peer->id);
/* Zeroconf channels will use the local alias here */
json_add_short_channel_id(response,
"short_channel_id",
&c->private_update->scid);
c->scid ? c->scid : c->alias[LOCAL]);
if (c->alias[REMOTE])
json_add_short_channel_id(response,
"remote_alias",
Expand All @@ -640,8 +671,36 @@ static struct command_result *json_listprivateinbound(struct command *cmd,
json_add_amount_msat(response, "htlc_maximum_msat",
c->private_update->htlc_maximum_msat);
json_add_hex_talarr(response, "features", peer->their_features);
json_object_end(response);
/* FIXME: the remainder only provide for private
* channel info in listchannels until the
* deprecation cycle is complete in 24.08 */
json_add_u32(response, "channel_flags",
c->private_update->channel_flags);
json_add_u32(response, "timestamp",
c->private_update->timestamp);
}
if (!c->private_update && c->local_private_update) {
json_add_node_id(response, "id", &peer->id);
if (c->scid)
json_add_short_channel_id(response,
"short_channel_id",
c->scid);
if (c->alias[REMOTE])
json_add_short_channel_id(response,
"remote_alias",
c->alias[REMOTE]);
}
if (c->local_private_update) {
json_add_u32(response,
"local_update_cltv_delta",
c->local_private_update->cltv_delta);
json_add_u32(response,
"local_update_channel_flags",
c->local_private_update->channel_flags);
json_add_u32(response, "local_update_timestamp",
c->local_private_update->timestamp);
}
json_object_end(response);
}
}
json_array_end(response);
Expand Down
2 changes: 2 additions & 0 deletions lightningd/opening_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ wallet_commit_channel(struct lightningd *ld,
ld->config.htlc_minimum_msat,
ld->config.htlc_maximum_msat,
ld->config.ignore_fee_limits,
NULL,
NULL);

/* Now we finally put it in the database. */
Expand Down Expand Up @@ -1476,6 +1477,7 @@ static struct channel *stub_chan(struct command *cmd,
ld->config.htlc_minimum_msat,
ld->config.htlc_maximum_msat,
false,
NULL,
NULL);

return channel;
Expand Down
22 changes: 20 additions & 2 deletions lightningd/routehint.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ routehint_candidates(const tal_t *ctx,
json_tok_full(buf, toks));
}

const jsmntok_t *remote_alias_tok;
struct short_channel_id remote_alias;
remote_alias_tok = json_get_member(buf, t, "remote_alias");
if (remote_alias_tok)
json_to_short_channel_id(buf, remote_alias_tok,
&remote_alias);

/* Do we know about this peer? */
peer = peer_by_id(ld, &r->pubkey);
if (!peer) {
Expand All @@ -112,8 +119,8 @@ routehint_candidates(const tal_t *ctx,
* the REMOTE alias, because it is the only scid we
* have, and it is mandatory once the channel is in
* CHANNELD_NORMAL or CHANNELD_AWAITING_SPLICE. */
if (!candidate.c)
candidate.c = find_channel_by_alias(peer, &r->short_channel_id, REMOTE);
if (!candidate.c && remote_alias_tok)
candidate.c = find_channel_by_alias(peer, &remote_alias, REMOTE);

if (!candidate.c) {
log_debug(ld->log, "%s: channel not found in peer %s",
Expand Down Expand Up @@ -223,6 +230,17 @@ routehint_candidates(const tal_t *ctx,
r->short_channel_id = *candidate.c->alias[REMOTE];
}

/* Public zeroconf channel may have used local alias, but
* routehint must provide the remote alias */
if(candidate.c->alias[LOCAL] &&
short_channel_id_eq(&r->short_channel_id,
candidate.c->alias[LOCAL])) {
if (!candidate.c->alias[REMOTE])
continue;

r->short_channel_id = *candidate.c->alias[REMOTE];
}

/* OK, finish it and append to one of the arrays. */
if (is_public) {
log_debug(ld->log, "%s: added to public",
Expand Down
2 changes: 1 addition & 1 deletion plugins/offers_invreq_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ static struct command_result *listincoming_done(struct command *cmd,
* we could use listpeers, but if it's private we probably
* don't want to blinded route through it! */
pftok = json_get_member(buf, t, "peer_features");
if (!pftok)
if (!pftok || !ci.public)
continue;
features = json_tok_bin_from_hex(tmpctx, buf, pftok);
if (!feature_offered(features, OPT_ROUTE_BLINDING))
Expand Down
Loading

0 comments on commit 1cf8d43

Please sign in to comment.