diff --git a/channeld/channel.c b/channeld/channel.c index 4d0cbbb70f54..cf0e8324b746 100644 --- a/channeld/channel.c +++ b/channeld/channel.c @@ -160,6 +160,9 @@ struct peer { u8 channel_flags; bool announce_depth_reached; + + /* Where we got up to in gossip broadcasts. */ + u64 gossip_index; }; static u8 *create_channel_announcement(const tal_t *ctx, struct peer *peer); @@ -176,15 +179,23 @@ static void *tal_arr_append_(void **p, size_t size) static void gossip_in(struct peer *peer, const u8 *msg) { - u16 type = fromwire_peektype(msg); + u8 *gossip; + u16 type; + + if (!fromwire_gossip_send_gossip(msg, msg, NULL, + &peer->gossip_index, &gossip)) + status_failed(STATUS_FAIL_GOSSIP_IO, + "Got bad message from gossipd: %s", + tal_hex(msg, msg)); + type = fromwire_peektype(gossip); if (type == WIRE_CHANNEL_ANNOUNCEMENT || type == WIRE_CHANNEL_UPDATE || type == WIRE_NODE_ANNOUNCEMENT) - msg_enqueue(&peer->peer_out, msg); + msg_enqueue(&peer->peer_out, gossip); else status_failed(STATUS_FAIL_GOSSIP_IO, - "Got bad message from gossipd: %s", - tal_hex(msg, msg)); + "Got bad message type %s from gossipd: %s", + wire_type_name(type), tal_hex(msg, msg)); } static void send_announcement_signatures(struct peer *peer) @@ -356,16 +367,16 @@ static void handle_peer_funding_locked(struct peer *peer, const u8 *msg) static void announce_channel(struct peer *peer) { + tal_t *tmpctx = tal_tmpctx(peer); u8 *cannounce, *cupdate; - cannounce = create_channel_announcement(peer, peer); - cupdate = create_channel_update(cannounce, peer, false); + cannounce = create_channel_announcement(tmpctx, peer); + cupdate = create_channel_update(tmpctx, peer, false); - /* Tell the master that we to announce channel (it does node) */ - wire_sync_write(MASTER_FD, take(towire_channel_announce(peer, - cannounce, - cupdate))); - tal_free(cannounce); + wire_sync_write(GOSSIP_FD, cannounce); + wire_sync_write(GOSSIP_FD, cupdate); + + tal_free(tmpctx); } static void handle_peer_announcement_signatures(struct peer *peer, const u8 *msg) @@ -2204,7 +2215,6 @@ static void req_in(struct peer *peer, const u8 *msg) case WIRE_CHANNEL_INIT: case WIRE_CHANNEL_OFFER_HTLC_REPLY: case WIRE_CHANNEL_PING_REPLY: - case WIRE_CHANNEL_ANNOUNCE: case WIRE_CHANNEL_SENDING_COMMITSIG: case WIRE_CHANNEL_GOT_COMMITSIG: case WIRE_CHANNEL_GOT_REVOKE: @@ -2256,6 +2266,7 @@ static void init_channel(struct peer *peer) &peer->feerate_min, &peer->feerate_max, &peer->their_commit_sig, &peer->cs, + &peer->gossip_index, &funding_pubkey[REMOTE], &points[REMOTE].revocation, &points[REMOTE].payment, @@ -2427,7 +2438,8 @@ static void send_shutdown_complete(struct peer *peer) /* Now we can tell master shutdown is complete. */ wire_sync_write(MASTER_FD, take(towire_channel_shutdown_complete(peer, - &peer->cs))); + &peer->cs, + peer->gossip_index))); fdpass_send(MASTER_FD, PEER_FD); fdpass_send(MASTER_FD, GOSSIP_FD); close(MASTER_FD); diff --git a/channeld/channel_wire.csv b/channeld/channel_wire.csv index 2a328102d970..5aff8d4e0e27 100644 --- a/channeld/channel_wire.csv +++ b/channeld/channel_wire.csv @@ -18,6 +18,7 @@ channel_init,,feerate_min,u32 channel_init,,feerate_max,u32 channel_init,,first_commit_sig,secp256k1_ecdsa_signature channel_init,,crypto_state,struct crypto_state +channel_init,,gossip_index,u64 channel_init,,remote_fundingkey,struct pubkey channel_init,,remote_revocation_basepoint,struct pubkey channel_init,,remote_payment_basepoint,struct pubkey @@ -108,13 +109,6 @@ channel_ping,,len,u16 channel_ping_reply,1111 channel_ping_reply,,totlen,u16 -# Channeld tells the master to announce the channel (with first update) -channel_announce,1012 -channel_announce,,announce_len,u16 -channel_announce,,announce,announce_len*u8 -channel_announce,,update_len,u16 -channel_announce,,update,update_len*u8 - # When we receive funding_locked. channel_got_funding_locked,1019 channel_got_funding_locked,,next_per_commit_point,struct pubkey @@ -183,6 +177,7 @@ channel_got_shutdown,,scriptpubkey,scriptpubkey_len*u8 # Shutdown is complete, ready for closing negotiation. + peer_fd & gossip_fd. channel_shutdown_complete,1025 channel_shutdown_complete,,crypto_state,struct crypto_state +channel_shutdown_complete,,gossip_index,u64 # Re-enable commit timer. channel_dev_reenable_commit,1026 diff --git a/closingd/closing.c b/closingd/closing.c index 0a1b5df3c27a..98ba6423dfe0 100644 --- a/closingd/closing.c +++ b/closingd/closing.c @@ -168,6 +168,7 @@ int main(int argc, char *argv[]) secp256k1_ecdsa_signature sig; bool reconnected; u64 next_index[NUM_SIDES], revocations_received; + u64 gossip_index; if (argc == 2 && streq(argv[1], "--version")) { printf("%s\n", version()); @@ -184,7 +185,7 @@ int main(int argc, char *argv[]) msg = wire_sync_read(ctx, REQ_FD); if (!fromwire_closing_init(ctx, msg, NULL, - &cs, &seed, + &cs, &gossip_index, &seed, &funding_txid, &funding_txout, &funding_satoshi, &funding_pubkey[REMOTE], @@ -473,7 +474,8 @@ int main(int argc, char *argv[]) } /* We're done! */ - wire_sync_write(REQ_FD, take(towire_closing_complete(ctx))); + wire_sync_write(REQ_FD, + take(towire_closing_complete(ctx, gossip_index))); tal_free(ctx); return 0; diff --git a/closingd/closing_wire.csv b/closingd/closing_wire.csv index 12ef79312161..662e6c620a0d 100644 --- a/closingd/closing_wire.csv +++ b/closingd/closing_wire.csv @@ -3,6 +3,7 @@ # Begin! (passes peer fd, gossipd-client fd) closing_init,2001 closing_init,,crypto_state,struct crypto_state +closing_init,,gossip_index,u64 closing_init,,seed,struct privkey closing_init,,funding_txid,struct sha256_double closing_init,,funding_txout,u16 @@ -33,3 +34,4 @@ closing_received_signature_reply,2102 # Negotiations complete, we're exiting. closing_complete,2004 +closing_complete,,gossip_index,u64 diff --git a/common/daemon_conn.c b/common/daemon_conn.c index 899a497e8aa1..0928b84b61c1 100644 --- a/common/daemon_conn.c +++ b/common/daemon_conn.c @@ -87,6 +87,12 @@ void daemon_conn_init(tal_t *ctx, struct daemon_conn *dc, int fd, io_set_finish(conn, finish, dc); } +void daemon_conn_clear(struct daemon_conn *dc) +{ + io_set_finish(dc->conn, NULL, NULL); + io_close(dc->conn); +} + void daemon_conn_send(struct daemon_conn *dc, const u8 *msg) { msg_enqueue(&dc->out, msg); diff --git a/common/daemon_conn.h b/common/daemon_conn.h index 456b1af67e5c..fec23720ce4d 100644 --- a/common/daemon_conn.h +++ b/common/daemon_conn.h @@ -43,6 +43,16 @@ void daemon_conn_init(tal_t *ctx, struct daemon_conn *dc, int fd, struct io_plan *(*daemon_conn_recv)( struct io_conn *, struct daemon_conn *), void (*finish)(struct io_conn *, struct daemon_conn *)); + +/** + * daemon_conn_clear - discard a daemon conn without triggering finish. + * @dc: the daemon_conn to clean up. + * + * This is used by gossipd when a peer is handed back, and we no longer + * want to deal with it via daemon_conn. @dc must not be used after this! + */ +void daemon_conn_clear(struct daemon_conn *dc); + /** * daemon_conn_send - Enqueue an outgoing message to be sent */ diff --git a/common/wireaddr.c b/common/wireaddr.c index ce4bea332121..9d529bacb8c2 100644 --- a/common/wireaddr.c +++ b/common/wireaddr.c @@ -28,6 +28,10 @@ bool fromwire_wireaddr(const u8 **cursor, size_t *max, struct wireaddr *addr) void towire_wireaddr(u8 **pptr, const struct wireaddr *addr) { + if (!addr || addr->type == ADDR_TYPE_PADDING) { + towire_u8(pptr, ADDR_TYPE_PADDING); + return; + } towire_u8(pptr, addr->type); towire(pptr, addr->addr, addr->addrlen); towire_u16(pptr, addr->port); diff --git a/common/wireaddr.h b/common/wireaddr.h index ae196b9ccaf4..ab51b3c98dfc 100644 --- a/common/wireaddr.h +++ b/common/wireaddr.h @@ -36,6 +36,7 @@ struct wireaddr { u16 port; }; +/* Inserts a single ADDR_TYPE_PADDING if addr is NULL */ void towire_wireaddr(u8 **pptr, const struct wireaddr *addr); bool fromwire_wireaddr(const u8 **cursor, size_t *max, struct wireaddr *addr); #endif /* LIGHTNING_COMMON_WIREADDR_H */ diff --git a/gossipd/Makefile b/gossipd/Makefile index 71fcc9b54c32..55afc3100e94 100644 --- a/gossipd/Makefile +++ b/gossipd/Makefile @@ -57,7 +57,7 @@ GOSSIPD_COMMON_OBJS := \ hsmd/gen_hsm_client_wire.o \ lightningd/gossip_msg.o -$(LIGHTNINGD_GOSSIP_OBJS) $(LIGHTNINGD_GOSSIP_CLIENT_OBJS): $(LIGHTNINGD_HEADERS) +$(LIGHTNINGD_GOSSIP_OBJS) $(LIGHTNINGD_GOSSIP_CLIENT_OBJS): $(LIGHTNINGD_HEADERS) $(LIGHTNINGD_GOSSIP_HEADERS) $(LIGHTNINGD_GOSSIP_CONTROL_OBJS) : $(LIGHTNINGD_GOSSIP_CONTROL_HEADERS) diff --git a/gossipd/broadcast.c b/gossipd/broadcast.c index c5d118243219..8fc02eefb6c5 100644 --- a/gossipd/broadcast.c +++ b/gossipd/broadcast.c @@ -27,13 +27,13 @@ void queue_broadcast(struct broadcast_state *bstate, const u8 *payload) { struct queued_message *msg; - u64 index = 0; + u64 index; + /* Remove any tag&type collisions */ - while (true) { - msg = next_broadcast_message(bstate, &index); - if (msg == NULL) - break; - else if (msg->type == type && memcmp(msg->tag, tag, tal_count(tag)) == 0) { + for (msg = uintmap_first(&bstate->broadcasts, &index); + msg; + msg = uintmap_after(&bstate->broadcasts, &index)) { + if (msg->type == type && memcmp(msg->tag, tag, tal_count(tag)) == 0) { uintmap_del(&bstate->broadcasts, index); tal_free(msg); } @@ -45,7 +45,7 @@ void queue_broadcast(struct broadcast_state *bstate, bstate->next_index += 1; } -struct queued_message *next_broadcast_message(struct broadcast_state *bstate, u64 *last_index) +struct queued_message *next_broadcast_message(struct broadcast_state *bstate, u64 last_index) { - return uintmap_after(&bstate->broadcasts, last_index); + return uintmap_after(&bstate->broadcasts, &last_index); } diff --git a/gossipd/broadcast.h b/gossipd/broadcast.h index 80545c4f64d7..baa561d4f747 100644 --- a/gossipd/broadcast.h +++ b/gossipd/broadcast.h @@ -35,6 +35,6 @@ void queue_broadcast(struct broadcast_state *bstate, const u8 *tag, const u8 *payload); -struct queued_message *next_broadcast_message(struct broadcast_state *bstate, u64 *last_index); +struct queued_message *next_broadcast_message(struct broadcast_state *bstate, u64 last_index); #endif /* LIGHTNING_LIGHTNINGD_GOSSIP_BROADCAST_H */ diff --git a/gossipd/gossip.c b/gossipd/gossip.c index 89ae6262110a..172a0f9cc11c 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,7 @@ #include #include #include +#include #define HSM_FD 3 @@ -71,6 +73,10 @@ struct daemon { /* Local and global features to offer to peers. */ u8 *localfeatures, *globalfeatures; + + u8 alias[33]; + u8 rgb[3]; + struct wireaddr *wireaddrs; }; /* Peers we're trying to reach. */ @@ -90,6 +96,30 @@ struct reaching { bool succeeded; }; +/* Things we need when we're talking direct to the peer. */ +struct local_peer_state { + /* Cryptostate */ + struct peer_crypto_state pcs; + + /* File descriptor corresponding to conn. */ + int fd; + + /* Our connection (and owner) */ + struct io_conn *conn; + + /* Waiting to send_peer_with_fds to master? */ + bool return_to_master; + + /* If we're exiting due to non-gossip msg, otherwise release */ + u8 *nongossip_msg; + + /* How many pongs are we expecting? */ + size_t num_pings_outstanding; + + /* Message queue for outgoing. */ + struct msg_queue peer_out; +}; + struct peer { struct daemon *daemon; @@ -105,41 +135,18 @@ struct peer { /* Feature bitmaps. */ u8 *gfeatures, *lfeatures; - /* Cryptostate */ - struct peer_crypto_state pcs; - - /* File descriptor corresponding to conn. */ - int fd; - - /* Our connection (and owner) */ - struct io_conn *conn; - /* High water mark for the staggered broadcast */ u64 broadcast_index; - /* Message queue for outgoing. */ - struct msg_queue peer_out; - /* Is it time to continue the staggered broadcast? */ bool gossip_sync; - /* The peer owner will use this to talk to gossipd */ - struct daemon_conn owner_conn; - - /* How many pongs are we expecting? */ - size_t num_pings_outstanding; - - /* Are we the owner of the peer? */ - bool local; - /* If we die, should we reach again? */ bool reach_again; - /* Waiting to send_peer_with_fds to master? */ - bool return_to_master; - - /* If we're exiting due to non-gossip msg, otherwise release */ - u8 *nongossip_msg; + /* Only one of these is set: */ + struct local_peer_state *local; + struct daemon_conn *remote; }; struct addrhint { @@ -192,6 +199,20 @@ static struct addrhint *find_addrhint(struct daemon *daemon, return NULL; } +static struct local_peer_state * +new_local_peer_state(struct peer *peer, const struct crypto_state *cs) +{ + struct local_peer_state *lps = tal(peer, struct local_peer_state); + + init_peer_crypto_state(peer, &lps->pcs); + lps->pcs.cs = *cs; + lps->return_to_master = false; + lps->num_pings_outstanding = 0; + msg_queue_init(&lps->peer_out, peer); + + return lps; +} + static struct peer *new_peer(const tal_t *ctx, struct daemon *daemon, const struct pubkey *their_id, @@ -200,17 +221,13 @@ static struct peer *new_peer(const tal_t *ctx, { struct peer *peer = tal(ctx, struct peer); - init_peer_crypto_state(peer, &peer->pcs); - peer->pcs.cs = *cs; peer->id = *their_id; peer->addr = *addr; peer->daemon = daemon; - peer->local = true; + peer->local = new_local_peer_state(peer, cs); + peer->remote = NULL; peer->reach_again = false; - peer->return_to_master = false; - peer->num_pings_outstanding = 0; peer->broadcast_index = 0; - msg_queue_init(&peer->peer_out, peer); return peer; } @@ -271,7 +288,7 @@ static void peer_error(struct peer *peer, const char *fmt, ...) /* Send error: we'll close after writing this. */ va_start(ap, fmt); - msg_enqueue(&peer->peer_out, + msg_enqueue(&peer->local->peer_out, take(towire_errorfmtv(peer, NULL, fmt, ap))); va_end(ap); } @@ -314,7 +331,8 @@ static struct io_plan *peer_init_received(struct io_conn *conn, /* We will not have anything queued, since we're not duplex. */ msg = towire_gossip_peer_connected(peer, &peer->id, &peer->addr, - &peer->pcs.cs, + &peer->local->pcs.cs, + peer->broadcast_index, peer->gfeatures, peer->lfeatures); if (!send_peer_with_fds(peer, msg)) return io_close(conn); @@ -335,7 +353,7 @@ static struct io_plan *read_init(struct io_conn *conn, struct peer *peer) * Each node MUST wait to receive `init` before sending any other * messages. */ - return peer_read_message(conn, &peer->pcs, peer_init_received); + return peer_read_message(conn, &peer->local->pcs, peer_init_received); } /* This creates a temporary peer which is not in the list and is owner @@ -350,7 +368,7 @@ static struct io_plan *init_new_peer(struct io_conn *conn, struct peer *peer = new_peer(conn, daemon, their_id, addr, cs); u8 *initmsg; - peer->fd = io_conn_fd(conn); + peer->local->fd = io_conn_fd(conn); /* BOLT #1: * @@ -359,7 +377,8 @@ static struct io_plan *init_new_peer(struct io_conn *conn, */ initmsg = towire_init(peer, daemon->globalfeatures, daemon->localfeatures); - return peer_write_message(conn, &peer->pcs, take(initmsg), read_init); + return peer_write_message(conn, &peer->local->pcs, + take(initmsg), read_init); } static struct io_plan *owner_msg_in(struct io_conn *conn, @@ -367,20 +386,77 @@ static struct io_plan *owner_msg_in(struct io_conn *conn, static struct io_plan *nonlocal_dump_gossip(struct io_conn *conn, struct daemon_conn *dc); -static void handle_gossip_msg(struct routing_state *rstate, u8 *msg) +/* Create a node_announcement with the given signature. It may be NULL + * in the case we need to create a provisional announcement for the + * HSM to sign. This is typically called twice: once with the dummy + * signature to get it signed and a second time to build the full + * packet with the signature. The timestamp is handed in since that is + * the only thing that may change between the dummy creation and the + * call with a signature.*/ +static u8 *create_node_announcement(const tal_t *ctx, struct daemon *daemon, + secp256k1_ecdsa_signature *sig, + u32 timestamp) +{ + u8 *features = NULL; + u8 *addresses = tal_arr(ctx, u8, 0); + u8 *announcement; + size_t i; + if (!sig) { + sig = tal(ctx, secp256k1_ecdsa_signature); + memset(sig, 0, sizeof(*sig)); + } + for (i = 0; i < tal_count(daemon->wireaddrs); i++) + towire_wireaddr(&addresses, daemon->wireaddrs+i); + + announcement = + towire_node_announcement(ctx, sig, features, timestamp, + &daemon->id, daemon->rgb, daemon->alias, + addresses); + return announcement; +} + +static void send_node_announcement(struct daemon *daemon) { + tal_t *tmpctx = tal_tmpctx(daemon); + u32 timestamp = time_now().ts.tv_sec; + secp256k1_ecdsa_signature sig; + u8 *msg, *nannounce = create_node_announcement(tmpctx, daemon, NULL, timestamp); + + if (!wire_sync_write(HSM_FD, take(towire_hsm_node_announcement_sig_req(tmpctx, nannounce)))) + status_failed(STATUS_FAIL_MASTER_IO, "Could not write to HSM: %s", strerror(errno)); + + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsm_node_announcement_sig_reply(msg, NULL, &sig)) + status_failed(STATUS_FAIL_MASTER_IO, "HSM returned an invalid node_announcement sig"); + + /* We got the signature for out provisional node_announcement back + * from the HSM, create the real announcement and forward it to + * gossipd so it can take care of forwarding it. */ + nannounce = create_node_announcement(tmpctx, daemon, &sig, timestamp); + handle_node_announcement(daemon->rstate, take(nannounce)); + tal_free(tmpctx); +} + +static void handle_gossip_msg(struct daemon *daemon, u8 *msg) +{ + struct routing_state *rstate = daemon->rstate; int t = fromwire_peektype(msg); switch(t) { case WIRE_CHANNEL_ANNOUNCEMENT: - handle_channel_announcement(rstate, msg, tal_count(msg)); + /* Add the channel_announcement to the routing state, + * it'll tell us whether this is local and signed, so + * we can hand in a node_announcement as well. */ + if(handle_channel_announcement(rstate, msg)) { + send_node_announcement(daemon); + } break; case WIRE_NODE_ANNOUNCEMENT: - handle_node_announcement(rstate, msg, tal_count(msg)); + handle_node_announcement(rstate, msg); break; case WIRE_CHANNEL_UPDATE: - handle_channel_update(rstate, msg, tal_count(msg)); + handle_channel_update(rstate, msg); break; } } @@ -395,7 +471,7 @@ static void handle_ping(struct peer *peer, u8 *ping) } if (pong) - msg_enqueue(&peer->peer_out, take(pong)); + msg_enqueue(&peer->local->peer_out, take(pong)); } static void handle_pong(struct peer *peer, const u8 *pong) @@ -408,12 +484,12 @@ static void handle_pong(struct peer *peer, const u8 *pong) return; } - if (!peer->num_pings_outstanding) { + if (!peer->local->num_pings_outstanding) { peer_error(peer, "Unexpected pong"); return; } - peer->num_pings_outstanding--; + peer->local->num_pings_outstanding--; daemon_conn_send(&peer->daemon->master, take(towire_gossip_ping_reply(pong, true, tal_len(pong)))); @@ -430,24 +506,25 @@ static void fail_release(struct peer *peer) static struct io_plan *ready_for_master(struct io_conn *conn, struct peer *peer) { u8 *msg; - if (peer->nongossip_msg) + if (peer->local->nongossip_msg) msg = towire_gossip_peer_nongossip(peer, &peer->id, &peer->addr, - &peer->pcs.cs, + &peer->local->pcs.cs, + peer->broadcast_index, peer->gfeatures, peer->lfeatures, - peer->nongossip_msg); + peer->local->nongossip_msg); else msg = towire_gossipctl_release_peer_reply(peer, &peer->addr, - &peer->pcs.cs, + &peer->local->pcs.cs, + peer->broadcast_index, peer->gfeatures, peer->lfeatures); if (send_peer_with_fds(peer, take(msg))) { /* In case we set this earlier. */ tal_del_destructor(peer, fail_release); - peer->return_to_master = false; return io_close_taken_fd(conn); } else return io_close(conn); @@ -460,14 +537,14 @@ static struct io_plan *peer_msgin(struct io_conn *conn, * pass up to master */ static struct io_plan *peer_next_in(struct io_conn *conn, struct peer *peer) { - if (peer->return_to_master) { - assert(!peer_in_started(conn, &peer->pcs)); - if (!peer_out_started(conn, &peer->pcs)) + if (peer->local->return_to_master) { + assert(!peer_in_started(conn, &peer->local->pcs)); + if (!peer_out_started(conn, &peer->local->pcs)) return ready_for_master(conn, peer); return io_wait(conn, peer, peer_next_in, peer); } - return peer_read_message(conn, &peer->pcs, peer_msgin); + return peer_read_message(conn, &peer->local->pcs, peer_msgin); } static struct io_plan *peer_msgin(struct io_conn *conn, @@ -485,7 +562,7 @@ static struct io_plan *peer_msgin(struct io_conn *conn, case WIRE_CHANNEL_ANNOUNCEMENT: case WIRE_NODE_ANNOUNCEMENT: case WIRE_CHANNEL_UPDATE: - handle_gossip_msg(peer->daemon->rstate, msg); + handle_gossip_msg(peer->daemon, msg); return peer_next_in(conn, peer); case WIRE_PING: @@ -514,8 +591,8 @@ static struct io_plan *peer_msgin(struct io_conn *conn, case WIRE_REVOKE_AND_ACK: case WIRE_INIT: /* Not our place to handle this, so we punt */ - peer->return_to_master = true; - peer->nongossip_msg = tal_steal(peer, msg); + peer->local->return_to_master = true; + peer->local->nongossip_msg = tal_steal(peer, msg); /* This will wait. */ return peer_next_in(conn, peer); @@ -546,28 +623,43 @@ static void wake_pkt_out(struct peer *peer) new_reltimer(&peer->daemon->timers, peer, time_from_msec(peer->daemon->broadcast_interval), wake_pkt_out, peer); - /* Notify the peer-write loop */ - msg_wake(&peer->peer_out); - /* Notify the daemon_conn-write loop */ - msg_wake(&peer->owner_conn.out); + + if (peer->local) + /* Notify the peer-write loop */ + msg_wake(&peer->local->peer_out); + else + /* Notify the daemon_conn-write loop */ + msg_wake(&peer->remote->out); +} + +/* Mutual recursion. */ +static struct io_plan *peer_pkt_out(struct io_conn *conn, struct peer *peer); + +static struct io_plan *local_gossip_broadcast_done(struct io_conn *conn, + struct peer *peer) +{ + status_trace("%s", __func__); + peer->broadcast_index++; + return peer_pkt_out(conn, peer); } static struct io_plan *peer_pkt_out(struct io_conn *conn, struct peer *peer) { /* First priority is queued packets, if any */ - const u8 *out = msg_dequeue(&peer->peer_out); + const u8 *out = msg_dequeue(&peer->local->peer_out); if (out) { if (is_all_channel_error(out)) - return peer_write_message(conn, &peer->pcs, take(out), + return peer_write_message(conn, &peer->local->pcs, + take(out), peer_close_after_error); - return peer_write_message(conn, &peer->pcs, take(out), + return peer_write_message(conn, &peer->local->pcs, take(out), peer_pkt_out); } /* Do we want to send this peer to the master daemon? */ - if (peer->return_to_master) { - assert(!peer_out_started(conn, &peer->pcs)); - if (!peer_in_started(conn, &peer->pcs)) + if (peer->local->return_to_master) { + assert(!peer_out_started(conn, &peer->local->pcs)); + if (!peer_in_started(conn, &peer->local->pcs)) return ready_for_master(conn, peer); return io_out_wait(conn, peer, peer_pkt_out, peer); } @@ -577,17 +669,18 @@ static struct io_plan *peer_pkt_out(struct io_conn *conn, struct peer *peer) struct queued_message *next; next = next_broadcast_message(peer->daemon->rstate->broadcasts, - &peer->broadcast_index); + peer->broadcast_index); if (next) - return peer_write_message(conn, &peer->pcs, - next->payload, peer_pkt_out); + return peer_write_message(conn, &peer->local->pcs, + next->payload, + local_gossip_broadcast_done); /* Gossip is drained. Wait for next timer. */ peer->gossip_sync = false; } - return msg_queue_wait(conn, &peer->peer_out, peer_pkt_out, peer); + return msg_queue_wait(conn, &peer->local->peer_out, peer_pkt_out, peer); } /* Now we're a fully-fledged peer. */ @@ -641,7 +734,7 @@ static void handle_get_update(struct peer *peer, const u8 *msg) reply: msg = towire_gossip_get_update_reply(msg, update); - daemon_conn_send(&peer->owner_conn, take(msg)); + daemon_conn_send(peer->remote, take(msg)); } /** @@ -651,13 +744,13 @@ static void handle_get_update(struct peer *peer, const u8 *msg) static struct io_plan *owner_msg_in(struct io_conn *conn, struct daemon_conn *dc) { - struct peer *peer = container_of(dc, struct peer, owner_conn); + struct peer *peer = dc->ctx; u8 *msg = dc->msg_in; int type = fromwire_peektype(msg); if (type == WIRE_CHANNEL_ANNOUNCEMENT || type == WIRE_CHANNEL_UPDATE || type == WIRE_NODE_ANNOUNCEMENT) { - handle_gossip_msg(peer->daemon->rstate, dc->msg_in); + handle_gossip_msg(peer->daemon, dc->msg_in); } else if (type == WIRE_GOSSIP_GET_UPDATE) { handle_get_update(peer, dc->msg_in); } @@ -681,6 +774,7 @@ static void forget_peer(struct io_conn *conn, struct daemon_conn *dc) static bool send_peer_with_fds(struct peer *peer, const u8 *msg) { int fds[2]; + int peer_fd = peer->local->fd; if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds) != 0) { status_trace("Failed to create socketpair: %s", @@ -692,24 +786,32 @@ static bool send_peer_with_fds(struct peer *peer, const u8 *msg) } /* Now we talk to socket to get to peer's owner daemon. */ - peer->local = false; - - daemon_conn_init(peer, &peer->owner_conn, fds[0], + peer->local = tal_free(peer->local); + peer->remote = tal(peer, struct daemon_conn); + daemon_conn_init(peer, peer->remote, fds[0], owner_msg_in, forget_peer); - peer->owner_conn.msg_queue_cleared_cb = nonlocal_dump_gossip; + peer->remote->msg_queue_cleared_cb = nonlocal_dump_gossip; /* Peer stays around, even though caller will close conn. */ tal_steal(peer->daemon, peer); daemon_conn_send(&peer->daemon->master, msg); - daemon_conn_send_fd(&peer->daemon->master, peer->fd); + daemon_conn_send_fd(&peer->daemon->master, peer_fd); daemon_conn_send_fd(&peer->daemon->master, fds[1]); - /* Don't get confused: we can't use this any more. */ - peer->fd = -1; return true; } +static struct io_plan *nonlocal_gossip_broadcast_done(struct io_conn *conn, + struct daemon_conn *dc) +{ + struct peer *peer = dc->ctx; + + status_trace("%s", __func__); + peer->broadcast_index++; + return nonlocal_dump_gossip(conn, dc); +} + /** * nonlocal_dump_gossip - catch the nonlocal peer up with the latest gossip. * @@ -718,88 +820,119 @@ static bool send_peer_with_fds(struct peer *peer, const u8 *msg) static struct io_plan *nonlocal_dump_gossip(struct io_conn *conn, struct daemon_conn *dc) { struct queued_message *next; - struct peer *peer = container_of(dc, struct peer, owner_conn); + struct peer *peer = dc->ctx; /* Make sure we are not connected directly */ - if (peer->local) - return msg_queue_wait(conn, &peer->owner_conn.out, - daemon_conn_write_next, dc); + assert(!peer->local); next = next_broadcast_message(peer->daemon->rstate->broadcasts, - &peer->broadcast_index); + peer->broadcast_index); if (!next) { - return msg_queue_wait(conn, &peer->owner_conn.out, + return msg_queue_wait(conn, &peer->remote->out, daemon_conn_write_next, dc); } else { - return io_write_wire(conn, next->payload, nonlocal_dump_gossip, dc); + u8 *msg = towire_gossip_send_gossip(conn, + peer->broadcast_index, + next->payload); + return io_write_wire(conn, take(msg), + nonlocal_gossip_broadcast_done, dc); } } static struct io_plan *new_peer_got_fd(struct io_conn *conn, struct peer *peer) { - peer->conn = io_new_conn(conn, peer->fd, peer_start_gossip, peer); - if (!peer->conn) { + peer->local->conn = io_new_conn(conn, peer->local->fd, + peer_start_gossip, peer); + if (!peer->local->conn) { status_trace("Could not create connection for peer: %s", strerror(errno)); tal_free(peer); } else { /* If conn dies, we forget peer. */ - tal_steal(peer->conn, peer); + tal_steal(peer->local->conn, peer); } return daemon_conn_read_next(conn, &peer->daemon->master); } -/* Read and close fd */ -static struct io_plan *discard_peer_fd(struct io_conn *conn, int *fd) -{ - struct daemon *daemon = tal_parent(fd); - close(*fd); - tal_free(fd); - return daemon_conn_read_next(conn, &daemon->master); -} +/* This lets us read the fds in before handling anything. */ +struct returning_peer { + struct daemon *daemon; + struct pubkey id; + struct crypto_state cs; + u64 gossip_index; + u8 *inner_msg; + int peer_fd, gossip_fd; +}; -static struct io_plan *handle_peer(struct io_conn *conn, struct daemon *daemon, - const u8 *msg) +static struct io_plan *handle_returning_peer(struct io_conn *conn, + struct returning_peer *rpeer) { + struct daemon *daemon = rpeer->daemon; struct peer *peer; - struct crypto_state cs; - struct pubkey id; - struct wireaddr addr; - u8 *gfeatures, *lfeatures; - u8 *inner_msg; - if (!fromwire_gossipctl_handle_peer(msg, msg, NULL, &id, &addr, &cs, - &gfeatures, &lfeatures, &inner_msg)) - master_badmsg(WIRE_GOSSIPCTL_HANDLE_PEER, msg); + peer = find_peer(daemon, &rpeer->id); + if (!peer) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "hand_back_peer unknown peer: %s", + type_to_string(trc, struct pubkey, &rpeer->id)); - /* If it already exists locally, that's probably a reconnect: - * drop this one. If it exists as remote, replace with this.*/ - peer = find_peer(daemon, &id); - if (peer) { - if (peer->local) { - int *fd = tal(daemon, int); - status_trace("handle_peer %s: duplicate, dropping", - type_to_string(trc, struct pubkey, &id)); - return io_recv_fd(conn, fd, discard_peer_fd, fd); - } - status_trace("handle_peer %s: found remote duplicate, dropping", - type_to_string(trc, struct pubkey, &id)); - tal_free(peer); + /* We don't need the gossip_fd; we know what gossip it got + * from gossip_index */ + close(rpeer->gossip_fd); + + /* Possible if there's a reconnect: ignore handed back. */ + if (peer->local) { + status_trace("hand_back_peer %s: reconnected, dropping handback", + type_to_string(trc, struct pubkey, &rpeer->id)); + + close(rpeer->peer_fd); + tal_free(rpeer); + return daemon_conn_read_next(conn, &daemon->master); } - status_trace("handle_peer %s: new peer", - type_to_string(trc, struct pubkey, &id)); - peer = new_peer(daemon, daemon, &id, &addr, &cs); - peer->gfeatures = tal_steal(peer, gfeatures); - peer->lfeatures = tal_steal(peer, lfeatures); - peer_finalized(peer); + status_trace("hand_back_peer %s: now local again", + type_to_string(trc, struct pubkey, &rpeer->id)); + + /* Now we talk to peer directly again. */ + daemon_conn_clear(peer->remote); + peer->remote = tal_free(peer->remote); + + peer->local = new_local_peer_state(peer, &rpeer->cs); + peer->local->fd = rpeer->peer_fd; + peer->broadcast_index = rpeer->gossip_index; - if (tal_len(inner_msg)) - msg_enqueue(&peer->peer_out, take(inner_msg)); + /* If they told us to send a message, queue it now */ + if (tal_len(rpeer->inner_msg)) + msg_enqueue(&peer->local->peer_out, take(rpeer->inner_msg)); + tal_free(rpeer); - return io_recv_fd(conn, &peer->fd, new_peer_got_fd, peer); + return new_peer_got_fd(conn, peer); +} + +static struct io_plan *read_returning_gossipfd(struct io_conn *conn, + struct returning_peer *rpeer) +{ + return io_recv_fd(conn, &rpeer->gossip_fd, + handle_returning_peer, rpeer); +} + +static struct io_plan *hand_back_peer(struct io_conn *conn, + struct daemon *daemon, + const u8 *msg) +{ + struct returning_peer *rpeer = tal(daemon, struct returning_peer); + + rpeer->daemon = daemon; + if (!fromwire_gossipctl_hand_back_peer(msg, msg, NULL, + &rpeer->id, &rpeer->cs, + &rpeer->gossip_index, + &rpeer->inner_msg)) + master_badmsg(WIRE_GOSSIPCTL_HAND_BACK_PEER, msg); + + return io_recv_fd(conn, &rpeer->peer_fd, + read_returning_gossipfd, rpeer); } static struct io_plan *release_peer(struct io_conn *conn, struct daemon *daemon, @@ -812,21 +945,21 @@ static struct io_plan *release_peer(struct io_conn *conn, struct daemon *daemon, master_badmsg(WIRE_GOSSIPCTL_RELEASE_PEER, msg); peer = find_peer(daemon, &id); - if (!peer || !peer->local || peer->return_to_master) { + if (!peer || !peer->local || peer->local->return_to_master) { /* This can happen with dying peers, or reconnect */ status_trace("release_peer: peer %s %s", type_to_string(trc, struct pubkey, &id), !peer ? "not found" - : peer->return_to_master ? "already releasing" + : peer->local ? "already releasing" : "not local"); msg = towire_gossipctl_release_peer_replyfail(msg); daemon_conn_send(&daemon->master, take(msg)); } else { - peer->return_to_master = true; - peer->nongossip_msg = NULL; + peer->local->return_to_master = true; + peer->local->nongossip_msg = NULL; /* Wake output, in case it's idle. */ - msg_wake(&peer->peer_out); + msg_wake(&peer->local->peer_out); } return daemon_conn_read_next(conn, &daemon->master); } @@ -939,7 +1072,7 @@ static struct io_plan *ping_req(struct io_conn *conn, struct daemon *daemon, if (tal_len(ping) > 65535) status_failed(STATUS_FAIL_MASTER_IO, "Oversize ping"); - msg_enqueue(&peer->peer_out, take(ping)); + msg_enqueue(&peer->local->peer_out, take(ping)); status_trace("sending ping expecting %sresponse", num_pong_bytes >= 65532 ? "no " : ""); @@ -953,7 +1086,7 @@ static struct io_plan *ping_req(struct io_conn *conn, struct daemon *daemon, daemon_conn_send(&daemon->master, take(towire_gossip_ping_reply(peer, true, 0))); else - peer->num_pings_outstanding++; + peer->local->num_pings_outstanding++; out: return daemon_conn_read_next(conn, &daemon->master); @@ -1111,10 +1244,12 @@ static struct io_plan *gossip_init(struct daemon_conn *master, &daemon->broadcast_interval, &chain_hash, &daemon->id, &port, &daemon->globalfeatures, - &daemon->localfeatures)) { + &daemon->localfeatures, + &daemon->wireaddrs, + daemon->rgb, daemon->alias)) { master_badmsg(WIRE_GOSSIPCTL_INIT, msg); } - daemon->rstate = new_routing_state(daemon, &chain_hash); + daemon->rstate = new_routing_state(daemon, &chain_hash, &daemon->id); setup_listeners(daemon, port); return daemon_conn_read_next(master->conn, master); @@ -1149,15 +1284,6 @@ static struct io_plan *resolve_channel_req(struct io_conn *conn, return daemon_conn_read_next(conn, &daemon->master); } -static void handle_forwarded_msg(struct io_conn *conn, struct daemon *daemon, const u8 *msg) -{ - u8 *payload; - if (!fromwire_gossip_forwarded_msg(msg, msg, NULL, &payload)) - master_badmsg(WIRE_GOSSIP_FORWARDED_MSG, msg); - - handle_gossip_msg(daemon->rstate, payload); -} - static struct io_plan *handshake_out_success(struct io_conn *conn, const struct pubkey *id, const struct wireaddr *addr, @@ -1401,12 +1527,8 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master case WIRE_GOSSIP_RESOLVE_CHANNEL_REQUEST: return resolve_channel_req(conn, daemon, daemon->master.msg_in); - case WIRE_GOSSIP_FORWARDED_MSG: - handle_forwarded_msg(conn, daemon, daemon->master.msg_in); - return daemon_conn_read_next(conn, &daemon->master); - - case WIRE_GOSSIPCTL_HANDLE_PEER: - return handle_peer(conn, daemon, master->msg_in); + case WIRE_GOSSIPCTL_HAND_BACK_PEER: + return hand_back_peer(conn, daemon, master->msg_in); case WIRE_GOSSIPCTL_REACH_PEER: return reach_peer(conn, daemon, master->msg_in); @@ -1429,6 +1551,7 @@ static struct io_plan *recv_req(struct io_conn *conn, struct daemon_conn *master case WIRE_GOSSIP_PEER_NONGOSSIP: case WIRE_GOSSIP_GET_UPDATE: case WIRE_GOSSIP_GET_UPDATE_REPLY: + case WIRE_GOSSIP_SEND_GOSSIP: break; } diff --git a/gossipd/gossip_wire.csv b/gossipd/gossip_wire.csv index a0c59a66fb1b..e5149503bcef 100644 --- a/gossipd/gossip_wire.csv +++ b/gossipd/gossip_wire.csv @@ -12,6 +12,10 @@ gossipctl_init,,gflen,u16 gossipctl_init,,gfeatures,gflen*u8 gossipctl_init,,lflen,u16 gossipctl_init,,lfeatures,lflen*u8 +gossipctl_init,,num_wireaddrs,u16 +gossipctl_init,,wireaddrs,num_wireaddrs*struct wireaddr +gossipctl_init,,rgb,3*u8 +gossipctl_init,,alias,32*u8 # Master -> gossipd: Optional hint for where to find peer. gossipctl_peer_addrhint,3014 @@ -27,6 +31,7 @@ gossip_peer_connected,3002 gossip_peer_connected,,id,struct pubkey gossip_peer_connected,,addr,struct wireaddr gossip_peer_connected,,crypto_state,struct crypto_state +gossip_peer_connected,,gossip_index,u64 gossip_peer_connected,,gflen,u16 gossip_peer_connected,,gfeatures,gflen*u8 gossip_peer_connected,,lflen,u16 @@ -37,6 +42,7 @@ gossip_peer_nongossip,3003 gossip_peer_nongossip,,id,struct pubkey gossip_peer_nongossip,,addr,struct wireaddr gossip_peer_nongossip,,crypto_state,struct crypto_state +gossip_peer_nongossip,,gossip_index,u64 gossip_peer_nongossip,,gflen,u16 gossip_peer_nongossip,,gfeatures,gflen*u8 gossip_peer_nongossip,,lflen,u16 @@ -52,6 +58,7 @@ gossipctl_release_peer,,id,struct pubkey gossipctl_release_peer_reply,3104 gossipctl_release_peer_reply,,addr,struct wireaddr gossipctl_release_peer_reply,,crypto_state,struct crypto_state +gossipctl_release_peer_reply,,gossip_index,u64 gossipctl_release_peer_reply,,gflen,u16 gossipctl_release_peer_reply,,gfeatures,gflen*u8 gossipctl_release_peer_reply,,lflen,u16 @@ -60,17 +67,13 @@ gossipctl_release_peer_reply,,lfeatures,lflen*u8 # Gossipd -> master: reply to gossip_release_peer if we couldn't find the peer. gossipctl_release_peer_replyfail,3204 -# Gossipd -> master: take over peer, with optional msg. (+peer fd) -gossipctl_handle_peer,3013 -gossipctl_handle_peer,,id,struct pubkey -gossipctl_handle_peer,,addr,struct wireaddr -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 +# master -> gossipd: take back peer, with optional msg. (+peer fd, +gossip fd) +gossipctl_hand_back_peer,3013 +gossipctl_hand_back_peer,,id,struct pubkey +gossipctl_hand_back_peer,,crypto_state,struct crypto_state +gossipctl_hand_back_peer,,gossip_index,u64 +gossipctl_hand_back_peer,,len,u16 +gossipctl_hand_back_peer,,msg,len*u8 # Pass JSON-RPC getnodes call through gossip_getnodes_request,3005 @@ -118,12 +121,6 @@ gossip_resolve_channel_reply,3109 gossip_resolve_channel_reply,,num_keys,u16 gossip_resolve_channel_reply,,keys,num_keys*struct pubkey -# The main daemon forward some gossip message to gossipd, allows injecting -# arbitrary gossip messages. -gossip_forwarded_msg,3010 -gossip_forwarded_msg,,msglen,u16 -gossip_forwarded_msg,,msg,msglen*u8 - # The main daemon asks for peers gossip_getpeers_request,3011 @@ -142,3 +139,8 @@ gossip_get_update_reply,3112 gossip_get_update_reply,,len,u16 gossip_get_update_reply,,update,len*u8 +# Gossipd can tell channeld etc about gossip to fwd. +gossip_send_gossip,3016 +gossip_send_gossip,,gossip_index,u64 +gossip_send_gossip,,len,u16 +gossip_send_gossip,,gossip,len*u8 diff --git a/gossipd/handshake.c b/gossipd/handshake.c index 0fa8738adf1b..02f9207c0a62 100644 --- a/gossipd/handshake.c +++ b/gossipd/handshake.c @@ -22,8 +22,6 @@ #include #include -#define HSM_FD 3 - #ifndef SUPERVERBOSE #define SUPERVERBOSE(...) #endif diff --git a/gossipd/routing.c b/gossipd/routing.c index 0182d87a7331..a02361f481bb 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -26,12 +26,14 @@ static struct node_map *empty_node_map(const tal_t *ctx) } struct routing_state *new_routing_state(const tal_t *ctx, - const struct sha256_double *chain_hash) + const struct sha256_double *chain_hash, + const struct pubkey *local_id) { struct routing_state *rstate = tal(ctx, struct routing_state); rstate->nodes = empty_node_map(rstate); rstate->broadcasts = new_broadcast_state(rstate); rstate->chain_hash = *chain_hash; + rstate->local_id = *local_id; return rstate; } @@ -422,9 +424,11 @@ static bool add_channel_direction(struct routing_state *rstate, c = half_add_connection(rstate, from, to, short_channel_id, direction); /* Remember the announcement so we can forward it to new peers */ - tal_free(c->channel_announcement); - c->channel_announcement = tal_dup_arr(c, u8, announcement, - tal_count(announcement), 0); + if (announcement) { + tal_free(c->channel_announcement); + c->channel_announcement = tal_dup_arr(c, u8, announcement, + tal_count(announcement), 0); + } return true; } @@ -461,12 +465,12 @@ static bool check_channel_announcement( check_signed_hash(&hash, bitcoin2_sig, bitcoin2_key); } -void handle_channel_announcement( +bool handle_channel_announcement( struct routing_state *rstate, - const u8 *announce, size_t len) + const u8 *announce) { u8 *serialized; - bool forward = false; + bool forward = false, local, sigfail; secp256k1_ecdsa_signature node_signature_1; secp256k1_ecdsa_signature node_signature_2; struct short_channel_id short_channel_id; @@ -477,8 +481,10 @@ void handle_channel_announcement( struct pubkey bitcoin_key_1; struct pubkey bitcoin_key_2; struct sha256_double chain_hash; + struct node_connection *c0, *c1; const tal_t *tmpctx = tal_tmpctx(rstate); u8 *features; + size_t len = tal_len(announce); serialized = tal_dup_arr(tmpctx, u8, announce, len, 0); if (!fromwire_channel_announcement(tmpctx, serialized, NULL, @@ -491,7 +497,7 @@ void handle_channel_announcement( &node_id_1, &node_id_2, &bitcoin_key_1, &bitcoin_key_2)) { tal_free(tmpctx); - return; + return false; } /* BOLT #7: @@ -505,34 +511,48 @@ void handle_channel_announcement( type_to_string(tmpctx, struct sha256_double, &chain_hash)); tal_free(tmpctx); - return; + return false; } // FIXME: Check features! //FIXME(cdecker) Check chain topology for the anchor TX - status_trace("Received channel_announcement for channel %s", + + local = pubkey_eq(&node_id_1, &rstate->local_id) || + pubkey_eq(&node_id_2, &rstate->local_id); + sigfail = !check_channel_announcement( + &node_id_1, &node_id_2, &bitcoin_key_1, &bitcoin_key_2, + &node_signature_1, &node_signature_2, &bitcoin_signature_1, + &bitcoin_signature_2, serialized); + + status_trace("Received channel_announcement for channel %s, local=%d, sigfail=%d", type_to_string(trc, struct short_channel_id, - &short_channel_id)); + &short_channel_id), local, sigfail); - if (!check_channel_announcement(&node_id_1, &node_id_2, &bitcoin_key_1, - &bitcoin_key_2, &node_signature_1, - &node_signature_2, &bitcoin_signature_1, - &bitcoin_signature_2, serialized)) { + + if (sigfail && !local) { status_trace( - "Signature verification of channel announcement failed"); + "Signature verification of non-local channel announcement failed"); tal_free(tmpctx); - return; + return false; } - forward |= add_channel_direction(rstate, &node_id_1, &node_id_2, - &short_channel_id, serialized); - forward |= add_channel_direction(rstate, &node_id_2, &node_id_1, - &short_channel_id, serialized); - if (!forward) { - status_trace("Not forwarding channel_announcement"); + /* Is this a new connection? */ + c0 = get_connection_by_scid(rstate, &short_channel_id, 0); + c1 = get_connection_by_scid(rstate, &short_channel_id, 1); + forward = !c0 || !c1 || !c0->channel_announcement || !c1->channel_announcement; + + add_channel_direction(rstate, &node_id_1, &node_id_2, &short_channel_id, + sigfail ? NULL : serialized); + add_channel_direction(rstate, &node_id_2, &node_id_1, &short_channel_id, + sigfail ? NULL : serialized); + + if (!forward || sigfail) { + status_trace("Not forwarding channel_announcement, forward=%d, sigfail=%d", forward, sigfail); tal_free(tmpctx); - return; + /* This will not be forwarded so we do not want to + * announce the node either, others might drop it. */ + return false; } u8 *tag = tal_arr(tmpctx, u8, 0); @@ -541,9 +561,10 @@ void handle_channel_announcement( tag, serialized); tal_free(tmpctx); + return local; } -void handle_channel_update(struct routing_state *rstate, const u8 *update, size_t len) +void handle_channel_update(struct routing_state *rstate, const u8 *update) { u8 *serialized; struct node_connection *c; @@ -557,6 +578,7 @@ void handle_channel_update(struct routing_state *rstate, const u8 *update, size_ u32 fee_proportional_millionths; const tal_t *tmpctx = tal_tmpctx(rstate); struct sha256_double chain_hash; + size_t len = tal_len(update); serialized = tal_dup_arr(tmpctx, u8, update, len, 0); if (!fromwire_channel_update(serialized, NULL, &signature, @@ -664,7 +686,7 @@ static struct wireaddr *read_addresses(const tal_t *ctx, const u8 *ser) } void handle_node_announcement( - struct routing_state *rstate, const u8 *node_ann, size_t len) + struct routing_state *rstate, const u8 *node_ann) { u8 *serialized; struct sha256_double hash; @@ -677,6 +699,7 @@ void handle_node_announcement( u8 *features, *addresses; const tal_t *tmpctx = tal_tmpctx(rstate); struct wireaddr *wireaddrs; + size_t len = tal_len(node_ann); serialized = tal_dup_arr(tmpctx, u8, node_ann, len, 0); if (!fromwire_node_announcement(tmpctx, serialized, NULL, diff --git a/gossipd/routing.h b/gossipd/routing.h index 658ebfd4476a..c35741a94365 100644 --- a/gossipd/routing.h +++ b/gossipd/routing.h @@ -83,6 +83,9 @@ struct routing_state { struct broadcast_state *broadcasts; struct sha256_double chain_hash; + + /* Our own ID so we can identify local channels */ + struct pubkey local_id; }; struct route_hop { @@ -93,7 +96,8 @@ struct route_hop { }; struct routing_state *new_routing_state(const tal_t *ctx, - const struct sha256_double *chain_hash); + const struct sha256_double *chain_hash, + const struct pubkey *local_id); /* msatoshi must be possible (< 21 million BTC), ie < 2^60. * If it returns more than msatoshi, it overflowed. */ @@ -116,9 +120,17 @@ struct node_connection *get_connection_by_scid(const struct routing_state *rstat const u8 direction); /* Handlers for incoming messages */ -void handle_channel_announcement(struct routing_state *rstate, const u8 *announce, size_t len); -void handle_channel_update(struct routing_state *rstate, const u8 *update, size_t len); -void handle_node_announcement(struct routing_state *rstate, const u8 *node, size_t len); + +/** + * handle_channel_announcement -- Add channel announcement to state + * + * Returns true if the channel was fully signed and is local. This + * means that if we haven't sent a node_announcement just yet, now + * would be a good time. + */ +bool handle_channel_announcement(struct routing_state *rstate, const u8 *announce); +void handle_channel_update(struct routing_state *rstate, const u8 *update); +void handle_node_announcement(struct routing_state *rstate, const u8 *node); /* Compute a route to a destination, for a given amount and riskfactor. */ struct route_hop *get_route(tal_t *ctx, struct routing_state *rstate, diff --git a/gossipd/test/run-find_route-specific.c b/gossipd/test/run-find_route-specific.c index 3581a543a913..908bfa6b6279 100644 --- a/gossipd/test/run-find_route-specific.c +++ b/gossipd/test/run-find_route-specific.c @@ -67,8 +67,6 @@ int main(void) secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); - rstate = new_routing_state(ctx, &zerohash); - pubkey_from_hexstr("03c173897878996287a8100469f954dd820fcd8941daed91c327f168f3329be0bf", strlen("03c173897878996287a8100469f954dd820fcd8941daed91c327f168f3329be0bf"), &a); @@ -79,6 +77,7 @@ int main(void) strlen("02ea622d5c8d6143f15ed3ce1d501dd0d3d09d3b1c83a44d0034949f8a9ab60f06"), &c); + rstate = new_routing_state(ctx, &zerohash, &a); /* [{'active': True, 'short_id': '6990:2:1/1', 'fee_per_kw': 10, 'delay': 5, 'flags': 1, 'destination': '0230ad0e74ea03976b28fda587bb75bdd357a1938af4424156a18265167f5e40ae', 'source': '02ea622d5c8d6143f15ed3ce1d501dd0d3d09d3b1c83a44d0034949f8a9ab60f06', 'last_update': 1504064344}, */ nc = get_or_make_connection(rstate, &c, &b); diff --git a/gossipd/test/run-find_route.c b/gossipd/test/run-find_route.c index 236f3e8e2aa8..21785cee0fdc 100644 --- a/gossipd/test/run-find_route.c +++ b/gossipd/test/run-find_route.c @@ -78,9 +78,9 @@ int main(void) secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); - rstate = new_routing_state(ctx, &zerohash); - memset(&tmp, 'a', sizeof(tmp)); + rstate = new_routing_state(ctx, &zerohash, &a); + pubkey_from_privkey(&tmp, &a); new_node(rstate, &a); diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 0d7255ec69a2..9b4eeee03da5 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -27,9 +27,10 @@ static void peer_nongossip(struct subd *gossip, const u8 *msg, struct crypto_state cs; struct wireaddr addr; u8 *gfeatures, *lfeatures, *in_pkt; + u64 gossip_index; if (!fromwire_gossip_peer_nongossip(msg, msg, NULL, - &id, &addr, &cs, + &id, &addr, &cs, &gossip_index, &gfeatures, &lfeatures, &in_pkt)) @@ -47,7 +48,8 @@ static void peer_nongossip(struct subd *gossip, const u8 *msg, return; } - peer_sent_nongossip(gossip->ld, &id, &addr, &cs, gfeatures, lfeatures, + peer_sent_nongossip(gossip->ld, &id, &addr, &cs, gossip_index, + gfeatures, lfeatures, peer_fd, gossip_fd, in_pkt); } @@ -64,12 +66,12 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) case WIRE_GOSSIP_GETPEERS_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_HAND_BACK_PEER: case WIRE_GOSSIPCTL_RELEASE_PEER: case WIRE_GOSSIPCTL_PEER_ADDRHINT: case WIRE_GOSSIP_GET_UPDATE: + case WIRE_GOSSIP_SEND_GOSSIP: /* This is a reply, so never gets through to here. */ case WIRE_GOSSIP_GET_UPDATE_REPLY: case WIRE_GOSSIP_GETNODES_REPLY: @@ -126,7 +128,8 @@ void gossip_init(struct lightningd *ld) &get_chainparams(ld)->genesis_blockhash, &ld->id, ld->portnum, get_supported_global_features(tmpctx), - get_supported_local_features(tmpctx)); + get_supported_local_features(tmpctx), + ld->wireaddrs, ld->rgb, ld->alias); subd_send_msg(ld->gossip, msg); tal_free(tmpctx); } diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index ba53ed767958..fd161f7c43fa 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -89,7 +89,7 @@ struct lightningd { struct pubkey id; /* My name is... my favorite color is... */ - char *alias; /* At least 32 bytes (zero-filled) */ + u8 *alias; /* At least 32 bytes (zero-filled) */ u8 *rgb; /* tal_len() == 3. */ /* Any pending timers. */ diff --git a/lightningd/options.c b/lightningd/options.c index e98d0adffc87..37e440fed639 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -168,8 +168,8 @@ static char *opt_set_alias(const char *arg, struct lightningd *ld) */ if (strlen(arg) > 32) return tal_fmt(NULL, "Alias '%s' is over 32 characters", arg); - ld->alias = tal_arrz(ld, char, 33); - strncpy(ld->alias, arg, 32); + ld->alias = tal_arrz(ld, u8, 33); + strncpy((char*)ld->alias, arg, 32); return NULL; } @@ -572,11 +572,11 @@ void setup_color_and_alias(struct lightningd *ld) memcpy(&noun, der+3+sizeof(adjective), sizeof(noun)); noun %= ARRAY_SIZE(codename_noun); adjective %= ARRAY_SIZE(codename_adjective); - ld->alias = tal_arrz(ld, char, 33); + ld->alias = tal_arrz(ld, u8, 33); assert(strlen(codename_adjective[adjective]) + strlen(codename_noun[noun]) < 33); - strcpy(ld->alias, codename_adjective[adjective]); - strcat(ld->alias, codename_noun[noun]); + strcpy((char*)ld->alias, codename_adjective[adjective]); + strcat((char*)ld->alias, codename_noun[noun]); } } diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 26b88068e032..992c5aa91e46 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -61,21 +61,25 @@ static void peer_offer_channel(struct lightningd *ld, struct funding_channel *fc, const struct wireaddr *addr, const struct crypto_state *cs, + u64 gossip_index, const u8 *gfeatures, const u8 *lfeatures, int peer_fd, int gossip_fd); static bool peer_start_channeld(struct peer *peer, const struct crypto_state *cs, + u64 gossip_index, int peer_fd, int gossip_fd, const u8 *funding_signed, bool reconnected); static void peer_start_closingd(struct peer *peer, struct crypto_state *cs, + u64 gossip_index, int peer_fd, int gossip_fd, bool reconnected); static void peer_accept_channel(struct lightningd *ld, const struct pubkey *peer_id, const struct wireaddr *addr, const struct crypto_state *cs, + u64 gossip_index, const u8 *gfeatures, const u8 *lfeatures, int peer_fd, int gossip_fd, const u8 *open_msg); @@ -175,6 +179,16 @@ static void drop_to_chain(struct peer *peer) broadcast_tx(peer->ld->topology, peer, peer->last_tx, NULL); } +/* This lets us give a more detailed error than just a destructor. */ +static void free_peer(struct peer *peer, const char *msg) +{ + if (peer->opening_cmd) { + command_fail(peer->opening_cmd, "%s", msg); + peer->opening_cmd = NULL; + } + tal_free(peer); +} + void peer_fail_permanent(struct peer *peer, const u8 *msg TAKES) { /* BOLT #1: @@ -183,10 +197,14 @@ void peer_fail_permanent(struct peer *peer, const u8 *msg TAKES) * zero (ie. all bytes zero), in which case it refers to all * channels. */ static const struct channel_id all_channels; + char *why; + + /* Subtle: we don't want tal_strndup here, it will take() msg! */ + why = tal_arrz(NULL, char, tal_len(msg) + 1); + memcpy(why, msg, tal_len(msg)); - log_unusual(peer->log, "Peer permanent failure in %s: %.*s", - peer_state_name(peer->state), - (int)tal_len(msg), (char *)msg); + log_unusual(peer->log, "Peer permanent failure in %s: %s", + peer_state_name(peer->state), why); /* We can have multiple errors, eg. onchaind failures. */ if (!peer->error) @@ -199,7 +217,8 @@ void peer_fail_permanent(struct peer *peer, const u8 *msg TAKES) if (peer_persists(peer)) drop_to_chain(peer); else - tal_free(peer); + free_peer(peer, why); + tal_free(why); return; } @@ -228,12 +247,13 @@ void peer_internal_error(struct peer *peer, const char *fmt, ...) void peer_fail_transient(struct peer *peer, const char *fmt, ...) { va_list ap; + const char *why; va_start(ap, fmt); - log_info(peer->log, "Peer transient failure in %s: ", - peer_state_name(peer->state)); - logv_add(peer->log, fmt, ap); + why = tal_vfmt(peer, fmt, ap); va_end(ap); + log_info(peer->log, "Peer transient failure in %s: %s", + peer_state_name(peer->state), why); #if DEVELOPER if (dev_disconnect_permanent(peer->ld)) { @@ -248,9 +268,10 @@ void peer_fail_transient(struct peer *peer, const char *fmt, ...) if (!peer_persists(peer)) { log_info(peer->log, "Only reached state %s: forgetting", peer_state_name(peer->state)); - tal_free(peer); + free_peer(peer, why); return; } + tal_free(why); /* Reconnect unless we've dropped/are dropping to chain. */ if (!peer_on_chain(peer) && peer->state != CLOSINGD_COMPLETE) { @@ -350,6 +371,7 @@ static struct peer *new_peer(struct lightningd *ld, peer->seed = NULL; peer->our_msatoshi = NULL; peer->state = UNINITIALIZED; + peer->opening_cmd = NULL; peer->channel_info = NULL; peer->last_tx = NULL; peer->last_sig = NULL; @@ -530,9 +552,10 @@ void peer_connected(struct lightningd *ld, const u8 *msg, u8 *error; struct peer *peer; struct wireaddr addr; + u64 gossip_index; if (!fromwire_gossip_peer_connected(msg, msg, NULL, - &id, &addr, &cs, + &id, &addr, &cs, &gossip_index, &gfeatures, &lfeatures)) fatal("Gossip gave bad GOSSIP_PEER_CONNECTED message %s", tal_hex(msg, msg)); @@ -581,7 +604,8 @@ void peer_connected(struct lightningd *ld, const u8 *msg, /* Reconnect: discard old one. */ case OPENINGD: - tal_free(peer); + free_peer(peer, "peer reconnected"); + peer = NULL; goto return_to_gossipd; case ONCHAIND_CHEATED: @@ -601,7 +625,8 @@ void peer_connected(struct lightningd *ld, const u8 *msg, peer_set_owner(peer, NULL); peer->addr = addr; - peer_start_channeld(peer, &cs, peer_fd, gossip_fd, NULL, + peer_start_channeld(peer, &cs, gossip_index, + peer_fd, gossip_fd, NULL, true); return; @@ -612,7 +637,8 @@ void peer_connected(struct lightningd *ld, const u8 *msg, peer_set_owner(peer, NULL); peer->addr = addr; - peer_start_closingd(peer, &cs, peer_fd, gossip_fd, + peer_start_closingd(peer, &cs, gossip_index, + peer_fd, gossip_fd, true); return; } @@ -621,11 +647,10 @@ void peer_connected(struct lightningd *ld, const u8 *msg, return_to_gossipd: /* Otherwise, we hand back to gossipd, to continue. */ - msg = towire_gossipctl_handle_peer(msg, &id, &addr, &cs, - gfeatures, lfeatures, NULL); + msg = towire_gossipctl_hand_back_peer(msg, &id, &cs, gossip_index, NULL); subd_send_msg(ld->gossip, take(msg)); subd_send_fd(ld->gossip, peer_fd); - close(gossip_fd); + subd_send_fd(ld->gossip, gossip_fd); /* If we were waiting for connection, we succeeded. */ connect_succeeded(ld, &id); @@ -634,17 +659,18 @@ void peer_connected(struct lightningd *ld, const u8 *msg, send_error: /* Hand back to gossipd, with an error packet. */ connect_failed(ld, &id, sanitize_error(msg, error, NULL)); - msg = towire_gossipctl_handle_peer(msg, &id, &addr, &cs, - gfeatures, lfeatures, error); + msg = towire_gossipctl_hand_back_peer(msg, &id, &cs, gossip_index, + error); subd_send_msg(ld->gossip, take(msg)); subd_send_fd(ld->gossip, peer_fd); - close(gossip_fd); + subd_send_fd(ld->gossip, gossip_fd); } void peer_sent_nongossip(struct lightningd *ld, const struct pubkey *id, const struct wireaddr *addr, const struct crypto_state *cs, + u64 gossip_index, const u8 *gfeatures, const u8 *lfeatures, int peer_fd, int gossip_fd, @@ -672,7 +698,8 @@ void peer_sent_nongossip(struct lightningd *ld, /* Open request? */ if (fromwire_peektype(in_msg) == WIRE_OPEN_CHANNEL) { - peer_accept_channel(ld, id, addr, cs, gfeatures, lfeatures, + peer_accept_channel(ld, id, addr, cs, gossip_index, + gfeatures, lfeatures, peer_fd, gossip_fd, in_msg); return; } @@ -685,11 +712,10 @@ void peer_sent_nongossip(struct lightningd *ld, send_error: /* Hand back to gossipd, with an error packet. */ connect_failed(ld, id, sanitize_error(error, error, NULL)); - msg = towire_gossipctl_handle_peer(error, id, addr, cs, - gfeatures, lfeatures, error); + msg = towire_gossipctl_hand_back_peer(ld, id, cs, gossip_index, error); subd_send_msg(ld->gossip, take(msg)); subd_send_fd(ld->gossip, peer_fd); - close(gossip_fd); + subd_send_fd(ld->gossip, gossip_fd); tal_free(error); } @@ -981,12 +1007,6 @@ struct funding_channel { struct bitcoin_tx *funding_tx; }; -static void fail_fundchannel_command(struct funding_channel *fc) -{ - /* FIXME: More details? */ - command_fail(fc->cmd, "Peer died"); -} - static void funding_broadcast_failed(struct peer *peer, int exitstatus, const char *err) { @@ -1250,7 +1270,7 @@ static void handle_irrevocably_resolved(struct peer *peer, const u8 *msg) log_info(peer->log, "onchaind complete, forgetting peer"); /* This will also free onchaind. */ - tal_free(peer); + free_peer(peer, "onchaind complete, forgetting peer"); } static unsigned int onchain_msg(struct subd *sd, const u8 *msg, const int *fds) @@ -1518,7 +1538,8 @@ static enum watch_result funding_lockin_cb(struct peer *peer, static void opening_got_hsm_funding_sig(struct funding_channel *fc, int peer_fd, int gossip_fd, const u8 *resp, - const struct crypto_state *cs) + const struct crypto_state *cs, + u64 gossip_index) { secp256k1_ecdsa_signature *sigs; struct bitcoin_tx *tx = fc->funding_tx; @@ -1562,99 +1583,26 @@ static void opening_got_hsm_funding_sig(struct funding_channel *fc, fc->peer->funding_txid, fc->peer->funding_outnum, funding_spent, NULL); - /* We could defer until after funding locked, but makes testing - * harder. */ - tal_del_destructor(fc, fail_fundchannel_command); - json_object_start(response, NULL); linear = linearize_tx(response, tx); json_add_hex(response, "tx", linear, tal_len(linear)); json_object_end(response); - command_success(fc->cmd, response); + command_success(fc->peer->opening_cmd, response); + fc->peer->opening_cmd = NULL; /* Start normal channel daemon. */ - peer_start_channeld(fc->peer, cs, peer_fd, gossip_fd, NULL, false); + peer_start_channeld(fc->peer, cs, gossip_index, + peer_fd, gossip_fd, NULL, false); peer_set_condition(fc->peer, OPENINGD, CHANNELD_AWAITING_LOCKIN); wallet_confirm_utxos(fc->peer->ld->wallet, fc->utxomap); tal_free(fc); } -/* Create a node_announcement with the given signature. It may be NULL - * in the case we need to create a provisional announcement for the - * HSM to sign. This is typically called twice: once with the dummy - * signature to get it signed and a second time to build the full - * packet with the signature. The timestamp is handed in since that is - * the only thing that may change between the dummy creation and the - * call with a signature.*/ -static u8 *create_node_announcement(const tal_t *ctx, struct lightningd *ld, - secp256k1_ecdsa_signature *sig, - u32 timestamp) -{ - u8 *features = NULL; - u8 *addresses = tal_arr(ctx, u8, 0); - u8 *announcement; - size_t i; - if (!sig) { - sig = tal(ctx, secp256k1_ecdsa_signature); - memset(sig, 0, sizeof(*sig)); - } - for (i = 0; i < tal_count(ld->wireaddrs); i++) - towire_wireaddr(&addresses, ld->wireaddrs+i); - - announcement = - towire_node_announcement(ctx, sig, features, timestamp, - &ld->id, ld->rgb, (u8 *)ld->alias, - addresses); - return announcement; -} - /* We were informed by channeld that it announced the channel and sent * an update, so we can now start sending a node_announcement. The * first step is to build the provisional announcement and ask the HSM * to sign it. */ -static void peer_channel_announce(struct peer *peer, const u8 *msg) -{ - struct lightningd *ld = peer->ld; - tal_t *tmpctx = tal_tmpctx(peer); - secp256k1_ecdsa_signature sig; - u8 *cannounce, *cupdate; - u8 *announcement, *wrappedmsg; - u32 timestamp = time_now().ts.tv_sec; - - if (!fromwire_channel_announce(msg, msg, NULL, &cannounce, &cupdate)) { - peer_internal_error(peer, "bad fromwire_channel_announced %s", - tal_hex(peer, msg)); - return; - } - - msg = towire_hsm_node_announcement_sig_req( - tmpctx, create_node_announcement(tmpctx, ld, NULL, timestamp)); - - if (!wire_sync_write(ld->hsm_fd, take(msg))) - fatal("Could not write to HSM: %s", strerror(errno)); - - msg = hsm_sync_read(tmpctx, ld); - if (!fromwire_hsm_node_announcement_sig_reply(msg, NULL, &sig)) - fatal("HSM returned an invalid node_announcement sig"); - - /* We got the signature for out provisional node_announcement back - * from the HSM, create the real announcement and forward it to - * gossipd so it can take care of forwarding it. */ - announcement = create_node_announcement(tmpctx, ld, &sig, timestamp); - - /* We have to send channel_announce before channel_update and - * node_announcement */ - wrappedmsg = towire_gossip_forwarded_msg(tmpctx, cannounce); - subd_send_msg(ld->gossip, take(wrappedmsg)); - - wrappedmsg = towire_gossip_forwarded_msg(tmpctx, cupdate); - subd_send_msg(ld->gossip, take(wrappedmsg)); - - wrappedmsg = towire_gossip_forwarded_msg(tmpctx, announcement); - subd_send_msg(ld->gossip, take(wrappedmsg)); - tal_free(tmpctx); -} static void peer_got_funding_locked(struct peer *peer, const u8 *msg) { @@ -1822,7 +1770,10 @@ static void peer_received_closing_signature(struct peer *peer, const u8 *msg) static void peer_closing_complete(struct peer *peer, const u8 *msg) { - if (!fromwire_closing_complete(msg, NULL)) { + /* FIXME: We should save this, to return to gossipd */ + u64 gossip_index; + + if (!fromwire_closing_complete(msg, NULL, &gossip_index)) { peer_internal_error(peer, "Bad closing_complete %s", tal_hex(peer, msg)); return; @@ -1860,6 +1811,7 @@ static unsigned closing_msg(struct subd *sd, const u8 *msg, const int *fds) static void peer_start_closingd(struct peer *peer, struct crypto_state *cs, + u64 gossip_index, int peer_fd, int gossip_fd, bool reconnected) { @@ -1935,6 +1887,7 @@ static void peer_start_closingd(struct peer *peer, */ initmsg = towire_closing_init(tmpctx, cs, + gossip_index, peer->seed, peer->funding_txid, peer->funding_outnum, @@ -1963,18 +1916,19 @@ static void peer_start_closingd_after_shutdown(struct peer *peer, const u8 *msg, const int *fds) { struct crypto_state cs; + u64 gossip_index; /* We expect 2 fds. */ assert(tal_count(fds) == 2); - if (!fromwire_channel_shutdown_complete(msg, NULL, &cs)) { + if (!fromwire_channel_shutdown_complete(msg, NULL, &cs, &gossip_index)) { peer_internal_error(peer, "bad shutdown_complete: %s", tal_hex(peer, msg)); return; } /* This sets peer->owner, closes down channeld. */ - peer_start_closingd(peer, &cs, fds[0], fds[1], false); + peer_start_closingd(peer, &cs, gossip_index, fds[0], fds[1], false); peer_set_condition(peer, CHANNELD_SHUTTING_DOWN, CLOSINGD_SIGEXCHANGE); } @@ -1996,9 +1950,6 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNEL_GOT_REVOKE: peer_got_revoke(sd->peer, msg); break; - case WIRE_CHANNEL_ANNOUNCE: - peer_channel_announce(sd->peer, msg); - break; case WIRE_CHANNEL_GOT_FUNDING_LOCKED: peer_got_funding_locked(sd->peer, msg); break; @@ -2038,6 +1989,7 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) static bool peer_start_channeld(struct peer *peer, const struct crypto_state *cs, + u64 gossip_index, int peer_fd, int gossip_fd, const u8 *funding_signed, bool reconnected) @@ -2128,7 +2080,7 @@ static bool peer_start_channeld(struct peer *peer, get_feerate(peer->ld->topology, FEERATE_NORMAL), get_feerate(peer->ld->topology, FEERATE_IMMEDIATE) * 5, peer->last_sig, - cs, + cs, gossip_index, &peer->channel_info->remote_fundingkey, &peer->channel_info->theirbase.revocation, &peer->channel_info->theirbase.payment, @@ -2189,6 +2141,7 @@ static void opening_funder_finished(struct subd *opening, const u8 *resp, struct crypto_state cs; secp256k1_ecdsa_signature remote_commit_sig; struct bitcoin_tx *remote_commit; + u64 gossip_index; assert(tal_count(fds) == 2); @@ -2205,6 +2158,7 @@ static void opening_funder_finished(struct subd *opening, const u8 *resp, remote_commit, &remote_commit_sig, &cs, + &gossip_index, &channel_info->theirbase.revocation, &channel_info->theirbase.payment, &channel_info->theirbase.htlc, @@ -2294,7 +2248,7 @@ static void opening_funder_finished(struct subd *opening, const u8 *resp, fatal("Could not write to HSM: %s", strerror(errno)); msg = hsm_sync_read(fc, fc->peer->ld); - opening_got_hsm_funding_sig(fc, fds[0], fds[1], msg, &cs); + opening_got_hsm_funding_sig(fc, fds[0], fds[1], msg, &cs, gossip_index); } static void opening_fundee_finished(struct subd *opening, @@ -2305,6 +2259,7 @@ static void opening_fundee_finished(struct subd *opening, u8 *funding_signed; struct channel_info *channel_info; struct crypto_state cs; + u64 gossip_index; secp256k1_ecdsa_signature remote_commit_sig; struct bitcoin_tx *remote_commit; @@ -2324,6 +2279,7 @@ static void opening_fundee_finished(struct subd *opening, remote_commit, &remote_commit_sig, &cs, + &gossip_index, &channel_info->theirbase.revocation, &channel_info->theirbase.payment, &channel_info->theirbase.htlc, @@ -2369,15 +2325,54 @@ static void opening_fundee_finished(struct subd *opening, peer_set_owner(peer, NULL); /* On to normal operation! */ - peer_start_channeld(peer, &cs, fds[0], fds[1], funding_signed, false); + peer_start_channeld(peer, &cs, gossip_index, + fds[0], fds[1], funding_signed, false); peer_set_condition(peer, OPENINGD, CHANNELD_AWAITING_LOCKIN); } +/* Negotiation failed, but we can keep gossipping */ +static unsigned int opening_negotiation_failed(struct subd *openingd, + const u8 *msg, + const int *fds) +{ + struct crypto_state cs; + u64 gossip_index; + struct peer *peer = openingd->peer; + u8 *err; + const char *why; + + /* We need the peer fd and gossip fd. */ + if (tal_count(fds) == 0) + return 2; + + if (!fromwire_opening_negotiation_failed(msg, msg, NULL, + &cs, &gossip_index, &err)) { + peer_internal_error(peer, + "bad OPENING_NEGOTIATION_FAILED %s", + tal_hex(msg, msg)); + return 0; + } + + msg = towire_gossipctl_hand_back_peer(msg, &peer->id, &cs, gossip_index, + NULL); + subd_send_msg(openingd->ld->gossip, take(msg)); + subd_send_fd(openingd->ld->gossip, fds[0]); + subd_send_fd(openingd->ld->gossip, fds[1]); + + why = tal_strndup(peer, (const char *)err, tal_len(err)); + log_unusual(peer->log, "Opening negotiation failed: %s", why); + + /* This will free openingd, since that's peer->owner */ + free_peer(peer, why); + return 0; +} + /* Peer has spontaneously exited from gossip due to open msg */ static void peer_accept_channel(struct lightningd *ld, const struct pubkey *peer_id, const struct wireaddr *addr, const struct crypto_state *cs, + u64 gossip_index, const u8 *gfeatures, const u8 *lfeatures, int peer_fd, int gossip_fd, const u8 *open_msg) @@ -2394,7 +2389,8 @@ static void peer_accept_channel(struct lightningd *ld, peer_set_condition(peer, UNINITIALIZED, OPENINGD); peer_set_owner(peer, new_peer_subd(ld, "lightning_openingd", peer, - opening_wire_type_name, NULL, + opening_wire_type_name, + opening_negotiation_failed, take(&peer_fd), take(&gossip_fd), NULL)); if (!peer->owner) { peer_fail_transient(peer, "Failed to subdaemon opening: %s", @@ -2428,7 +2424,7 @@ static void peer_accept_channel(struct lightningd *ld, &peer->our_config, max_to_self_delay, min_effective_htlc_capacity_msat, - cs, peer->seed); + cs, gossip_index, peer->seed); subd_send_msg(peer->owner, take(msg)); @@ -2451,6 +2447,7 @@ static void peer_offer_channel(struct lightningd *ld, struct funding_channel *fc, const struct wireaddr *addr, const struct crypto_state *cs, + u64 gossip_index, const u8 *gfeatures, const u8 *lfeatures, int peer_fd, int gossip_fd) { @@ -2469,7 +2466,8 @@ static void peer_offer_channel(struct lightningd *ld, peer_set_owner(fc->peer, new_peer_subd(ld, "lightning_openingd", fc->peer, - opening_wire_type_name, NULL, + opening_wire_type_name, + opening_negotiation_failed, take(&peer_fd), take(&gossip_fd), NULL)); if (!fc->peer->owner) { fc->peer = tal_free(fc->peer); @@ -2507,7 +2505,7 @@ static void peer_offer_channel(struct lightningd *ld, &fc->peer->our_config, max_to_self_delay, min_effective_htlc_capacity_msat, - cs, fc->peer->seed); + cs, gossip_index, fc->peer->seed); subd_send_msg(fc->peer->owner, take(msg)); utxos = from_utxoptr_arr(fc, fc->utxomap); @@ -2522,7 +2520,7 @@ static void peer_offer_channel(struct lightningd *ld, /* Peer now owns fc; if it dies, we fail fc. */ tal_steal(fc->peer, fc); - tal_add_destructor(fc, fail_fundchannel_command); + fc->peer->opening_cmd = fc->cmd; subd_req(fc, fc->peer->owner, take(msg), -1, 2, opening_funder_finished, fc); @@ -2536,6 +2534,7 @@ static void gossip_peer_released(struct subd *gossip, { struct lightningd *ld = gossip->ld; struct crypto_state cs; + u64 gossip_index; u8 *gfeatures, *lfeatures; struct wireaddr addr; @@ -2543,6 +2542,7 @@ static void gossip_peer_released(struct subd *gossip, fc->peer = peer_by_id(ld, &fc->peerid); if (!fromwire_gossipctl_release_peer_reply(fc, resp, NULL, &addr, &cs, + &gossip_index, &gfeatures, &lfeatures)) { if (!fromwire_gossipctl_release_peer_replyfail(resp, NULL)) { fatal("Gossip daemon gave invalid reply %s", @@ -2568,7 +2568,8 @@ static void gossip_peer_released(struct subd *gossip, } /* OK, offer peer a channel. */ - peer_offer_channel(ld, fc, &addr, &cs, gfeatures, lfeatures, + peer_offer_channel(ld, fc, &addr, &cs, gossip_index, + gfeatures, lfeatures, fds[0], fds[1]); } diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index 53c7c8c6d65b..aee2378a9d6e 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -26,9 +26,6 @@ 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; @@ -41,6 +38,9 @@ struct peer { /* Which side offered channel? */ enum side funder; + /* Command which ordered us to open channel, if any. */ + struct command *opening_cmd; + /* Inside ld->peers. */ struct list_node list; @@ -176,6 +176,7 @@ void peer_sent_nongossip(struct lightningd *ld, const struct pubkey *id, const struct wireaddr *addr, const struct crypto_state *cs, + u64 gossip_index, const u8 *gfeatures, const u8 *lfeatures, int peer_fd, int gossip_fd, @@ -212,6 +213,9 @@ void peer_fail_permanent_str(struct peer *peer, const char *str TAKES); /* Permanent error, but due to internal problems, not peer. */ void peer_internal_error(struct peer *peer, const char *fmt, ...); +/* Peer has failed to open; return to gossipd. */ +void opening_failed(struct peer *peer, const u8 *msg TAKES); + const char *peer_state_name(enum peer_state state); void peer_set_condition(struct peer *peer, enum peer_state oldstate, enum peer_state state); diff --git a/lightningd/subd.c b/lightningd/subd.c index 95d6703357cf..a1d79c4608fd 100644 --- a/lightningd/subd.c +++ b/lightningd/subd.c @@ -377,7 +377,6 @@ static bool log_status_fail(struct subd *sd, case STATUS_FAIL_INTERNAL_ERROR: name = "STATUS_FAIL_INTERNAL_ERROR"; goto log_str_broken; - /* * These errors happen when the other peer misbehaves: */ @@ -524,8 +523,13 @@ static void destroy_subd(struct subd *sd) switch (waitpid(sd->pid, &status, WNOHANG)) { case 0: - log_debug(sd->log, "Status closed, but not exited. Killing"); - kill(sd->pid, SIGKILL); + /* If it's an essential daemon, don't kill: we want the + * exit status */ + if (!sd->must_not_exit) { + log_debug(sd->log, + "Status closed, but not exited. Killing"); + kill(sd->pid, SIGKILL); + } waitpid(sd->pid, &status, 0); fail_if_subd_fails = false; break; @@ -548,10 +552,20 @@ static void destroy_subd(struct subd *sd) if (sd->peer) { /* Don't loop back when we fail it. */ struct peer *peer = sd->peer; + struct db *db = sd->ld->wallet->db; + bool outer_transaction; + sd->peer = NULL; + + /* We can be freed both inside msg handling, or spontaneously. */ + outer_transaction = db->in_transaction; + if (!outer_transaction) + db_begin_transaction(db); peer_fail_transient(peer, "Owning subdaemon %s died (%i)", sd->name, status); + if (!outer_transaction) + db_commit_transaction(db); } if (sd->must_not_exit) { diff --git a/openingd/Makefile b/openingd/Makefile index d112d7c41c8c..6575478c85a1 100644 --- a/openingd/Makefile +++ b/openingd/Makefile @@ -59,7 +59,8 @@ OPENINGD_COMMON_OBJS := \ common/type_to_string.o \ common/utils.o \ common/utxo.o \ - common/version.o + common/version.o \ + common/wire_error.o $(LIGHTNINGD_OPENING_OBJS): $(LIGHTNINGD_HEADERS) diff --git a/openingd/opening.c b/openingd/opening.c index 002c7268029b..3357c3779e37 100644 --- a/openingd/opening.c +++ b/openingd/opening.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +38,7 @@ struct state { struct crypto_state cs; + u64 gossip_index; struct pubkey next_per_commit[NUM_SIDES]; /* Initially temporary, then final channel id. */ @@ -63,6 +66,40 @@ struct state { const struct chainparams *chainparams; }; +/* For negotiation failures: we can still gossip with client. */ +static void negotiation_failed(struct state *state, bool send_error, + const char *fmt, ...) +{ + va_list ap; + const char *errmsg; + u8 *msg; + + va_start(ap, fmt); + errmsg = tal_vfmt(state, fmt, ap); + va_end(ap); + + /* Make sure it's correct length for towire_. */ + tal_resize(&errmsg, strlen(errmsg)+1); + + /* We don't send error in response to their error packet. */ + if (send_error) { + /* Tell peer we're bailing on this channel. */ + msg = towire_errorfmt(errmsg, &state->channel_id, "%s", errmsg); + sync_crypto_write(&state->cs, PEER_FD, take(msg)); + } + + /* Tell master we should return to gossiping. */ + msg = towire_opening_negotiation_failed(state, &state->cs, + state->gossip_index, + (const u8 *)errmsg); + wire_sync_write(REQ_FD, msg); + fdpass_send(REQ_FD, PEER_FD); + fdpass_send(REQ_FD, GOSSIP_FD); + + tal_free(state); + exit(0); +} + static void check_config_bounds(struct state *state, const struct channel_config *remoteconf) { @@ -75,9 +112,10 @@ static void check_config_bounds(struct state *state, * unreasonably large. */ if (remoteconf->to_self_delay > state->max_to_self_delay) - peer_failed(PEER_FD, &state->cs, &state->channel_id, - "to_self_delay %u larger than %u", - remoteconf->to_self_delay, state->max_to_self_delay); + negotiation_failed(state, true, + "to_self_delay %u larger than %u", + remoteconf->to_self_delay, + state->max_to_self_delay); /* BOLT #2: * @@ -92,11 +130,11 @@ static void check_config_bounds(struct state *state, /* Overflow check before capacity calc. */ if (remoteconf->channel_reserve_satoshis > state->funding_satoshis) - peer_failed(PEER_FD, &state->cs, &state->channel_id, - "Invalid channel_reserve_satoshis %"PRIu64 - " for funding_satoshis %"PRIu64, - remoteconf->channel_reserve_satoshis, - state->funding_satoshis); + negotiation_failed(state, true, + "Invalid channel_reserve_satoshis %"PRIu64 + " for funding_satoshis %"PRIu64, + remoteconf->channel_reserve_satoshis, + state->funding_satoshis); /* Consider highest reserve. */ reserve_msat = remoteconf->channel_reserve_satoshis * 1000; @@ -109,32 +147,32 @@ static void check_config_bounds(struct state *state, capacity_msat = remoteconf->max_htlc_value_in_flight_msat; if (remoteconf->htlc_minimum_msat * (u64)1000 > capacity_msat) - peer_failed(PEER_FD, &state->cs, &state->channel_id, - "Invalid htlc_minimum_msat %"PRIu64 - " for funding_satoshis %"PRIu64 - " capacity_msat %"PRIu64, - remoteconf->htlc_minimum_msat, - state->funding_satoshis, - capacity_msat); + negotiation_failed(state, true, + "Invalid htlc_minimum_msat %"PRIu64 + " for funding_satoshis %"PRIu64 + " capacity_msat %"PRIu64, + remoteconf->htlc_minimum_msat, + state->funding_satoshis, + capacity_msat); if (capacity_msat < state->min_effective_htlc_capacity_msat) - peer_failed(PEER_FD, &state->cs, &state->channel_id, - "Channel capacity with funding %"PRIu64" msat," - " reserves %"PRIu64"/%"PRIu64" msat," - " max_htlc_value_in_flight_msat %"PRIu64 - " is %"PRIu64" msat, which is below %"PRIu64" msat", - state->funding_satoshis * 1000, - remoteconf->channel_reserve_satoshis * 1000, - state->localconf.channel_reserve_satoshis * 1000, - remoteconf->max_htlc_value_in_flight_msat, - capacity_msat, - state->min_effective_htlc_capacity_msat); + negotiation_failed(state, true, + "Channel capacity with funding %"PRIu64" msat," + " reserves %"PRIu64"/%"PRIu64" msat," + " max_htlc_value_in_flight_msat %"PRIu64 + " is %"PRIu64" msat, which is below %"PRIu64" msat", + state->funding_satoshis * 1000, + remoteconf->channel_reserve_satoshis * 1000, + state->localconf.channel_reserve_satoshis * 1000, + remoteconf->max_htlc_value_in_flight_msat, + capacity_msat, + state->min_effective_htlc_capacity_msat); /* We don't worry about how many HTLCs they accept, as long as > 0! */ if (remoteconf->max_accepted_htlcs == 0) - peer_failed(PEER_FD, &state->cs, &state->channel_id, - "max_accepted_htlcs %u invalid", - remoteconf->max_accepted_htlcs); + negotiation_failed(state, true, + "max_accepted_htlcs %u invalid", + remoteconf->max_accepted_htlcs); /* BOLT #2: * @@ -189,6 +227,33 @@ static u8 *read_next_peer_msg(struct state *state, const tal_t *ctx) if (!wire_sync_write(GOSSIP_FD, take(msg))) status_failed(STATUS_FAIL_PEER_IO, "Relaying gossip message"); + } else if (fromwire_peektype(msg) == WIRE_ERROR) { + struct channel_id chanid; + char *err = sanitize_error(msg, msg, &chanid); + + /* BOLT #1: + * + * The channel is referred to by `channel_id`, unless + * `channel_id` is 0 (i.e. all bytes are 0), in which + * case it refers to all channels. + * ... + + * The receiving node: + * - upon receiving `error`: + * - MUST fail the channel referred to by the error + * message. + * - if no existing channel is referred to by the + * message: + * - MUST ignore the message. + */ + if (channel_id_is_all(&chanid)) + peer_failed(PEER_FD, &state->cs, + &state->channel_id, + "Error packet: %s", err); + + if (structeq(&chanid, &state->channel_id)) + negotiation_failed(state, false, + "Error packet: %s", err); } else { return msg; } @@ -298,7 +363,7 @@ static u8 *funder_channel(struct state *state, * The `temporary_channel_id` MUST be the same as the * `temporary_channel_id` in the `open_channel` message. */ if (!structeq(&id_in, &state->channel_id)) - peer_failed(PEER_FD, &state->cs, &id_in, + peer_failed(PEER_FD, &state->cs, &state->channel_id, "accept_channel ids don't match: sent %s got %s", type_to_string(msg, struct channel_id, &id_in), type_to_string(msg, struct channel_id, @@ -313,9 +378,9 @@ static u8 *funder_channel(struct state *state, * `open_channel`. */ if (minimum_depth > max_minimum_depth) - peer_failed(PEER_FD, &state->cs, &state->channel_id, - "minimum_depth %u larger than %u", - minimum_depth, max_minimum_depth); + negotiation_failed(state, true, + "minimum_depth %u larger than %u", + minimum_depth, max_minimum_depth); check_config_bounds(state, state->remoteconf); /* Now, ask create funding transaction to pay those two addresses. */ @@ -439,7 +504,7 @@ static u8 *funder_channel(struct state *state, state->remoteconf, tx, &sig, - &state->cs, + &state->cs, state->gossip_index, &theirs.revocation, &theirs.payment, &theirs.htlc, @@ -506,10 +571,11 @@ static u8 *fundee_channel(struct state *state, * unknown to the receiver. */ if (!structeq(&chain_hash, &state->chainparams->genesis_blockhash)) { - peer_failed(PEER_FD, &state->cs, &state->channel_id, - "Unknown chain-hash %s", - type_to_string(peer_msg, struct sha256_double, - &chain_hash)); + negotiation_failed(state, true, + "Unknown chain-hash %s", + type_to_string(peer_msg, + struct sha256_double, + &chain_hash)); } /* BOLT #2 FIXME: @@ -538,14 +604,14 @@ static u8 *fundee_channel(struct state *state, * too small for timely processing, or unreasonably large. */ if (state->feerate_per_kw < min_feerate) - peer_failed(PEER_FD, &state->cs, &state->channel_id, - "feerate_per_kw %u below minimum %u", - state->feerate_per_kw, min_feerate); + negotiation_failed(state, true, + "feerate_per_kw %u below minimum %u", + state->feerate_per_kw, min_feerate); if (state->feerate_per_kw > max_feerate) - peer_failed(PEER_FD, &state->cs, &state->channel_id, - "feerate_per_kw %u above maximum %u", - state->feerate_per_kw, max_feerate); + negotiation_failed(state, true, + "feerate_per_kw %u above maximum %u", + state->feerate_per_kw, max_feerate); set_reserve(&state->localconf.channel_reserve_satoshis, state->funding_satoshis); @@ -662,6 +728,7 @@ static u8 *fundee_channel(struct state *state, their_commit, &theirsig, &state->cs, + state->gossip_index, &theirs.revocation, &theirs.payment, &theirs.htlc, @@ -714,6 +781,7 @@ int main(int argc, char *argv[]) &state->max_to_self_delay, &state->min_effective_htlc_capacity_msat, &state->cs, + &state->gossip_index, &seed)) master_badmsg(WIRE_OPENING_INIT, msg); diff --git a/openingd/opening_wire.csv b/openingd/opening_wire.csv index 3ebaa8dc7faa..598336869c5c 100644 --- a/openingd/opening_wire.csv +++ b/openingd/opening_wire.csv @@ -9,6 +9,7 @@ opening_init,,our_config,struct channel_config opening_init,,max_to_self_delay,u32 opening_init,,min_effective_htlc_capacity_msat,u64 opening_init,,crypto_state,struct crypto_state +opening_init,,gossip_index,u64 # Seed to generate all the keys from opening_init,,seed,struct privkey @@ -34,6 +35,7 @@ opening_funder_reply,,their_config,struct channel_config opening_funder_reply,,first_commit,struct bitcoin_tx opening_funder_reply,,first_commit_sig,secp256k1_ecdsa_signature opening_funder_reply,,crypto_state,struct crypto_state +opening_funder_reply,,gossip_index,u64 opening_funder_reply,,revocation_basepoint,struct pubkey opening_funder_reply,,payment_basepoint,struct pubkey opening_funder_reply,,htlc_basepoint,struct pubkey @@ -58,6 +60,7 @@ opening_fundee_reply,,their_config,struct channel_config opening_fundee_reply,,first_commit,struct bitcoin_tx opening_fundee_reply,,first_commit_sig,secp256k1_ecdsa_signature opening_fundee_reply,,crypto_state,struct crypto_state +opening_fundee_reply,,gossip_index,u64 opening_fundee_reply,,revocation_basepoint,struct pubkey opening_fundee_reply,,payment_basepoint,struct pubkey opening_fundee_reply,,htlc_basepoint,struct pubkey @@ -73,3 +76,12 @@ opening_fundee_reply,,feerate_per_kw,u32 # The (encrypted) funding signed message: send this and we're committed. opening_fundee_reply,,msglen,u16 opening_fundee_reply,,funding_signed_msg,msglen*u8 + +# We disagreed with opening parameters, but peer is ok for gossip (+ peerfd) +opening_negotiation_failed,6010 +opening_negotiation_failed,,crypto_state,struct crypto_state +opening_negotiation_failed,,gossip_index,u64 +opening_negotiation_failed,,len,u16 +# FIXME: string support! +opening_negotiation_failed,,msg,len*u8 + diff --git a/tests/test_lightningd.py b/tests/test_lightningd.py index adc05f16a751..21e06785f543 100644 --- a/tests/test_lightningd.py +++ b/tests/test_lightningd.py @@ -221,8 +221,8 @@ def connect(self): assert ret['id'] == l2.info['id'] - l1.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER') - l2.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER') + l1.daemon.wait_for_log('WIRE_GOSSIPCTL_HAND_BACK_PEER') + l2.daemon.wait_for_log('WIRE_GOSSIPCTL_HAND_BACK_PEER') return l1,l2 # Returns the short channel-id: :: @@ -342,8 +342,8 @@ def test_connect(self): assert l2.rpc.getpeer(l1.info['id'])['state'] == 'GOSSIPING' # 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'])) + l1.daemon.wait_for_log('hand_back_peer {}: now local again'.format(l2.info['id'])) + l2.daemon.wait_for_log('hand_back_peer {}: now local again'.format(l1.info['id'])) def test_balance(self): l1,l2 = self.connect() @@ -709,8 +709,8 @@ def test_bad_opening(self): assert ret['id'] == l2.info['id'] - l1.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER') - l2.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER') + l1.daemon.wait_for_log('WIRE_GOSSIPCTL_HAND_BACK_PEER') + l2.daemon.wait_for_log('WIRE_GOSSIPCTL_HAND_BACK_PEER') addr = l1.rpc.newaddr()['address'] txid = l1.bitcoin.rpc.sendtoaddress(addr, 10**6 / 10**8 + 0.01) @@ -1406,7 +1406,7 @@ def test_forward(self): assert ret['id'] == l3.info['id'] - l3.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER') + l3.daemon.wait_for_log('WIRE_GOSSIPCTL_HAND_BACK_PEER') self.fund_channel(l1, l2, 10**6) self.fund_channel(l2, l3, 10**6) @@ -1497,14 +1497,14 @@ def test_forward_different_fees_and_cltv(self): ret = l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port']) assert ret['id'] == l2.info['id'] - l1.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER') - l2.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER') + l1.daemon.wait_for_log('WIRE_GOSSIPCTL_HAND_BACK_PEER') + l2.daemon.wait_for_log('WIRE_GOSSIPCTL_HAND_BACK_PEER') ret = l2.rpc.connect(l3.info['id'], 'localhost', l3.info['port']) assert ret['id'] == l3.info['id'] - l2.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER') - l3.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER') + l2.daemon.wait_for_log('WIRE_GOSSIPCTL_HAND_BACK_PEER') + l3.daemon.wait_for_log('WIRE_GOSSIPCTL_HAND_BACK_PEER') c1 = self.fund_channel(l1, l2, 10**6) c2 = self.fund_channel(l2, l3, 10**6) @@ -1596,14 +1596,14 @@ def test_forward_pad_fees_and_cltv(self): ret = l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port']) assert ret['id'] == l2.info['id'] - l1.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER') - l2.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER') + l1.daemon.wait_for_log('WIRE_GOSSIPCTL_HAND_BACK_PEER') + l2.daemon.wait_for_log('WIRE_GOSSIPCTL_HAND_BACK_PEER') ret = l2.rpc.connect(l3.info['id'], 'localhost', l3.info['port']) assert ret['id'] == l3.info['id'] - l2.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER') - l3.daemon.wait_for_log('WIRE_GOSSIPCTL_HANDLE_PEER') + l2.daemon.wait_for_log('WIRE_GOSSIPCTL_HAND_BACK_PEER') + l3.daemon.wait_for_log('WIRE_GOSSIPCTL_HAND_BACK_PEER') c1 = self.fund_channel(l1, l2, 10**6) c2 = self.fund_channel(l2, l3, 10**6) @@ -2116,6 +2116,45 @@ def test_funding_change(self): assert outputs[0] > 8990000 assert outputs[2] == 10000000 + def test_funding_fail(self): + """Add some funds, fund a channel without enough funds""" + # Previous runs with same bitcoind can leave funds! + l1 = self.node_factory.get_node(random_hsm=True) + max_locktime = 3 * 6 * 24 + l2 = self.node_factory.get_node(options=['--locktime-blocks={}'.format(max_locktime + 1)]) + l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port']) + + funds = 1000000 + + addr = l1.rpc.newaddr()['address'] + txid = l1.bitcoin.rpc.sendtoaddress(addr, funds / 10**8) + bitcoind.generate_block(1) + + # Wait for it to arrive. + wait_for(lambda: len(l1.rpc.listfunds()['outputs']) > 0) + + # Fail because l1 dislikes l2's huge locktime. + self.assertRaisesRegex(ValueError, r'to_self_delay \d+ larger than \d+', + l1.rpc.fundchannel, l2.info['id'], int(funds/10)) + assert l1.rpc.getpeers()['peers'][0]['connected'] + assert l2.rpc.getpeers()['peers'][0]['connected'] + + # Restart l2 without ridiculous locktime. + l2.daemon.cmd_line.remove('--locktime-blocks={}'.format(max_locktime + 1)) + l2.restart() + l1.rpc.connect(l2.info['id'], 'localhost', l2.info['port']) + + # We don't have enough left to cover fees if we try to spend it all. + self.assertRaisesRegex(ValueError, r'Cannot afford funding transaction', + l1.rpc.fundchannel, l2.info['id'], funds) + + # Should still be connected. + assert l1.rpc.getpeers()['peers'][0]['connected'] + assert l2.rpc.getpeers()['peers'][0]['connected'] + + # This works. + l1.rpc.fundchannel(l2.info['id'], int(funds/10)) + def test_addfunds_from_block(self): """Send funds to the daemon without telling it explicitly """ @@ -2267,7 +2306,7 @@ def test_channel_reenable(self): l2.daemon.wait_for_log('Received node_announcement for node {}'.format(l1.info['id'])) # Both directions should be active before the restart - assert [c['active'] for c in l1.rpc.getchannels()['channels']] == [True, True] + wait_for(lambda: [c['active'] for c in l1.rpc.getchannels()['channels']] == [True, True]) # Restart l2, will cause l1 to reconnect l2.stop() @@ -2276,7 +2315,7 @@ def test_channel_reenable(self): # Now they should sync and re-establish again l1.daemon.wait_for_log('Received node_announcement for node {}'.format(l2.info['id'])) l2.daemon.wait_for_log('Received node_announcement for node {}'.format(l1.info['id'])) - assert [c['active'] for c in l1.rpc.getchannels()['channels']] == [True, True] + wait_for(lambda: [c['active'] for c in l1.rpc.getchannels()['channels']] == [True, True]) @unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1") def test_update_fee(self): diff --git a/tests/utils.py b/tests/utils.py index b15191455f33..fda6a78916bf 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -79,8 +79,8 @@ def stop(self, timeout=10): self.proc.wait() self.thread.join() - if failed: - raise(ValueError("Process '{}' did not cleanly shutdown".format(self.proc.pid))) + if self.proc.returncode: + raise ValueError("Process '{}' did not cleanly shutdown: return code {}".format(self.proc.pid, rc)) return self.proc.returncode @@ -364,3 +364,17 @@ def stop(self, timeout=10): raise ValueError("Node did not exit cleanly, rc={}".format(rc)) else: return rc + + def restart(self, timeout=10, clean=True): + """Stop and restart the lightning node. + + Keyword arguments: + timeout: number of seconds to wait for a shutdown + clean: whether to issue a `stop` RPC command before killing + """ + if clean: + self.stop(timeout) + else: + self.daemon.stop() + + self.daemon.start()