offers: make find_best_peer take a feature bitmap.

This means we can ask for more than one required feature at a time.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2025-11-18 10:36:27 +10:30
parent 13852b7ff5
commit a3441ff2d0
4 changed files with 22 additions and 11 deletions

View File

@@ -1,6 +1,7 @@
/* This plugin covers both sending and receiving offers */
#include "config.h"
#include <ccan/array_size/array_size.h>
#include <ccan/bitops/bitops.h>
#include <ccan/rune/rune.h>
#include <ccan/tal/str/str.h>
#include <common/bech32.h>
@@ -314,7 +315,7 @@ struct find_best_peer_data {
struct command_result *(*cb)(struct command *,
const struct chaninfo *,
void *);
int needed_feature;
u64 needed_features;
void *arg;
};
@@ -333,6 +334,7 @@ static struct command_result *listincoming_done(struct command *cmd,
struct chaninfo ci;
const jsmntok_t *pftok;
u8 *features;
u64 feature_bits;
const char *err;
struct amount_msat feebase;
bool enabled;
@@ -373,11 +375,20 @@ static struct command_result *listincoming_done(struct command *cmd,
if (!pftok)
continue;
features = json_tok_bin_from_hex(tmpctx, buf, pftok);
if (!feature_offered(features, data->needed_feature))
continue;
/* It must have all the features we need */
feature_bits = data->needed_features;
while (feature_bits) {
int feature = bitops_ls64(feature_bits);
if (!feature_offered(features, feature))
goto next;
feature_bits &= ~(1ULL << feature);
}
if (!best || amount_msat_greater(ci.capacity, best->capacity))
best = tal_dup(tmpctx, struct chaninfo, &ci);
next:;
}
/* Free data if they don't */
@@ -386,7 +397,7 @@ static struct command_result *listincoming_done(struct command *cmd,
}
struct command_result *find_best_peer_(struct command *cmd,
int needed_feature,
u64 needed_features,
struct command_result *(*cb)(struct command *,
const struct chaninfo *,
void *),
@@ -396,7 +407,7 @@ struct command_result *find_best_peer_(struct command *cmd,
struct find_best_peer_data *data = tal(cmd, struct find_best_peer_data);
data->cb = cb;
data->arg = arg;
data->needed_feature = needed_feature;
data->needed_features = needed_features;
req = jsonrpc_request_start(cmd, "listincoming",
listincoming_done, forward_error, data);
return send_outreq(req);

View File

@@ -78,14 +78,14 @@ struct chaninfo {
/* Calls listpeerchannels, then cb with best peer (if any!) which has needed_feature */
struct command_result *find_best_peer_(struct command *cmd,
int needed_feature,
u64 needed_features,
struct command_result *(*cb)(struct command *,
const struct chaninfo *,
void *),
void *arg);
#define find_best_peer(cmd, needed_feature, cb, arg) \
find_best_peer_((cmd), (needed_feature), \
#define find_best_peer(cmd, needed_features, cb, arg) \
find_best_peer_((cmd), (needed_features), \
typesafe_cb_preargs(struct command_result *, void *, \
(cb), (arg), \
struct command *, \

View File

@@ -381,7 +381,7 @@ static struct command_result *add_blindedpaths(struct command *cmd,
if (!we_want_blinded_path(cmd->plugin, true))
return create_invoicereq(cmd, ir);
return find_best_peer(cmd, OPT_ROUTE_BLINDING,
return find_best_peer(cmd, 1ULL << OPT_ROUTE_BLINDING,
found_best_peer, ir);
}

View File

@@ -303,7 +303,7 @@ static struct command_result *maybe_add_path(struct command *cmd,
*/
if (!offinfo->offer->offer_paths) {
if (we_want_blinded_path(cmd->plugin, false))
return find_best_peer(cmd, OPT_ONION_MESSAGES,
return find_best_peer(cmd, 1ULL << OPT_ONION_MESSAGES,
found_best_peer, offinfo);
}
return create_offer(cmd, offinfo);
@@ -729,7 +729,7 @@ struct command_result *json_invoicerequest(struct command *cmd,
idata->invreq = invreq;
idata->single_use = *single_use;
idata->label = label;
return find_best_peer(cmd, OPT_ONION_MESSAGES,
return find_best_peer(cmd, 1ULL << OPT_ONION_MESSAGES,
found_best_peer_invrequest, idata);
}