lightningd: generalize peer_any_channel to filter on entire channel, not just state.

We're going to use this to ask if there are any channels which make it
important to reconnect to the peer.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2024-11-24 12:08:16 +10:30
parent 4ee59e7a49
commit 64af5db45c
9 changed files with 75 additions and 28 deletions

View file

@ -653,28 +653,56 @@ const char *channel_state_str(enum channel_state state)
return "unknown"; return "unknown";
} }
struct channel *peer_any_channel(struct peer *peer, #define peer_any_channel(peer, filter, arg, others) \
bool (*channel_state_filter)(enum channel_state), peer_any_channel_((peer), \
typesafe_cb_preargs(bool, void *, \
(filter), (arg), \
const struct channel *), \
(arg), \
others)
struct channel *peer_any_channel_(struct peer *peer,
bool (*filter)(const struct channel *,
void *arg),
void *arg,
bool *others) bool *others)
{ {
struct channel *channel, *ret = NULL; struct channel *channel, *ret = NULL;
list_for_each(&peer->channels, channel, list) { list_for_each(&peer->channels, channel, list) {
if (channel_state_filter && !channel_state_filter(channel->state)) if (filter && !filter(channel, arg))
continue; continue;
/* Already found one? */ /* Already found one? */
if (ret) { if (ret) {
if (others)
*others = true; *others = true;
} else { } else {
if (others) if (others)
*others = false; *others = false;
ret = channel; ret = channel;
} }
/* Don't keep searching if others is NULL (they don't care). */
if (!others)
break;
} }
return ret; return ret;
} }
static bool filter_by_state(const struct channel *c,
bool (*channel_state_filter)(enum channel_state))
{
return channel_state_filter(c->state);
}
struct channel *peer_any_channel_bystate(struct peer *peer,
bool (*channel_state_filter)(enum channel_state),
bool *others)
{
return peer_any_channel(peer,
filter_by_state, channel_state_filter,
others);
}
struct channel_inflight *channel_inflight_find(struct channel *channel, struct channel_inflight *channel_inflight_find(struct channel *channel,
const struct bitcoin_txid *txid) const struct bitcoin_txid *txid)
{ {

View file

@ -771,7 +771,22 @@ const char *channel_change_state_reason_str(enum state_change reason);
/* Find a channel which is passes filter, if any: sets *others if there /* Find a channel which is passes filter, if any: sets *others if there
* is more than one. */ * is more than one. */
struct channel *peer_any_channel(struct peer *peer, #define peer_any_channel(peer, filter, arg, others) \
peer_any_channel_((peer), \
typesafe_cb_preargs(bool, void *, \
(filter), (arg), \
const struct channel *), \
(arg), \
others)
struct channel *peer_any_channel_(struct peer *peer,
bool (*filter)(const struct channel *,
void *arg),
void *arg,
bool *others);
/* More common version for filtering by state */
struct channel *peer_any_channel_bystate(struct peer *peer,
bool (*channel_state_filter)(enum channel_state), bool (*channel_state_filter)(enum channel_state),
bool *others); bool *others);

View file

@ -2576,7 +2576,8 @@ static struct command_result *json_dev_feerate(struct command *cmd,
if (!peer) if (!peer)
return command_fail(cmd, LIGHTNINGD, "Peer not connected"); return command_fail(cmd, LIGHTNINGD, "Peer not connected");
channel = peer_any_channel(peer, channel_state_can_add_htlc, &more_than_one); channel = peer_any_channel_bystate(peer, channel_state_can_add_htlc,
&more_than_one);
if (!channel || !channel->owner) if (!channel || !channel->owner)
return command_fail(cmd, LIGHTNINGD, "Peer bad state"); return command_fail(cmd, LIGHTNINGD, "Peer bad state");
/* This is a dev command: fix the api if you need this! */ /* This is a dev command: fix the api if you need this! */
@ -2628,7 +2629,7 @@ static struct command_result *json_dev_peer_shachain(struct command *cmd,
if (!peer) if (!peer)
return command_fail(cmd, LIGHTNINGD, "Peer not connected"); return command_fail(cmd, LIGHTNINGD, "Peer not connected");
channel = peer_any_channel(peer, channel_state_can_add_htlc, &more_than_one); channel = peer_any_channel_bystate(peer, channel_state_can_add_htlc, &more_than_one);
if (!channel || !channel->owner) if (!channel || !channel->owner)
return command_fail(cmd, LIGHTNINGD, "Peer bad state"); return command_fail(cmd, LIGHTNINGD, "Peer bad state");
/* This is a dev command: fix the api if you need this! */ /* This is a dev command: fix the api if you need this! */
@ -2683,7 +2684,8 @@ static struct command_result *json_dev_quiesce(struct command *cmd,
return command_fail(cmd, LIGHTNINGD, "Peer not connected"); return command_fail(cmd, LIGHTNINGD, "Peer not connected");
/* FIXME: If this becomes a real API, check for OPT_QUIESCE! */ /* FIXME: If this becomes a real API, check for OPT_QUIESCE! */
channel = peer_any_channel(peer, channel_state_wants_peercomms, &more_than_one); channel = peer_any_channel_bystate(peer, channel_state_wants_peercomms,
&more_than_one);
if (!channel || !channel->owner) if (!channel || !channel->owner)
return command_fail(cmd, LIGHTNINGD, "Peer bad state"); return command_fail(cmd, LIGHTNINGD, "Peer bad state");
/* This is a dev command: fix the api if you need this! */ /* This is a dev command: fix the api if you need this! */

View file

@ -608,7 +608,7 @@ static struct command_result *param_channel_or_peer(struct command *cmd,
(*sc)->uc = NULL; (*sc)->uc = NULL;
if (peer) { if (peer) {
(*sc)->channel = peer_any_channel(peer, channel_state_can_close, &more_than_one); (*sc)->channel = peer_any_channel_bystate(peer, channel_state_can_close, &more_than_one);
if ((*sc)->channel) { if ((*sc)->channel) {
if (more_than_one) if (more_than_one)
goto more_than_one; goto more_than_one;
@ -632,7 +632,7 @@ static struct command_result *param_channel_or_peer(struct command *cmd,
if ((*sc)->uc) if ((*sc)->uc)
return NULL; return NULL;
(*sc)->unsaved_channel = peer_any_channel(peer, channel_state_uncommitted, &more_than_one); (*sc)->unsaved_channel = peer_any_channel_bystate(peer, channel_state_uncommitted, &more_than_one);
if ((*sc)->unsaved_channel) { if ((*sc)->unsaved_channel) {
if (more_than_one) if (more_than_one)
goto more_than_one; goto more_than_one;

View file

@ -291,7 +291,7 @@ static void do_connect(struct delayed_reconnect *d)
/* We consider this transient unless we have a channel */ /* We consider this transient unless we have a channel */
peer = peer_by_id(d->ld, &d->id); peer = peer_by_id(d->ld, &d->id);
transient = !peer || !peer_any_channel(peer, channel_state_wants_peercomms, NULL); transient = !peer || !peer_any_channel_bystate(peer, channel_state_wants_peercomms, NULL);
connectmsg = towire_connectd_connect_to_peer(NULL, connectmsg = towire_connectd_connect_to_peer(NULL,
&d->id, &d->id,
@ -427,7 +427,7 @@ static void connect_failed(struct lightningd *ld,
/* If we have an active channel, then reconnect. */ /* If we have an active channel, then reconnect. */
peer = peer_by_id(ld, id); peer = peer_by_id(ld, id);
if (peer && peer_any_channel(peer, channel_state_wants_peercomms, NULL)) { if (peer && peer_any_channel_bystate(peer, channel_state_wants_peercomms, NULL)) {
try_reconnect(peer, peer, addrhint); try_reconnect(peer, peer, addrhint);
} else } else
log_peer_debug(ld->log, id, "Not reconnecting: %s", log_peer_debug(ld->log, id, "Not reconnecting: %s",

View file

@ -1387,7 +1387,7 @@ wallet_commit_channel(struct lightningd *ld,
bool anysegwit = !chainparams->is_elements && feature_negotiated(channel->peer->ld->our_features, bool anysegwit = !chainparams->is_elements && feature_negotiated(channel->peer->ld->our_features,
channel->peer->their_features, channel->peer->their_features,
OPT_SHUTDOWN_ANYSEGWIT); OPT_SHUTDOWN_ANYSEGWIT);
bool any_active = peer_any_channel(channel->peer, channel_state_wants_peercomms, NULL); bool any_active = peer_any_channel_bystate(channel->peer, channel_state_wants_peercomms, NULL);
if (!amount_sat_to_msat(&our_msat, our_funding)) { if (!amount_sat_to_msat(&our_msat, our_funding)) {
log_broken(channel->log, "Unable to convert funds"); log_broken(channel->log, "Unable to convert funds");

View file

@ -108,7 +108,7 @@ wallet_commit_channel(struct lightningd *ld,
u64 static_remotekey_start; u64 static_remotekey_start;
u32 lease_start_blockheight = 0; /* No leases on v1 */ u32 lease_start_blockheight = 0; /* No leases on v1 */
struct timeabs timestamp; struct timeabs timestamp;
bool any_active = peer_any_channel(uc->peer, channel_state_wants_peercomms, NULL); bool any_active = peer_any_channel_bystate(uc->peer, channel_state_wants_peercomms, NULL);
struct channel_stats zero_channel_stats; struct channel_stats zero_channel_stats;
enum addrtype addrtype; enum addrtype addrtype;

View file

@ -1546,7 +1546,7 @@ static const struct wireaddr *best_remote_addr(const tal_t *ctx,
continue; continue;
if (peer->remote_addr->type != atype) if (peer->remote_addr->type != atype)
continue; continue;
daddr.preferred = peer_any_channel(peer, daddr.preferred = peer_any_channel_bystate(peer,
channel_state_relationship, channel_state_relationship,
NULL); NULL);
daddr.addr = *peer->remote_addr; daddr.addr = *peer->remote_addr;
@ -2647,7 +2647,8 @@ static struct command_result *json_disconnect(struct command *cmd,
return command_fail(cmd, LIGHTNINGD, "Peer not connected"); return command_fail(cmd, LIGHTNINGD, "Peer not connected");
} }
channel = peer_any_channel(peer, channel_state_wants_peercomms, NULL); channel = peer_any_channel_bystate(peer, channel_state_wants_peercomms,
NULL);
if (channel && !*force) { if (channel && !*force) {
return command_fail(cmd, LIGHTNINGD, return command_fail(cmd, LIGHTNINGD,
"Peer has (at least one) channel in state %s", "Peer has (at least one) channel in state %s",
@ -3195,7 +3196,8 @@ static struct command_result *param_dev_channel(struct command *cmd,
if (res) if (res)
return res; return res;
*channel = peer_any_channel(peer, channel_state_wants_peercomms, &more_than_one); *channel = peer_any_channel_bystate(peer, channel_state_wants_peercomms,
&more_than_one);
if (!*channel) if (!*channel)
return command_fail_badparam(cmd, name, buffer, tok, return command_fail_badparam(cmd, name, buffer, tok,
"No channel with that peer"); "No channel with that peer");

View file

@ -875,11 +875,11 @@ struct command_result *param_u64(struct command *cmd UNNEEDED, const char *name
const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
uint64_t **num UNNEEDED) uint64_t **num UNNEEDED)
{ fprintf(stderr, "param_u64 called!\n"); abort(); } { fprintf(stderr, "param_u64 called!\n"); abort(); }
/* Generated stub for peer_any_channel */ /* Generated stub for peer_any_channel_bystate */
struct channel *peer_any_channel(struct peer *peer UNNEEDED, struct channel *peer_any_channel_bystate(struct peer *peer UNNEEDED,
bool (*channel_state_filter)(enum channel_state) UNNEEDED, bool (*channel_state_filter)(enum channel_state) UNNEEDED,
bool *others UNNEEDED) bool *others UNNEEDED)
{ fprintf(stderr, "peer_any_channel called!\n"); abort(); } { fprintf(stderr, "peer_any_channel_bystate called!\n"); abort(); }
/* Generated stub for peer_restart_dualopend */ /* Generated stub for peer_restart_dualopend */
bool peer_restart_dualopend(struct peer *peer UNNEEDED, bool peer_restart_dualopend(struct peer *peer UNNEEDED,
struct peer_fd *peer_fd UNNEEDED, struct peer_fd *peer_fd UNNEEDED,