gossipd: rewrite to do the handshake internally.

Now the flow is much simpler from a lightningd POV:

1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
   and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
   features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
   it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.

Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
  connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
  a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
  messages, which changes the test_disconnect case.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2017-10-11 20:39:49 +10:30 committed by Christian Decker
parent 2273ce783e
commit 474887512d
20 changed files with 1497 additions and 1711 deletions

View File

@ -13,6 +13,7 @@ LIGHTNINGD_GOSSIP_CONTROL_OBJS := $(LIGHTNINGD_GOSSIP_CONTROL_SRC:.c=.o)
# gossipd needs these:
LIGHTNINGD_GOSSIP_HEADERS := gossipd/gen_gossip_wire.h \
gossipd/handshake.h \
gossipd/routing.h \
gossipd/broadcast.h
LIGHTNINGD_GOSSIP_SRC := gossipd/gossip.c \
@ -48,7 +49,11 @@ GOSSIPD_COMMON_OBJS := \
common/type_to_string.o \
common/utils.o \
common/version.o \
lightningd/gossip_msg.o
common/wire_error.o \
hsmd/client.o \
hsmd/gen_hsm_client_wire.o \
lightningd/gossip_msg.o \
lightningd/netaddr.o
$(LIGHTNINGD_GOSSIP_OBJS) $(LIGHTNINGD_GOSSIP_CLIENT_OBJS): $(LIGHTNINGD_HEADERS)

File diff suppressed because it is too large Load Diff

View File

@ -1,52 +1,71 @@
# Peers can give a bad message, we close their fd, but no harm done.
gossipstatus_peer_bad_msg,13000
gossipstatus_peer_bad_msg,,unique_id,u64
gossipstatus_peer_bad_msg,,len,u16
gossipstatus_peer_bad_msg,,err,len*u8
# Misc problems like opening control fd.
gossipstatus_peer_failed,13001
gossipstatus_peer_failed,,unique_id,u64
gossipstatus_peer_failed,,len,u16
gossipstatus_peer_failed,,err,len*u8
#include <common/cryptomsg.h>
# Initialize the gossip daemon
# Initialize the gossip daemon.
gossipctl_init,3000
gossipctl_init,,broadcast_interval,u32
gossipctl_init,,chain_hash,struct sha256_double
gossipctl_init,,id,struct pubkey
# If non-zero, port to listen on.
gossipctl_init,,port,u16
gossipctl_init,,gflen,u16
gossipctl_init,,gfeatures,gflen*u8
gossipctl_init,,lflen,u16
gossipctl_init,,lfeatures,lflen*u8
# These take an fd, but have no response
gossipctl_new_peer,3001
gossipctl_new_peer,,unique_id,u64
gossipctl_new_peer,,crypto_state,struct crypto_state
# Master -> gossipd: Optional hint for where to find peer.
gossipctl_peer_addrhint,3014
gossipctl_peer_addrhint,,id,struct pubkey
gossipctl_peer_addrhint,,addr,struct ipaddr
# Tell it to release a peer which has initialized.
gossipctl_release_peer,3002
gossipctl_release_peer,,unique_id,u64
# Master -> gossipd: connect to a peer. We may get a peer_connected.
gossipctl_reach_peer,3001
gossipctl_reach_peer,,id,struct pubkey
# This releases the peer and returns the cryptostate (followed two fds: peer and gossip)
gossipctl_release_peer_reply,3102
# Gossipd -> master: we got a peer. Two fds: peer and gossip
gossip_peer_connected,3002
gossip_peer_connected,,id,struct pubkey
gossip_peer_connected,,crypto_state,struct crypto_state
gossip_peer_connected,,gflen,u16
gossip_peer_connected,,gfeatures,gflen*u8
gossip_peer_connected,,lflen,u16
gossip_peer_connected,,lfeatures,lflen*u8
# Gossipd -> master: peer sent non-gossip packet. Two fds: peer and gossip
gossip_peer_nongossip,3003
gossip_peer_nongossip,,id,struct pubkey
gossip_peer_nongossip,,crypto_state,struct crypto_state
gossip_peer_nongossip,,gflen,u16
gossip_peer_nongossip,,gfeatures,gflen*u8
gossip_peer_nongossip,,lflen,u16
gossip_peer_nongossip,,lfeatures,lflen*u8
gossip_peer_nongossip,,len,u16
gossip_peer_nongossip,,msg,len*u8
# Master -> gossipd: release a peer (so we can open a channel)
gossipctl_release_peer,3004
gossipctl_release_peer,,id,struct pubkey
# Gossipd -> master: reply to gossip_release_peer. Two fds: peer and gossip.
gossipctl_release_peer_reply,3104
gossipctl_release_peer_reply,,crypto_state,struct crypto_state
gossipctl_release_peer_reply,,gflen,u16
gossipctl_release_peer_reply,,gfeatures,gflen*u8
gossipctl_release_peer_reply,,lflen,u16
gossipctl_release_peer_reply,,lfeatures,lflen*u8
# This is if we couldn't find the peer.
gossipctl_release_peer_replyfail,3202
# Gossipd -> master: reply to gossip_release_peer if we couldn't find the peer.
gossipctl_release_peer_replyfail,3204
# This is where we save a peer's features.
#gossipstatus_peer_features,3001
#gossipstatus_peer_features,,unique_id,u64
#gossipstatus_peer_features,,gflen,u16
#gossipstatus_peer_features,,globalfeatures,gflen*u8
#gossipstatus_peer_features,,lflen,u16
#gossipstatus_peer_features,,localfeatures,lflen*u8
# Peer can send non-gossip packet (usually an open_channel) (followed two fds: peer and gossip)
gossipstatus_peer_nongossip,3004
gossipstatus_peer_nongossip,,unique_id,u64
gossipstatus_peer_nongossip,,crypto_state,struct crypto_state
gossipstatus_peer_nongossip,,len,u16
gossipstatus_peer_nongossip,,msg,len*u8
# Gossipd -> master: take over peer, with optional msg. (+peer fd)
gossipctl_handle_peer,3013
gossipctl_handle_peer,,id,struct pubkey
gossipctl_handle_peer,,crypto_state,struct crypto_state
gossipctl_handle_peer,,gflen,u16
gossipctl_handle_peer,,gfeatures,gflen*u8
gossipctl_handle_peer,,lflen,u16
gossipctl_handle_peer,,lfeatures,lflen*u8
gossipctl_handle_peer,,len,u16
gossipctl_handle_peer,,msg,len*u8
# Pass JSON-RPC getnodes call through
gossip_getnodes_request,3005
@ -73,13 +92,16 @@ gossip_getchannels_reply,3107
gossip_getchannels_reply,,num_channels,u16
gossip_getchannels_reply,,nodes,num_channels*struct gossip_getchannels_entry
# Ping/pong test.
# Ping/pong test. Waits for a reply if it expects one.
gossip_ping,3008
gossip_ping,,unique_id,u64
gossip_ping,,id,struct pubkey
gossip_ping,,num_pong_bytes,u16
gossip_ping,,len,u16
gossip_ping_reply,3108
# False if id in gossip_ping was unknown.
gossip_ping_reply,,sent,bool
# 0 == no pong expected
gossip_ping_reply,,totlen,u16
# Given a short_channel_id, return the endpoints
@ -96,25 +118,3 @@ gossip_forwarded_msg,3010
gossip_forwarded_msg,,msglen,u16
gossip_forwarded_msg,,msg,msglen*u8
# If peer is still connected, fail it (master does this for reconnect)
gossipctl_drop_peer,3011
gossipctl_drop_peer,,unique_id,u64
# Get a gossip fd for this peer (it has reconnected)
gossipctl_get_peer_gossipfd,3012
gossipctl_get_peer_gossipfd,,unique_id,u64
# Does it want a full dump of gossip?
gossipctl_get_peer_gossipfd,,sync,bool
# + fd.
gossipctl_get_peer_gossipfd_reply,3112
# Failure (can't make new socket)
gossipctl_get_peer_gossipfd_replyfail,3212
# Send canned message to peer and fail it.
gossipctl_fail_peer,3013
gossipctl_fail_peer,,unique_id,u64
gossipctl_fail_peer,,crypto_state,struct crypto_state
gossipctl_fail_peer,,len,u16
gossipctl_fail_peer,,failmsg,len*u8

