connectd: get our own addresses to contact node from node_announcements.

Let lightningd feed us hints to try first, but we can extract the
addresses from node_announcement messages ourselves.

(Lightningd used to ask gossipd on our behalf: this is far simpler!)

One side effect of this is that we don't hand back address hints given to us
by lightningd: it would use these again for reconnecting.  This is breaks
test_sendpay_grouping, so we disable it temporarily.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2024-11-24 12:05:16 +10:30
parent 5b92383b02
commit 23dc10cf81
8 changed files with 140 additions and 186 deletions

View file

@ -50,6 +50,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <wire/peer_wire.h>
#include <wire/wire_io.h>
#include <wire/wire_sync.h>
@ -193,6 +194,100 @@ static struct peer *new_peer(struct daemon *daemon,
return peer;
}
/*~ Helper to append a wireaddr to an array if wireaddr_internal */
static void append_addr(struct wireaddr_internal **wireaddrs,
const struct wireaddr *addr)
{
struct wireaddr_internal addrint;
addrint.itype = ADDR_INTERNAL_WIREADDR;
addrint.u.wireaddr.is_websocket = false;
addrint.u.wireaddr.wireaddr = *addr;
tal_arr_expand(wireaddrs, addrint);
}
/*~ Nodes (can) advertize one or more addresses in their node_announcement:
* these are lower priority than ones explicitly supplied to the `connect`
* command, though. */
static void append_gossmap_addresses(struct wireaddr_internal **wireaddrs,
struct daemon *daemon,
const struct node_id *node_id)
{
struct gossmap_node *node;
u8 *nannounce;
struct node_id id;
secp256k1_ecdsa_signature signature;
u32 timestamp;
u8 *addresses, *features;
u8 rgb_color[3], alias[32];
struct tlv_node_ann_tlvs *na_tlvs;
struct wireaddr *alladdrs, *addrs[3];
struct gossmap *gossmap = get_gossmap(daemon);
node = gossmap_find_node(gossmap, node_id);
if (!node)
return;
nannounce = gossmap_node_get_announce(tmpctx, gossmap,
node);
if (!nannounce)
return;
if (!fromwire_node_announcement(tmpctx, nannounce,
&signature, &features,
&timestamp,
&id, rgb_color, alias,
&addresses,
&na_tlvs)) {
status_broken("Bad node_announcement for %s in gossip_store: %s",
fmt_node_id(tmpctx, node_id),
tal_hex(tmpctx, nannounce));
return;
}
alladdrs = fromwire_wireaddr_array(tmpctx, addresses);
if (!alladdrs) {
status_broken("Bad wireaddrs in node_announcement in gossip_store: %s",
tal_hex(tmpctx, nannounce));
return;
}
/* Orders the gossip addresses.
*
* Ignore deprecated protocols. Adds all IPv6 addresses, followed by
* IPv4 and then TOR. This ensures we are modern and use IPv6 when
* possible, falling back to direct (faster) IPv4 and finally (less
* stable) TOR connections. */
for (size_t i = 0; i < ARRAY_SIZE(addrs); i++)
addrs[i] = tal_arr(tmpctx, struct wireaddr, 0);
for (size_t i = 0; i < tal_count(alladdrs); i++) {
/* A switch, so compiler tells you to update it if we
* add a new type! */
switch (alladdrs[i].type) {
case ADDR_TYPE_IPV6:
case ADDR_TYPE_DNS:
tal_arr_expand(&addrs[0], alladdrs[i]);
break;
case ADDR_TYPE_IPV4:
tal_arr_expand(&addrs[1], alladdrs[i]);
break;
case ADDR_TYPE_TOR_V3:
tal_arr_expand(&addrs[2], alladdrs[i]);
break;
case ADDR_TYPE_TOR_V2_REMOVED:
/* Ignore. We also ignore unknowns */
break;
}
}
/* Now, we first append V6/DNS, then V4, then Tor */
for (size_t i = 0; i < ARRAY_SIZE(addrs); i++) {
for (size_t j = 0; j < tal_count(addrs[i]); j++) {
append_addr(wireaddrs, &addrs[i][j]);
}
}
}
/*~ Note the lack of static: this is called by peer_exchange_initmsg.c once the
* INIT messages are exchanged, and also by the retry code above. */
struct io_plan *peer_connected(struct io_conn *conn,
@ -665,14 +760,12 @@ struct io_plan *connection_out(struct io_conn *conn, struct connecting *connect)
*/
static void connect_failed(struct daemon *daemon,
const struct node_id *id,
const struct wireaddr_internal *addrhint,
enum jsonrpc_errcode errcode,
const char *errfmt, ...)
PRINTF_FMT(5,6);
PRINTF_FMT(4,5);
static void connect_failed(struct daemon *daemon,
const struct node_id *id,
const struct wireaddr_internal *addrhint,
enum jsonrpc_errcode errcode,
const char *errfmt, ...)
{
@ -689,8 +782,7 @@ static void connect_failed(struct daemon *daemon,
/* lightningd may have a connect command waiting to know what
* happened. We leave it to lightningd to decide if it wants to try
* again. */
msg = towire_connectd_connect_failed(NULL, id, errcode, errmsg,
addrhint);
msg = towire_connectd_connect_failed(NULL, id, errcode, errmsg);
daemon_conn_send(daemon->master, take(msg));
}
@ -819,7 +911,6 @@ static void try_connect_one_addr(struct connecting *connect)
struct io_conn *conn;
bool use_dns = connect->daemon->use_dns;
struct addrinfo hints, *ais, *aii;
struct wireaddr_internal addrhint;
int gai_err;
struct sockaddr_in *sa4;
struct sockaddr_in6 *sa6;
@ -829,7 +920,7 @@ static void try_connect_one_addr(struct connecting *connect)
/* Out of addresses? */
if (connect->addrnum == tal_count(connect->addrs)) {
connect_failed(connect->daemon, &connect->id,
connect->addrhint, CONNECT_ALL_ADDRESSES_FAILED,
CONNECT_ALL_ADDRESSES_FAILED,
"All addresses failed: %s",
connect->errors);
tal_free(connect);
@ -899,23 +990,22 @@ static void try_connect_one_addr(struct connecting *connect)
}
/* create new addrhints on-the-fly per result ... */
for (aii = ais; aii; aii = aii->ai_next) {
addrhint.itype = ADDR_INTERNAL_WIREADDR;
addrhint.u.wireaddr.is_websocket = false;
struct wireaddr wa;
if (aii->ai_family == AF_INET) {
sa4 = (struct sockaddr_in *) aii->ai_addr;
wireaddr_from_ipv4(&addrhint.u.wireaddr.wireaddr,
wireaddr_from_ipv4(&wa,
&sa4->sin_addr,
addr->u.wireaddr.wireaddr.port);
} else if (aii->ai_family == AF_INET6) {
sa6 = (struct sockaddr_in6 *) aii->ai_addr;
wireaddr_from_ipv6(&addrhint.u.wireaddr.wireaddr,
wireaddr_from_ipv6(&wa,
&sa6->sin6_addr,
addr->u.wireaddr.wireaddr.port);
} else {
/* skip unsupported ai_family */
continue;
}
tal_arr_expand(&connect->addrs, addrhint);
append_addr(&connect->addrs, &wa);
/* don't forget to update convenience pointer */
addr = &connect->addrs[connect->addrnum];
}
@ -1604,14 +1694,9 @@ static void add_seed_addrs(struct wireaddr_internal **addrs,
for (size_t j = 0; j < tal_count(new_addrs); j++) {
if (new_addrs[j].type == ADDR_TYPE_DNS)
continue;
struct wireaddr_internal a;
a.itype = ADDR_INTERNAL_WIREADDR;
a.u.wireaddr.is_websocket = false;
a.u.wireaddr.wireaddr = new_addrs[j];
status_peer_debug(id, "Resolved %s to %s", hostnames[i],
fmt_wireaddr(tmpctx,
&a.u.wireaddr.wireaddr));
tal_arr_expand(addrs, a);
fmt_wireaddr(tmpctx, &new_addrs[j]));
append_addr(addrs, &new_addrs[j]);
}
/* Other seeds will likely have the same information. */
return;
@ -1620,86 +1705,23 @@ static void add_seed_addrs(struct wireaddr_internal **addrs,
}
}
/*~ Adds just one address type.
*
* Ignores deprecated and the `addrhint`. */
static void add_gossip_addrs_bytypes(struct wireaddr_internal **addrs,
const struct wireaddr *normal_addrs,
const struct wireaddr *addrhint,
u64 types)
static bool addr_in(const struct wireaddr_internal *needle,
const struct wireaddr_internal haystack[])
{
for (size_t i = 0; i < tal_count(normal_addrs); i++) {
if (addrhint && wireaddr_eq(addrhint, &normal_addrs[i]))
continue;
/* I guess this is possible in future! */
if (normal_addrs[i].type > 63)
continue;
if (((u64)1 << normal_addrs[i].type) & types) {
struct wireaddr_internal addr;
addr.itype = ADDR_INTERNAL_WIREADDR;
addr.u.wireaddr.is_websocket = false;
addr.u.wireaddr.wireaddr = normal_addrs[i];
tal_arr_expand(addrs, addr);
}
}
for (size_t i = 0; i < tal_count(haystack); i++)
if (wireaddr_internal_eq(needle, &haystack[i]))
return true;
return false;
}
/*~ Orders the addresses which lightningd gave us.
*
* Ignores deprecated protocols and the `addrhint` that is assumed to be
* already added first. Adds all IPv6 addresses, followed by IPv4 and then TOR.
* This ensures we are modern and use IPv6 when possible, falling back to
* direct (faster) IPv4 and finally (less stable) TOR connections. */
static void add_gossip_addrs(struct wireaddr_internal **addrs,
const struct wireaddr *normal_addrs,
const struct wireaddr *addrhint)
{
u64 types[] = { 0, 0, 0 };
/* Note gratuitous use of switch() means we'll know if a new one
* appears! */
for (size_t i = ADDR_TYPE_IPV4; i <= ADDR_TYPE_DNS; i++) {
switch ((enum wire_addr_type)i) {
/* First priority */
case ADDR_TYPE_IPV6:
case ADDR_TYPE_DNS:
types[0] |= ((u64)1 << i);
break;
/* Second priority */
case ADDR_TYPE_IPV4:
types[1] |= ((u64)1 << i);
break;
case ADDR_TYPE_TOR_V3:
/* Third priority */
types[2] |= ((u64)1 << i);
break;
/* We can't use these to connect to! */
case ADDR_TYPE_TOR_V2_REMOVED:
break;
}
/* Other results returned are possible, but we don't understand
* them anyway! */
}
/* Add in priority order */
for (size_t i = 0; i < ARRAY_SIZE(types); i++)
add_gossip_addrs_bytypes(addrs, normal_addrs, addrhint, types[i]);
}
/*~ Consumes addrhint if not NULL.
*
* That's a pretty ugly interface: we should use TAKEN, but we only have one
* caller so it's marginal. */
/*~ Try to connect to a single peer, given some addresses (in order) */
static void try_connect_peer(struct daemon *daemon,
const struct node_id *id,
struct wireaddr *gossip_addrs,
struct wireaddr_internal *addrhint STEALS,
struct wireaddr_internal *addrs TAKES,
bool dns_fallback,
bool transient)
{
struct wireaddr_internal *addrs;
bool use_proxy = daemon->always_use_proxy;
struct connecting *connect;
struct peer *peer;
@ -1718,29 +1740,14 @@ static void try_connect_peer(struct daemon *daemon,
/* If we've been passed in new connection details
* for this connection, update our addrhint + add
* to addresses to check */
if (addrhint) {
connect->addrhint = tal_steal(connect, addrhint);
tal_arr_expand(&connect->addrs, *addrhint);
for (size_t i = 0; i < tal_count(addrs); i++) {
if (!addr_in(&addrs[i], connect->addrs))
tal_arr_expand(&connect->addrs, addrs[i]);
}
return;
}
/* Start an array of addresses to try. */
addrs = tal_arr(tmpctx, struct wireaddr_internal, 0);
/* They can supply an optional address for the connect RPC */
/* We add this first so its tried first by connectd */
if (addrhint)
tal_arr_expand(&addrs, *addrhint);
/* Tell it to omit the existing hint (if that's a wireaddr itself) */
add_gossip_addrs(&addrs, gossip_addrs,
addrhint
&& addrhint->itype == ADDR_INTERNAL_WIREADDR
&& !addrhint->u.wireaddr.is_websocket
? &addrhint->u.wireaddr.wireaddr : NULL);
if (tal_count(addrs) == 0) {
/* Don't resolve via DNS seed if we're supposed to use proxy. */
if (use_proxy) {
@ -1763,7 +1770,7 @@ static void try_connect_peer(struct daemon *daemon,
/* Still no address? Fail immediately. Lightningd can still choose
* to retry; an address may get gossiped or appear on the DNS seed. */
if (tal_count(addrs) == 0) {
connect_failed(daemon, id, addrhint,
connect_failed(daemon, id,
CONNECT_NO_KNOWN_ADDRESS,
"Unable to connect, no address known for peer");
return;
@ -1774,13 +1781,12 @@ static void try_connect_peer(struct daemon *daemon,
connect = tal(daemon, struct connecting);
connect->daemon = daemon;
connect->id = *id;
connect->addrs = tal_steal(connect, addrs);
connect->addrs = tal_dup_talarr(connect, struct wireaddr_internal, addrs);
connect->addrnum = 0;
/* connstate is supposed to be updated as we go, to give context for
* errors which occur. We miss it in a few places; would be nice to
* fix! */
connect->connstate = "Connection establishment";
connect->addrhint = tal_steal(connect, addrhint);
connect->errors = tal_strdup(connect, "");
connect->conn = NULL;
connect->transient = transient;
@ -1791,22 +1797,28 @@ static void try_connect_peer(struct daemon *daemon,
try_connect_one_addr(connect);
}
/* lightningd tells us to connect to a peer by id, with optional addr hint. */
/* lightningd tells us to connect to a peer by id, with optional addresses to try. */
static void connect_to_peer(struct daemon *daemon, const u8 *msg)
{
struct node_id id;
struct wireaddr_internal *addrhint;
struct wireaddr *addrs;
struct wireaddr_internal *addrs;
bool dns_fallback;
bool transient;
if (!fromwire_connectd_connect_to_peer(tmpctx, msg,
&id, &addrs, &addrhint,
&id, &addrs,
&dns_fallback,
&transient))
master_badmsg(WIRE_CONNECTD_CONNECT_TO_PEER, msg);
try_connect_peer(daemon, &id, addrs, addrhint, dns_fallback, transient);
/* fromwire doesn't allocate empty arrays! */
if (!addrs)
addrs = tal_arr(tmpctx, struct wireaddr_internal, 0);
/* Do gossmap lookup to find any addresses from there, and append. */
append_gossmap_addresses(&addrs, daemon, &id);
try_connect_peer(daemon, &id, addrs, dns_fallback, transient);
}
/* lightningd tells us a peer should be disconnected. */

View file

@ -170,9 +170,6 @@ struct connecting {
size_t addrnum;
struct wireaddr_internal *addrs;
/* NULL if there wasn't a hint. */
struct wireaddr_internal *addrhint;
/* How far did we get? */
const char *connstate;

View file

@ -60,8 +60,7 @@ msgdata,connectd_scid_map,node_id,node_id,
msgtype,connectd_connect_to_peer,2001
msgdata,connectd_connect_to_peer,id,node_id,
msgdata,connectd_connect_to_peer,len,u32,
msgdata,connectd_connect_to_peer,addrs,wireaddr,len
msgdata,connectd_connect_to_peer,addrhint,?wireaddr_internal,
msgdata,connectd_connect_to_peer,addrs,wireaddr_internal,len
msgdata,connectd_connect_to_peer,dns_fallback,bool,
msgdata,connectd_connect_to_peer,transient,bool,
@ -70,7 +69,6 @@ msgtype,connectd_connect_failed,2020
msgdata,connectd_connect_failed,id,node_id,
msgdata,connectd_connect_failed,failcode,enum jsonrpc_errcode,
msgdata,connectd_connect_failed,failreason,wirestring,
msgdata,connectd_connect_failed,addrhint,?wireaddr_internal,
# Connectd -> master: we got a peer.
msgtype,connectd_peer_connected,2002

1 #include <bitcoin/block.h>
60 # Connectd->master: connect failed. msgtype,connectd_connect_failed,2020
61 msgtype,connectd_connect_failed,2020 msgdata,connectd_connect_failed,id,node_id,
62 msgdata,connectd_connect_failed,id,node_id, msgdata,connectd_connect_failed,failcode,enum jsonrpc_errcode,
63 msgdata,connectd_connect_failed,failcode,enum jsonrpc_errcode, msgdata,connectd_connect_failed,failreason,wirestring,
msgdata,connectd_connect_failed,failreason,wirestring,
64 msgdata,connectd_connect_failed,addrhint,?wireaddr_internal, # Connectd -> master: we got a peer.
65 # Connectd -> master: we got a peer. msgtype,connectd_peer_connected,2002
66 msgtype,connectd_peer_connected,2002 msgdata,connectd_peer_connected,id,node_id,
69 msgdata,connectd_peer_connected,addr,wireaddr_internal, msgdata,connectd_peer_connected,remote_addr,?wireaddr,
70 msgdata,connectd_peer_connected,remote_addr,?wireaddr, msgdata,connectd_peer_connected,incoming,bool,
71 msgdata,connectd_peer_connected,incoming,bool, msgdata,connectd_peer_connected,flen,u16,
msgdata,connectd_peer_connected,flen,u16,
72 msgdata,connectd_peer_connected,features,u8,flen
73 # connectd -> master: peer disconnected.
74 msgtype,connectd_peer_disconnect_done,2006

View file

@ -176,27 +176,6 @@ static void connectd_peer_gone(struct daemon *daemon, const u8 *msg)
tal_free(peer);
}
/*~ lightningd asks us if we know any addresses for a given id. */
static struct io_plan *handle_get_address(struct io_conn *conn,
struct daemon *daemon,
const u8 *msg)
{
struct node_id id;
struct wireaddr *addrs;
struct gossmap *gossmap = gossmap_manage_get_gossmap(daemon->gm);
if (!fromwire_gossipd_get_addrs(msg, &id))
master_badmsg(WIRE_GOSSIPD_GET_ADDRS, msg);
addrs = gossmap_manage_get_node_addresses(tmpctx,
gossmap,
&id);
daemon_conn_send(daemon->master,
take(towire_gossipd_get_addrs_reply(NULL, addrs)));
return daemon_conn_read_next(conn, daemon->master);
}
static void handle_recv_gossip(struct daemon *daemon, const u8 *outermsg)
{
struct node_id source;
@ -609,9 +588,6 @@ static struct io_plan *recv_req(struct io_conn *conn,
inject_gossip(daemon, msg);
goto done;
case WIRE_GOSSIPD_GET_ADDRS:
return handle_get_address(conn, daemon, msg);
case WIRE_GOSSIPD_DEV_MEMLEAK:
if (daemon->developer) {
dev_gossip_memleak(daemon, msg);
@ -633,7 +609,6 @@ static struct io_plan *recv_req(struct io_conn *conn,
case WIRE_GOSSIPD_DEV_MEMLEAK_REPLY:
case WIRE_GOSSIPD_ADDGOSSIP_REPLY:
case WIRE_GOSSIPD_NEW_BLOCKHEIGHT_REPLY:
case WIRE_GOSSIPD_GET_ADDRS_REPLY:
case WIRE_GOSSIPD_REMOTE_CHANNEL_UPDATE:
case WIRE_GOSSIPD_CONNECT_TO_PEER:
break;

View file

@ -71,14 +71,6 @@ msgdata,gossipd_addgossip,known_channel,?amount_sat,
msgtype,gossipd_addgossip_reply,3144
msgdata,gossipd_addgossip_reply,err,wirestring,
# Lightningd asks gossipd for any known addresses for that node.
msgtype,gossipd_get_addrs,3050
msgdata,gossipd_get_addrs,id,node_id,
msgtype,gossipd_get_addrs_reply,3150
msgdata,gossipd_get_addrs_reply,num,u16,
msgdata,gossipd_get_addrs_reply,addrs,wireaddr,num
subtype,peer_update
subtypedata,peer_update,scid,short_channel_id,
subtypedata,peer_update,fee_base,u32,

1 #include <common/cryptomsg.h>
71 subtypedata,peer_update,htlc_maximum_msat,amount_msat, msgtype,gossipd_connect_to_peer,3011
72 # Tell lightningd we received channel update info for a local channel msgdata,gossipd_connect_to_peer,id,node_id,
73 msgtype,gossipd_remote_channel_update,3010 msgdata,gossipd_connect_to_peer,num,u16,
msgdata,gossipd_remote_channel_update,source_node,?node_id,
msgdata,gossipd_remote_channel_update,peer_update,peer_update,
# Ask lightningd to connect to a peer.
msgtype,gossipd_connect_to_peer,3011
msgdata,gossipd_connect_to_peer,id,node_id,
msgdata,gossipd_connect_to_peer,num,u16,
msgdata,gossipd_connect_to_peer,addrs,wireaddr,num,
74 msgdata,gossipd_connect_to_peer,addrs,wireaddr,num,
75
76

View file

@ -282,19 +282,12 @@ HTABLE_DEFINE_TYPE(struct delayed_reconnect,
node_id_hash, node_id_delayed_reconnect_eq,
delayed_reconnect_map);
static void gossipd_got_addrs(struct subd *subd,
const u8 *msg,
const int *fds,
struct delayed_reconnect *d)
/* We might be off a delay timer. */
static void do_connect(struct delayed_reconnect *d)
{
struct wireaddr *addrs;
u8 *connectmsg;
struct peer *peer;
bool transient;
if (!fromwire_gossipd_get_addrs_reply(tmpctx, msg, &addrs))
fatal("Gossipd gave bad GOSSIPD_GET_ADDRS_REPLY %s",
tal_hex(msg, msg));
struct peer *peer;
u8 *connectmsg;
/* We consider this transient unless we have a channel */
peer = peer_by_id(d->ld, &d->id);
@ -302,7 +295,6 @@ static void gossipd_got_addrs(struct subd *subd,
connectmsg = towire_connectd_connect_to_peer(NULL,
&d->id,
addrs,
d->addrhint,
d->dns_fallback,
transient);
@ -310,14 +302,6 @@ static void gossipd_got_addrs(struct subd *subd,
tal_free(d);
}
/* We might be off a delay timer. Now ask gossipd about public addresses. */
static void do_connect(struct delayed_reconnect *d)
{
u8 *msg = towire_gossipd_get_addrs(NULL, &d->id);
subd_req(d, d->ld->gossip, take(msg), -1, 0, gossipd_got_addrs, d);
}
static void destroy_delayed_reconnect(struct delayed_reconnect *d)
{
delayed_reconnect_map_del(d->ld->delayed_reconnect_map, d);
@ -428,9 +412,9 @@ void try_reconnect(const tal_t *ctx,
/* We were trying to connect, but they disconnected. */
static void connect_failed(struct lightningd *ld,
const struct node_id *id,
const struct wireaddr_internal *addrhint,
enum jsonrpc_errcode errcode,
const char *errmsg,
const struct wireaddr_internal *addrhint)
const char *errmsg)
{
struct peer *peer;
struct connect *c;
@ -454,8 +438,8 @@ void connect_failed_disconnect(struct lightningd *ld,
const struct node_id *id,
const struct wireaddr_internal *addrhint)
{
connect_failed(ld, id, CONNECT_DISCONNECTED_DURING,
"disconnected during connection", addrhint);
connect_failed(ld, id, addrhint, CONNECT_DISCONNECTED_DURING,
"disconnected during connection");
}
static void handle_connect_failed(struct lightningd *ld, const u8 *msg)
@ -463,14 +447,12 @@ static void handle_connect_failed(struct lightningd *ld, const u8 *msg)
struct node_id id;
enum jsonrpc_errcode errcode;
char *errmsg;
struct wireaddr_internal *addrhint;
if (!fromwire_connectd_connect_failed(tmpctx, msg, &id, &errcode, &errmsg,
&addrhint))
if (!fromwire_connectd_connect_failed(tmpctx, msg, &id, &errcode, &errmsg))
fatal("Connect gave bad CONNECTD_CONNECT_FAILED message %s",
tal_hex(msg, msg));
connect_failed(ld, &id, errcode, errmsg, addrhint);
connect_failed(ld, &id, NULL, errcode, errmsg);
}
const char *connect_any_cmd_id(const tal_t *ctx,

View file

@ -187,7 +187,6 @@ static void handle_connect_to_peer(struct subd *gossip, const u8 *msg)
u8 *connectmsg;
connectmsg = towire_connectd_connect_to_peer(NULL,
id,
addrs,
NULL, //addrhint,
false, //dns_fallback
true); //transient
@ -207,13 +206,11 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds)
case WIRE_GOSSIPD_DEV_SET_TIME:
case WIRE_GOSSIPD_NEW_BLOCKHEIGHT:
case WIRE_GOSSIPD_ADDGOSSIP:
case WIRE_GOSSIPD_GET_ADDRS:
/* This is a reply, so never gets through to here. */
case WIRE_GOSSIPD_INIT_REPLY:
case WIRE_GOSSIPD_DEV_MEMLEAK_REPLY:
case WIRE_GOSSIPD_ADDGOSSIP_REPLY:
case WIRE_GOSSIPD_NEW_BLOCKHEIGHT_REPLY:
case WIRE_GOSSIPD_GET_ADDRS_REPLY:
break;
case WIRE_GOSSIPD_INIT_CUPDATE:

View file

@ -5069,6 +5069,7 @@ def test_listpays_with_filter_by_status(node_factory, bitcoind):
assert len(l2.rpc.listpays()['pays']) == 1
@pytest.mark.xfail(strict=True)
def test_sendpay_grouping(node_factory, bitcoind):
"""`listpays` should be smart enough to group repeated `pay` calls.