diff --git a/connectd/connectd.c b/connectd/connectd.c index 8a49ad35b..b2b07eaab 100644 --- a/connectd/connectd.c +++ b/connectd/connectd.c @@ -312,6 +312,7 @@ static struct peer *new_peer(struct daemon *daemon, peer->sent_to_peer = NULL; peer->urgent = false; peer->ready_to_die = false; + peer->active = false; peer->peer_outq = msg_queue_new(peer, false); #if DEVELOPER @@ -321,11 +322,6 @@ static struct peer *new_peer(struct daemon *daemon, peer->to_peer = conn; - /* Aim for connection to shuffle data back and forth: sets up - * peer->subds[0] */ - if (!multiplex_subd_setup(peer, fd_for_subd)) - return tal_free(peer); - /* Now we own it */ tal_steal(peer, peer->to_peer); peer_htable_add(&daemon->peers, peer); @@ -424,9 +420,9 @@ struct io_plan *peer_connected(struct io_conn *conn, /*~ daemon_conn is a message queue for inter-daemon communication: we * queue up the `connect_peer_connected` message to tell lightningd - * we have connected, and give the peer fd. */ + * we have connected. Once it says something interesting, we tell + * it that, too. */ daemon_conn_send(daemon->master, take(msg)); - daemon_conn_send_fd(daemon->master, subd_fd); /*~ Now we set up this connection to read/write from subd */ return multiplex_peer_setup(conn, peer); @@ -1791,7 +1787,7 @@ static void try_connect_peer(struct daemon *daemon, existing = peer_htable_get(&daemon->peers, id); if (existing) { /* If it's exiting now, we've raced: reconnect after */ - if (tal_count(existing->subds) != 0 + if ((tal_count(existing->subds) != 0 || !existing->active) && existing->to_peer && !existing->ready_to_die) { /* Tell it it's already connected so it doesn't @@ -1897,9 +1893,11 @@ void peer_conn_closed(struct peer *peer) struct connecting *connect = find_connecting(peer->daemon, &peer->id); /* These should be closed already! */ - assert(!peer->subds); + assert(tal_count(peer->subds) == 0); assert(!peer->to_peer); - assert(peer->ready_to_die); + assert(peer->ready_to_die || !peer->active); + + status_peer_debug(&peer->id, "peer_conn_closed"); /* Tell gossipd to stop asking this peer gossip queries */ daemon_conn_send(peer->daemon->gossipd, @@ -1923,32 +1921,24 @@ void peer_conn_closed(struct peer *peer) try_connect_one_addr(connect); } -/* A peer is gone: clean things up. */ -static void cleanup_dead_peer(struct daemon *daemon, const struct node_id *id) -{ - struct peer *peer; - - /* We should stay in sync with lightningd at all times. */ - peer = peer_htable_get(&daemon->peers, id); - if (!peer) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "peer_disconnected unknown peer: %s", - type_to_string(tmpctx, struct node_id, id)); - status_peer_debug(id, "disconnect"); - - /* When it's finished, it will call peer_conn_closed() */ - close_peer_conn(peer); -} - /* lightningd tells us a peer should be disconnected. */ static void peer_discard(struct daemon *daemon, const u8 *msg) { struct node_id id; + struct peer *peer; if (!fromwire_connectd_discard_peer(msg, &id)) master_badmsg(WIRE_CONNECTD_DISCARD_PEER, msg); - cleanup_dead_peer(daemon, &id); + /* We should stay in sync with lightningd, but this can happen + * under stress. */ + peer = peer_htable_get(&daemon->peers, &id); + if (!peer) + return; + status_peer_debug(&id, "disconnect"); + + /* When it's finished, it will call peer_conn_closed() */ + close_peer_conn(peer); } /* lightningd tells us to send a msg and disconnect. */ @@ -2031,6 +2021,10 @@ static struct io_plan *recv_req(struct io_conn *conn, send_custommsg(daemon, msg); goto out; + case WIRE_CONNECTD_PEER_MAKE_ACTIVE: + peer_make_active(daemon, msg); + goto out; + case WIRE_CONNECTD_DEV_MEMLEAK: #if DEVELOPER dev_connect_memleak(daemon, msg); @@ -2041,6 +2035,7 @@ static struct io_plan *recv_req(struct io_conn *conn, case WIRE_CONNECTD_ACTIVATE_REPLY: case WIRE_CONNECTD_PEER_CONNECTED: case WIRE_CONNECTD_PEER_ALREADY_CONNECTED: + case WIRE_CONNECTD_PEER_ACTIVE: case WIRE_CONNECTD_RECONNECTED: case WIRE_CONNECTD_CONNECT_FAILED: case WIRE_CONNECTD_DEV_MEMLEAK_REPLY: diff --git a/connectd/connectd.h b/connectd/connectd.h index ce488a907..825a21891 100644 --- a/connectd/connectd.h +++ b/connectd/connectd.h @@ -63,6 +63,9 @@ struct peer { * it's done). */ bool ready_to_die; + /* Has this ever been active? (i.e. ever had a subd attached?) */ + bool active; + /* When socket has Nagle overridden */ bool urgent; diff --git a/connectd/connectd_wire.csv b/connectd/connectd_wire.csv index e891e63f0..7af157794 100644 --- a/connectd/connectd_wire.csv +++ b/connectd/connectd_wire.csv @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -62,7 +63,7 @@ msgdata,connectd_connect_failed,failreason,wirestring, msgdata,connectd_connect_failed,seconds_to_delay,u32, msgdata,connectd_connect_failed,addrhint,?wireaddr_internal, -# Connectd -> master: we got a peer. Plus fd for peer daemon +# Connectd -> master: we got a peer. msgtype,connectd_peer_connected,2002 msgdata,connectd_peer_connected,id,node_id, msgdata,connectd_peer_connected,addr,wireaddr_internal, @@ -75,6 +76,18 @@ msgdata,connectd_peer_connected,features,u8,flen msgtype,connectd_peer_disconnect_done,2006 msgdata,connectd_peer_disconnect_done,id,node_id, +# Master -> connectd: make peer active immediately (we want to talk) +msgtype,connectd_peer_make_active,2004 +msgdata,connectd_peer_make_active,id,node_id, +msgdata,connectd_peer_make_active,channel_id,?channel_id, + +# Connectd -> master: peer said something interesting (or you said make_active) +# Plus fd for peer daemon. +msgtype,connectd_peer_active,2005 +msgdata,connectd_peer_active,id,node_id, +msgdata,connectd_peer_active,msgtype,?u16, +msgdata,connectd_peer_active,channel_id,?channel_id, + # master -> connectd: peer no longer wanted, you can disconnect. msgtype,connectd_discard_peer,2015 msgdata,connectd_discard_peer,id,node_id, diff --git a/connectd/multiplex.c b/connectd/multiplex.c index 49198176d..eb384acee 100644 --- a/connectd/multiplex.c +++ b/connectd/multiplex.c @@ -401,6 +401,67 @@ void send_custommsg(struct daemon *daemon, const u8 *msg) inject_peer_msg(peer, take(custommsg)); } +/* FIXME: fwd decl */ +static struct subd *multiplex_subd_setup(struct peer *peer, int *fd_for_subd); + +static struct subd *activate_peer(struct peer *peer, + const enum peer_wire *type, + const struct channel_id *channel_id) +{ + int fd_for_subd; + u16 t, *tp; + struct subd *subd; + + /* If it wasn't active before, it is now! */ + peer->active = true; + + subd = multiplex_subd_setup(peer, &fd_for_subd); + if (!subd) + return NULL; + + /* wire routines want a u16, not an enum */ + if (type) { + t = *type; + tp = &t; + } else { + tp = NULL; + } + + /* We tell lightningd to fire up a subdaemon to handle this! */ + daemon_conn_send(peer->daemon->master, + take(towire_connectd_peer_active(NULL, &peer->id, + tp, + channel_id))); + daemon_conn_send_fd(peer->daemon->master, fd_for_subd); + return subd; +} + +void peer_make_active(struct daemon *daemon, const u8 *msg) +{ + struct node_id id; + struct peer *peer; + struct channel_id *channel_id; + + if (!fromwire_connectd_peer_make_active(msg, msg, &id, &channel_id)) + master_badmsg(WIRE_CONNECTD_PEER_MAKE_ACTIVE, msg); + + /* Races can happen: this might be gone by now. */ + peer = peer_htable_get(&daemon->peers, &id); + if (!peer) + return; + + /* Could be disconnecting now */ + if (!peer->to_peer) + return; + + /* Could be made active already by receiving a message (esp reestablish!) */ + if (tal_count(peer->subds) != 0) + return; + + if (!activate_peer(peer, NULL, channel_id)) + tal_free(peer); +} + static void handle_ping_in(struct peer *peer, const u8 *msg) { u8 *pong; @@ -593,7 +654,7 @@ static struct io_plan *write_to_peer(struct io_conn *peer_conn, msg = msg_dequeue(peer->peer_outq); /* Is it time to send final? */ - if (!msg && peer->final_msg && !peer->subds) { + if (!msg && peer->final_msg && tal_count(peer->subds) == 0) { /* OK, send this then close. */ msg = peer->final_msg; peer->final_msg = NULL; @@ -603,8 +664,10 @@ static struct io_plan *write_to_peer(struct io_conn *peer_conn, /* Still nothing to send? */ if (!msg) { - /* We close once subds are all closed. */ - if (!peer->subds) { + /* We close once subds are all closed; or if we're not + active, when told to die. */ + if ((peer->active || peer->ready_to_die) + && tal_count(peer->subds) == 0) { set_closing_timer(peer, peer_conn); return io_sock_shutdown(peer_conn); } @@ -748,10 +811,19 @@ static struct io_plan *read_body_from_peer_done(struct io_conn *peer_conn, return read_hdr_from_peer(peer_conn, peer); } - /* If we don't find a subdaemon for this, discard and keep reading. */ + /* If we don't find a subdaemon for this, activate a new one. */ subd = find_subd(peer, &channel_id); - if (!subd) - return read_hdr_from_peer(peer_conn, peer); + if (!subd) { + struct channel_id channel_id; + enum peer_wire t = fromwire_peektype(decrypted); + bool has_channel_id = extract_channel_id(decrypted, &channel_id); + status_peer_debug(&peer->id, "Activating for message %s", + peer_wire_name(t)); + subd = activate_peer(peer, &t, + has_channel_id ? &channel_id : NULL); + if (!subd) + return io_close(peer_conn); + } /* Tell them to write. */ msg_enqueue(subd->outq, take(decrypted)); @@ -806,19 +878,18 @@ static void destroy_subd(struct subd *subd) struct peer *peer = subd->peer; size_t pos; + status_peer_debug(&peer->id, + "destroy_subd: %zu subds, to_peer conn %p, read_to_die = %u", + tal_count(peer->subds), peer->to_peer, + peer->ready_to_die); for (pos = 0; peer->subds[pos] != subd; pos++) assert(pos < tal_count(peer->subds)); tal_arr_remove(&peer->subds, pos); - /* Last one out frees array, sets to NULL as an indicator */ - if (tal_count(peer->subds) == 0) { - peer->subds = tal_free(peer->subds); - - /* In case they were waiting for this to send final_msg */ - if (peer->final_msg) - msg_wake(peer->peer_outq); - } + /* In case they were waiting for this to send final_msg */ + if (tal_count(peer->subds) == 0 && peer->final_msg) + msg_wake(peer->peer_outq); /* Make sure we try to keep reading from peer, so we know if * it hangs up! */ @@ -835,7 +906,7 @@ void close_peer_conn(struct peer *peer) peer->ready_to_die = true; /* Already dead? */ - if (!peer->subds && !peer->to_peer) { + if (tal_count(peer->subds) == 0 && !peer->to_peer) { peer_conn_closed(peer); return; } @@ -844,7 +915,7 @@ void close_peer_conn(struct peer *peer) msg_wake(peer->peer_outq); } -bool multiplex_subd_setup(struct peer *peer, int *fd_for_subd) +static struct subd *multiplex_subd_setup(struct peer *peer, int *fd_for_subd) { int fds[2]; struct subd *subd; @@ -852,7 +923,7 @@ bool multiplex_subd_setup(struct peer *peer, int *fd_for_subd) if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds) != 0) { status_broken("Failed to create socketpair: %s", strerror(errno)); - return false; + return NULL; } subd = tal(peer->subds, struct subd); @@ -868,7 +939,7 @@ bool multiplex_subd_setup(struct peer *peer, int *fd_for_subd) tal_add_destructor(subd, destroy_subd); *fd_for_subd = fds[1]; - return true; + return subd; } static void destroy_peer_conn(struct io_conn *peer_conn, struct peer *peer) @@ -876,14 +947,15 @@ static void destroy_peer_conn(struct io_conn *peer_conn, struct peer *peer) assert(peer->to_peer == peer_conn); peer->to_peer = NULL; - /* Flush internal connections if not already. */ - if (peer->subds) { + /* Flush internal connections if any. */ + if (tal_count(peer->subds) != 0) { for (size_t i = 0; i < tal_count(peer->subds); i++) msg_wake(peer->subds[i]->outq); return; } - if (peer->ready_to_die) + /* If lightningd says we're ready, or we were never had a subd, finish */ + if (peer->ready_to_die || !peer->active) peer_conn_closed(peer); } @@ -898,6 +970,9 @@ struct io_plan *multiplex_peer_setup(struct io_conn *peer_conn, peer->expecting_pong = PONG_UNEXPECTED; set_ping_timer(peer); + /* This used to be in openingd; don't break tests. */ + status_peer_debug(&peer->id, "Handed peer, entering loop"); + return io_duplex(peer_conn, read_hdr_from_peer(peer_conn, peer), write_to_peer(peer_conn, peer)); @@ -907,7 +982,7 @@ void multiplex_final_msg(struct peer *peer, const u8 *final_msg TAKES) { peer->ready_to_die = true; peer->final_msg = tal_dup_talarr(peer, u8, final_msg); - if (!peer->subds) + if (tal_count(peer->subds) == 0) io_wake(peer->peer_outq); } diff --git a/connectd/multiplex.h b/connectd/multiplex.h index 1c87ccb59..f389d88da 100644 --- a/connectd/multiplex.h +++ b/connectd/multiplex.h @@ -10,9 +10,6 @@ struct peer; struct io_conn; struct feature_set; -/* Set up peer->to_subd; sets fd_for_subd to pass to lightningd. */ -bool multiplex_subd_setup(struct peer *peer, int *fd_for_subd); - /* Take over peer_conn as peer->to_peer */ struct io_plan *multiplex_peer_setup(struct io_conn *peer_conn, struct peer *peer); @@ -37,4 +34,7 @@ void send_manual_ping(struct daemon *daemon, const u8 *msg); /* When lightningd says to send a custom message (from a plugin) */ void send_custommsg(struct daemon *daemon, const u8 *msg); + +/* Lightningd wants to talk to you. */ +void peer_make_active(struct daemon *daemon, const u8 *msg); #endif /* LIGHTNING_CONNECTD_MULTIPLEX_H */ diff --git a/contrib/pyln-testing/pyln/testing/utils.py b/contrib/pyln-testing/pyln/testing/utils.py index c47fffd98..29d8c2a31 100644 --- a/contrib/pyln-testing/pyln/testing/utils.py +++ b/contrib/pyln-testing/pyln/testing/utils.py @@ -1369,7 +1369,7 @@ class NodeFactory(object): # getpeers. if not fundchannel: for src, dst in connections: - dst.daemon.wait_for_log(r'{}-.*-chan#[0-9]*: Handed peer, entering loop'.format(src.info['id'])) + dst.daemon.wait_for_log(r'{}-connectd: Handed peer, entering loop'.format(src.info['id'])) return bitcoind = nodes[0].bitcoin diff --git a/lightningd/channel.c b/lightningd/channel.c index 94b9fc0e7..23bd3ae17 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -205,6 +205,7 @@ struct open_attempt *new_channel_open_attempt(struct channel *channel) oa->our_upfront_shutdown_script = NULL; oa->cmd = NULL; oa->aborted = false; + oa->open_msg = NULL; return oa; } diff --git a/lightningd/channel.h b/lightningd/channel.h index cd0113317..676b14a75 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -67,6 +67,9 @@ struct open_attempt { struct command *cmd; struct amount_sat funding; const u8 *our_upfront_shutdown_script; + + /* First msg to send to dualopend (to make it create channel) */ + const u8 *open_msg; }; struct channel { diff --git a/lightningd/connect_control.c b/lightningd/connect_control.c index e7e6cdb80..d08e52d18 100644 --- a/lightningd/connect_control.c +++ b/lightningd/connect_control.c @@ -419,6 +419,7 @@ static unsigned connectd_msg(struct subd *connectd, const u8 *msg, const int *fd case WIRE_CONNECTD_DISCARD_PEER: case WIRE_CONNECTD_DEV_MEMLEAK: case WIRE_CONNECTD_PEER_FINAL_MSG: + case WIRE_CONNECTD_PEER_MAKE_ACTIVE: case WIRE_CONNECTD_PING: case WIRE_CONNECTD_SEND_ONIONMSG: case WIRE_CONNECTD_CUSTOMMSG_OUT: @@ -434,9 +435,13 @@ static unsigned connectd_msg(struct subd *connectd, const u8 *msg, const int *fd break; case WIRE_CONNECTD_PEER_CONNECTED: + peer_connected(connectd->ld, msg); + break; + + case WIRE_CONNECTD_PEER_ACTIVE: if (tal_count(fds) != 1) return 1; - peer_connected(connectd->ld, msg, fds[0]); + peer_active(connectd->ld, msg, fds[0]); break; case WIRE_CONNECTD_PEER_DISCONNECT_DONE: @@ -629,8 +634,7 @@ static struct command_result *json_sendcustommsg(struct command *cmd, type_to_string(cmd, struct node_id, dest)); } - /* FIXME: This won't work once connectd keeps peers */ - if (!peer_get_owning_subd(peer)) { + if (!peer->is_connected) { return command_fail(cmd, JSONRPC2_INVALID_REQUEST, "Peer is not connected: %s", type_to_string(cmd, struct node_id, dest)); diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c index 8ccfd0634..c2a498451 100644 --- a/lightningd/dual_open_control.c +++ b/lightningd/dual_open_control.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -2525,7 +2526,6 @@ static struct command_result *json_openchannel_init(struct command *cmd, struct open_attempt *oa; struct lease_rates *rates; struct command_result *res; - u8 *msg; if (!param(cmd, buffer, params, p_req("id", param_node_id, &id), @@ -2591,9 +2591,12 @@ static struct command_result *json_openchannel_init(struct command *cmd, } channel = peer_unsaved_channel(peer); - if (!channel || !channel->owner) - return command_fail(cmd, FUNDING_PEER_NOT_CONNECTED, - "Peer not connected"); + if (!channel) { + channel = new_unsaved_channel(peer, + peer->ld->config.fee_base, + peer->ld->config.fee_per_satoshi); + } + if (channel->open_attempt || !list_empty(&channel->inflights)) return command_fail(cmd, FUNDING_STATE_INVALID, @@ -2670,7 +2673,7 @@ static struct command_result *json_openchannel_init(struct command *cmd, } else our_upfront_shutdown_script_wallet_index = NULL; - msg = towire_dualopend_opener_init(NULL, + oa->open_msg = towire_dualopend_opener_init(oa, psbt, *amount, oa->our_upfront_shutdown_script, our_upfront_shutdown_script_wallet_index, @@ -2682,7 +2685,10 @@ static struct command_result *json_openchannel_init(struct command *cmd, false, rates); - subd_send_msg(channel->owner, take(msg)); + /* Tell connectd to hand us this so we can start dualopend */ + subd_send_msg(peer->ld->connectd, + take(towire_connectd_peer_make_active(NULL, &peer->id, + NULL))); return command_still_pending(cmd); } @@ -3056,7 +3062,6 @@ static struct command_result *json_queryrates(struct command *cmd, struct wally_psbt *psbt; struct open_attempt *oa; u32 *our_upfront_shutdown_script_wallet_index; - u8 *msg; struct command_result *res; if (!param(cmd, buffer, params, @@ -3077,6 +3082,10 @@ static struct command_result *json_queryrates(struct command *cmd, return command_fail(cmd, FUNDING_UNKNOWN_PEER, "Unknown peer"); } + if (!peer->is_connected) + return command_fail(cmd, FUNDING_PEER_NOT_CONNECTED, + "Peer not connected"); + /* We can't query rates for a peer we have a channel with */ channel = peer_active_channel(peer); if (channel) @@ -3086,9 +3095,12 @@ static struct command_result *json_queryrates(struct command *cmd, channel_state_name(channel)); channel = peer_unsaved_channel(peer); - if (!channel || !channel->owner) - return command_fail(cmd, FUNDING_PEER_NOT_CONNECTED, - "Peer not connected"); + if (!channel) { + channel = new_unsaved_channel(peer, + peer->ld->config.fee_base, + peer->ld->config.fee_per_satoshi); + } + if (channel->open_attempt || !list_empty(&channel->inflights)) return command_fail(cmd, FUNDING_STATE_INVALID, @@ -3140,7 +3152,7 @@ static struct command_result *json_queryrates(struct command *cmd, } else our_upfront_shutdown_script_wallet_index = NULL; - msg = towire_dualopend_opener_init(NULL, + oa->open_msg = towire_dualopend_opener_init(oa, psbt, *amount, oa->our_upfront_shutdown_script, our_upfront_shutdown_script_wallet_index, @@ -3152,7 +3164,10 @@ static struct command_result *json_queryrates(struct command *cmd, true, NULL); - subd_send_msg(channel->owner, take(msg)); + /* Tell connectd to hand us this so we can start dualopend */ + subd_send_msg(peer->ld->connectd, + take(towire_connectd_peer_make_active(NULL, &peer->id, + NULL))); return command_still_pending(cmd); } @@ -3212,9 +3227,9 @@ AUTODATA(json_command, &openchannel_signed_command); AUTODATA(json_command, &openchannel_bump_command); AUTODATA(json_command, &openchannel_abort_command); -static void start_fresh_dualopend(struct peer *peer, - struct peer_fd *peer_fd, - struct channel *channel) +bool peer_start_dualopend(struct peer *peer, + struct peer_fd *peer_fd, + struct channel *channel) { int hsmfd; u32 max_to_self_delay; @@ -3242,7 +3257,7 @@ static void start_fresh_dualopend(struct peer *peer, channel_internal_error(channel, "Running lightningd_dualopend: %s", strerror(errno)); - return; + return false; } channel_config(peer->ld, &channel->our_config, @@ -3268,7 +3283,7 @@ static void start_fresh_dualopend(struct peer *peer, &channel->local_funding_pubkey, channel->minimum_depth); subd_send_msg(channel->owner, take(msg)); - + return true; } void peer_restart_dualopend(struct peer *peer, @@ -3284,7 +3299,7 @@ void peer_restart_dualopend(struct peer *peer, u8 *msg; if (channel_unsaved(channel)) { - start_fresh_dualopend(peer, peer_fd, channel); + peer_start_dualopend(peer, peer_fd, channel); return; } hsmfd = hsm_get_client_fd(peer->ld, &peer->id, channel->dbid, @@ -3374,16 +3389,3 @@ void peer_restart_dualopend(struct peer *peer, subd_send_msg(channel->owner, take(msg)); } - -void peer_start_dualopend(struct peer *peer, struct peer_fd *peer_fd) -{ - struct channel *channel; - - /* And we never touch this. */ - assert(!peer_unsaved_channel(peer)); - channel = new_unsaved_channel(peer, - peer->ld->config.fee_base, - peer->ld->config.fee_per_satoshi); - - start_fresh_dualopend(peer, peer_fd, channel); -} diff --git a/lightningd/dual_open_control.h b/lightningd/dual_open_control.h index 741a65a0e..aa623659f 100644 --- a/lightningd/dual_open_control.h +++ b/lightningd/dual_open_control.h @@ -6,7 +6,8 @@ struct peer_fd; -void peer_start_dualopend(struct peer *peer, struct peer_fd *peer_fd); +bool peer_start_dualopend(struct peer *peer, struct peer_fd *peer_fd, + struct channel *channel); void peer_restart_dualopend(struct peer *peer, struct peer_fd *peer_fd, diff --git a/lightningd/opening_common.c b/lightningd/opening_common.c index 21bc0fb84..81da45837 100644 --- a/lightningd/opening_common.c +++ b/lightningd/opening_common.c @@ -71,6 +71,7 @@ new_uncommitted_channel(struct peer *peer) tal_add_destructor(uc, destroy_uncommitted_channel); uc->got_offer = false; + uc->open_daemon = NULL; return uc; } diff --git a/lightningd/opening_common.h b/lightningd/opening_common.h index 021532493..4dc609f4d 100644 --- a/lightningd/opening_common.h +++ b/lightningd/opening_common.h @@ -87,6 +87,9 @@ struct funding_channel { /* Whether or not this is in the middle of getting funded */ bool inflight; + /* Initial openingd_funder_start msg */ + const u8 *open_msg; + /* Any commands trying to cancel us. */ struct command **cancels; @@ -95,8 +98,7 @@ struct funding_channel { struct peer_fd *peer_fd; }; -struct uncommitted_channel * -new_uncommitted_channel(struct peer *peer); +struct uncommitted_channel *new_uncommitted_channel(struct peer *peer); void opend_channel_errmsg(struct uncommitted_channel *uc, struct peer_fd *peer_fd, diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 957f399b0..10f556325 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -894,7 +895,7 @@ static unsigned int openingd_msg(struct subd *openingd, return 0; } -void peer_start_openingd(struct peer *peer, struct peer_fd *peer_fd) +bool peer_start_openingd(struct peer *peer, struct peer_fd *peer_fd) { int hsmfd; u32 max_to_self_delay; @@ -902,9 +903,9 @@ void peer_start_openingd(struct peer *peer, struct peer_fd *peer_fd) struct uncommitted_channel *uc; const u8 *msg; - assert(!peer->uncommitted_channel); - - uc = peer->uncommitted_channel = new_uncommitted_channel(peer); + assert(peer->uncommitted_channel); + uc = peer->uncommitted_channel; + assert(!uc->open_daemon); hsmfd = hsm_get_client_fd(peer->ld, &uc->peer->id, uc->dbid, HSM_CAP_COMMITMENT_POINT @@ -925,7 +926,7 @@ void peer_start_openingd(struct peer *peer, struct peer_fd *peer_fd) "Running lightning_openingd: %s", strerror(errno))); tal_free(uc); - return; + return false; } channel_config(peer->ld, &uc->our_config, @@ -954,6 +955,7 @@ void peer_start_openingd(struct peer *peer, struct peer_fd *peer_fd) feerate_max(peer->ld, NULL), IFDEV(peer->ld->dev_force_tmp_channel_id, NULL)); subd_send_msg(uc->open_daemon, take(msg)); + return true; } static struct command_result *json_fundchannel_complete(struct command *cmd, @@ -986,12 +988,15 @@ static struct command_result *json_fundchannel_complete(struct command *cmd, return command_fail(cmd, LIGHTNINGD, "Peer already %s", channel_state_name(channel)); - if (!peer->uncommitted_channel) + if (!peer->is_connected) return command_fail(cmd, FUNDING_PEER_NOT_CONNECTED, "Peer not connected"); - if (!peer->uncommitted_channel->fc || !peer->uncommitted_channel->fc->inflight) + if (!peer->uncommitted_channel + || !peer->uncommitted_channel->fc + || !peer->uncommitted_channel->fc->inflight) return command_fail(cmd, LIGHTNINGD, "No channel funding in progress."); + if (peer->uncommitted_channel->fc->cmd) return command_fail(cmd, LIGHTNINGD, "Channel funding in progress."); @@ -1082,6 +1087,8 @@ static struct command_result *json_fundchannel_cancel(struct command *cmd, return command_still_pending(cmd); } + log_debug(cmd->ld->log, "fundchannel_cancel no uncommitted_channel!"); + /* Handle `fundchannel_cancel` after `fundchannel_complete`. */ return cancel_channel_before_broadcast(cmd, peer); } @@ -1101,7 +1108,6 @@ static struct command_result *json_fundchannel_start(struct command *cmd, bool *announce_channel; u32 *feerate_per_kw; - u8 *msg = NULL; struct amount_sat *amount; struct amount_msat *push_msat; u32 *upfront_shutdown_script_wallet_index; @@ -1154,6 +1160,10 @@ static struct command_result *json_fundchannel_start(struct command *cmd, return command_fail(cmd, FUNDING_UNKNOWN_PEER, "Unknown peer"); } + if (!peer->is_connected) + return command_fail(cmd, FUNDING_PEER_NOT_CONNECTED, + "Peer not connected"); + channel = peer_active_channel(peer); if (channel) { return command_fail(cmd, LIGHTNINGD, "Peer already %s", @@ -1170,9 +1180,10 @@ static struct command_result *json_fundchannel_start(struct command *cmd, " must use `openchannel_init` not" " `fundchannel_start`."); - return command_fail(cmd, FUNDING_PEER_NOT_CONNECTED, - "Peer not connected"); - } + log_debug(cmd->ld->log, "fundchannel_start: allocating uncommitted_channel"); + peer->uncommitted_channel = new_uncommitted_channel(peer); + } else + log_debug(cmd->ld->log, "fundchannel_start: reusing uncommitted_channel"); if (peer->uncommitted_channel->fc) { return command_fail(cmd, LIGHTNINGD, "Already funding channel"); @@ -1228,7 +1239,8 @@ static struct command_result *json_fundchannel_start(struct command *cmd, } else upfront_shutdown_script_wallet_index = NULL; - msg = towire_openingd_funder_start(NULL, + fc->open_msg + = towire_openingd_funder_start(fc, *amount, fc->push, fc->our_upfront_shutdown_script, @@ -1236,7 +1248,10 @@ static struct command_result *json_fundchannel_start(struct command *cmd, *feerate_per_kw, fc->channel_flags); - subd_send_msg(peer->uncommitted_channel->open_daemon, take(msg)); + /* Tell connectd to make this active; when it does, we can continue */ + subd_send_msg(peer->ld->connectd, + take(towire_connectd_peer_make_active(NULL, &peer->id, + NULL))); return command_still_pending(cmd); } diff --git a/lightningd/opening_control.h b/lightningd/opening_control.h index f7860d950..a8f8d982a 100644 --- a/lightningd/opening_control.h +++ b/lightningd/opening_control.h @@ -14,7 +14,7 @@ struct uncommitted_channel; void json_add_uncommitted_channel(struct json_stream *response, const struct uncommitted_channel *uc); -void peer_start_openingd(struct peer *peer, +bool peer_start_openingd(struct peer *peer, struct peer_fd *peer_fd); struct subd *peer_get_owning_subd(struct peer *peer); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index e3bfd1ca0..28dc35acc 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -944,7 +944,6 @@ struct peer_connected_hook_payload { struct wireaddr *remote_addr; bool incoming; struct peer *peer; - struct peer_fd *peer_fd; u8 *error; }; @@ -1028,11 +1027,6 @@ static void peer_connected_hook_final(struct peer_connected_hook_payload *payloa } case DUALOPEND_OPEN_INIT: case DUALOPEND_AWAITING_LOCKIN: - assert(!channel->owner); - channel->peer->addr = addr; - channel->peer->connected_incoming = payload->incoming; - peer_restart_dualopend(peer, payload->peer_fd, channel); - return; case CHANNELD_AWAITING_LOCKIN: case CHANNELD_NORMAL: case CHANNELD_SHUTTING_DOWN: @@ -1040,31 +1034,31 @@ static void peer_connected_hook_final(struct peer_connected_hook_payload *payloa assert(!channel->owner); channel->peer->addr = addr; channel->peer->connected_incoming = payload->incoming; - peer_start_channeld(channel, payload->peer_fd, NULL, true, - NULL); - return; + goto make_active; } abort(); } /* If we get here, it means we have no channel */ assert(!channel); - if (feature_negotiated(ld->our_features, - peer->their_features, - OPT_DUAL_FUND)) { - peer_start_dualopend(peer, payload->peer_fd); - } else - peer_start_openingd(peer, payload->peer_fd); return; send_error: - log_debug(ld->log, "Telling connectd to send error %s", - tal_hex(tmpctx, error)); + log_peer_debug(ld->log, &peer->id, "Telling connectd to send error %s", + tal_hex(tmpctx, error)); /* Get connectd to send error and close. */ subd_send_msg(ld->connectd, take(towire_connectd_peer_final_msg(NULL, &peer->id, error))); - tal_free(payload->peer_fd); + return; + +make_active: + log_peer_debug(ld->log, &peer->id, + "Telling connectd to make active, state %s", + channel_state_name(channel)); + subd_send_msg(ld->connectd, + take(towire_connectd_peer_make_active(NULL, &peer->id, + &channel->cid))); } static bool @@ -1179,8 +1173,8 @@ REGISTER_PLUGIN_HOOK(peer_connected, struct peer_connected_hook_payload *); /* Connectd tells us a peer has connected: it never hands us duplicates, since - * it holds them until we say peer_died. */ -void peer_connected(struct lightningd *ld, const u8 *msg, int peer_fd) + * it holds them until we say peer_disconnected. */ +void peer_connected(struct lightningd *ld, const u8 *msg) { struct node_id id; u8 *their_features; @@ -1198,8 +1192,6 @@ void peer_connected(struct lightningd *ld, const u8 *msg, int peer_fd) fatal("Connectd gave bad CONNECT_PEER_CONNECTED message %s", tal_hex(msg, msg)); - hook_payload->peer_fd = new_peer_fd(hook_payload, peer_fd); - /* If we're already dealing with this peer, hand off to correct * subdaemon. Otherwise, we'll hand to openingd to wait there. */ peer = peer_by_id(ld, &id); @@ -1237,6 +1229,137 @@ void peer_connected(struct lightningd *ld, const u8 *msg, int peer_fd) plugin_hook_call_peer_connected(ld, hook_payload); } +/* connectd tells us a peer has an interesting message, and hands us an + * fd to give to the correct subdaemon. Unlike peer_connected, this is racy: + * we might have just told it to disconnect peer. */ +void peer_active(struct lightningd *ld, const u8 *msg, int fd) +{ + struct node_id id; + u16 *msgtype; + struct channel *channel; + struct channel_id *channel_id; + struct peer *peer; + bool dual_fund; + u8 *error; + struct peer_fd *peer_fd = new_peer_fd(tmpctx, fd); + + /* FIXME: Use msgtype to determine what to do! */ + if (!fromwire_connectd_peer_active(msg, msg, &id, &msgtype, &channel_id)) + fatal("Connectd gave bad CONNECTD_PEER_ACTIVE message %s", + tal_hex(msg, msg)); + + peer = peer_by_id(ld, &id); + if (!peer) { + /* This race is possible, but I want to see it in CI. */ + log_broken(ld->log, "Unknown active peer %s", + type_to_string(tmpctx, struct node_id, &id)); + return; + } + + channel = peer_active_channel(peer); + + /* It might be v2 opening, though, since we hang onto these */ + if (!channel) + channel = peer_unsaved_channel(peer); + + if (channel) { + switch (channel->state) { + case ONCHAIN: + case FUNDING_SPEND_SEEN: + case CLOSINGD_COMPLETE: + /* Channel is supposed to be active!*/ + abort(); + case CLOSED: + /* Channel should not have been loaded */ + abort(); + + /* We consider this "active" but we only send an error */ + case AWAITING_UNILATERAL: { + /* channel->error is not saved in db, so this can + * happen if we restart. */ + error = towire_errorfmt(tmpctx, &channel->cid, + "Awaiting unilateral close"); + goto send_error; + } + case DUALOPEND_OPEN_INIT: + /* We asked for this, to open? */ + if (!msgtype + && channel->open_attempt + && channel->open_attempt->open_msg) { + if (peer_start_dualopend(peer, peer_fd, channel)) + subd_send_msg(channel->owner, channel->open_attempt->open_msg); + return; + } + /* Fall through. */ + case DUALOPEND_AWAITING_LOCKIN: + assert(!channel->owner); + peer_restart_dualopend(peer, peer_fd, channel); + return; + case CHANNELD_AWAITING_LOCKIN: + case CHANNELD_NORMAL: + case CHANNELD_SHUTTING_DOWN: + case CLOSINGD_SIGEXCHANGE: + assert(!channel->owner); + peer_start_channeld(channel, + peer_fd, + NULL, true, + NULL); + return; + } + abort(); + } + + dual_fund = feature_negotiated(ld->our_features, + peer->their_features, + OPT_DUAL_FUND); + + /* Did we ask for this? */ + if (!msgtype) { + /* If it was dual_fund, it will have peer_unsaved_channel above */ + if (dual_fund) { + log_broken(ld->log, "Unsolicited active df peer %s?", + type_to_string(tmpctx, struct node_id, + &peer->id)); + } else { + const struct uncommitted_channel *uc + = peer->uncommitted_channel; + + if (!uc->open_daemon + && uc->fc + && uc->fc->open_msg) { + if (peer_start_openingd(peer, peer_fd)) { + subd_send_msg(uc->open_daemon, + uc->fc->open_msg); + } + } else { + log_broken(ld->log, "Unsolicited active peer %s?", + type_to_string(tmpctx, struct node_id, + &peer->id)); + } + } + } else { + /* OK, it's unsolicited. What kind of open do they want? */ + if (dual_fund) { + channel = new_unsaved_channel(peer, + peer->ld->config.fee_base, + peer->ld->config.fee_per_satoshi); + peer_start_dualopend(peer, peer_fd, channel); + } else { + peer->uncommitted_channel = new_uncommitted_channel(peer); + peer_start_openingd(peer, peer_fd); + } + } + return; + +send_error: + log_peer_debug(ld->log, &peer->id, "Telling connectd to send error %s", + tal_hex(tmpctx, error)); + /* Get connectd to send error and close. */ + subd_send_msg(ld->connectd, + take(towire_connectd_peer_final_msg(NULL, &peer->id, + error))); +} + struct disconnect_command { struct list_node list; /* Command structure. This is the parent of the close command. */ @@ -1262,8 +1385,13 @@ void peer_disconnect_done(struct lightningd *ld, const u8 *msg) /* If we still have peer, it's disconnected now */ p = peer_by_id(ld, &id); - if (p) + if (p) { p->is_connected = false; + /* If we only cared about peer because of connectd, free it. */ + if (list_empty(&p->channels) && !p->uncommitted_channel) { + tal_free(p); + } + } /* Fire off plugin notifications */ notify_disconnect(ld, &id); @@ -1744,6 +1872,9 @@ static struct command_result *json_disconnect(struct command *cmd, peer = peer_by_id(cmd->ld, id); if (!peer) { + return command_fail(cmd, LIGHTNINGD, "Unknown peer"); + } + if (!peer->is_connected) { return command_fail(cmd, LIGHTNINGD, "Peer not connected"); } channel = peer_active_channel(peer); @@ -1761,11 +1892,15 @@ static struct command_result *json_disconnect(struct command *cmd, channel_unsaved_close_conn(channel, "disconnect command"); goto wait_for_connectd; } - if (!peer->uncommitted_channel) { - return command_fail(cmd, LIGHTNINGD, "Peer not connected"); + if (peer->uncommitted_channel) { + kill_uncommitted_channel(peer->uncommitted_channel, + "disconnect command"); + goto wait_for_connectd; } - kill_uncommitted_channel(peer->uncommitted_channel, - "disconnect command"); + + /* It's just sitting in connectd. */ + subd_send_msg(cmd->ld->connectd, + take(towire_connectd_discard_peer(NULL, id))); wait_for_connectd: /* Connectd tells us when it's finally disconnected */ diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index a407d6c5b..5f006466a 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -67,8 +67,9 @@ struct peer *peer_from_json(struct lightningd *ld, const char *buffer, const jsmntok_t *peeridtok); -void peer_connected(struct lightningd *ld, const u8 *msg, int peer_fd); +void peer_connected(struct lightningd *ld, const u8 *msg); void peer_disconnect_done(struct lightningd *ld, const u8 *msg); +void peer_active(struct lightningd *ld, const u8 *msg, int peer_fd); /* Could be configurable. */ #define OUR_CHANNEL_FLAGS CHANNEL_FLAGS_ANNOUNCE_CHANNEL diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index a7ebce3d8..02d4d4964 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -204,6 +204,9 @@ bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, /* Generated stub for fromwire_channeld_dev_memleak_reply */ bool fromwire_channeld_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNEEDED) { fprintf(stderr, "fromwire_channeld_dev_memleak_reply called!\n"); abort(); } +/* Generated stub for fromwire_connectd_peer_active */ +bool fromwire_connectd_peer_active(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id *id UNNEEDED, u16 **msgtype UNNEEDED, struct channel_id **channel_id UNNEEDED) +{ fprintf(stderr, "fromwire_connectd_peer_active called!\n"); abort(); } /* Generated stub for fromwire_connectd_peer_connected */ bool fromwire_connectd_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id *id UNNEEDED, struct wireaddr_internal *addr UNNEEDED, struct wireaddr **remote_addr UNNEEDED, bool *incoming UNNEEDED, u8 **features UNNEEDED) { fprintf(stderr, "fromwire_connectd_peer_connected called!\n"); abort(); } @@ -460,6 +463,14 @@ struct oneshot *new_reltimer_(struct timers *timers UNNEEDED, struct timerel expire UNNEEDED, void (*cb)(void *) UNNEEDED, void *arg UNNEEDED) { fprintf(stderr, "new_reltimer_ called!\n"); abort(); } +/* Generated stub for new_uncommitted_channel */ +struct uncommitted_channel *new_uncommitted_channel(struct peer *peer UNNEEDED) +{ fprintf(stderr, "new_uncommitted_channel called!\n"); abort(); } +/* Generated stub for new_unsaved_channel */ +struct channel *new_unsaved_channel(struct peer *peer UNNEEDED, + u32 feerate_base UNNEEDED, + u32 feerate_ppm UNNEEDED) +{ fprintf(stderr, "new_unsaved_channel called!\n"); abort(); } /* Generated stub for node_id_cmp */ int node_id_cmp(const struct node_id *a UNNEEDED, const struct node_id *b UNNEEDED) { fprintf(stderr, "node_id_cmp called!\n"); abort(); } @@ -586,10 +597,11 @@ void peer_start_channeld(struct channel *channel UNNEEDED, const u8 *reestablish_only UNNEEDED) { fprintf(stderr, "peer_start_channeld called!\n"); abort(); } /* Generated stub for peer_start_dualopend */ -void peer_start_dualopend(struct peer *peer UNNEEDED, struct peer_fd *peer_fd UNNEEDED) +bool peer_start_dualopend(struct peer *peer UNNEEDED, struct peer_fd *peer_fd UNNEEDED, + struct channel *channel UNNEEDED) { fprintf(stderr, "peer_start_dualopend called!\n"); abort(); } /* Generated stub for peer_start_openingd */ -void peer_start_openingd(struct peer *peer UNNEEDED, +bool peer_start_openingd(struct peer *peer UNNEEDED, struct peer_fd *peer_fd UNNEEDED) { fprintf(stderr, "peer_start_openingd called!\n"); abort(); } /* Generated stub for peer_unsaved_channel */ @@ -640,9 +652,15 @@ u8 *towire_channeld_dev_memleak(const tal_t *ctx UNNEEDED) /* Generated stub for towire_channeld_dev_reenable_commit */ u8 *towire_channeld_dev_reenable_commit(const tal_t *ctx UNNEEDED) { fprintf(stderr, "towire_channeld_dev_reenable_commit called!\n"); abort(); } +/* Generated stub for towire_connectd_discard_peer */ +u8 *towire_connectd_discard_peer(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED) +{ fprintf(stderr, "towire_connectd_discard_peer called!\n"); abort(); } /* Generated stub for towire_connectd_peer_final_msg */ u8 *towire_connectd_peer_final_msg(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED, const u8 *msg UNNEEDED) { fprintf(stderr, "towire_connectd_peer_final_msg called!\n"); abort(); } +/* Generated stub for towire_connectd_peer_make_active */ +u8 *towire_connectd_peer_make_active(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED, const struct channel_id *channel_id UNNEEDED) +{ fprintf(stderr, "towire_connectd_peer_make_active called!\n"); abort(); } /* Generated stub for towire_dualopend_dev_memleak */ u8 *towire_dualopend_dev_memleak(const tal_t *ctx UNNEEDED) { fprintf(stderr, "towire_dualopend_dev_memleak called!\n"); abort(); } diff --git a/openingd/dualopend.c b/openingd/dualopend.c index afc0d68fa..b8ac657fc 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -3932,9 +3932,6 @@ int main(int argc, char *argv[]) * N'th per-commitment point. But since N=0, it won't give us one. */ assert(none == NULL); - /*~ Turns out this is useful for testing, to make sure we're ready. */ - status_debug("Handed peer, entering loop"); - /*~ We manually run a little poll() loop here. With only two fds */ pollfd[0].fd = REQ_FD; pollfd[0].events = POLLIN; diff --git a/openingd/openingd.c b/openingd/openingd.c index 0370d186b..7bcff4de8 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -313,6 +313,7 @@ static u8 *funder_channel_start(struct state *state, u8 channel_flags) struct tlv_accept_channel_tlvs *accept_tlvs; char *err_reason; + status_debug("funder_channel_start"); if (!setup_channel_funder(state)) return NULL; @@ -1428,9 +1429,6 @@ int main(int argc, char *argv[]) * N'th per-commitment point. But since N=0, it won't give us one. */ assert(none == NULL); - /*~ Turns out this is useful for testing, to make sure we're ready. */ - status_debug("Handed peer, entering loop"); - /*~ We manually run a little poll() loop here. With only three fds */ pollfd[0].fd = REQ_FD; pollfd[0].events = POLLIN; diff --git a/tests/test_closing.py b/tests/test_closing.py index 705cac755..69db8c3f1 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -3448,7 +3448,8 @@ def test_you_forgot_closed_channel(node_factory, executor): assert only_one(only_one(l1.rpc.listpeers()['peers'])['channels'])['state'] == 'CLOSINGD_SIGEXCHANGE' # l1 reconnects, it should succeed. - l1.rpc.disconnect(l2.info['id'], force=True) + if only_one(l1.rpc.listpeers(l2.info['id'])['peers'])['connected']: + l1.rpc.disconnect(l2.info['id'], force=True) l1.rpc.connect(l2.info['id'], 'localhost', l2.port) fut.result(TIMEOUT) diff --git a/tests/test_connection.py b/tests/test_connection.py index 9e1e2105c..3c9117cdc 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -409,7 +409,7 @@ def test_remote_disconnect(node_factory): l1, l2 = node_factory.get_nodes(2) l1.rpc.connect(l2.info['id'], 'localhost', l2.port) - assert l2.rpc.listpeers()['peers'] != [] + wait_for(lambda: l2.rpc.listpeers()['peers'] != []) l2.rpc.disconnect(l1.info['id']) # l1 should notice! @@ -2576,9 +2576,9 @@ def test_disconnectpeer(node_factory, bitcoind): wait_for(lambda: l2.rpc.getpeer(l1.info['id']) is None) # Make sure you cannot disconnect after disconnecting - with pytest.raises(RpcError, match=r'Peer not connected'): + with pytest.raises(RpcError, match=r'Unknown peer'): l1.rpc.disconnect(l2.info['id']) - with pytest.raises(RpcError, match=r'Peer not connected'): + with pytest.raises(RpcError, match=r'Unknown peer'): l2.rpc.disconnect(l1.info['id']) # Fund channel l1 -> l3 diff --git a/tests/test_misc.py b/tests/test_misc.py index a19b076b2..43a318b93 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -2337,6 +2337,7 @@ def test_listforwards(node_factory, bitcoind): assert len(c24_forwards) == 1 +@pytest.mark.openchannel('v1') def test_version_reexec(node_factory, bitcoind): badopeningd = os.path.join(os.path.dirname(__file__), "plugins", "badopeningd.sh") version = subprocess.check_output(['lightningd/lightningd', @@ -2358,7 +2359,12 @@ def test_version_reexec(node_factory, bitcoind): 'fff6')) # type f.write(bytes('badversion\0', encoding='utf8')) + # Opening a channel will fire subd. l1.rpc.connect(l2.info['id'], 'localhost', l2.port) + try: + l1.fundchannel(l2) + except RpcError: + pass l1.daemon.wait_for_log("openingd.*version 'badversion' not '{}': restarting".format(version)) diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 259ebf03d..a38fb1808 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -148,6 +148,9 @@ bool fromwire_channeld_offer_htlc_reply(const tal_t *ctx UNNEEDED, const void *p /* Generated stub for fromwire_channeld_sending_commitsig */ bool fromwire_channeld_sending_commitsig(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u64 *commitnum UNNEEDED, struct penalty_base **pbase UNNEEDED, struct fee_states **fee_states UNNEEDED, struct height_states **blockheight_states UNNEEDED, struct changed_htlc **changed UNNEEDED, struct bitcoin_signature *commit_sig UNNEEDED, struct bitcoin_signature **htlc_sigs UNNEEDED) { fprintf(stderr, "fromwire_channeld_sending_commitsig called!\n"); abort(); } +/* Generated stub for fromwire_connectd_peer_active */ +bool fromwire_connectd_peer_active(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id *id UNNEEDED, u16 **msgtype UNNEEDED, struct channel_id **channel_id UNNEEDED) +{ fprintf(stderr, "fromwire_connectd_peer_active called!\n"); abort(); } /* Generated stub for fromwire_connectd_peer_connected */ bool fromwire_connectd_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id *id UNNEEDED, struct wireaddr_internal *addr UNNEEDED, struct wireaddr **remote_addr UNNEEDED, bool *incoming UNNEEDED, u8 **features UNNEEDED) { fprintf(stderr, "fromwire_connectd_peer_connected called!\n"); abort(); } @@ -476,6 +479,9 @@ struct chain_coin_mvt *new_coin_wallet_deposit(const tal_t *ctx UNNEEDED, /* Generated stub for new_peer_fd */ struct peer_fd *new_peer_fd(const tal_t *ctx UNNEEDED, int peer_fd UNNEEDED) { fprintf(stderr, "new_peer_fd called!\n"); abort(); } +/* Generated stub for new_uncommitted_channel */ +struct uncommitted_channel *new_uncommitted_channel(struct peer *peer UNNEEDED) +{ fprintf(stderr, "new_uncommitted_channel called!\n"); abort(); } /* Generated stub for notify_chain_mvt */ void notify_chain_mvt(struct lightningd *ld UNNEEDED, const struct chain_coin_mvt *mvt UNNEEDED) { fprintf(stderr, "notify_chain_mvt called!\n"); abort(); } @@ -631,10 +637,11 @@ void peer_start_channeld(struct channel *channel UNNEEDED, const u8 *reestablish_only UNNEEDED) { fprintf(stderr, "peer_start_channeld called!\n"); abort(); } /* Generated stub for peer_start_dualopend */ -void peer_start_dualopend(struct peer *peer UNNEEDED, struct peer_fd *peer_fd UNNEEDED) +bool peer_start_dualopend(struct peer *peer UNNEEDED, struct peer_fd *peer_fd UNNEEDED, + struct channel *channel UNNEEDED) { fprintf(stderr, "peer_start_dualopend called!\n"); abort(); } /* Generated stub for peer_start_openingd */ -void peer_start_openingd(struct peer *peer UNNEEDED, +bool peer_start_openingd(struct peer *peer UNNEEDED, struct peer_fd *peer_fd UNNEEDED) { fprintf(stderr, "peer_start_openingd called!\n"); abort(); } /* Generated stub for plugin_hook_call_ */ @@ -729,6 +736,9 @@ u8 *towire_connectd_discard_peer(const tal_t *ctx UNNEEDED, const struct node_id /* Generated stub for towire_connectd_peer_final_msg */ u8 *towire_connectd_peer_final_msg(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED, const u8 *msg UNNEEDED) { fprintf(stderr, "towire_connectd_peer_final_msg called!\n"); abort(); } +/* Generated stub for towire_connectd_peer_make_active */ +u8 *towire_connectd_peer_make_active(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED, const struct channel_id *channel_id UNNEEDED) +{ fprintf(stderr, "towire_connectd_peer_make_active called!\n"); abort(); } /* Generated stub for towire_dualopend_dev_memleak */ u8 *towire_dualopend_dev_memleak(const tal_t *ctx UNNEEDED) { fprintf(stderr, "towire_dualopend_dev_memleak called!\n"); abort(); }