1 # Peers can give a bad message, we close their fd, but no harm done. #include <common/cryptomsg.h>
# Peers can give a bad message, we close their fd, but no harm done.
gossipstatus_peer_bad_msg,13000
gossipstatus_peer_bad_msg,,unique_id,u64
gossipstatus_peer_bad_msg,,len,u16
gossipstatus_peer_bad_msg,,err,len*u8
# Misc problems like opening control fd.
gossipstatus_peer_failed,13001
gossipstatus_peer_failed,,unique_id,u64
gossipstatus_peer_failed,,len,u16
gossipstatus_peer_failed,,err,len*u8
#include <common/cryptomsg.h>
# Initialize the gossip daemon
1 gossipctl_init,3000 #include <common/cryptomsg.h>
2 gossipctl_init,,broadcast_interval,u32 # Initialize the gossip daemon.
3 gossipctl_init,,chain_hash,struct sha256_double gossipctl_init,3000
4 # These take an fd, but have no response gossipctl_init,,broadcast_interval,u32
5 gossipctl_new_peer,3001 gossipctl_init,,chain_hash,struct sha256_double
6 gossipctl_new_peer,,unique_id,u64 gossipctl_init,,id,struct pubkey
7 # If non-zero, port to listen on.
8 gossipctl_init,,port,u16
9 gossipctl_init,,gflen,u16
10 gossipctl_init,,gfeatures,gflen*u8
11 gossipctl_init,,lflen,u16
12 gossipctl_init,,lfeatures,lflen*u8
13 # Master -> gossipd: Optional hint for where to find peer.
14 gossipctl_new_peer,,crypto_state,struct crypto_state gossipctl_peer_addrhint,3014
15 # Tell it to release a peer which has initialized. gossipctl_peer_addrhint,,id,struct pubkey
16 gossipctl_release_peer,3002 gossipctl_peer_addrhint,,addr,struct ipaddr
17 gossipctl_release_peer,,unique_id,u64 # Master -> gossipd: connect to a peer. We may get a peer_connected.
18 # This releases the peer and returns the cryptostate (followed two fds: peer and gossip) gossipctl_reach_peer,3001
19 gossipctl_release_peer_reply,3102 gossipctl_reach_peer,,id,struct pubkey
20 gossipctl_release_peer_reply,,crypto_state,struct crypto_state # Gossipd -> master: we got a peer. Two fds: peer and gossip
21 # This is if we couldn't find the peer. gossip_peer_connected,3002
22 gossipctl_release_peer_replyfail,3202 gossip_peer_connected,,id,struct pubkey
23 # This is where we save a peer's features. gossip_peer_connected,,crypto_state,struct crypto_state
24 #gossipstatus_peer_features,3001 gossip_peer_connected,,gflen,u16
25 #gossipstatus_peer_features,,unique_id,u64 gossip_peer_connected,,gfeatures,gflen*u8
26 gossip_peer_connected,,lflen,u16
27 gossip_peer_connected,,lfeatures,lflen*u8
28 # Gossipd -> master: peer sent non-gossip packet. Two fds: peer and gossip
29 gossip_peer_nongossip,3003
30 gossip_peer_nongossip,,id,struct pubkey
31 gossip_peer_nongossip,,crypto_state,struct crypto_state
32 gossip_peer_nongossip,,gflen,u16
33 gossip_peer_nongossip,,gfeatures,gflen*u8
34 gossip_peer_nongossip,,lflen,u16
35 gossip_peer_nongossip,,lfeatures,lflen*u8
36 gossip_peer_nongossip,,len,u16
37 gossip_peer_nongossip,,msg,len*u8
38 # Master -> gossipd: release a peer (so we can open a channel)
39 gossipctl_release_peer,3004
40 gossipctl_release_peer,,id,struct pubkey
41 # Gossipd -> master: reply to gossip_release_peer. Two fds: peer and gossip.
42 gossipctl_release_peer_reply,3104
43 gossipctl_release_peer_reply,,crypto_state,struct crypto_state
44 gossipctl_release_peer_reply,,gflen,u16
45 gossipctl_release_peer_reply,,gfeatures,gflen*u8
46 gossipctl_release_peer_reply,,lflen,u16
47 gossipctl_release_peer_reply,,lfeatures,lflen*u8
48 # Gossipd -> master: reply to gossip_release_peer if we couldn't find the peer.
49 gossipctl_release_peer_replyfail,3204
50 #gossipstatus_peer_features,,gflen,u16 # Gossipd -> master: take over peer, with optional msg. (+peer fd)
51 gossipctl_handle_peer,3013
52 gossipctl_handle_peer,,id,struct pubkey
53 gossipctl_handle_peer,,crypto_state,struct crypto_state
54 gossipctl_handle_peer,,gflen,u16
55 #gossipstatus_peer_features,,globalfeatures,gflen*u8 gossipctl_handle_peer,,gfeatures,gflen*u8
56 #gossipstatus_peer_features,,lflen,u16 gossipctl_handle_peer,,lflen,u16
57 #gossipstatus_peer_features,,localfeatures,lflen*u8 gossipctl_handle_peer,,lfeatures,lflen*u8
58 # Peer can send non-gossip packet (usually an open_channel) (followed two fds: peer and gossip) gossipctl_handle_peer,,len,u16
59 gossipstatus_peer_nongossip,3004 gossipctl_handle_peer,,msg,len*u8
60 gossipstatus_peer_nongossip,,unique_id,u64 # Pass JSON-RPC getnodes call through
61 gossipstatus_peer_nongossip,,crypto_state,struct crypto_state gossip_getnodes_request,3005
62 gossipstatus_peer_nongossip,,len,u16 #include <lightningd/gossip_msg.h>
63 gossipstatus_peer_nongossip,,msg,len*u8 gossip_getnodes_reply,3105
64 # Pass JSON-RPC getnodes call through gossip_getnodes_reply,,num_nodes,u16
65 gossip_getnodes_request,3005 gossip_getnodes_reply,,nodes,num_nodes*struct gossip_getnodes_entry
66 #include <lightningd/gossip_msg.h> # Pass JSON-RPC getroute call through
67 gossip_getnodes_reply,3105 gossip_getroute_request,3006
68 gossip_getnodes_reply,,num_nodes,u16 gossip_getroute_request,,source,struct pubkey
gossip_getnodes_reply,,nodes,num_nodes*struct gossip_getnodes_entry
# Pass JSON-RPC getroute call through
gossip_getroute_request,3006
gossip_getroute_request,,source,struct pubkey
69 gossip_getroute_request,,destination,struct pubkey gossip_getroute_request,,destination,struct pubkey
70 gossip_getroute_request,,msatoshi,u32 gossip_getroute_request,,msatoshi,u32
71 gossip_getroute_request,,riskfactor,u16 gossip_getroute_request,,riskfactor,u16
92 # The main daemon forward some gossip message to gossipd, allows injecting gossip_resolve_channel_reply,3109
93 # arbitrary gossip messages. gossip_resolve_channel_reply,,num_keys,u16
94 gossip_forwarded_msg,3010 gossip_resolve_channel_reply,,keys,num_keys*struct pubkey
95 gossip_forwarded_msg,,msglen,u16 # The main daemon forward some gossip message to gossipd, allows injecting
96 gossip_forwarded_msg,,msg,msglen*u8 # arbitrary gossip messages.
97 # If peer is still connected, fail it (master does this for reconnect) gossip_forwarded_msg,3010
98 gossipctl_drop_peer,3011 gossip_forwarded_msg,,msglen,u16
99 gossipctl_drop_peer,,unique_id,u64 gossip_forwarded_msg,,msg,msglen*u8
100 # Get a gossip fd for this peer (it has reconnected)
101 gossipctl_get_peer_gossipfd,3012
102
103
104
105 gossipctl_get_peer_gossipfd,,unique_id,u64
106 # Does it want a full dump of gossip?
107 gossipctl_get_peer_gossipfd,,sync,bool
118
119
120

