mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 01:43:36 +01:00
plugins: generalize "connect if we can't route" logic, link into offers plugin.
We're going to dynamically connect if we need to, to reply to incoming invoice_requests. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
541cc9dd1f
commit
b94be330e6
@ -31,11 +31,11 @@ PLUGIN_PAY_LIB_SRC := plugins/libplugin-pay.c
|
||||
PLUGIN_PAY_LIB_HEADER := plugins/libplugin-pay.h
|
||||
PLUGIN_PAY_LIB_OBJS := $(PLUGIN_PAY_LIB_SRC:.c=.o)
|
||||
|
||||
PLUGIN_OFFERS_SRC := plugins/offers.c plugins/offers_offer.c plugins/offers_invreq_hook.c plugins/offers_inv_hook.c
|
||||
PLUGIN_OFFERS_SRC := plugins/offers.c plugins/offers_offer.c plugins/offers_invreq_hook.c plugins/offers_inv_hook.c plugins/establish_onion_path.c
|
||||
PLUGIN_OFFERS_OBJS := $(PLUGIN_OFFERS_SRC:.c=.o)
|
||||
PLUGIN_OFFERS_HEADER := $(PLUGIN_OFFERS_SRC:.c=.h)
|
||||
|
||||
PLUGIN_FETCHINVOICE_SRC := plugins/fetchinvoice.c
|
||||
PLUGIN_FETCHINVOICE_SRC := plugins/fetchinvoice.c plugins/establish_onion_path.c
|
||||
PLUGIN_FETCHINVOICE_OBJS := $(PLUGIN_FETCHINVOICE_SRC:.c=.o)
|
||||
PLUGIN_FETCHINVOICE_HEADER :=
|
||||
|
||||
@ -212,7 +212,7 @@ $(PLUGIN_KEYSEND_OBJS): $(PLUGIN_PAY_LIB_HEADER)
|
||||
|
||||
plugins/spenderp: bitcoin/block.o bitcoin/preimage.o bitcoin/psbt.o common/psbt_open.o common/json_channel_type.o common/channel_type.o common/features.o wire/peer_wiregen.o $(PLUGIN_SPENDER_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS)
|
||||
|
||||
plugins/offers: $(PLUGIN_OFFERS_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) common/addr.o common/bolt12.o common/bolt12_merkle.o common/bolt11_json.o common/iso4217.o $(WIRE_OBJS) $(WIRE_BOLT12_OBJS) bitcoin/block.o common/channel_id.o bitcoin/preimage.o common/blindedpath.o common/invoice_path_id.o common/blinding.o common/hmac.o common/json_blinded_path.o common/gossmap.o common/fp16.o $(JSMN_OBJS)
|
||||
plugins/offers: $(PLUGIN_OFFERS_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) common/addr.o common/bolt12.o common/bolt12_merkle.o common/bolt11_json.o common/iso4217.o $(WIRE_OBJS) $(WIRE_BOLT12_OBJS) bitcoin/block.o common/channel_id.o bitcoin/preimage.o common/blindedpath.o common/invoice_path_id.o common/blinding.o common/hmac.o common/json_blinded_path.o common/gossmap.o common/fp16.o $(JSMN_OBJS) common/dijkstra.o common/route.o common/gossmods_listpeerchannels.o
|
||||
|
||||
plugins/fetchinvoice: $(PLUGIN_FETCHINVOICE_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) common/bolt12.o common/bolt12_merkle.o common/iso4217.o $(WIRE_OBJS) $(WIRE_BOLT12_OBJS) bitcoin/block.o common/channel_id.o bitcoin/preimage.o $(JSMN_OBJS) common/gossmap.o common/fp16.o common/dijkstra.o common/route.o common/blindedpath.o common/hmac.o common/blinding.o common/gossmods_listpeerchannels.o
|
||||
|
||||
|
177
plugins/establish_onion_path.c
Normal file
177
plugins/establish_onion_path.c
Normal file
@ -0,0 +1,177 @@
|
||||
#include "config.h"
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/dijkstra.h>
|
||||
#include <common/gossmap.h>
|
||||
#include <common/gossmods_listpeerchannels.h>
|
||||
#include <common/json_stream.h>
|
||||
#include <common/route.h>
|
||||
#include <plugins/establish_onion_path.h>
|
||||
|
||||
struct connect_info {
|
||||
struct pubkey local_id, dst;
|
||||
const char *connect_disable;
|
||||
struct gossmap *gossmap;
|
||||
struct command_result *(*cb)(struct command *,
|
||||
const struct pubkey *,
|
||||
void *arg);
|
||||
struct command_result *(*fail)(struct command *, const char *,
|
||||
void *arg);
|
||||
void *arg;
|
||||
};
|
||||
|
||||
static struct command_result *connect_ok(struct command *cmd,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
struct connect_info *ci)
|
||||
{
|
||||
struct pubkey *path = tal_arr(tmpctx, struct pubkey, 2);
|
||||
|
||||
/* Create direct mini-path */
|
||||
path[0] = ci->local_id;
|
||||
path[1] = ci->dst;
|
||||
|
||||
return ci->cb(cmd, path, ci->arg);
|
||||
}
|
||||
|
||||
static struct command_result *command_failed(struct command *cmd,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
struct connect_info *ci)
|
||||
{
|
||||
return ci->fail(cmd, json_strdup(tmpctx, buf, result), ci->arg);
|
||||
}
|
||||
|
||||
static struct command_result *connect_direct(struct command *cmd,
|
||||
struct connect_info *ci)
|
||||
{
|
||||
struct out_req *req;
|
||||
|
||||
if (ci->connect_disable) {
|
||||
return ci->fail(cmd,
|
||||
tal_fmt(tmpctx, "%s set: not initiating a new connection",
|
||||
ci->connect_disable),
|
||||
ci->arg);
|
||||
}
|
||||
|
||||
req = jsonrpc_request_start(cmd->plugin, cmd,
|
||||
"connect", connect_ok, command_failed, ci);
|
||||
json_add_pubkey(req->js, "id", &ci->dst);
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
||||
|
||||
static bool can_carry_onionmsg(const struct gossmap *map,
|
||||
const struct gossmap_chan *c,
|
||||
int dir,
|
||||
struct amount_msat amount UNUSED,
|
||||
void *arg UNUSED)
|
||||
{
|
||||
const struct gossmap_node *n;
|
||||
/* Don't use it if either side says it's disabled */
|
||||
if (!c->half[dir].enabled || !c->half[!dir].enabled)
|
||||
return false;
|
||||
|
||||
/* Check features of recipient */
|
||||
n = gossmap_nth_node(map, c, !dir);
|
||||
return gossmap_node_get_feature(map, n, OPT_ONION_MESSAGES) != -1;
|
||||
}
|
||||
|
||||
static const struct pubkey *path_to_node(const tal_t *ctx,
|
||||
struct gossmap *gossmap,
|
||||
struct plugin *plugin,
|
||||
const char *buf,
|
||||
const jsmntok_t *listpeerchannels,
|
||||
const struct pubkey *local_id,
|
||||
const struct pubkey *dst_key)
|
||||
{
|
||||
struct route_hop *r;
|
||||
const struct dijkstra *dij;
|
||||
const struct gossmap_node *src;
|
||||
const struct gossmap_node *dst;
|
||||
struct pubkey *nodes;
|
||||
struct gossmap_localmods *mods;
|
||||
struct node_id local_nodeid, dst_nodeid;
|
||||
|
||||
node_id_from_pubkey(&local_nodeid, local_id);
|
||||
node_id_from_pubkey(&dst_nodeid, dst_key);
|
||||
mods = gossmods_from_listpeerchannels(tmpctx, &local_nodeid, buf, listpeerchannels,
|
||||
false, gossmod_add_localchan, NULL);
|
||||
|
||||
gossmap_apply_localmods(gossmap, mods);
|
||||
dst = gossmap_find_node(gossmap, &dst_nodeid);
|
||||
if (!dst)
|
||||
goto fail;
|
||||
|
||||
/* If we don't exist in gossip, routing can't happen. */
|
||||
src = gossmap_find_node(gossmap, &local_nodeid);
|
||||
if (!src)
|
||||
goto fail;
|
||||
|
||||
dij = dijkstra(tmpctx, gossmap, dst, AMOUNT_MSAT(0), 0,
|
||||
can_carry_onionmsg, route_score_shorter, NULL);
|
||||
|
||||
r = route_from_dijkstra(tmpctx, gossmap, dij, src, AMOUNT_MSAT(0), 0);
|
||||
if (!r)
|
||||
goto fail;
|
||||
|
||||
nodes = tal_arr(ctx, struct pubkey, tal_count(r) + 1);
|
||||
nodes[0] = *local_id;
|
||||
for (size_t i = 0; i < tal_count(r); i++) {
|
||||
if (!pubkey_from_node_id(&nodes[i+1], &r[i].node_id)) {
|
||||
plugin_err(plugin, "Could not convert nodeid %s",
|
||||
fmt_node_id(tmpctx, &r[i].node_id));
|
||||
}
|
||||
}
|
||||
|
||||
gossmap_remove_localmods(gossmap, mods);
|
||||
return nodes;
|
||||
|
||||
fail:
|
||||
gossmap_remove_localmods(gossmap, mods);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct command_result *listpeerchannels_done(struct command *cmd,
|
||||
const char *buf,
|
||||
const jsmntok_t *result,
|
||||
struct connect_info *ci)
|
||||
{
|
||||
const struct pubkey *path;
|
||||
|
||||
path = path_to_node(tmpctx, ci->gossmap, cmd->plugin, buf, result,
|
||||
&ci->local_id, &ci->dst);
|
||||
if (!path)
|
||||
return connect_direct(cmd, ci);
|
||||
|
||||
return ci->cb(cmd, path, ci->arg);
|
||||
}
|
||||
|
||||
struct command_result *establish_onion_path_(struct command *cmd,
|
||||
struct gossmap *gossmap,
|
||||
const struct pubkey *local_id,
|
||||
const struct pubkey *dst,
|
||||
const char *connect_disable,
|
||||
struct command_result *(*success)(struct command *,
|
||||
const struct pubkey *,
|
||||
void *arg),
|
||||
struct command_result *(*fail)(struct command *,
|
||||
const char *why,
|
||||
void *arg),
|
||||
void *arg)
|
||||
{
|
||||
struct connect_info *ci = tal(cmd, struct connect_info);
|
||||
struct out_req *req;
|
||||
|
||||
ci->local_id = *local_id;
|
||||
ci->dst = *dst;
|
||||
ci->cb = success;
|
||||
ci->fail = fail;
|
||||
ci->arg = arg;
|
||||
ci->connect_disable = connect_disable;
|
||||
ci->gossmap = gossmap;
|
||||
|
||||
req = jsonrpc_request_start(cmd->plugin, cmd, "listpeerchannels",
|
||||
listpeerchannels_done,
|
||||
command_failed,
|
||||
ci);
|
||||
return send_outreq(cmd->plugin, req);
|
||||
}
|
46
plugins/establish_onion_path.h
Normal file
46
plugins/establish_onion_path.h
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef LIGHTNING_PLUGINS_ESTABLISH_ONION_PATH_H
|
||||
#define LIGHTNING_PLUGINS_ESTABLISH_ONION_PATH_H
|
||||
#include "config.h"
|
||||
#include <ccan/typesafe_cb/typesafe_cb.h>
|
||||
#include <plugins/libplugin.h>
|
||||
|
||||
/**
|
||||
* establish_onion_path: derive (or connect) a path to this peer.
|
||||
* @cmd: the command context
|
||||
* @gossmap: a gossip map to do lookup in
|
||||
* @local_id: our own id
|
||||
* @dst: the destination node
|
||||
* @connect_disable: if non-null, the arg name which is disabling direct connection
|
||||
* @success: the success callback
|
||||
* @fail: the failure callback
|
||||
* @arg: callback argument
|
||||
*
|
||||
* If it cannot find an onion-message-carrying path, will connect directly,
|
||||
* unless connect_disable is non-NULL.
|
||||
*/
|
||||
struct command_result *establish_onion_path_(struct command *cmd,
|
||||
struct gossmap *gossmap,
|
||||
const struct pubkey *local_id,
|
||||
const struct pubkey *dst,
|
||||
const char *connect_disable,
|
||||
struct command_result *(*success)(struct command *,
|
||||
const struct pubkey *,
|
||||
void *arg),
|
||||
struct command_result *(*fail)(struct command *,
|
||||
const char *why,
|
||||
void *arg),
|
||||
void *arg);
|
||||
|
||||
#define establish_onion_path(cmd, gossmap, local_id, id, disable, success, fail, arg) \
|
||||
establish_onion_path_((cmd), (gossmap), (local_id), (id), (disable), \
|
||||
typesafe_cb_preargs(struct command_result *, void *, \
|
||||
(success), (arg), \
|
||||
struct command *, \
|
||||
const struct pubkey *), \
|
||||
typesafe_cb_preargs(struct command_result *, void *, \
|
||||
(fail), (arg), \
|
||||
struct command *, \
|
||||
const char *), \
|
||||
(arg))
|
||||
|
||||
#endif /* LIGHTNING_PLUGINS_ESTABLISH_ONION_PATH_H */
|
@ -789,7 +789,7 @@ connect_direct(struct command *cmd,
|
||||
node_id_from_pubkey(&ca->node_id, dst);
|
||||
|
||||
/* Make a direct path -> dst. */
|
||||
sent->path = tal_arr(sent, struct pubkey, 2);
|
||||
sent->path = tal_arr(sent, struct pubkey, 2);
|
||||
sent->path[0] = local_id;
|
||||
if (!pubkey_from_node_id(&sent->path[1], &ca->node_id)) {
|
||||
/* Should not happen! */
|
||||
|
Loading…
Reference in New Issue
Block a user