From af065417e142c519262b1fd00fb310fde1dd9049 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 7 May 2018 13:59:22 +0930 Subject: [PATCH] gossipd: handle wildcard addresses correctly. If we're given a wildcard address, we can't announce it like that: we need to try to turn it into a real address (using guess_address). Then we use that address. As a side-effect of this cleanup, we only announce *any* '--addr' if it's routable. This fix means that our tests have to force '--announce-addr' because otherwise localhost isn't routable. This means that gossipd really controls the addresses now, and breaks them into two arrays: what we bind to, and what we announce. That is now what we return to the master for json_getinfo(), which prints them as 'bindings' and 'addresses' respectively. Signed-off-by: Rusty Russell --- common/wireaddr.c | 13 ++++ common/wireaddr.h | 2 + gossipd/gossip.c | 127 +++++++++++++++++++++++++++--------- gossipd/gossip_wire.csv | 9 +-- gossipd/netaddress.c | 81 ++++------------------- gossipd/netaddress.h | 8 ++- lightningd/gossip_control.c | 11 ++-- lightningd/jsonrpc.c | 25 +++---- lightningd/lightningd.c | 4 +- lightningd/lightningd.h | 12 ++-- lightningd/options.c | 19 +++--- tests/test_lightningd.py | 15 +++-- tests/utils.py | 6 +- 13 files changed, 182 insertions(+), 150 deletions(-) diff --git a/common/wireaddr.c b/common/wireaddr.c index 82aa68931..a5044eba6 100644 --- a/common/wireaddr.c +++ b/common/wireaddr.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -164,6 +165,18 @@ bool wireaddr_to_ipv6(const struct wireaddr *addr, struct sockaddr_in6 *s6) return true; } +bool wireaddr_is_wildcard(const struct wireaddr *addr) +{ + switch (addr->type) { + case ADDR_TYPE_IPV6: + case ADDR_TYPE_IPV4: + return memeqzero(addr->addr, addr->addrlen); + case ADDR_TYPE_PADDING: + return false; + } + abort(); +} + char *fmt_wireaddr_internal(const tal_t *ctx, const struct wireaddr_internal *a) { diff --git a/common/wireaddr.h b/common/wireaddr.h index 19a3f0905..994774c01 100644 --- a/common/wireaddr.h +++ b/common/wireaddr.h @@ -75,6 +75,8 @@ void wireaddr_from_ipv6(struct wireaddr *addr, bool wireaddr_to_ipv4(const struct wireaddr *addr, struct sockaddr_in *s4); bool wireaddr_to_ipv6(const struct wireaddr *addr, struct sockaddr_in6 *s6); +bool wireaddr_is_wildcard(const struct wireaddr *addr); + enum wireaddr_internal_type { ADDR_INTERNAL_SOCKNAME, ADDR_INTERNAL_ALLPROTO, diff --git a/gossipd/gossip.c b/gossipd/gossip.c index a84efcd93..beece573e 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -129,8 +129,13 @@ struct daemon { u8 alias[33]; u8 rgb[3]; - struct wireaddr_internal *wireaddrs; - enum addr_listen_announce *listen_announce; + + /* Addresses master told us to use */ + struct wireaddr_internal *proposed_wireaddr; + enum addr_listen_announce *proposed_listen_announce; + + /* What we actually announce. */ + struct wireaddr *announcable; /* To make sure our node_announcement timestamps increase */ u32 last_announce_timestamp; @@ -566,15 +571,8 @@ static u8 *create_node_announcement(const tal_t *ctx, struct daemon *daemon, sig = tal(ctx, secp256k1_ecdsa_signature); memset(sig, 0, sizeof(*sig)); } - for (i = 0; i < tal_count(daemon->wireaddrs); i++) { - if (!(daemon->listen_announce[i] & ADDR_ANNOUNCE)) - continue; - /* You can only announce wiretypes! */ - if (daemon->wireaddrs[i].itype != ADDR_INTERNAL_WIREADDR) - continue; - towire_wireaddr(&addresses, - &daemon->wireaddrs[i].u.wireaddr); - } + for (i = 0; i < tal_count(daemon->announcable); i++) + towire_wireaddr(&addresses, &daemon->announcable[i]); announcement = towire_node_announcement(ctx, sig, features, timestamp, @@ -1607,51 +1605,113 @@ static bool handle_wireaddr_listen(struct daemon *daemon, "Invalid listener wireaddress type %u", wireaddr->type); } -static void setup_listeners(struct daemon *daemon) +/* If it's a wildcard, turns it into a real address pointing to internet */ +static bool public_address(struct wireaddr *wireaddr) +{ + if (wireaddr_is_wildcard(wireaddr)) { + if (!guess_address(wireaddr)) + return false; + } + + return address_routable(wireaddr); +} + +static void add_announcable(struct daemon *daemon, const struct wireaddr *addr) +{ + size_t n = tal_count(daemon->announcable); + tal_resize(&daemon->announcable, n+1); + daemon->announcable[n] = *addr; +} + +static void add_binding(struct wireaddr_internal **binding, + const struct wireaddr_internal *addr) +{ + size_t n = tal_count(*binding); + tal_resize(binding, n+1); + (*binding)[n] = *addr; +} + +/* Initializes daemon->announcable array, returns addresses we bound to. */ +static struct wireaddr_internal *setup_listeners(const tal_t *ctx, + struct daemon *daemon) { struct sockaddr_un addrun; int fd; + struct wireaddr_internal *binding; + + binding = tal_arr(ctx, struct wireaddr_internal, 0); + daemon->announcable = tal_arr(daemon, struct wireaddr, 0); - for (size_t i = 0; i < tal_count(daemon->wireaddrs); i++) { - struct wireaddr wa = daemon->wireaddrs[i].u.wireaddr; + for (size_t i = 0; i < tal_count(daemon->proposed_wireaddr); i++) { + struct wireaddr_internal wa = daemon->proposed_wireaddr[i]; - if (!(daemon->listen_announce[i] & ADDR_LISTEN)) + if (!(daemon->proposed_listen_announce[i] & ADDR_LISTEN)) { + assert(daemon->proposed_listen_announce[i] + & ADDR_ANNOUNCE); + /* You can only announce wiretypes! */ + assert(daemon->proposed_wireaddr[i].itype + == ADDR_INTERNAL_WIREADDR); + add_announcable(daemon, &wa.u.wireaddr); continue; + } - switch (daemon->wireaddrs[i].itype) { + switch (wa.itype) { case ADDR_INTERNAL_SOCKNAME: addrun.sun_family = AF_UNIX; - memcpy(addrun.sun_path, daemon->wireaddrs[i].u.sockname, + memcpy(addrun.sun_path, wa.u.sockname, sizeof(addrun.sun_path)); fd = make_listen_fd(AF_INET, &addrun, sizeof(addrun), false); status_trace("Created socket listener on file %s", addrun.sun_path); io_new_listener(daemon, fd, connection_in, daemon); + /* We don't announce socket names */ + add_binding(&binding, &wa); continue; case ADDR_INTERNAL_ALLPROTO: { bool ipv6_ok; - memset(wa.addr, 0, sizeof(wa.addr)); - wa.type = ADDR_TYPE_IPV6; - wa.addrlen = 16; - - ipv6_ok = handle_wireaddr_listen(daemon, &wa, true); - wa.type = ADDR_TYPE_IPV4; - wa.addrlen = 4; + wa.itype = ADDR_INTERNAL_WIREADDR; + wa.u.wireaddr.port = wa.u.port; + memset(wa.u.wireaddr.addr, 0, + sizeof(wa.u.wireaddr.addr)); + + /* Try both IPv6 and IPv4. */ + wa.u.wireaddr.type = ADDR_TYPE_IPV6; + wa.u.wireaddr.addrlen = 16; + + ipv6_ok = handle_wireaddr_listen(daemon, &wa.u.wireaddr, + true); + if (ipv6_ok) { + add_binding(&binding, &wa); + if (public_address(&wa.u.wireaddr)) + add_announcable(daemon, &wa.u.wireaddr); + } + wa.u.wireaddr.type = ADDR_TYPE_IPV4; + wa.u.wireaddr.addrlen = 4; /* OK if this fails, as long as one succeeds! */ - handle_wireaddr_listen(daemon, &wa, ipv6_ok); + if (handle_wireaddr_listen(daemon, &wa.u.wireaddr, + ipv6_ok)) { + add_binding(&binding, &wa); + if (public_address(&wa.u.wireaddr)) + add_announcable(daemon, &wa.u.wireaddr); + } continue; } case ADDR_INTERNAL_WIREADDR: - handle_wireaddr_listen(daemon, &wa, false); + handle_wireaddr_listen(daemon, &wa.u.wireaddr, false); + add_binding(&binding, &wa); + if (public_address(&wa.u.wireaddr)) + add_announcable(daemon, &wa.u.wireaddr); continue; } /* Shouldn't happen. */ status_failed(STATUS_FAIL_INTERNAL_ERROR, "Invalid listener address type %u", - daemon->wireaddrs[i].itype); + daemon->proposed_wireaddr[i].itype); } + + return binding; } /* Parse an incoming gossip init message and assign config variables @@ -1667,8 +1727,8 @@ static struct io_plan *gossip_init(struct daemon_conn *master, if (!fromwire_gossipctl_init( daemon, msg, &daemon->broadcast_interval, &chain_hash, &daemon->id, &daemon->globalfeatures, - &daemon->localfeatures, &daemon->wireaddrs, - &daemon->listen_announce, daemon->rgb, + &daemon->localfeatures, &daemon->proposed_wireaddr, + &daemon->proposed_listen_announce, daemon->rgb, daemon->alias, &update_channel_interval, &daemon->reconnect)) { master_badmsg(WIRE_GOSSIPCTL_INIT, msg); } @@ -1691,18 +1751,21 @@ static struct io_plan *gossip_activate(struct daemon_conn *master, const u8 *msg) { bool listen; + struct wireaddr_internal *binding; if (!fromwire_gossipctl_activate(msg, &listen)) master_badmsg(WIRE_GOSSIPCTL_ACTIVATE, msg); if (listen) - setup_listeners(daemon); + binding = setup_listeners(tmpctx, daemon); + else + binding = NULL; /* OK, we're ready! */ daemon_conn_send(&daemon->master, take(towire_gossipctl_activate_reply(NULL, - daemon->wireaddrs, - daemon->listen_announce))); + binding, + daemon->announcable))); return daemon_conn_read_next(master->conn, master); } diff --git a/gossipd/gossip_wire.csv b/gossipd/gossip_wire.csv index 030c499e8..c65115115 100644 --- a/gossipd/gossip_wire.csv +++ b/gossipd/gossip_wire.csv @@ -24,11 +24,12 @@ gossipctl_activate,3025 # Do we listen? gossipctl_activate,,listen,bool -# Gossipd->master, I am ready, here are the final addresses. +# Gossipd->master, I am ready, here's the addresses I bound, can announce. gossipctl_activate_reply,3125 -gossipctl_activate_reply,,num_wireaddrs,u16 -gossipctl_activate_reply,,wireaddrs,num_wireaddrs*struct wireaddr_internal -gossipctl_activate_reply,,listen_announce,num_wireaddrs*enum addr_listen_announce +gossipctl_activate_reply,,num_bindings,u16 +gossipctl_activate_reply,,bindings,num_bindings*struct wireaddr_internal +gossipctl_activate_reply,,num_announcable,u16 +gossipctl_activate_reply,,announcable,num_announcable*struct wireaddr # Master -> gossipd: Optional hint for where to find peer. gossipctl_peer_addrhint,3014 diff --git a/gossipd/netaddress.c b/gossipd/netaddress.c index a7939e970..22cb85df4 100644 --- a/gossipd/netaddress.c +++ b/gossipd/netaddress.c @@ -201,48 +201,39 @@ static bool IsRoutable(const struct wireaddr *addr) * then query address. */ /* Returns 0 if protocol completely unsupported, ADDR_LISTEN if we * can't reach addr, ADDR_LISTEN_AND_ANNOUNCE if we can (and fill saddr). */ -static enum addr_listen_announce get_local_sockname(int af, void *saddr, - socklen_t saddrlen) +static bool get_local_sockname(int af, void *saddr, socklen_t saddrlen) { int fd = socket(af, SOCK_DGRAM, 0); if (fd < 0) { status_trace("Failed to create %u socket: %s", af, strerror(errno)); - return 0; + return false; } if (connect(fd, saddr, saddrlen) != 0) { status_trace("Failed to connect %u socket: %s", af, strerror(errno)); close(fd); - return ADDR_LISTEN; + return false; } if (getsockname(fd, saddr, &saddrlen) != 0) { status_trace("Failed to get %u socket name: %s", af, strerror(errno)); close(fd); - return ADDR_LISTEN; + return false; } close(fd); - return ADDR_LISTEN_AND_ANNOUNCE; + return true; } -/* Return 0 if not available, or whether it's listenable-only or announceable. - * If it's listenable only, will set wireaddr to all-zero address for universal - * binding. */ -static enum addr_listen_announce guess_one_address(struct wireaddr *addr, - u16 portnum, - enum wire_addr_type type) +bool guess_address(struct wireaddr *addr) { - enum addr_listen_announce ret; - - addr->type = type; - addr->port = portnum; + bool ret; /* We point to Google nameservers, works unless you're inside Google :) */ - switch (type) { + switch (addr->type) { case ADDR_TYPE_IPV4: { struct sockaddr_in sin; sin.sin_port = htons(53); @@ -252,7 +243,7 @@ static enum addr_listen_announce guess_one_address(struct wireaddr *addr, ret = get_local_sockname(AF_INET, &sin, sizeof(sin)); addr->addrlen = sizeof(sin.sin_addr); memcpy(addr->addr, &sin.sin_addr, addr->addrlen); - break; + return ret; } case ADDR_TYPE_IPV6: { struct sockaddr_in6 sin6; @@ -266,59 +257,15 @@ static enum addr_listen_announce guess_one_address(struct wireaddr *addr, ret = get_local_sockname(AF_INET6, &sin6, sizeof(sin6)); addr->addrlen = sizeof(sin6.sin6_addr); memcpy(addr->addr, &sin6.sin6_addr, addr->addrlen); - break; + return ret; } case ADDR_TYPE_PADDING: - status_trace("Padding address, ignoring"); - return 0; - } - - if (ret == 0) - return ret; - - /* If we can reach it, but resulting address is unroutable, listen only */ - if (ret == ADDR_LISTEN_AND_ANNOUNCE && !IsRoutable(addr)) { - status_trace("Address %s is not routable", - type_to_string(tmpctx, struct wireaddr, addr)); - ret = ADDR_LISTEN; - } - - if (ret == ADDR_LISTEN) { - /* This corresponds to INADDR_ANY or in6addr_any */ - memset(addr->addr, 0, addr->addrlen); - } else { - status_trace("Public address %s", - type_to_string(tmpctx, struct wireaddr, addr)); + break; } - return ret; + abort(); } -void guess_addresses(struct wireaddr_internal **wireaddrs, - enum addr_listen_announce **listen_announce, - u16 portnum) +bool address_routable(const struct wireaddr *wireaddr) { - size_t n = tal_count(*wireaddrs); - - status_trace("Trying to guess public addresses..."); - - /* We allocate an extra, then remove if it's not needed. */ - tal_resize(wireaddrs, n+1); - tal_resize(listen_announce, n+1); - - (*wireaddrs)[n].itype = ADDR_INTERNAL_WIREADDR; - /* We do IPv6 first: on Linux, that binds to IPv4 too. */ - (*listen_announce)[n] = guess_one_address(&(*wireaddrs)[n].u.wireaddr, - portnum, ADDR_TYPE_IPV6); - if ((*listen_announce)[n] != 0) { - n++; - tal_resize(wireaddrs, n+1); - tal_resize(listen_announce, n+1); - (*wireaddrs)[n].itype = ADDR_INTERNAL_WIREADDR; - } - (*listen_announce)[n] = guess_one_address(&(*wireaddrs)[n].u.wireaddr, - portnum, ADDR_TYPE_IPV4); - if ((*listen_announce)[n] == 0) { - tal_resize(wireaddrs, n); - tal_resize(listen_announce, n); - } + return IsRoutable(wireaddr); } diff --git a/gossipd/netaddress.h b/gossipd/netaddress.h index 58a3fa25d..664b10ad0 100644 --- a/gossipd/netaddress.h +++ b/gossipd/netaddress.h @@ -4,8 +4,10 @@ #include #include -void guess_addresses(struct wireaddr_internal **wireaddrs, - enum addr_listen_announce **listen_announce, - u16 portnum); +/* Address is a wildcard: try to guess what it looks like to outside world */ +bool guess_address(struct wireaddr *wireaddr); + +/* Is this address public? */ +bool address_routable(const struct wireaddr *wireaddr); #endif /* LIGHTNING_GOSSIPD_NETADDRESS_H */ diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 897a58528..c0dfa08d6 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -183,8 +183,8 @@ void gossip_init(struct lightningd *ld) u8 *msg; int hsmfd; u64 capabilities = HSM_CAP_ECDH | HSM_CAP_SIGN_GOSSIP; - struct wireaddr_internal *wireaddrs = ld->wireaddrs; - enum addr_listen_announce *listen_announce = ld->listen_announce; + struct wireaddr_internal *wireaddrs = ld->proposed_wireaddr; + enum addr_listen_announce *listen_announce = ld->proposed_listen_announce; msg = towire_hsm_client_hsmfd(tmpctx, &ld->id, capabilities); if (!wire_sync_write(ld->hsm_fd, msg)) @@ -230,12 +230,9 @@ static void gossip_activate_done(struct subd *gossip UNUSED, { struct lightningd *ld = gossip->ld; - /* Reply gives us the actual wireaddrs we're using */ - tal_free(ld->wireaddrs); - tal_free(ld->listen_announce); if (!fromwire_gossipctl_activate_reply(gossip->ld, reply, - &ld->wireaddrs, - &ld->listen_announce)) + &ld->binding, + &ld->announcable)) fatal("Bad gossipctl_activate_reply: %s", tal_hex(reply, reply)); diff --git a/lightningd/jsonrpc.c b/lightningd/jsonrpc.c index 660de3fc8..8fda08270 100644 --- a/lightningd/jsonrpc.c +++ b/lightningd/jsonrpc.c @@ -150,30 +150,21 @@ static void json_getinfo(struct command *cmd, json_object_start(response, NULL); json_add_pubkey(response, "id", &cmd->ld->id); if (cmd->ld->listen) { - bool have_listen_no_announce = false; if (deprecated_apis) json_add_num(response, "port", cmd->ld->portnum); /* These are the addresses we're announcing */ json_array_start(response, "address"); - for (size_t i = 0; i < tal_count(cmd->ld->wireaddrs); i++) { - if (cmd->ld->listen_announce[i] & ADDR_ANNOUNCE) - json_add_address_internal(response, NULL, - cmd->ld->wireaddrs+i); - else - have_listen_no_announce = true; - } + for (size_t i = 0; i < tal_count(cmd->ld->announcable); i++) + json_add_address(response, NULL, cmd->ld->announcable+i); json_array_end(response); - if (have_listen_no_announce) { - json_array_start(response, "listen-only"); - for (size_t i = 0; i < tal_count(cmd->ld->wireaddrs); i++) { - if (cmd->ld->listen_announce[i] == ADDR_LISTEN) - json_add_address_internal(response, NULL, - cmd->ld->wireaddrs+i); - } - json_array_end(response); - } + /* This is what we're actually bound to. */ + json_array_start(response, "binding"); + for (size_t i = 0; i < tal_count(cmd->ld->binding); i++) + json_add_address_internal(response, NULL, + cmd->ld->binding+i); + json_array_end(response); } json_add_string(response, "version", version()); json_add_num(response, "blockheight", get_block_height(cmd->ld->topology)); diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 15b94251b..2ce639c4e 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -69,8 +69,8 @@ static struct lightningd *new_lightningd(const tal_t *ctx) list_head_init(&ld->waitsendpay_commands); list_head_init(&ld->sendpay_commands); list_head_init(&ld->close_commands); - ld->wireaddrs = tal_arr(ld, struct wireaddr_internal, 0); - ld->listen_announce = tal_arr(ld, enum addr_listen_announce, 0); + ld->proposed_wireaddr = tal_arr(ld, struct wireaddr_internal, 0); + ld->proposed_listen_announce = tal_arr(ld, enum addr_listen_announce, 0); ld->portnum = DEFAULT_PORT; ld->listen = true; ld->autolisten = true; diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index bab518a4e..311726222 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -120,10 +120,14 @@ struct lightningd { /* Do we want to guess addresses to listen and announce? */ bool autolisten; - /* Addresses to bind/announce to the network (tal_count()) */ - struct wireaddr_internal *wireaddrs; - /* And the bitset for each, whether to listen, announce or both */ - enum addr_listen_announce *listen_announce; + /* Setup: Addresses to bind/announce to the network (tal_count()) */ + struct wireaddr_internal *proposed_wireaddr; + /* Setup: And the bitset for each, whether to listen, announce or both */ + enum addr_listen_announce *proposed_listen_announce; + + /* Actual bindings and announcables from gossipd */ + struct wireaddr_internal *binding; + struct wireaddr *announcable; /* Bearer of all my secrets. */ int hsm_fd; diff --git a/lightningd/options.c b/lightningd/options.c index b461d0396..a9ec6fc9e 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -149,16 +149,16 @@ static char *opt_add_addr_withtype(const char *arg, struct lightningd *ld, enum addr_listen_announce ala) { - size_t n = tal_count(ld->wireaddrs); + size_t n = tal_count(ld->proposed_wireaddr); char const *err_msg; assert(arg != NULL); - tal_resize(&ld->wireaddrs, n+1); - tal_resize(&ld->listen_announce, n+1); - ld->listen_announce[n] = ala; + tal_resize(&ld->proposed_wireaddr, n+1); + tal_resize(&ld->proposed_listen_announce, n+1); + ld->proposed_listen_announce[n] = ala; - if (!parse_wireaddr_internal(arg, &ld->wireaddrs[n], ld->portnum, + if (!parse_wireaddr_internal(arg, &ld->proposed_wireaddr[n], ld->portnum, true, &err_msg)) { return tal_fmt(NULL, "Unable to parse address '%s': %s", arg, err_msg); } @@ -918,17 +918,20 @@ static void add_config(struct lightningd *ld, /* Covered by opt_add_addr below */ } else if (opt->cb_arg == (void *)opt_add_addr) { json_add_opt_addrs(response, name0, - ld->wireaddrs, ld->listen_announce, + ld->proposed_wireaddr, + ld->proposed_listen_announce, ADDR_LISTEN_AND_ANNOUNCE); return; } else if (opt->cb_arg == (void *)opt_add_bind_addr) { json_add_opt_addrs(response, name0, - ld->wireaddrs, ld->listen_announce, + ld->proposed_wireaddr, + ld->proposed_listen_announce, ADDR_LISTEN); return; } else if (opt->cb_arg == (void *)opt_add_announce_addr) { json_add_opt_addrs(response, name0, - ld->wireaddrs, ld->listen_announce, + ld->proposed_wireaddr, + ld->proposed_listen_announce, ADDR_ANNOUNCE); return; #if DEVELOPER diff --git a/tests/test_lightningd.py b/tests/test_lightningd.py index 1385c784d..a0807632c 100644 --- a/tests/test_lightningd.py +++ b/tests/test_lightningd.py @@ -4283,10 +4283,17 @@ class LightningDTests(BaseLightningDTests): def test_address(self): l1 = self.node_factory.get_node() - assert len(l1.rpc.getinfo()['address']) == 1 - assert l1.rpc.getinfo()['address'][0]['type'] == 'ipv4' - assert l1.rpc.getinfo()['address'][0]['address'] == '127.0.0.1' - assert int(l1.rpc.getinfo()['address'][0]['port']) == l1.port + addr = l1.rpc.getinfo()['address'] + assert len(addr) == 1 + assert addr[0]['type'] == 'ipv4' + assert addr[0]['address'] == '127.0.0.1' + assert int(addr[0]['port']) == l1.port + + bind = l1.rpc.getinfo()['binding'] + assert len(bind) == 1 + assert bind[0]['type'] == 'ipv4' + assert bind[0]['address'] == '127.0.0.1' + assert int(bind[0]['port']) == l1.port def test_listconfigs(self): l1 = self.node_factory.get_node() diff --git a/tests/utils.py b/tests/utils.py index 5ddba846e..29a9fde29 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -261,7 +261,9 @@ class LightningD(TailableProc): opts = { 'bitcoin-datadir': bitcoin_dir, 'lightning-dir': lightning_dir, - 'addr': '127.0.0.1:{}'.format(port), + 'bind-addr': '127.0.0.1:{}'.format(port), + # lightningd won't announce non-routable addresses by default. + 'announce-addr': '127.0.0.1:{}'.format(port), 'allow-deprecated-apis': 'false', 'override-fee-rates': '15000/7500/1000', 'network': 'regtest', @@ -370,7 +372,7 @@ class LightningNode(object): def start(self): self.daemon.start() # This shortcut is sufficient for our simple tests. - self.port = self.rpc.getinfo()['address'][0]['port'] + self.port = self.rpc.getinfo()['binding'][0]['port'] def stop(self, timeout=10): """ Attempt to do a clean shutdown, but kill if it hangs