View File

@ -34,13 +34,13 @@ LIGHTNINGD_COMMON_OBJS := \
common/utils.o \
common/utxo.o \
common/version.o \
common/wire_error.o \
common/withdraw_tx.o
LIGHTNINGD_SRC := \
lightningd/bitcoind.c \
lightningd/build_utxos.c \
lightningd/chaintopology.c \
lightningd/dns.c \
lightningd/gossip_control.c \
lightningd/gossip_msg.c \
lightningd/hsm_control.c \
@ -50,7 +50,6 @@ LIGHTNINGD_SRC := \
lightningd/lightningd.c \
lightningd/log.c \
lightningd/netaddr.c \
lightningd/new_connection.c \
lightningd/opt_time.c \
lightningd/options.c \
lightningd/pay.c \

View File

@ -13,16 +13,18 @@ static bool ping_reply(struct subd *subd, const u8 *msg, const int *fds,
struct command *cmd)
{
u16 totlen;
bool ok;
bool ok, sent = true;
log_debug(subd->ld->log, "Got ping reply!");
if (streq(subd->name, "lightning_channeld"))
ok = fromwire_channel_ping_reply(msg, NULL, &totlen);
else
ok = fromwire_gossip_ping_reply(msg, NULL, &totlen);
ok = fromwire_gossip_ping_reply(msg, NULL, &sent, &totlen);
if (!ok)
command_fail(cmd, "Bad reply message");
else if (!sent)
command_fail(cmd, "Unknown peer");
else {
struct json_result *response = new_json_result(cmd);
@ -41,6 +43,8 @@ static void json_dev_ping(struct command *cmd,
u8 *msg;
jsmntok_t *peeridtok, *lentok, *pongbytestok;
unsigned int len, pongbytes;
struct pubkey id;
struct subd *owner;
if (!json_get_params(buffer, params,
"peerid", &peeridtok,
@ -51,21 +55,8 @@ static void json_dev_ping(struct command *cmd,
return;
}
peer = peer_from_json(cmd->ld, buffer, peeridtok);
if (!peer) {
command_fail(cmd, "Could not find peer with that peerid");
return;
}
/* FIXME: These checks are horrible, use a peer flag to say it's
* ready to forward! */
if (peer->owner && !streq(peer->owner->name, "lightning_channeld")
&& !streq(peer->owner->name, "lightning_gossipd")) {
command_fail(cmd, "Peer in %s",
peer->owner ? peer->owner->name : "unattached");
return;
}
if (!json_tok_number(buffer, lentok, &len)) {
command_fail(cmd, "'%.*s' is not a valid number",
(int)(lentok->end - lentok->start),
@ -80,13 +71,32 @@ static void json_dev_ping(struct command *cmd,
return;
}
if (streq(peer->owner->name, "lightning_channeld"))
msg = towire_channel_ping(cmd, pongbytes, len);
else
msg = towire_gossip_ping(cmd, peer->unique_id, pongbytes, len);
if (!json_tok_pubkey(buffer, peeridtok, &id)) {
command_fail(cmd, "'%.*s' is not a valid pubkey",
(int)(peeridtok->end - peeridtok->start),
buffer + peeridtok->start);
return;
}
/* FIXME: If subdaemon dies? */
subd_req(peer->owner, peer->owner, take(msg), -1, 0, ping_reply, cmd);
/* First, see if it's in channeld. */
peer = peer_by_id(cmd->ld, &id);
if (peer) {
if (!peer->owner ||
!streq(peer->owner->name, "lightning_channeld")) {
command_fail(cmd, "Peer in %s",
peer->owner
? peer->owner->name : "unattached");
return;
}
msg = towire_channel_ping(cmd, pongbytes, len);
owner = peer->owner;
} else {
/* We assume it's in gossipd. */
msg = towire_gossip_ping(cmd, &id, pongbytes, len);
owner = cmd->ld->gossip;
}
subd_req(owner, owner, take(msg), -1, 0, ping_reply, cmd);
}
static const struct json_command dev_ping_command = {

View File

@ -1,247 +0,0 @@
/* Async dns helper. */
#include "dns.h"
#include "lightningd.h"
#include "log.h"
#include "netaddr.h"
#include <assert.h>
#include <ccan/err/err.h>
#include <ccan/read_write_all/read_write_all.h>
#include <ccan/tal/str/str.h>
#include <ccan/tal/tal.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
struct dns_async {
struct lightningd *ld;
struct io_plan *(*init)(struct io_conn *, struct lightningd *,
const struct netaddr *,
void *);
void (*fail)(struct lightningd *, void *arg);
const char *name;
void *arg;
int pid;
size_t num_addresses;
struct netaddr *addresses;
};
/* This runs in the child */
static void lookup_and_write(int fd, const char *name, const char *port)
{
struct addrinfo *addr, *i;
struct netaddr *addresses;
size_t num;
struct addrinfo hints;
/* We don't want UDP sockets (yet?) */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(name, port, &hints, &addr) != 0)
return;
num = 0;
for (i = addr; i; i = i->ai_next)
num++;
addresses = tal_arr(NULL, struct netaddr, num);
num = 0;
for (i = addr; i; i = i->ai_next) {
addresses[num].type = i->ai_socktype;
addresses[num].protocol = i->ai_protocol;
addresses[num].addrlen = i->ai_addrlen;
memset(&addresses[num].saddr, 0, sizeof(addresses[num].saddr));
/* Let parent report this error. */
if (i->ai_addrlen <= sizeof(addresses[num].saddr))
memcpy(&addresses[num].saddr, i->ai_addr, i->ai_addrlen);
num++;
}
if (!num) {
tal_free(addresses);
return;
}
if (write_all(fd, &num, sizeof(num)))
write_all(fd, addresses, num * sizeof(addresses[0]));
tal_free(addresses);
}
static struct io_plan *connected(struct io_conn *conn, struct dns_async *d)
{
struct io_plan *plan;
/* No longer need to try more connections via connect_failed. */
io_set_finish(conn, NULL, NULL);
plan = d->init(conn, d->ld, &d->addresses[-1], d->arg);
tal_free(d);
return plan;
}
static void try_connect_one(struct dns_async *d);
/* If this connection failed, try connecting to another address. */
static void connect_failed(struct io_conn *conn, struct dns_async *d)
{
try_connect_one(d);
}
static struct io_plan *init_conn(struct io_conn *conn, struct dns_async *d)
{
struct addrinfo a;
netaddr_to_addrinfo(&a, &d->addresses[0]);
/* Consume that address. */
d->addresses++;
d->num_addresses--;
io_set_finish(conn, connect_failed, d);
/* That new connection owns d */
return io_connect(conn, &a, connected, d);
}
static void try_connect_one(struct dns_async *d)
{
int fd;
while (d->num_addresses) {
const struct netaddr *a = &d->addresses[0];
/* Now we can warn if it's overlength */
if (a->addrlen > sizeof(a->saddr)) {
log_broken(d->ld->log,
"DNS lookup gave overlength address for %s"
" for family %u, len=%u",
d->name, a->saddr.s.sa_family, a->addrlen);
} else {
/* Might not even be able to create eg. IPv6 sockets */
fd = socket(a->saddr.s.sa_family, a->type, a->protocol);
if (fd >= 0) {
io_new_conn(d->ld, fd, init_conn, d);
return;
}
}
/* Consume that address. */
d->addresses++;
d->num_addresses--;
}
/* We're out of things to try. Fail. */
d->fail(d->ld, d->arg);
tal_free(d);
}
static struct io_plan *start_connecting(struct io_conn *conn,
struct dns_async *d)
{
assert(d->num_addresses);
/* OK, we've read all we want, child should exit. */
waitpid(d->pid, NULL, 0);
/* No need to call dns_lookup_failed now. */
io_set_finish(conn, NULL, NULL);
try_connect_one(d);
return io_close(conn);
}
struct dns_async *multiaddress_connect_(struct lightningd *ld,
const struct netaddr *addresses,
struct io_plan *(*init)(struct io_conn *,
struct lightningd *,
const struct netaddr *,
void *arg),
void (*fail)(struct lightningd *, void *arg),
void *arg)
{
struct dns_async *d = tal(ld, struct dns_async);
d->ld = ld;
d->init = init;
d->fail = fail;
d->arg = arg;
d->name = "names from address list";
d->num_addresses = tal_count(addresses);
d->addresses = tal_dup_arr(d, struct netaddr, addresses,
d->num_addresses, 0);
try_connect_one(d);
return d;
}
static struct io_plan *read_addresses(struct io_conn *conn, struct dns_async *d)
{
d->addresses = tal_arr(d, struct netaddr, d->num_addresses);
return io_read(conn, d->addresses,
d->num_addresses * sizeof(d->addresses[0]),
start_connecting, d);
}
static struct io_plan *init_dns_conn(struct io_conn *conn, struct dns_async *d)
{
return io_read(conn, &d->num_addresses, sizeof(d->num_addresses),
read_addresses, d);
}
static void dns_lookup_failed(struct io_conn *conn, struct dns_async *d)
{
waitpid(d->pid, NULL, 0);
d->fail(d->ld, d->arg);
tal_free(d);
}
struct dns_async *dns_resolve_and_connect_(struct lightningd *ld,
const char *name, const char *port,
struct io_plan *(*init)(struct io_conn *,
struct lightningd *,
const struct netaddr *,
void *arg),
void (*fail)(struct lightningd *, void *arg),
void *arg)
{
int pfds[2];
struct dns_async *d = tal(ld, struct dns_async);
struct io_conn *conn;
d->ld = ld;
d->init = init;
d->fail = fail;
d->arg = arg;
d->name = tal_fmt(d, "%s:%s", name, port);
/* First fork child to get addresses. */
if (pipe(pfds) != 0) {
log_unusual(ld->log,
"Creating pipes for dns lookup: %s",
strerror(errno));
return NULL;
}
fflush(stdout);
d->pid = fork();
switch (d->pid) {
case -1:
log_unusual(ld->log, "forking for dns lookup: %s",
strerror(errno));
close(pfds[0]);
close(pfds[1]);
return NULL;
case 0:
close(pfds[0]);
lookup_and_write(pfds[1], name, port);
exit(0);
}
close(pfds[1]);
conn = io_new_conn(ld, pfds[0], init_dns_conn, d);
io_set_finish(conn, dns_lookup_failed, d);
return d;
}

View File

@ -1,53 +0,0 @@
#ifndef LIGHTNING_LIGHTNINGD_DNS_H
#define LIGHTNING_LIGHTNINGD_DNS_H
#include "config.h"
#include <ccan/io/io.h>
#include <ccan/tal/tal.h>
#include <ccan/typesafe_cb/typesafe_cb.h>
#include <stdbool.h>
struct lightningd;
struct netaddr;
#define dns_resolve_and_connect(dstate, name, port, initfn, failfn, arg) \
dns_resolve_and_connect_((dstate), (name), (port), \
typesafe_cb_preargs(struct io_plan *, void *, \
(initfn), (arg), \
struct io_conn *, \
struct lightningd *, \
const struct netaddr *), \
typesafe_cb_preargs(void, void *, (failfn), (arg), \
struct lightningd *), \
(arg))
struct dns_async *dns_resolve_and_connect_(struct lightningd *ld,
const char *name, const char *port,
struct io_plan *(*init)(struct io_conn *,
struct lightningd *,
const struct netaddr *,
void *arg),
void (*fail)(struct lightningd *, void *arg),
void *arg);
/* Don't do lookup, just try to connect to these addresses. */
#define multiaddress_connect(dstate, addresses, initfn, failfn, arg) \
multiaddress_connect_((dstate), (addresses), \
typesafe_cb_preargs(struct io_plan *, void *, \
(initfn), (arg), \
struct io_conn *, \
struct lightningd *, \
const struct netaddr *), \
typesafe_cb_preargs(void, void *, (failfn), (arg), \
struct lightningd *), \
(arg))
struct dns_async *multiaddress_connect_(struct lightningd *ld,
const struct netaddr *addresses,
struct io_plan *(*init)(struct io_conn *,
struct lightningd *,
const struct netaddr *,
void *arg),
void (*fail)(struct lightningd *, void *arg),
void *arg);
#endif /* LIGHTNING_LIGHTNINGD_DNS_H */

View File

@ -27,69 +27,34 @@ static void gossip_finished(struct subd *gossip, int status)
errx(1, "Gossip failed (signal %u), exiting.", WTERMSIG(status));
}
static void peer_bad_message(struct subd *gossip, const u8 *msg)
{
u64 unique_id;
struct peer *peer;
u8 *err;
if (!fromwire_gossipstatus_peer_bad_msg(msg, msg, NULL,
&unique_id, &err))
fatal("Gossip gave bad PEER_BAD message %s", tal_hex(msg, msg));
peer = peer_by_unique_id(gossip->ld, unique_id);
if (!peer)
fatal("Gossip gave bad peerid %"PRIu64, unique_id);
log_debug(gossip->log, "Peer %s gave bad msg %s",
type_to_string(msg, struct pubkey, &peer->id),
tal_hex(msg, msg));
peer_fail_permanent(peer, msg);
}
static void peer_failed(struct subd *gossip, const u8 *msg)
{
u64 unique_id;
struct peer *peer;
u8 *err;
if (!fromwire_gossipstatus_peer_failed(msg, msg, NULL,
&unique_id, &err))
fatal("Gossip gave bad PEER_FAILED message %s",
tal_hex(msg, msg));
peer = peer_by_unique_id(gossip->ld, unique_id);
if (!peer)
fatal("Gossip gave bad peerid %"PRIu64, unique_id);
peer_fail_permanent(peer, msg);
}
static void peer_nongossip(struct subd *gossip, const u8 *msg,
int peer_fd, int gossip_fd)
{
u64 unique_id;
struct peer *peer;
u8 *inner;
struct pubkey id;
struct crypto_state cs;
u8 *gfeatures, *lfeatures, *in_pkt;
if (!fromwire_gossipstatus_peer_nongossip(msg, msg, NULL,
&unique_id, &cs, &inner))
fatal("Gossip gave bad PEER_NONGOSSIP message %s",
if (!fromwire_gossip_peer_nongossip(msg, msg, NULL,
&id, &cs,
&gfeatures,
&lfeatures,
&in_pkt))
fatal("Gossip gave bad GOSSIP_PEER_NONGOSSIP message %s",
tal_hex(msg, msg));
peer = peer_by_unique_id(gossip->ld, unique_id);
if (!peer)
fatal("Gossip gave bad peerid %"PRIu64, unique_id);
/* We already checked the features when it first connected. */
if (unsupported_features(gfeatures, lfeatures)) {
log_unusual(gossip->log,
"Gossip gave unsupported features %s/%s",
tal_hex(msg, gfeatures),
tal_hex(msg, lfeatures));
close(peer_fd);
close(gossip_fd);
return;
}
if (peer->owner != gossip)
fatal("Gossip gave bad peerid %"PRIu64" (owner %s)",
unique_id, peer->owner ? peer->owner->name : "(none)");
log_info(peer->log, "Gossip ended up receipt of %s",
wire_type_name(fromwire_peektype(inner)));
peer_fundee_open(peer, inner, &cs, peer_fd, gossip_fd);
peer_sent_nongossip(gossip->ld, &id, &cs, gfeatures, lfeatures,
peer_fd, gossip_fd, in_pkt);
}
static int gossip_msg(struct subd *gossip, const u8 *msg, const int *fds)
@ -99,35 +64,31 @@ static int gossip_msg(struct subd *gossip, const u8 *msg, const int *fds)
switch (t) {
/* These are messages we send, not them. */
case WIRE_GOSSIPCTL_INIT:
case WIRE_GOSSIPCTL_NEW_PEER:
case WIRE_GOSSIPCTL_FAIL_PEER:
case WIRE_GOSSIPCTL_RELEASE_PEER:
case WIRE_GOSSIPCTL_DROP_PEER:
case WIRE_GOSSIPCTL_GET_PEER_GOSSIPFD:
case WIRE_GOSSIP_GETNODES_REQUEST:
case WIRE_GOSSIP_GETROUTE_REQUEST:
case WIRE_GOSSIP_GETCHANNELS_REQUEST:
case WIRE_GOSSIP_PING:
case WIRE_GOSSIP_RESOLVE_CHANNEL_REQUEST:
case WIRE_GOSSIP_FORWARDED_MSG:
case WIRE_GOSSIPCTL_REACH_PEER:
case WIRE_GOSSIPCTL_HANDLE_PEER:
case WIRE_GOSSIPCTL_RELEASE_PEER:
case WIRE_GOSSIPCTL_PEER_ADDRHINT:
/* This is a reply, so never gets through to here. */
case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY:
case WIRE_GOSSIPCTL_RELEASE_PEER_REPLYFAIL:
case WIRE_GOSSIPCTL_GET_PEER_GOSSIPFD_REPLY:
case WIRE_GOSSIPCTL_GET_PEER_GOSSIPFD_REPLYFAIL:
case WIRE_GOSSIP_GETNODES_REPLY:
case WIRE_GOSSIP_GETROUTE_REPLY:
case WIRE_GOSSIP_GETCHANNELS_REPLY:
case WIRE_GOSSIP_PING_REPLY:
case WIRE_GOSSIP_RESOLVE_CHANNEL_REPLY:
case WIRE_GOSSIPCTL_RELEASE_PEER_REPLY:
case WIRE_GOSSIPCTL_RELEASE_PEER_REPLYFAIL:
break;
case WIRE_GOSSIPSTATUS_PEER_BAD_MSG:
peer_bad_message(gossip, msg);
case WIRE_GOSSIP_PEER_CONNECTED:
if (tal_count(fds) != 2)
return 2;
peer_connected(gossip->ld, msg, fds[0], fds[1]);
break;
case WIRE_GOSSIPSTATUS_PEER_FAILED:
peer_failed(gossip, msg);
break;
case WIRE_GOSSIPSTATUS_PEER_NONGOSSIP:
case WIRE_GOSSIP_PEER_NONGOSSIP:
if (tal_count(fds) != 2)
return 2;
peer_nongossip(gossip, msg, fds[0], fds[1]);
@ -164,7 +125,10 @@ void gossip_init(struct lightningd *ld)
err(1, "Could not subdaemon gossip");
msg = towire_gossipctl_init(tmpctx, ld->broadcast_interval,
&get_chainparams(ld)->genesis_blockhash);
&get_chainparams(ld)->genesis_blockhash,
&ld->id, ld->portnum,
get_supported_global_features(tmpctx),
get_supported_local_features(tmpctx));
subd_send_msg(ld->gossip, msg);
tal_free(tmpctx);
}

View File

@ -1,6 +1,7 @@
#ifndef LIGHTNING_LIGHTNINGD_GOSSIP_CONTROL_H
#define LIGHTNING_LIGHTNINGD_GOSSIP_CONTROL_H
#include "config.h"
#include <ccan/short_types/short_types.h>
#include <stdbool.h>
struct lightningd;

View File

@ -655,5 +655,6 @@ void setup_jsonrpc(struct lightningd *ld, const char *rpc_filename)
if (listen(fd, 1) != 0)
err(1, "Listening on '%s'", rpc_filename);
log_debug(ld->log, "Listening on '%s'", rpc_filename);
io_new_listener(ld, fd, incoming_jcon_connected, ld);
}

View File

@ -31,16 +31,6 @@
char *bitcoin_datadir;
struct peer *find_peer_by_unique_id(struct lightningd *ld, u64 unique_id)
{
struct peer *peer;
list_for_each(&ld->peers, peer, list) {
if (peer->unique_id == unique_id)
return peer;
}
return NULL;
}
void notify_new_block(struct chain_topology *topo, u32 height);
void notify_new_block(struct chain_topology *topo, u32 height)
{
@ -81,7 +71,6 @@ static struct lightningd *new_lightningd(const tal_t *ctx,
struct lightningd *ld = tal(ctx, struct lightningd);
list_head_init(&ld->peers);
ld->peer_counter = 0;
ld->dev_debug_subdaemon = NULL;
htlc_in_map_init(&ld->htlcs_in);
htlc_out_map_init(&ld->htlcs_out);
@ -90,6 +79,7 @@ static struct lightningd *new_lightningd(const tal_t *ctx,
ld->log = new_log(log_book, log_book, "lightningd(%u):", (int)getpid());
list_head_init(&ld->pay_commands);
list_head_init(&ld->connects);
ld->portnum = DEFAULT_PORT;
timers_init(&ld->timers, time_mono());
ld->topology = new_topology(ld, ld->log);
@ -260,15 +250,9 @@ int main(int argc, char *argv[])
/* Initialize wallet, now that we are in the correct directory */
ld->wallet = wallet_new(ld, ld->log);
/* Mark ourselves live. */
log_info(ld->log, "Hello world from %s!", version());
/* Set up HSM. */
hsm_init(ld, newdir);
/* Set up gossip daemon. */
gossip_init(ld);
/* Initialize block topology. */
setup_topology(ld->topology,
&ld->timers,
@ -281,6 +265,9 @@ int main(int argc, char *argv[])
err(1, "Could not load invoices from the database");
}
/* Set up gossip daemon. */
gossip_init(ld);
/* Load peers from database */
wallet_channels_load_active(ld->wallet, &ld->peers);
@ -302,8 +289,8 @@ int main(int argc, char *argv[])
/* Create RPC socket (if any) */
setup_jsonrpc(ld, ld->rpc_filename);
/* Ready for connections from peers. */
setup_listeners(ld);
/* Mark ourselves live. */
log_info(ld->log, "Hello world from %s!", version());
#if 0
/* Load peers from database. */

View File

@ -103,8 +103,9 @@ struct lightningd {
struct list_head peers;
/* FIXME: This should stay in HSM */
struct secret peer_seed;
/* Used to give a unique seed to every peer. */
u64 peer_counter;
/* Outstanding connect commands. */
struct list_head connects;
/* Our chain topology. */
struct chain_topology *topology;
@ -150,7 +151,5 @@ struct lightningd {
void derive_peer_seed(struct lightningd *ld, struct privkey *peer_seed,
const struct pubkey *peer_id, const u64 channel_id);
struct peer *find_peer_by_unique_id(struct lightningd *ld, u64 unique_id);
struct chainparams *get_chainparams(const struct lightningd *ld);
#endif /* LIGHTNING_LIGHTNINGD_LIGHTNINGD_H */

View File

@ -1,3 +1,4 @@
/* FIXME: We should deprecate this in favor of BOLT7 address descriptor */
#ifndef LIGHTNING_LIGHTNINGD_NETADDR_H
#define LIGHTNING_LIGHTNINGD_NETADDR_H
#include "config.h"

View File

@ -1,283 +0,0 @@
#include <ccan/array_size/array_size.h>
#include <ccan/fdpass/fdpass.h>
#include <ccan/tal/str/str.h>
#include <common/cryptomsg.h>
#include <errno.h>
#include <fcntl.h>
#include <handshaked/gen_handshake_wire.h>
#include <hsmd/gen_hsm_wire.h>
#include <lightningd/hsm_control.h>
#include <lightningd/jsonrpc.h>
#include <lightningd/lightningd.h>
#include <lightningd/log.h>
#include <lightningd/new_connection.h>
#include <lightningd/peer_control.h>
#include <lightningd/subd.h>
#include <unistd.h>
#include <wire/wire_sync.h>
const u8 supported_local_features[] = {LOCALFEATURES_INITIAL_ROUTING_SYNC};
const u8 supported_global_features[] = {0x00};
/* Before we have identified the peer, we just have a connection object. */
struct connection {
/* Lightning daemon, for when we're handed through callbacks. */
struct lightningd *ld;
/* Where we connected to/from. */
struct netaddr netaddr;
/* Unique identifier for handshaked. */
u64 unique_id;
/* Json command which made us connect (if any) */
struct command *cmd;
/* If we are initiating, we known their id. Otherwise NULL. */
struct pubkey *known_id;
};
static void connection_destroy(struct connection *c)
{
/* FIXME: better diagnostics. */
if (c->cmd)
command_fail(c->cmd, "Failed to connect to peer");
}
static void
PRINTF_FMT(3,4) connection_failed(struct connection *c, struct log *log,
const char *fmt, ...)
{
const char *msg;
va_list ap;
va_start(ap, fmt);
msg = tal_vfmt(c, fmt, ap);
va_end(ap);
log_info(log, "%s", msg);
if (c->cmd) {
command_fail(c->cmd, "%s", msg);
/* Don't fail in destructor, too. */
c->cmd = NULL;
}
tal_free(c);
}
struct connection *new_connection(const tal_t *ctx,
struct lightningd *ld,
struct command *cmd,
const struct pubkey *known_id)
{
static u64 id_counter = 1;
struct connection *c = tal(ctx, struct connection);
c->ld = ld;
c->unique_id = id_counter++;
c->cmd = cmd;
if (known_id)
c->known_id = tal_dup(c, struct pubkey, known_id);
else
c->known_id = NULL;
tal_add_destructor(c, connection_destroy);
return c;
}
/**
* requires_unsupported_features - Check if we support what's being asked
*
* Given the features vector that the remote connection is expecting
* from us, we check to see if we support all even bit features, i.e.,
* the required features. We do so by subtracting our own features in
* the provided positions and see if even bits remain.
*
* @bitmap: the features bitmap the peer is asking for
* @supportmap: what do we support
* @smlen: how long is our supportmap
*/
static bool requires_unsupported_features(const u8 *bitmap,
const u8 *supportmap,
size_t smlen)
{
size_t len = tal_count(bitmap);
u8 support;
for (size_t i=0; i<len; i++) {
/* Find matching bitmap byte in supportmap, 0x00 if none */
if (len > smlen) {
support = 0x00;
} else {
support = supportmap[smlen-1];
}
/* Cancel out supported bits, check for even bits */
if ((~support & bitmap[i]) & 0x55)
return true;
}
return false;
}
static bool handshake_succeeded(struct subd *handshaked,
const u8 *msg, const int *fds,
struct connection *c)
{
struct crypto_state cs;
struct pubkey *id;
u8 *globalfeatures, *localfeatures;
assert(tal_count(fds) == 1);
/* FIXME: Look for peer duplicates! */
if (!c->known_id) {
id = tal(msg, struct pubkey);
if (!fromwire_handshake_responder_reply(c, msg, NULL, id, &cs,
&globalfeatures,
&localfeatures))
goto err;
log_info(handshaked->log, "Peer in from %s",
type_to_string(ltmp, struct pubkey, id));
} else {
id = c->known_id;
if (!fromwire_handshake_initiator_reply(c, msg, NULL, &cs,
&globalfeatures,
&localfeatures))
goto err;
log_info(handshaked->log, "Peer out to %s",
type_to_string(ltmp, struct pubkey, id));
}
/* BOLT #1:
*
* For unknown feature bits which are non-zero, the receiver
* MUST ignore the bit if the bit number is odd, and MUST fail
* the connection if the bit number is even.
*/
if (requires_unsupported_features(
globalfeatures, supported_global_features,
ARRAY_SIZE(supported_global_features))) {
connection_failed(c, handshaked->log,
"peer %s: bad globalfeatures: %s",
type_to_string(c, struct pubkey, id),
tal_hex(msg, globalfeatures));
return true;
}
if (requires_unsupported_features(
localfeatures, supported_local_features,
ARRAY_SIZE(supported_local_features))) {
connection_failed(c, handshaked->log,
"peer %s: bad localfeatures: %s",
type_to_string(c, struct pubkey, id),
tal_hex(msg, localfeatures));
return true;
}
if (c->cmd) {
struct json_result *response;
response = new_json_result(c->cmd);
json_object_start(response, NULL);
json_add_pubkey(response, "id", id);
json_object_end(response);
command_success(c->cmd, response);
c->cmd = NULL;
}
add_peer(handshaked->ld, c->unique_id, fds[0], id, &cs);
/* Now shut handshaked down (frees c as well) */
return false;
err:
log_broken(handshaked->log, "Malformed resp: %s", tal_hex(c, msg));
close(fds[0]);
return false;
}
/* Same path for connecting in vs connecting out. */
static struct io_plan *hsm_then_handshake(struct io_conn *conn,
struct lightningd *ld,
struct connection *c)
{
const tal_t *tmpctx = tal_tmpctx(conn);
int connfd = io_conn_fd(conn), hsmfd;
struct subd *handshaked;
u8 *msg;
/* Get HSM fd for this peer. */
msg = towire_hsmctl_hsmfd_ecdh(tmpctx, c->unique_id);
if (!wire_sync_write(ld->hsm_fd, msg))
fatal("Could not write to HSM: %s", strerror(errno));
msg = hsm_sync_read(tmpctx, ld);
if (!fromwire_hsmctl_hsmfd_ecdh_fd_reply(msg, NULL))
fatal("Malformed hsmfd response: %s", tal_hex(msg, msg));
hsmfd = fdpass_recv(ld->hsm_fd);
if (hsmfd < 0)
fatal("Could not read fd from HSM: %s", strerror(errno));
/* Make sure connection fd is blocking */
io_fd_block(connfd, true);
/* Give handshake daemon the hsm fd. */
handshaked = new_subd(ld,
"lightning_handshaked", NULL,
handshake_wire_type_name,
NULL, NULL, NULL,
take(&hsmfd), take(&connfd), NULL);
if (!handshaked) {
log_unusual(ld->log, "Could not subdaemon handshake: %s",
strerror(errno));
goto error;
}
/* If handshake daemon fails, we just drop connection. */
tal_steal(handshaked, c);
if (c->known_id) {
msg = towire_handshake_initiator(tmpctx, &ld->id, c->known_id);
} else {
msg = towire_handshake_responder(tmpctx, &ld->id);
}
/* Now hand peer request to the handshake daemon: hands it
* back on success */
subd_req(c, handshaked, take(msg), -1, 1, handshake_succeeded, c);
tal_free(tmpctx);
/* We don't need conn, we've passed fd to handshaked. */
return io_close_taken_fd(conn);
error:
close(hsmfd);
tal_free(tmpctx);
return io_close(conn);
}
struct io_plan *connection_out(struct io_conn *conn,
struct lightningd *ld,
const struct netaddr *netaddr,
struct connection *c)
{
c->netaddr = *netaddr;
return hsm_then_handshake(conn, ld, c);
}
struct io_plan *connection_in(struct io_conn *conn, struct lightningd *ld)
{
struct connection *c = new_connection(ld, ld, NULL, NULL);
/* FIXME: Don't assume TCP here. */
if (!netaddr_from_fd(io_conn_fd(conn), SOCK_STREAM, IPPROTO_TCP,
&c->netaddr)) {
log_unusual(ld->log, "Could not get address of incoming fd");
return io_close(conn);
}
return hsm_then_handshake(conn, ld, c);
}
const struct pubkey *connection_known_id(const struct connection *c)
{
return c->known_id;
}

View File

@ -1,25 +0,0 @@
#ifndef LIGHTNING_LIGHTNINGD_NEW_CONNECTION_H
#define LIGHTNING_LIGHTNINGD_NEW_CONNECTION_H
#include "config.h"
#include <stdbool.h>
struct command;
struct io_conn;
struct lightningd;
struct netaddr;
struct pubkey;
struct connection *new_connection(const tal_t *ctx,
struct lightningd *ld,
struct command *cmd,
const struct pubkey *known_id);
struct io_plan *connection_out(struct io_conn *conn,
struct lightningd *dstate,
const struct netaddr *netaddr,
struct connection *c);
struct io_plan *connection_in(struct io_conn *conn, struct lightningd *ld);
const struct pubkey *connection_known_id(const struct connection *c);
#endif /* LIGHTNING_LIGHTNINGD_NEW_CONNECTION_H */

File diff suppressed because it is too large Load Diff

View File

@ -29,6 +29,9 @@ struct peer {
/* ID of peer */
struct pubkey id;
/* Global and local features bitfields. */
const u8 *gfeatures, *lfeatures;
/* Error message (iff in error state) */
u8 *error;
@ -127,6 +130,12 @@ static inline bool peer_on_chain(const struct peer *peer)
return peer_state_on_chain(peer->state);
}
static inline bool peer_wants_reconnect(const struct peer *peer)
{
return peer->state >= CHANNELD_AWAITING_LOCKIN
&& peer->state <= CLOSINGD_COMPLETE;
}
/* BOLT #2:
*
* On disconnection, the funder MUST remember the channel for
@ -142,7 +151,6 @@ static inline bool peer_persists(const struct peer *peer)
return peer->state >= CHANNELD_AWAITING_LOCKIN;
}
struct peer *peer_by_unique_id(struct lightningd *ld, u64 unique_id);
struct peer *peer_by_id(struct lightningd *ld, const struct pubkey *id);
struct peer *peer_from_json(struct lightningd *ld,
const char *buffer,
@ -151,13 +159,23 @@ struct peer *peer_from_json(struct lightningd *ld,
void peer_last_tx(struct peer *peer, struct bitcoin_tx *tx,
const secp256k1_ecdsa_signature *sig);
void peer_fundee_open(struct peer *peer, const u8 *msg,
const struct crypto_state *cs,
int peer_fd, int gossip_fd);
/* The three ways peers enter from the network:
*
* peer_connected - when it first connects to gossipd (after init exchange).
* peer_sent_nongossip - when it tries to fund a channel.
* gossip_peer_released - when we tell gossipd to release it so we can fund
* a channel.
*/
void peer_connected(struct lightningd *ld, const u8 *msg,
int peer_fd, int gossip_fd);
void add_peer(struct lightningd *ld, u64 unique_id,
int fd, const struct pubkey *id,
const struct crypto_state *cs);
void peer_sent_nongossip(struct lightningd *ld,
const struct pubkey *id,
const struct crypto_state *cs,
const u8 *gfeatures,
const u8 *lfeatures,
int peer_fd, int gossip_fd,
const u8 *in_msg);
/**
* populate_peer -- Populate daemon fields in a peer
@ -171,6 +189,13 @@ void add_peer(struct lightningd *ld, u64 unique_id,
*/
void populate_peer(struct lightningd *ld, struct peer *peer);
/* Returns true if these contain any unsupported features. */
bool unsupported_features(const u8 *gfeatures, const u8 *lfeatures);
/* For sending our features: tal_len() returns length. */
u8 *get_supported_global_features(const tal_t *ctx);
u8 *get_supported_local_features(const tal_t *ctx);
/* Could be configurable. */
#define OUR_CHANNEL_FLAGS CHANNEL_FLAGS_ANNOUNCE_CHANNEL

View File

@ -5,9 +5,6 @@
enum peer_state {
UNINITIALIZED,
/* In gossip daemon. */
GOSSIPD,
/* Negotiating channel opening: in opening daemon */
OPENINGD,

View File

@ -55,9 +55,6 @@ void register_opts(struct lightningd *ld UNNEEDED)
/* Generated stub for setup_jsonrpc */
void setup_jsonrpc(struct lightningd *ld UNNEEDED, const char *rpc_filename UNNEEDED)
{ fprintf(stderr, "setup_jsonrpc called!\n"); abort(); }
/* Generated stub for setup_listeners */
void setup_listeners(struct lightningd *ld UNNEEDED)
{ fprintf(stderr, "setup_listeners called!\n"); abort(); }
/* Generated stub for setup_topology */
void setup_topology(struct chain_topology *topology UNNEEDED,
struct timers *timers UNNEEDED,

View File

@ -212,8 +212,8 @@ class LightningDTests(BaseLightningDTests):
assert ret['id'] == l2.info['id']
l1.daemon.wait_for_log('WIRE_GOSSIPCTL_NEW_PEER')
l2.daemon.wait_for_log('WIRE_GOSSIPCTL_NEW_PEER')
l1.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER')
l2.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER')
return l1,l2
def fund_channel(self, l1, l2, amount):
@ -267,18 +267,13 @@ class LightningDTests(BaseLightningDTests):
def test_connect(self):
l1,l2 = self.connect()
p1 = l1.rpc.getpeer(l2.info['id'], 'info')
p2 = l2.rpc.getpeer(l1.info['id'], 'info')
# Main daemon has no idea about these peers; they're in gossipd.
assert l1.rpc.getpeer(l2.info['id'], 'info') == None
assert l2.rpc.getpeer(l1.info['id'], 'info') == None
assert p1['state'] == 'GOSSIPD'
assert p2['state'] == 'GOSSIPD'
# It should have gone through these steps
assert 'state: UNINITIALIZED -> GOSSIPD' in p1['log']
# Both should still be owned by gossip
assert p1['owner'] == 'lightning_gossipd'
assert p2['owner'] == 'lightning_gossipd'
# Both gossipds will have them as new peers once handed back.
l1.daemon.wait_for_log('handle_peer {}: new peer'.format(l2.info['id']))
l2.daemon.wait_for_log('handle_peer {}: new peer'.format(l1.info['id']))
def test_balance(self):
l1,l2 = self.connect()
@ -403,8 +398,8 @@ class LightningDTests(BaseLightningDTests):
assert ret['id'] == l2.info['id']
l1.daemon.wait_for_log('WIRE_GOSSIPCTL_NEW_PEER')
l2.daemon.wait_for_log('WIRE_GOSSIPCTL_NEW_PEER')
l1.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER')
l2.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER')
addr = l1.rpc.newaddr()['address']
txid = l1.bitcoin.rpc.sendtoaddress(addr, 10**6 / 10**8 + 0.01)
@ -1087,7 +1082,7 @@ class LightningDTests(BaseLightningDTests):
assert ret['id'] == l3.info['id']
l3.daemon.wait_for_log('WIRE_GOSSIPCTL_NEW_PEER')
l3.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER')
self.fund_channel(l1, l2, 10**6)
self.fund_channel(l2, l3, 10**6)
@ -1138,20 +1133,20 @@ class LightningDTests(BaseLightningDTests):
l1.rpc.sendpay(to_json(route), rhash)
def test_disconnect(self):
# These should all make us fail.
# These should all make us fail, and retry.
# FIXME: Configure short timeout for reconnect!
disconnects = ['-WIRE_INIT',
'@WIRE_INIT',
'+WIRE_INIT']
l1 = self.node_factory.get_node(disconnect=disconnects)
l2 = self.node_factory.get_node()
for d in disconnects:
self.assertRaises(ValueError, l1.rpc.connect,
l2.info['id'], 'localhost:{}'.format(l2.info['port']))
assert l1.rpc.getpeer(l2.info['id']) == None
# Now we should connect normally.
l1.rpc.connect(l2.info['id'], 'localhost:{}'.format(l2.info['port']))
# Should have 3 connect fails.
for d in disconnects:
l1.daemon.wait_for_log('Failed connected out for {}, will try again'
.format(l2.info['id']))
def test_disconnect_funder(self):
# Now error on funder side duringchannel open.
disconnects = ['-WIRE_OPEN_CHANNEL',