diff --git a/channeld/Makefile b/channeld/Makefile index 6f26ef416219..bef41c69a92a 100644 --- a/channeld/Makefile +++ b/channeld/Makefile @@ -4,6 +4,7 @@ CHANNELD_HEADERS := \ channeld/full_channel_error_names_gen.h \ channeld/channeld_wiregen.h \ channeld/channeld_htlc.h \ + channeld/channeld.h \ channeld/commit_tx.h \ channeld/full_channel.h \ channeld/full_channel_error.h \ @@ -40,19 +41,17 @@ CHANNELD_COMMON_OBJS := \ common/channel_config.o \ common/channel_id.o \ common/channel_type.o \ - common/crypto_state.o \ - common/crypto_sync.o \ common/cryptomsg.o \ common/daemon.o \ common/daemon_conn.o \ common/derive_basepoints.o \ - common/dev_disconnect.o \ common/ecdh_hsmd.o \ common/features.o \ common/fee_states.o \ - common/status_wiregen.o \ - common/peer_status_wiregen.o \ common/gossip_rcvd_filter.o \ + common/peer_io.o \ + common/peer_status_wiregen.o \ + common/status_wiregen.o \ common/gossip_store.o \ common/hmac.o \ common/htlc_state.o \ diff --git a/channeld/channeld.c b/channeld/channeld.c index 4b1dcf12052c..117311f0c931 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -15,12 +15,11 @@ #include #include #include +#include #include #include #include #include -#include -#include #include #include #include @@ -29,7 +28,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -42,22 +42,12 @@ #include #include #include -#include #include #include -/* stdin == requests, 3 == peer, 4 = gossip, 5 = gossip_store, 6 = HSM */ +/* stdin == requests, 3 == peer, 4 = HSM */ #define MASTER_FD STDIN_FILENO -#define HSM_FD 6 - -enum pong_expect_type { - /* We weren't expecting a ping reply */ - PONG_UNEXPECTED = 0, - /* We were expecting a ping reply due to ping command */ - PONG_EXPECTED_COMMAND = 1, - /* We were expecting a ping reply due to ping timer */ - PONG_EXPECTED_PROBING = 2, -}; +#define HSM_FD 4 struct peer { struct per_peer_state *pps; @@ -110,12 +100,6 @@ struct peer { u64 commit_timer_attempts; u32 commit_msec; - /* Random ping timer, to detect dead connections. */ - struct oneshot *ping_timer; - - /* Are we expecting a pong? */ - enum pong_expect_type expecting_pong; - /* The feerate we want. */ u32 desired_feerate; @@ -158,6 +142,13 @@ struct peer { struct msg_queue *update_queue; #endif +#if DEVELOPER + /* If set, don't fire commit counter when this hits 0 */ + u32 *dev_disable_commit; + + /* If set, send channel_announcement after 1 second, not 30 */ + bool dev_fast_gossip; +#endif /* Information used for reestablishment. */ bool last_was_revoke; struct changed_htlc *last_sent_commit; @@ -184,6 +175,9 @@ struct peer { /* We allow a 'tx-sigs' message between reconnect + funding_locked */ bool tx_sigs_allowed; + + /* Most recent channel_update message. */ + u8 *channel_update; }; static u8 *create_channel_announcement(const tal_t *ctx, struct peer *peer); @@ -200,23 +194,17 @@ static void billboard_update(const struct peer *peer) peer_billboard(false, update); } -static const u8 *hsm_req(const tal_t *ctx, const u8 *req TAKES) +const u8 *hsm_req(const tal_t *ctx, const u8 *req TAKES) { u8 *msg; - int type = fromwire_peektype(req); + /* hsmd goes away at shutdown. That's OK. */ if (!wire_sync_write(HSM_FD, req)) - status_failed(STATUS_FAIL_HSM_IO, - "Writing %s to HSM: %s", - hsmd_wire_name(type), - strerror(errno)); + exit(0); msg = wire_sync_read(ctx, HSM_FD); if (!msg) - status_failed(STATUS_FAIL_HSM_IO, - "Reading resp to %s: %s", - hsmd_wire_name(type), - strerror(errno)); + exit(0); return msg; } @@ -266,7 +254,7 @@ static void maybe_send_stfu(struct peer *peer) if (!peer->stfu_sent[LOCAL] && !pending_updates(peer->channel, LOCAL, false)) { u8 *msg = towire_stfu(NULL, &peer->channel_id, peer->stfu_initiator == LOCAL); - sync_crypto_write(peer->pps, take(msg)); + peer_write(peer->pps, take(msg)); peer->stfu_sent[LOCAL] = true; } @@ -382,7 +370,9 @@ static void maybe_send_stfu(struct peer *peer) } #endif -/* Create and send channel_update to gossipd (and maybe peer) */ +/* Tell gossipd to create channel_update (then it goes into + * gossip_store, then streams out to peers, or sends it directly if + * it's a private channel) */ static void send_channel_update(struct peer *peer, int disable_flag) { u8 *msg; @@ -395,7 +385,7 @@ static void send_channel_update(struct peer *peer, int disable_flag) assert(peer->short_channel_ids[LOCAL].u64); - msg = towire_gossipd_local_channel_update(NULL, + msg = towire_channeld_local_channel_update(NULL, &peer->short_channel_ids[LOCAL], disable_flag == ROUTING_FLAGS_DISABLED, @@ -404,64 +394,23 @@ static void send_channel_update(struct peer *peer, int disable_flag) peer->fee_base, peer->fee_per_satoshi, advertized_htlc_max(peer->channel)); - wire_sync_write(peer->pps->gossip_fd, take(msg)); -} - -/* Get the latest channel update for this channel from gossipd */ -static const u8 *get_local_channel_update(const tal_t *ctx, struct peer *peer) -{ - const u8 *msg; - - msg = towire_gossipd_get_update(NULL, &peer->short_channel_ids[LOCAL]); - wire_sync_write(peer->pps->gossip_fd, take(msg)); - - /* Wait for reply to come back; handle other gossipd msgs meanwhile */ - while ((msg = wire_sync_read(tmpctx, peer->pps->gossip_fd)) != NULL) { - u8 *update; - if (fromwire_gossipd_get_update_reply(ctx, msg, &update)) - return update; - - handle_gossip_msg(peer->pps, take(msg)); - } - - /* Gossipd hangs up on us to kill us when a new - * connection comes in. */ - peer_failed_connection_lost(); + wire_sync_write(MASTER_FD, take(msg)); } -/** - * Add a channel locally and send a channel update to the peer - * - * Send a local_add_channel message to gossipd in order to make the channel - * usable locally, and also tell our peer about our parameters via a - * channel_update message. The peer may accept the update and use the contained - * information to route incoming payments through the channel. The - * channel_update is not preceeded by a channel_announcement and won't make much - * sense to other nodes, so we don't tell gossipd about it. - */ -static void make_channel_local_active(struct peer *peer) +/* Tells gossipd about our new channel, before it sees a + * channel_update from peer */ +static void tell_gossipd_new_channel(struct peer *peer) { u8 *msg; - const u8 *ann; const u8 *annfeatures = get_agreed_channelfeatures(tmpctx, peer->our_features, peer->their_features); - ann = private_channel_announcement(tmpctx, - &peer->short_channel_ids[LOCAL], - &peer->node_ids[LOCAL], - &peer->node_ids[REMOTE], - annfeatures); - - /* Tell gossipd about local channel. */ - msg = towire_gossip_store_private_channel(NULL, - peer->channel->funding_sats, - ann); - wire_sync_write(peer->pps->gossip_fd, take(msg)); - - /* Tell gossipd and the other side what parameters we expect should - * they route through us */ - send_channel_update(peer, 0); + /* Tell lightningd to tell gossipd about local channel. */ + msg = towire_channeld_local_private_channel(NULL, + peer->channel->funding_sats, + annfeatures); + wire_sync_write(MASTER_FD, take(msg)); } static void send_announcement_signatures(struct peer *peer) @@ -513,7 +462,7 @@ static void send_announcement_signatures(struct peer *peer) NULL, &peer->channel_id, &peer->short_channel_ids[LOCAL], &peer->announcement_node_sigs[LOCAL], &peer->announcement_bitcoin_sigs[LOCAL]); - sync_crypto_write(peer->pps, take(msg)); + peer_write(peer->pps, take(msg)); } /* Tentatively create a channel_announcement, possibly with invalid @@ -572,9 +521,9 @@ static void announce_channel(struct peer *peer) cannounce = create_channel_announcement(tmpctx, peer); - wire_sync_write(peer->pps->gossip_fd, - take(towire_gossipd_local_channel_announcement(NULL, - cannounce))); + wire_sync_write(MASTER_FD, + take(towire_channeld_local_channel_announcement(NULL, + cannounce))); send_channel_update(peer, 0); } @@ -590,7 +539,9 @@ static void channel_announcement_negotiate(struct peer *peer) if (!peer->channel_local_active) { peer->channel_local_active = true; - make_channel_local_active(peer); + /* Tell gossipd and the other side what parameters we + * expect should they route through us */ + send_channel_update(peer, 0); } /* BOLT #7: @@ -635,7 +586,7 @@ static void channel_announcement_negotiate(struct peer *peer) /* Give other nodes time to notice new block. */ notleak(new_reltimer(&peer->timers, peer, - time_from_sec(GOSSIP_ANNOUNCE_DELAY(dev_fast_gossip)), + time_from_sec(GOSSIP_ANNOUNCE_DELAY(peer->dev_fast_gossip)), announce_channel, peer)); } } @@ -967,7 +918,7 @@ static void maybe_send_shutdown(struct peer *peer) msg = towire_shutdown(NULL, &peer->channel_id, peer->final_scriptpubkey, tlvs); - sync_crypto_write(peer->pps, take(msg)); + peer_write(peer->pps, take(msg)); peer->send_shutdown = false; peer->shutdown_sent[LOCAL] = true; billboard_update(peer); @@ -977,7 +928,7 @@ static void send_shutdown_complete(struct peer *peer) { /* Now we can tell master shutdown is complete. */ wire_sync_write(MASTER_FD, - take(towire_channeld_shutdown_complete(NULL, peer->pps))); + take(towire_channeld_shutdown_complete(NULL))); per_peer_state_fdpass_send(MASTER_FD, peer->pps); close(MASTER_FD); } @@ -1102,29 +1053,6 @@ static struct bitcoin_signature *calc_commitsigs(const tal_t *ctx, return htlc_sigs; } -/* Mutual recursion */ -static void send_ping(struct peer *peer); - -static void set_ping_timer(struct peer *peer) -{ - peer->ping_timer = new_reltimer(&peer->timers, peer, - time_from_sec(15 + pseudorand(30)), - send_ping, peer); -} - -static void send_ping(struct peer *peer) -{ - /* Already have a ping in flight? */ - if (peer->expecting_pong != PONG_UNEXPECTED) { - status_debug("Last ping unreturned: hanging up"); - exit(0); - } - - sync_crypto_write_no_delay(peer->pps, take(make_ping(NULL, 1, 0))); - peer->expecting_pong = PONG_EXPECTED_PROBING; - set_ping_timer(peer); -} - /* Peer protocol doesn't want sighash flags. */ static secp256k1_ecdsa_signature *raw_sigs(const tal_t *ctx, const struct bitcoin_signature *sigs) @@ -1248,8 +1176,7 @@ static void send_commit(struct peer *peer) u32 feerate_target; #if DEVELOPER - /* Hack to suppress all commit sends if dev_disconnect says to */ - if (dev_suppress_commit) { + if (peer->dev_disable_commit && !*peer->dev_disable_commit) { peer->commit_timer = NULL; return; } @@ -1323,7 +1250,7 @@ static void send_commit(struct peer *peer) msg = towire_update_fee(NULL, &peer->channel_id, feerate_target); - sync_crypto_write(peer->pps, take(msg)); + peer_write(peer->pps, take(msg)); } } @@ -1339,7 +1266,7 @@ static void send_commit(struct peer *peer) &peer->channel_id, our_blockheight); - sync_crypto_write(peer->pps, take(msg)); + peer_write(peer->pps, take(msg)); } } @@ -1384,6 +1311,14 @@ static void send_commit(struct peer *peer) } else pbase = NULL; +#if DEVELOPER + if (peer->dev_disable_commit) { + (*peer->dev_disable_commit)--; + if (*peer->dev_disable_commit == 0) + status_unusual("dev-disable-commit-after: disabling"); + } +#endif + status_debug("Telling master we're about to commit..."); /* Tell master to save this next commit to database, then wait. */ msg = sending_commitsig_msg(NULL, peer->next_index[REMOTE], @@ -1405,7 +1340,7 @@ static void send_commit(struct peer *peer) msg = towire_commitment_signed(NULL, &peer->channel_id, &commit_sig.s, raw_sigs(tmpctx, htlc_sigs)); - sync_crypto_write_no_delay(peer->pps, take(msg)); + peer_write(peer->pps, take(msg)); maybe_send_shutdown(peer); @@ -1573,7 +1508,7 @@ static void send_revocation(struct peer *peer, WIRE_CHANNELD_GOT_COMMITSIG_REPLY); /* Now we can finally send revoke_and_ack to peer */ - sync_crypto_write_no_delay(peer->pps, take(msg)); + peer_write(peer->pps, take(msg)); } static void handle_peer_commit_sig(struct peer *peer, const u8 *msg) @@ -2088,23 +2023,6 @@ static void handle_peer_shutdown(struct peer *peer, const u8 *shutdown) billboard_update(peer); } -/* Try to handle a custommsg Returns true if it was a custom message and has - * been handled, false if the message was not handled. - */ -static bool channeld_handle_custommsg(const u8 *msg) -{ - enum peer_wire type = fromwire_peektype(msg); - if (type % 2 == 1 && !peer_wire_is_defined(type)) { - /* The message is not part of the messages we know how to - * handle. Assuming this is a custommsg, we just forward it to the - * master. */ - wire_sync_write(MASTER_FD, take(towire_custommsg_in(NULL, msg))); - return true; - } else { - return false; - } -} - static void handle_unexpected_tx_sigs(struct peer *peer, const u8 *msg) { const struct witness_stack **ws; @@ -2190,29 +2108,6 @@ static void handle_unexpected_reestablish(struct peer *peer, const u8 *msg) &channel_id)); } -static void handle_ping_reply(struct peer *peer, const u8 *msg) -{ - u8 *ignored; - size_t i; - - /* We print this out because we asked for pong, so can't spam us... */ - if (!fromwire_pong(msg, msg, &ignored)) - status_unusual("Got malformed ping reply %s", - tal_hex(tmpctx, msg)); - - /* We print this because dev versions of c-lightning embed - * version here: see check_ping_make_pong! */ - for (i = 0; i < tal_count(ignored); i++) { - if (ignored[i] < ' ' || ignored[i] == 127) - break; - } - status_debug("Got pong %zu bytes (%.*s...)", - tal_count(ignored), (int)i, (char *)ignored); - wire_sync_write(MASTER_FD, - take(towire_channeld_ping_reply(NULL, true, - tal_bytelen(msg)))); -} - static void peer_in(struct peer *peer, const u8 *msg) { enum peer_wire type = fromwire_peektype(msg); @@ -2222,18 +2117,14 @@ static void peer_in(struct peer *peer, const u8 *msg) */ bool soft_error = peer->funding_locked[REMOTE] || peer->funding_locked[LOCAL]; - if (channeld_handle_custommsg(msg)) - return; - /* Since LND seems to send errors which aren't actually fatal events, * we treat errors here as soft. */ - if (handle_peer_gossip_or_error(peer->pps, &peer->channel_id, soft_error, msg)) + if (handle_peer_error(peer->pps, &peer->channel_id, soft_error, msg)) return; /* Must get funding_locked before almost anything. */ if (!peer->funding_locked[REMOTE]) { if (type != WIRE_FUNDING_LOCKED - && type != WIRE_PONG && type != WIRE_SHUTDOWN /* We expect these for v2 !! */ && type != WIRE_TX_SIGNATURES @@ -2305,25 +2196,12 @@ static void peer_in(struct peer *peer, const u8 *msg) case WIRE_INIT_RBF: case WIRE_ACK_RBF: break; - case WIRE_PONG: - switch (peer->expecting_pong) { - case PONG_EXPECTED_COMMAND: - handle_ping_reply(peer, msg); - /* fall thru */ - case PONG_EXPECTED_PROBING: - peer->expecting_pong = PONG_UNEXPECTED; - return; - case PONG_UNEXPECTED: - status_debug("Unexpected pong?"); - return; - } - abort(); case WIRE_CHANNEL_REESTABLISH: handle_unexpected_reestablish(peer, msg); return; - /* These are all swallowed by handle_peer_gossip_or_error */ + /* These are all swallowed by connectd */ case WIRE_CHANNEL_ANNOUNCEMENT: case WIRE_CHANNEL_UPDATE: case WIRE_NODE_ANNOUNCEMENT: @@ -2333,6 +2211,7 @@ static void peer_in(struct peer *peer, const u8 *msg) case WIRE_GOSSIP_TIMESTAMP_FILTER: case WIRE_REPLY_SHORT_CHANNEL_IDS_END: case WIRE_PING: + case WIRE_PONG: case WIRE_WARNING: case WIRE_ERROR: case WIRE_OBS2_ONION_MESSAGE: @@ -2350,7 +2229,7 @@ static void resend_revoke(struct peer *peer) struct pubkey point; /* Current commit is peer->next_index[LOCAL]-1, revoke prior */ u8 *msg = make_revocation_msg(peer, peer->next_index[LOCAL]-2, &point); - sync_crypto_write(peer->pps, take(msg)); + peer_write(peer->pps, take(msg)); } static void send_fail_or_fulfill(struct peer *peer, const struct htlc *h) @@ -2376,7 +2255,7 @@ static void send_fail_or_fulfill(struct peer *peer, const struct htlc *h) peer_failed_warn(peer->pps, &peer->channel_id, "HTLC %"PRIu64" state %s not failed/fulfilled", h->id, htlc_state_name(h->state)); - sync_crypto_write(peer->pps, take(msg)); + peer_write(peer->pps, take(msg)); } static int cmp_changed_htlc_id(const struct changed_htlc *a, @@ -2479,7 +2358,7 @@ static void resend_commitment(struct peer *peer, struct changed_htlc *last) , tlvs #endif ); - sync_crypto_write(peer->pps, take(msg)); + peer_write(peer->pps, take(msg)); } } @@ -2487,12 +2366,12 @@ static void resend_commitment(struct peer *peer, struct changed_htlc *last) if (peer->channel->opener == LOCAL) { msg = towire_update_fee(NULL, &peer->channel_id, channel_feerate(peer->channel, REMOTE)); - sync_crypto_write(peer->pps, take(msg)); + peer_write(peer->pps, take(msg)); if (peer->channel->lease_expiry > 0) { msg = towire_update_blockheight(NULL, &peer->channel_id, channel_blockheight(peer->channel, REMOTE)); - sync_crypto_write(peer->pps, take(msg)); + peer_write(peer->pps, take(msg)); } } @@ -2506,7 +2385,7 @@ static void resend_commitment(struct peer *peer, struct changed_htlc *last) msg = towire_commitment_signed(NULL, &peer->channel_id, &commit_sig.s, raw_sigs(tmpctx, htlc_sigs)); - sync_crypto_write(peer->pps, take(msg)); + peer_write(peer->pps, take(msg)); /* If we have already received the revocation for the previous, the * other side shouldn't be asking for a retransmit! */ @@ -2888,7 +2767,7 @@ static void peer_reconnect(struct peer *peer, ); } - sync_crypto_write(peer->pps, take(msg)); + peer_write(peer->pps, take(msg)); peer_billboard(false, "Sent reestablish, waiting for theirs"); bool soft_error = peer->funding_locked[REMOTE] @@ -2906,10 +2785,9 @@ static void peer_reconnect(struct peer *peer, * before we've reestablished channel). */ do { clean_tmpctx(); - msg = sync_crypto_read(tmpctx, peer->pps); - } while (channeld_handle_custommsg(msg) || - handle_peer_gossip_or_error(peer->pps, &peer->channel_id, soft_error, - msg) || + msg = peer_read(tmpctx, peer->pps); + } while (handle_peer_error(peer->pps, &peer->channel_id, soft_error, + msg) || capture_premature_msg(&premature_msgs, msg)); got_reestablish: @@ -2992,7 +2870,7 @@ static void peer_reconnect(struct peer *peer, msg = towire_funding_locked(NULL, &peer->channel_id, &peer->next_local_per_commit); - sync_crypto_write(peer->pps, take(msg)); + peer_write(peer->pps, take(msg)); } /* Note: next_index is the index of the current commit we're working @@ -3291,10 +3169,12 @@ static void handle_funding_depth(struct peer *peer, const u8 *msg) peer->next_index[LOCAL], type_to_string(tmpctx, struct pubkey, &peer->next_local_per_commit)); + tell_gossipd_new_channel(peer); + msg = towire_funding_locked(NULL, &peer->channel_id, &peer->next_local_per_commit); - sync_crypto_write(peer->pps, take(msg)); + peer_write(peer->pps, take(msg)); peer->funding_locked[LOCAL] = true; } @@ -3308,6 +3188,15 @@ static void handle_funding_depth(struct peer *peer, const u8 *msg) billboard_update(peer); } +static const u8 *get_cupdate(const struct peer *peer) +{ + /* Technically we only need to tell it the first time (unless it's + * changed). But it's not that common. */ + wire_sync_write(MASTER_FD, + take(towire_channeld_used_channel_update(NULL))); + return peer->channel_update; +} + static void handle_offer_htlc(struct peer *peer, const u8 *inmsg) { u8 *msg; @@ -3360,7 +3249,7 @@ static void handle_offer_htlc(struct peer *peer, const u8 *inmsg) , tlvs #endif ); - sync_crypto_write(peer->pps, take(msg)); + peer_write(peer->pps, take(msg)); start_commit_timer(peer); /* Tell the master. */ msg = towire_channeld_offer_htlc_reply(NULL, peer->htlc_id, @@ -3369,7 +3258,7 @@ static void handle_offer_htlc(struct peer *peer, const u8 *inmsg) peer->htlc_id++; return; case CHANNEL_ERR_INVALID_EXPIRY: - failwiremsg = towire_incorrect_cltv_expiry(inmsg, cltv_expiry, get_local_channel_update(tmpctx, peer)); + failwiremsg = towire_incorrect_cltv_expiry(inmsg, cltv_expiry, get_cupdate(peer)); failstr = tal_fmt(inmsg, "Invalid cltv_expiry %u", cltv_expiry); goto failed; case CHANNEL_ERR_DUPLICATE: @@ -3383,18 +3272,18 @@ static void handle_offer_htlc(struct peer *peer, const u8 *inmsg) goto failed; /* FIXME: Fuzz the boundaries a bit to avoid probing? */ case CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED: - failwiremsg = towire_temporary_channel_failure(inmsg, get_local_channel_update(inmsg, peer)); + failwiremsg = towire_temporary_channel_failure(inmsg, get_cupdate(peer)); failstr = tal_fmt(inmsg, "Capacity exceeded - HTLC fee: %s", fmt_amount_sat(inmsg, htlc_fee)); goto failed; case CHANNEL_ERR_HTLC_BELOW_MINIMUM: - failwiremsg = towire_amount_below_minimum(inmsg, amount, get_local_channel_update(inmsg, peer)); + failwiremsg = towire_amount_below_minimum(inmsg, amount, get_cupdate(peer)); failstr = tal_fmt(inmsg, "HTLC too small (%s minimum)", type_to_string(tmpctx, struct amount_msat, &peer->channel->config[REMOTE].htlc_minimum)); goto failed; case CHANNEL_ERR_TOO_MANY_HTLCS: - failwiremsg = towire_temporary_channel_failure(inmsg, get_local_channel_update(inmsg, peer)); + failwiremsg = towire_temporary_channel_failure(inmsg, get_cupdate(peer)); failstr = "Too many HTLCs"; goto failed; case CHANNEL_ERR_DUST_FAILURE: @@ -3404,7 +3293,7 @@ static void handle_offer_htlc(struct peer *peer, const u8 *inmsg) * - SHOULD NOT send this HTLC * - SHOULD fail this HTLC if it's forwarded */ - failwiremsg = towire_temporary_channel_failure(inmsg, get_local_channel_update(inmsg, peer)); + failwiremsg = towire_temporary_channel_failure(inmsg, get_cupdate(peer)); failstr = "HTLC too dusty, allowed dust limit reached"; goto failed; } @@ -3587,13 +3476,21 @@ static void handle_shutdown_cmd(struct peer *peer, const u8 *inmsg) start_commit_timer(peer); } +/* Lightningd tells us when channel_update has changed. */ +static void handle_channel_update(struct peer *peer, const u8 *msg) +{ + peer->channel_update = tal_free(peer->channel_update); + if (!fromwire_channeld_channel_update(peer, msg, &peer->channel_update)) + master_badmsg(WIRE_CHANNELD_CHANNEL_UPDATE, msg); +} + static void handle_send_error(struct peer *peer, const u8 *msg) { char *reason; if (!fromwire_channeld_send_error(msg, msg, &reason)) master_badmsg(WIRE_CHANNELD_SEND_ERROR, msg); status_debug("Send error reason: %s", reason); - sync_crypto_write(peer->pps, + peer_write(peer->pps, take(towire_errorfmt(NULL, &peer->channel_id, "%s", reason))); @@ -3601,61 +3498,10 @@ static void handle_send_error(struct peer *peer, const u8 *msg) take(towire_channeld_send_error_reply(NULL))); } -static void handle_send_ping(struct peer *peer, const u8 *msg) -{ - u8 *ping; - u16 len, num_pong_bytes; - - if (!fromwire_channeld_ping(msg, &num_pong_bytes, &len)) - master_badmsg(WIRE_CHANNELD_PING, msg); - - /* We're not supposed to send another ping until previous replied */ - if (peer->expecting_pong != PONG_UNEXPECTED) { - wire_sync_write(MASTER_FD, - take(towire_channeld_ping_reply(NULL, false, 0))); - return; - } - - /* It should never ask for an oversize ping. */ - ping = make_ping(NULL, num_pong_bytes, len); - if (tal_count(ping) > 65535) - status_failed(STATUS_FAIL_MASTER_IO, "Oversize ping"); - - sync_crypto_write_no_delay(peer->pps, take(ping)); - - /* Since we're doing this manually, kill and restart timer. */ - status_debug("sending ping expecting %sresponse", - num_pong_bytes >= 65532 ? "no " : ""); - - /* BOLT #1: - * - * A node receiving a `ping` message: - *... - * - if `num_pong_bytes` is less than 65532: - * - MUST respond by sending a `pong` message, with `byteslen` equal - * to `num_pong_bytes`. - * - otherwise (`num_pong_bytes` is **not** less than 65532): - * - MUST ignore the `ping`. - */ - if (num_pong_bytes >= 65532) { - wire_sync_write(MASTER_FD, - take(towire_channeld_ping_reply(NULL, - true, 0))); - return; - } - - /* We'll respond to lightningd once the pong comes in */ - peer->expecting_pong = PONG_EXPECTED_COMMAND; - - /* Restart our timed pings now. */ - tal_free(peer->ping_timer); - set_ping_timer(peer); -} - #if DEVELOPER static void handle_dev_reenable_commit(struct peer *peer) { - dev_suppress_commit = false; + peer->dev_disable_commit = tal_free(peer->dev_disable_commit); start_commit_timer(peer); status_debug("dev_reenable_commit"); wire_sync_write(MASTER_FD, @@ -3695,17 +3541,6 @@ static void handle_dev_quiesce(struct peer *peer, const u8 *msg) #endif /* EXPERIMENTAL_FEATURES */ #endif /* DEVELOPER */ -/* We were told to send a custommsg to the peer by `lightningd`. All the - * verification is done on the side of `lightningd` so we should be good to - * just forward it here. */ -static void channeld_send_custommsg(struct peer *peer, const u8 *msg) -{ - u8 *inner; - if (!fromwire_custommsg_out(tmpctx, msg, &inner)) - master_badmsg(WIRE_CUSTOMMSG_OUT, msg); - sync_crypto_write(peer->pps, take(inner)); -} - static void req_in(struct peer *peer, const u8 *msg) { enum channeld_wire t = fromwire_peektype(msg); @@ -3750,8 +3585,8 @@ static void req_in(struct peer *peer, const u8 *msg) case WIRE_CHANNELD_SEND_ERROR: handle_send_error(peer, msg); return; - case WIRE_CHANNELD_PING: - handle_send_ping(peer, msg); + case WIRE_CHANNELD_CHANNEL_UPDATE: + handle_channel_update(peer, msg); return; #if DEVELOPER case WIRE_CHANNELD_DEV_REENABLE_COMMIT: @@ -3788,20 +3623,12 @@ static void req_in(struct peer *peer, const u8 *msg) case WIRE_CHANNELD_SEND_ERROR_REPLY: case WIRE_CHANNELD_DEV_QUIESCE_REPLY: case WIRE_CHANNELD_UPGRADED: - case WIRE_CHANNELD_PING_REPLY: - break; - } - - /* Now handle common messages. */ - switch ((enum common_wire)t) { - case WIRE_CUSTOMMSG_OUT: - channeld_send_custommsg(peer, msg); - return; - /* We send these. */ - case WIRE_CUSTOMMSG_IN: + case WIRE_CHANNELD_USED_CHANNEL_UPDATE: + case WIRE_CHANNELD_LOCAL_CHANNEL_UPDATE: + case WIRE_CHANNELD_LOCAL_CHANNEL_ANNOUNCEMENT: + case WIRE_CHANNELD_LOCAL_PRIVATE_CHANNEL: break; } - master_badmsg(-1, msg); } @@ -3828,6 +3655,8 @@ static void init_channel(struct peer *peer) struct penalty_base *pbases; u8 *reestablish_only; struct channel_type *channel_type; + u32 *dev_disable_commit; /* Always NULL */ + bool dev_fast_gossip; #if !DEVELOPER bool dev_fail_process_onionpacket; /* Ignored */ #endif @@ -3836,66 +3665,72 @@ static void init_channel(struct peer *peer) msg = wire_sync_read(tmpctx, MASTER_FD); if (!fromwire_channeld_init(peer, msg, - &chainparams, - &peer->our_features, - &peer->channel_id, - &funding, - &funding_sats, - &minimum_depth, - &peer->our_blockheight, - &blockheight_states, - &lease_expiry, - &conf[LOCAL], &conf[REMOTE], - &fee_states, - &peer->feerate_min, - &peer->feerate_max, - &peer->feerate_penalty, - &peer->their_commit_sig, - &peer->pps, - &funding_pubkey[REMOTE], - &points[REMOTE], - &peer->remote_per_commit, - &peer->old_remote_per_commit, - &opener, - &peer->fee_base, - &peer->fee_per_satoshi, - &local_msat, - &points[LOCAL], - &funding_pubkey[LOCAL], - &peer->node_ids[LOCAL], - &peer->node_ids[REMOTE], - &peer->commit_msec, - &peer->cltv_delta, - &peer->last_was_revoke, - &peer->last_sent_commit, - &peer->next_index[LOCAL], - &peer->next_index[REMOTE], - &peer->revocations_received, - &peer->htlc_id, - &htlcs, - &peer->funding_locked[LOCAL], - &peer->funding_locked[REMOTE], - &peer->short_channel_ids[LOCAL], - &reconnected, - &peer->send_shutdown, - &peer->shutdown_sent[REMOTE], - &peer->final_scriptpubkey, - &peer->channel_flags, - &fwd_msg, - &peer->announce_depth_reached, - &last_remote_per_commit_secret, - &peer->their_features, - &peer->remote_upfront_shutdown_script, - &remote_ann_node_sig, - &remote_ann_bitcoin_sig, - &channel_type, - &dev_fast_gossip, - &dev_fail_process_onionpacket, - &pbases, - &reestablish_only)) { + &chainparams, + &peer->our_features, + &peer->channel_id, + &funding, + &funding_sats, + &minimum_depth, + &peer->our_blockheight, + &blockheight_states, + &lease_expiry, + &conf[LOCAL], &conf[REMOTE], + &fee_states, + &peer->feerate_min, + &peer->feerate_max, + &peer->feerate_penalty, + &peer->their_commit_sig, + &funding_pubkey[REMOTE], + &points[REMOTE], + &peer->remote_per_commit, + &peer->old_remote_per_commit, + &opener, + &peer->fee_base, + &peer->fee_per_satoshi, + &local_msat, + &points[LOCAL], + &funding_pubkey[LOCAL], + &peer->node_ids[LOCAL], + &peer->node_ids[REMOTE], + &peer->commit_msec, + &peer->cltv_delta, + &peer->last_was_revoke, + &peer->last_sent_commit, + &peer->next_index[LOCAL], + &peer->next_index[REMOTE], + &peer->revocations_received, + &peer->htlc_id, + &htlcs, + &peer->funding_locked[LOCAL], + &peer->funding_locked[REMOTE], + &peer->short_channel_ids[LOCAL], + &reconnected, + &peer->send_shutdown, + &peer->shutdown_sent[REMOTE], + &peer->final_scriptpubkey, + &peer->channel_flags, + &fwd_msg, + &peer->announce_depth_reached, + &last_remote_per_commit_secret, + &peer->their_features, + &peer->remote_upfront_shutdown_script, + &remote_ann_node_sig, + &remote_ann_bitcoin_sig, + &channel_type, + &dev_fast_gossip, + &dev_fail_process_onionpacket, + &dev_disable_commit, + &pbases, + &reestablish_only, + &peer->channel_update)) { master_badmsg(WIRE_CHANNELD_INIT, msg); } +#if DEVELOPER + peer->dev_disable_commit = dev_disable_commit; + peer->dev_fast_gossip = dev_fast_gossip; +#endif + status_debug("option_static_remotekey = %u, option_anchor_outputs = %u", channel_type_has(channel_type, OPT_STATIC_REMOTEKEY), channel_type_has(channel_type, OPT_ANCHOR_OUTPUTS)); @@ -3908,8 +3743,9 @@ static void init_channel(struct peer *peer) tal_dup(peer, struct penalty_base, &pbases[i])); tal_free(pbases); - /* stdin == requests, 3 == peer, 4 = gossip, 5 = gossip_store, 6 = HSM */ - per_peer_state_set_fds(peer->pps, 3, 4, 5); + /* stdin == requests, 3 == peer */ + peer->pps = new_per_peer_state(peer); + per_peer_state_set_fd(peer->pps, 3); status_debug("init %s: remote_per_commit = %s, old_remote_per_commit = %s" " next_idx_local = %"PRIu64 @@ -3986,6 +3822,11 @@ static void init_channel(struct peer *peer) /* from now we need keep watch over WIRE_CHANNELD_FUNDING_DEPTH */ peer->depth_togo = minimum_depth; + /* Make sure gossipd knows about this channel if we have sent + * funding_locked */ + if (peer->funding_locked[LOCAL]) + tell_gossipd_new_channel(peer); + /* OK, now we can process peer messages. */ if (reconnected) peer_reconnect(peer, &last_remote_per_commit_secret, @@ -3995,7 +3836,7 @@ static void init_channel(struct peer *peer) /* If we have a messages to send, send them immediately */ if (fwd_msg) - sync_crypto_write(peer->pps, take(fwd_msg)); + peer_write(peer->pps, take(fwd_msg)); /* Reenable channel */ channel_announcement_negotiate(peer); @@ -4003,14 +3844,6 @@ static void init_channel(struct peer *peer) billboard_update(peer); } -static void try_read_gossip_store(struct peer *peer) -{ - u8 *msg = gossip_store_next(tmpctx, peer->pps); - - if (msg) - sync_crypto_write(peer->pps, take(msg)); -} - int main(int argc, char *argv[]) { setup_locale(); @@ -4024,10 +3857,8 @@ int main(int argc, char *argv[]) status_setup_sync(MASTER_FD); peer = tal(NULL, struct peer); - peer->expecting_pong = PONG_UNEXPECTED; timers_init(&peer->timers, time_mono()); peer->commit_timer = NULL; - set_ping_timer(peer); peer->have_sigs[LOCAL] = peer->have_sigs[REMOTE] = false; peer->announce_depth_reached = false; peer->channel_local_active = false; @@ -4060,11 +3891,10 @@ int main(int argc, char *argv[]) FD_ZERO(&fds_in); FD_SET(MASTER_FD, &fds_in); FD_SET(peer->pps->peer_fd, &fds_in); - FD_SET(peer->pps->gossip_fd, &fds_in); FD_ZERO(&fds_out); FD_SET(peer->pps->peer_fd, &fds_out); - nfds = peer->pps->gossip_fd+1; + nfds = peer->pps->peer_fd+1; while (!shutdown_complete(peer)) { struct timemono first; @@ -4072,7 +3902,6 @@ int main(int argc, char *argv[]) struct timeval timeout, *tptr; struct timer *expired; const u8 *msg; - struct timerel trel; struct timemono now = time_mono(); /* Free any temporary allocations */ @@ -4104,13 +3933,6 @@ int main(int argc, char *argv[]) tptr = &timeout; } - /* If timer to next gossip is sooner, use that instead. */ - if (time_to_next_gossip(peer->pps, &trel) - && (!tptr || time_less(trel, timeval_to_timerel(*tptr)))) { - timeout = timerel_to_timeval(trel); - tptr = &timeout; - } - if (select(nfds, &rfds, NULL, NULL, tptr) < 0) { /* Signals OK, eg. SIGUSR1 */ if (errno == EINTR) @@ -4129,17 +3951,9 @@ int main(int argc, char *argv[]) req_in(peer, msg); } else if (FD_ISSET(peer->pps->peer_fd, &rfds)) { /* This could take forever, but who cares? */ - msg = sync_crypto_read(tmpctx, peer->pps); + msg = peer_read(tmpctx, peer->pps); peer_in(peer, msg); - } else if (FD_ISSET(peer->pps->gossip_fd, &rfds)) { - msg = wire_sync_read(tmpctx, peer->pps->gossip_fd); - /* Gossipd hangs up on us to kill us when a new - * connection comes in. */ - if (!msg) - peer_failed_connection_lost(); - handle_gossip_msg(peer->pps, take(msg)); - } else /* Lowest priority: stream from store. */ - try_read_gossip_store(peer); + } } /* We only exit when shutdown is complete. */ diff --git a/channeld/channeld.h b/channeld/channeld.h new file mode 100644 index 000000000000..a2b26b08246a --- /dev/null +++ b/channeld/channeld.h @@ -0,0 +1,10 @@ +#ifndef LIGHTNING_CHANNELD_CHANNELD_H +#define LIGHTNING_CHANNELD_CHANNELD_H +#include "config.h" +#include +#include +#include + +const u8 *hsm_req(const tal_t *ctx, const u8 *req TAKES); + +#endif /* LIGHTNING_CHANNELD_CHANNELD_H */ diff --git a/channeld/channeld_wire.csv b/channeld/channeld_wire.csv index 7888fb4d4ce6..a444125ce069 100644 --- a/channeld/channeld_wire.csv +++ b/channeld/channeld_wire.csv @@ -8,7 +8,6 @@ #include #include #include -#include # Begin! (passes gossipd-client fd) msgtype,channeld_init,1000 @@ -28,7 +27,6 @@ msgdata,channeld_init,feerate_min,u32, msgdata,channeld_init,feerate_max,u32, msgdata,channeld_init,feerate_penalty,u32, msgdata,channeld_init,first_commit_sig,bitcoin_signature, -msgdata,channeld_init,per_peer_state,per_peer_state, msgdata,channeld_init,remote_fundingkey,pubkey, msgdata,channeld_init,remote_basepoints,basepoints, msgdata,channeld_init,remote_per_commit,pubkey, @@ -74,10 +72,13 @@ msgdata,channeld_init,remote_ann_bitcoin_sig,?secp256k1_ecdsa_signature, msgdata,channeld_init,desired_type,channel_type, msgdata,channeld_init,dev_fast_gossip,bool, msgdata,channeld_init,dev_fail_process_onionpacket,bool, +msgdata,channeld_init,dev_disable_commit,?u32, msgdata,channeld_init,num_penalty_bases,u32, msgdata,channeld_init,pbases,penalty_base,num_penalty_bases msgdata,channeld_init,reestablish_only_len,u16, msgdata,channeld_init,reestablish_only,u8,reestablish_only_len +msgdata,channeld_init,channel_update_len,u16, +msgdata,channeld_init,channel_update,u8,channel_update_len # master->channeld funding hit new depth(funding locked if >= lock depth) msgtype,channeld_funding_depth,1002 @@ -186,7 +187,6 @@ msgdata,channeld_got_shutdown,wrong_funding,?bitcoin_outpoint, # Shutdown is complete, ready for closing negotiation. + peer_fd & gossip_fd. msgtype,channeld_shutdown_complete,1025 -msgdata,channeld_shutdown_complete,per_peer_state,per_peer_state, # Re-enable commit timer. msgtype,channeld_dev_reenable_commit,1026 @@ -226,6 +226,35 @@ msgdata,channeld_send_error,reason,wirestring, # Tell master channeld has sent the error message. msgtype,channeld_send_error_reply,1108 +# Tell channeld about the latest channel_update +msgtype,channeld_channel_update,1001 +msgdata,channeld_channel_update,len,u16, +msgdata,channeld_channel_update,msg,u8,len + +# Tell lightningd we used the latest channel_update for an error. +msgtype,channeld_used_channel_update,1102 + +# Channeld: tell gossipd to make this channel_update. +msgtype,channeld_local_channel_update,1013 +msgdata,channeld_local_channel_update,short_channel_id,short_channel_id, +msgdata,channeld_local_channel_update,disable,bool, +msgdata,channeld_local_channel_update,cltv_expiry_delta,u16, +msgdata,channeld_local_channel_update,htlc_minimum_msat,amount_msat, +msgdata,channeld_local_channel_update,fee_base_msat,u32, +msgdata,channeld_local_channel_update,fee_proportional_millionths,u32, +msgdata,channeld_local_channel_update,htlc_maximum_msat,amount_msat, + +# Channeld: tell gossipd about our channel_announcement +msgtype,channeld_local_channel_announcement,1014 +msgdata,channeld_local_channel_announcement,len,u16, +msgdata,channeld_local_channel_announcement,cannounce,u8,len + +# Channeld: tell gossipd about this (as-yet) unannounced channel +msgtype,channeld_local_private_channel,1015 +msgdata,channeld_local_private_channel,capacity,amount_sat, +msgdata,channeld_local_private_channel,len,u16, +msgdata,channeld_local_private_channel,features,u8,len + # Ask channeld to quiesce. msgtype,channeld_dev_quiesce,1009 msgtype,channeld_dev_quiesce_reply,1109 @@ -237,14 +266,3 @@ msgdata,channeld_upgraded,new_type,channel_type, # Tell peer about our latest and greatest blockheight. msgtype,channeld_blockheight,1012 msgdata,channeld_blockheight,blockheight,u32, - -# Ping/pong test. Waits for a reply if it expects one. -msgtype,channeld_ping,1030 -msgdata,channeld_ping,num_pong_bytes,u16, -msgdata,channeld_ping,len,u16, - -msgtype,channeld_ping_reply,1130 -# False if we there was already a ping in progress. -msgdata,channeld_ping_reply,sent,bool, -# 0 == no pong expected, otherwise length of pong. -msgdata,channeld_ping_reply,totlen,u16, diff --git a/channeld/test/run-commit_tx.c b/channeld/test/run-commit_tx.c index 7610fbd9a3b7..f222e7ae3d59 100644 --- a/channeld/test/run-commit_tx.c +++ b/channeld/test/run-commit_tx.c @@ -24,7 +24,7 @@ static bool print_superverbose; bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_bigsize called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for fromwire_node_id */ diff --git a/channeld/watchtower.c b/channeld/watchtower.c index a895dfc1d31b..744588d72da6 100644 --- a/channeld/watchtower.c +++ b/channeld/watchtower.c @@ -1,6 +1,7 @@ #include "config.h" #include #include +#include #include #include #include @@ -26,7 +27,7 @@ penalty_tx_create(const tal_t *ctx, struct bitcoin_tx *tx; struct keyset keyset; size_t weight; - u8 *msg; + const u8 *msg; struct amount_sat fee, min_out, amt; struct bitcoin_signature sig; u32 locktime = 0; @@ -105,16 +106,12 @@ penalty_tx_create(const tal_t *ctx, bitcoin_tx_finalize(tx); u8 *hsm_sign_msg = - towire_hsmd_sign_penalty_to_us(ctx, &remote_per_commitment_secret, + towire_hsmd_sign_penalty_to_us(tmpctx, &remote_per_commitment_secret, tx, wscript); - if (!wire_sync_write(hsm_fd, take(hsm_sign_msg))) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Writing sign request to hsm"); - - msg = wire_sync_read(tmpctx, hsm_fd); - if (!msg || !fromwire_hsmd_sign_tx_reply(msg, &sig)) - status_failed(STATUS_FAIL_INTERNAL_ERROR, + msg = hsm_req(tmpctx, hsm_sign_msg); + if (!fromwire_hsmd_sign_tx_reply(msg, &sig)) + status_failed(STATUS_FAIL_HSM_IO, "Reading sign_tx_reply: %s", tal_hex(tmpctx, msg)); witness = bitcoin_witness_sig_and_element(tx, &sig, &ONE, sizeof(ONE), diff --git a/cli/test/run-human-mode.c b/cli/test/run-human-mode.c index a3a122b1d0e8..bf7c4a25f82a 100644 --- a/cli/test/run-human-mode.c +++ b/cli/test/run-human-mode.c @@ -70,7 +70,7 @@ struct amount_sat fromwire_amount_sat(const u8 **cursor UNNEEDED, size_t *max UN bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_bigsize called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for fromwire_node_id */ diff --git a/cli/test/run-large-input.c b/cli/test/run-large-input.c index 7bb64233326b..40c8d67f91e9 100644 --- a/cli/test/run-large-input.c +++ b/cli/test/run-large-input.c @@ -70,7 +70,7 @@ struct amount_sat fromwire_amount_sat(const u8 **cursor UNNEEDED, size_t *max UN bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_bigsize called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for fromwire_node_id */ diff --git a/cli/test/run-remove-hint.c b/cli/test/run-remove-hint.c index 3311a9aec7d3..18e21e490e45 100644 --- a/cli/test/run-remove-hint.c +++ b/cli/test/run-remove-hint.c @@ -73,7 +73,7 @@ struct amount_sat fromwire_amount_sat(const u8 **cursor UNNEEDED, size_t *max UN bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_bigsize called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for fromwire_node_id */ diff --git a/closingd/Makefile b/closingd/Makefile index 6fca67f75303..53c732399c07 100644 --- a/closingd/Makefile +++ b/closingd/Makefile @@ -26,15 +26,10 @@ CLOSINGD_COMMON_OBJS := \ common/bip32.o \ common/channel_id.o \ common/close_tx.o \ - common/crypto_state.o \ - common/crypto_sync.o \ common/cryptomsg.o \ common/daemon.o \ common/daemon_conn.o \ - common/dev_disconnect.o \ common/derive_basepoints.o \ - common/peer_status_wiregen.o \ - common/status_wiregen.o \ common/gossip_rcvd_filter.o \ common/gossip_store.o \ common/htlc_wire.o \ @@ -45,11 +40,14 @@ CLOSINGD_COMMON_OBJS := \ common/onionreply.o \ common/peer_billboard.o \ common/peer_failed.o \ + common/peer_io.o \ + common/peer_status_wiregen.o \ common/per_peer_state.o \ common/permute_tx.o \ common/ping.o \ common/psbt_open.o \ common/pseudorand.o \ + common/status_wiregen.o \ common/read_peer_msg.o \ common/setup.o \ common/socket_close.o \ diff --git a/closingd/closingd.c b/closingd/closingd.c index b3f54e3b7dfb..7cf8fb296c3d 100644 --- a/closingd/closingd.c +++ b/closingd/closingd.c @@ -6,12 +6,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include #include @@ -27,13 +27,12 @@ #include #include #include -#include #include #include -/* stdin == requests, 3 == peer, 4 = gossip, 5 = gossip_store, 6 = hsmd */ +/* stdin == requests, 3 == peer, 4 = hsmd */ #define REQ_FD STDIN_FILENO -#define HSM_FD 6 +#define HSM_FD 4 static void notify(enum log_level level, const char *fmt, ...) { @@ -119,24 +118,10 @@ static u8 *closing_read_peer_msg(const tal_t *ctx, { for (;;) { u8 *msg; - bool from_gossipd; clean_tmpctx(); - msg = peer_or_gossip_sync_read(ctx, pps, &from_gossipd); - if (from_gossipd) { - handle_gossip_msg(pps, take(msg)); - continue; - } - /* Handle custommsgs */ - enum peer_wire type = fromwire_peektype(msg); - if (type % 2 == 1 && !peer_wire_is_defined(type)) { - /* The message is not part of the messages we know - * how to handle. Assume is custommsg, forward it - * to master. */ - wire_sync_write(REQ_FD, take(towire_custommsg_in(NULL, msg))); - continue; - } - if (!handle_peer_gossip_or_error(pps, channel_id, false, msg)) + msg = peer_read(ctx, pps); + if (!handle_peer_error(pps, channel_id, false, msg)) return msg; } } @@ -214,7 +199,7 @@ static void send_offer(struct per_peer_state *pps, msg = towire_closing_signed(NULL, channel_id, fee_to_offer, &our_sig.s, close_tlvs); - sync_crypto_write(pps, take(msg)); + peer_write(pps, take(msg)); } static void tell_master_their_offer(const struct bitcoin_signature *their_sig, @@ -897,7 +882,6 @@ int main(int argc, char *argv[]) msg = wire_sync_read(tmpctx, REQ_FD); if (!fromwire_closingd_init(ctx, msg, &chainparams, - &pps, &channel_id, &funding, &funding_sats, @@ -914,12 +898,12 @@ int main(int argc, char *argv[]) &fee_negotiation_step, &fee_negotiation_step_unit, &use_quickclose, - &dev_fast_gossip, &wrong_funding)) master_badmsg(WIRE_CLOSINGD_INIT, msg); - /* stdin == requests, 3 == peer, 4 = gossip, 5 = gossip_store, 6 = hsmd */ - per_peer_state_set_fds(notleak(pps), 3, 4, 5); + /* stdin == requests, 3 == peer, 4 = hsmd */ + pps = notleak(new_per_peer_state(ctx)); + per_peer_state_set_fd(pps, 3); funding_wscript = bitcoin_redeem_2of2(ctx, &funding_pubkey[LOCAL], diff --git a/closingd/closingd_wire.csv b/closingd/closingd_wire.csv index a6b066d739a3..94ab71c757e0 100644 --- a/closingd/closingd_wire.csv +++ b/closingd/closingd_wire.csv @@ -2,12 +2,10 @@ #include #include #include -#include #include # Begin! (passes peer fd, gossipd-client fd) msgtype,closingd_init,2001 msgdata,closingd_init,chainparams,chainparams, -msgdata,closingd_init,pps,per_peer_state, msgdata,closingd_init,channel_id,channel_id, msgdata,closingd_init,funding,bitcoin_outpoint, msgdata,closingd_init,funding_satoshi,amount_sat, @@ -28,7 +26,6 @@ msgdata,closingd_init,remote_scriptpubkey,u8,remote_scriptpubkey_len msgdata,closingd_init,fee_negotiation_step,u64, msgdata,closingd_init,fee_negotiation_step_unit,u8, msgdata,closingd_init,use_quickclose,bool, -msgdata,closingd_init,dev_fast_gossip,bool, msgdata,closingd_init,shutdown_wrong_funding,?bitcoin_outpoint, # Message for any commands waiting. diff --git a/common/Makefile b/common/Makefile index 2f5368ad6f6a..9c8dbfe39893 100644 --- a/common/Makefile +++ b/common/Makefile @@ -9,8 +9,8 @@ COMMON_SRC_NOGEN := \ common/bigsize.c \ common/billboard.c \ common/bip32.c \ - common/blinding.c \ common/blindedpath.c \ + common/blinding.c \ common/blockheight_states.c \ common/bolt11.c \ common/bolt11_json.c \ @@ -19,11 +19,9 @@ COMMON_SRC_NOGEN := \ common/channel_config.c \ common/channel_id.c \ common/channel_type.c \ - common/coin_mvt.c \ common/close_tx.c \ + common/coin_mvt.c \ common/configdir.c \ - common/crypto_state.c \ - common/crypto_sync.c \ common/cryptomsg.c \ common/daemon.c \ common/daemon_conn.c \ @@ -38,6 +36,7 @@ COMMON_SRC_NOGEN := \ common/fp16.c \ common/gossip_rcvd_filter.c \ common/gossip_store.c \ + common/gossmap.c \ common/hash_u5.c \ common/hmac.c \ common/hsm_encryption.c \ @@ -54,7 +53,6 @@ COMMON_SRC_NOGEN := \ common/json_tok.c \ common/key_derive.c \ common/keyset.c \ - common/gossmap.c \ common/lease_rates.c \ common/memleak.c \ common/msg_queue.c \ @@ -62,15 +60,16 @@ COMMON_SRC_NOGEN := \ common/onion.c \ common/onionreply.c \ common/param.c \ - common/penalty_base.c \ - common/per_peer_state.c \ common/peer_billboard.c \ common/peer_failed.c \ + common/peer_io.c \ + common/penalty_base.c \ + common/per_peer_state.c \ common/permute_tx.c \ common/ping.c \ + common/private_channel_announcement.c \ common/psbt_internal.c \ common/psbt_open.c \ - common/private_channel_announcement.c \ common/pseudorand.c \ common/random_select.c \ common/read_peer_msg.c \ @@ -97,6 +96,7 @@ COMMON_SRC_GEN := common/status_wiregen.c common/peer_status_wiregen.c COMMON_HEADERS_NOGEN := $(COMMON_SRC_NOGEN:.c=.h) \ common/closing_fee.h \ + common/crypto_state.h \ common/ecdh.h \ common/errcode.h \ common/gossip_constants.h \ diff --git a/common/channel_id.c b/common/channel_id.c index 517427b7469c..c2f4ce6e04dc 100644 --- a/common/channel_id.c +++ b/common/channel_id.c @@ -88,10 +88,10 @@ void towire_channel_id(u8 **pptr, const struct channel_id *channel_id) towire(pptr, channel_id, sizeof(*channel_id)); } -void fromwire_channel_id(const u8 **cursor, size_t *max, +bool fromwire_channel_id(const u8 **cursor, size_t *max, struct channel_id *channel_id) { - fromwire(cursor, max, channel_id, sizeof(*channel_id)); + return fromwire(cursor, max, channel_id, sizeof(*channel_id)) != NULL; } REGISTER_TYPE_TO_HEXSTR(channel_id); diff --git a/common/channel_id.h b/common/channel_id.h index 81b6ef0248ea..d6ce8687aaf7 100644 --- a/common/channel_id.h +++ b/common/channel_id.h @@ -38,6 +38,6 @@ void derive_tmp_channel_id(struct channel_id *channel_id, /* Marshalling/unmarshalling functions */ void towire_channel_id(u8 **pptr, const struct channel_id *channel_id); -void fromwire_channel_id(const u8 **cursor, size_t *max, +bool fromwire_channel_id(const u8 **cursor, size_t *max, struct channel_id *channel_id); #endif /* LIGHTNING_COMMON_CHANNEL_ID_H */ diff --git a/common/crypto_state.c b/common/crypto_state.c deleted file mode 100644 index d592ddfd3500..000000000000 --- a/common/crypto_state.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "config.h" -#include -#include - -void towire_crypto_state(u8 **ptr, const struct crypto_state *cs) -{ - towire_u64(ptr, cs->rn); - towire_u64(ptr, cs->sn); - towire_secret(ptr, &cs->sk); - towire_secret(ptr, &cs->rk); - towire_secret(ptr, &cs->s_ck); - towire_secret(ptr, &cs->r_ck); -} - -void fromwire_crypto_state(const u8 **ptr, size_t *max, struct crypto_state *cs) -{ - cs->rn = fromwire_u64(ptr, max); - cs->sn = fromwire_u64(ptr, max); - fromwire_secret(ptr, max, &cs->sk); - fromwire_secret(ptr, max, &cs->rk); - fromwire_secret(ptr, max, &cs->s_ck); - fromwire_secret(ptr, max, &cs->r_ck); -} diff --git a/common/crypto_state.h b/common/crypto_state.h index c2fa658c8ce5..8a2674719961 100644 --- a/common/crypto_state.h +++ b/common/crypto_state.h @@ -12,7 +12,4 @@ struct crypto_state { struct secret s_ck, r_ck; }; -void towire_crypto_state(u8 **pptr, const struct crypto_state *cs); -void fromwire_crypto_state(const u8 **ptr, size_t *max, struct crypto_state *cs); - #endif /* LIGHTNING_COMMON_CRYPTO_STATE_H */ diff --git a/common/crypto_sync.c b/common/crypto_sync.c deleted file mode 100644 index 93733884b073..000000000000 --- a/common/crypto_sync.c +++ /dev/null @@ -1,134 +0,0 @@ -#include "config.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void sync_crypto_write(struct per_peer_state *pps, const void *msg TAKES) -{ -#if DEVELOPER - bool post_sabotage = false, post_close; - int type = fromwire_peektype(msg); -#endif - u8 *enc; - - status_peer_io(LOG_IO_OUT, NULL, msg); - enc = cryptomsg_encrypt_msg(NULL, &pps->cs, msg); - -#if DEVELOPER - switch (dev_disconnect(type)) { - case DEV_DISCONNECT_BEFORE: - dev_sabotage_fd(pps->peer_fd, true); - peer_failed_connection_lost(); - case DEV_DISCONNECT_DROPPKT: - enc = tal_free(enc); /* FALL THRU */ - case DEV_DISCONNECT_AFTER: - post_sabotage = true; - post_close = true; - break; - case DEV_DISCONNECT_BLACKHOLE: - dev_blackhole_fd(pps->peer_fd); - break; - case DEV_DISCONNECT_NORMAL: - break; - case DEV_DISCONNECT_DISABLE_AFTER: - post_sabotage = true; - post_close = false; - break; - } -#endif - if (!write_all(pps->peer_fd, enc, tal_count(enc))) - peer_failed_connection_lost(); - tal_free(enc); - -#if DEVELOPER - if (post_sabotage) - dev_sabotage_fd(pps->peer_fd, post_close); -#endif -} - -/* We're happy for the kernel to batch update and gossip messages, but a - * commitment message, for example, should be instantly sent. There's no - * great way of doing this, unfortunately. - * - * Setting TCP_NODELAY on Linux flushes the socket, which really means - * we'd want to toggle on then off it *after* sending. But Linux has - * TCP_CORK. On FreeBSD, it seems (looking at source) not to, so - * there we'd want to set it before the send, and reenable it - * afterwards. Even if this is wrong on other non-Linux platforms, it - * only means one extra packet. - */ -void sync_crypto_write_no_delay(struct per_peer_state *pps, - const void *msg TAKES) -{ - int val; - int opt; - const char *optname; - static bool complained = false; - -#ifdef TCP_CORK - opt = TCP_CORK; - optname = "TCP_CORK"; -#elif defined(TCP_NODELAY) - opt = TCP_NODELAY; - optname = "TCP_NODELAY"; -#else -#error "Please report platform with neither TCP_CORK nor TCP_NODELAY?" -#endif - - val = 1; - if (setsockopt(pps->peer_fd, IPPROTO_TCP, opt, &val, sizeof(val)) != 0) { - /* This actually happens in testing, where we blackhole the fd */ - if (!complained) { - status_unusual("setsockopt %s=1: %s", - optname, - strerror(errno)); - complained = true; - } - } - sync_crypto_write(pps, msg); - - val = 0; - setsockopt(pps->peer_fd, IPPROTO_TCP, opt, &val, sizeof(val)); -} - -u8 *sync_crypto_read(const tal_t *ctx, struct per_peer_state *pps) -{ - u8 hdr[18], *enc, *dec; - u16 len; - - if (!read_all(pps->peer_fd, hdr, sizeof(hdr))) { - status_debug("Failed reading header: %s", strerror(errno)); - peer_failed_connection_lost(); - } - - if (!cryptomsg_decrypt_header(&pps->cs, hdr, &len)) { - status_debug("Failed hdr decrypt with rn=%"PRIu64, - pps->cs.rn-1); - peer_failed_connection_lost(); - } - - enc = tal_arr(ctx, u8, len + 16); - if (!read_all(pps->peer_fd, enc, tal_count(enc))) { - status_debug("Failed reading body: %s", strerror(errno)); - peer_failed_connection_lost(); - } - - dec = cryptomsg_decrypt_body(ctx, &pps->cs, enc); - tal_free(enc); - if (!dec) - peer_failed_connection_lost(); - else - status_peer_io(LOG_IO_IN, NULL, dec); - - return dec; -} diff --git a/common/crypto_sync.h b/common/crypto_sync.h deleted file mode 100644 index 29816289d9df..000000000000 --- a/common/crypto_sync.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef LIGHTNING_COMMON_CRYPTO_SYNC_H -#define LIGHTNING_COMMON_CRYPTO_SYNC_H -#include "config.h" -#include -#include - -struct per_peer_state; - -/* Exits with peer_failed_connection_lost() if write fails. */ -void sync_crypto_write(struct per_peer_state *pps, const void *msg TAKES); - -/* Same, but disabled nagle for this message. */ -void sync_crypto_write_no_delay(struct per_peer_state *pps, - const void *msg TAKES); - -/* Exits with peer_failed_connection_lost() if can't read packet. */ -u8 *sync_crypto_read(const tal_t *ctx, struct per_peer_state *pps); - -#endif /* LIGHTNING_COMMON_CRYPTO_SYNC_H */ diff --git a/common/dev_disconnect.c b/common/dev_disconnect.c index bb2453c30f50..608b2f7a842c 100644 --- a/common/dev_disconnect.c +++ b/common/dev_disconnect.c @@ -15,9 +15,6 @@ static int dev_disconnect_fd = -1; static char dev_disconnect_line[200]; static int dev_disconnect_count, dev_disconnect_len; -static bool dev_disconnect_nocommit; - -bool dev_suppress_commit; static void next_dev_disconnect(void) { @@ -36,12 +33,6 @@ static void next_dev_disconnect(void) dev_disconnect_line[r] = '\n'; dev_disconnect_len = strcspn(dev_disconnect_line, "\n"); dev_disconnect_line[dev_disconnect_len] = '\0'; - if (strends(dev_disconnect_line, "-nocommit")) { - dev_disconnect_line[strlen(dev_disconnect_line) - - strlen("-nocommit")] = '\0'; - dev_disconnect_nocommit = true; - } else - dev_disconnect_nocommit = false; asterisk = strchr(dev_disconnect_line, '*'); if (asterisk) { @@ -60,7 +51,7 @@ void dev_disconnect_init(int fd) dev_disconnect_fd = fd; } -enum dev_disconnect dev_disconnect(int pkt_type) +enum dev_disconnect dev_disconnect(const struct node_id *id, int pkt_type) { if (dev_disconnect_fd == -1) return DEV_DISCONNECT_NORMAL; @@ -68,7 +59,8 @@ enum dev_disconnect dev_disconnect(int pkt_type) if (!dev_disconnect_count) next_dev_disconnect(); - if (!streq(peer_wire_name(pkt_type), dev_disconnect_line+1)) + if (!dev_disconnect_line[0] + || !streq(peer_wire_name(pkt_type), dev_disconnect_line+1)) return DEV_DISCONNECT_NORMAL; if (--dev_disconnect_count != 0) { @@ -79,10 +71,8 @@ enum dev_disconnect dev_disconnect(int pkt_type) err(1, "lseek failure"); } - status_debug("dev_disconnect: %s%s", dev_disconnect_line, - dev_disconnect_nocommit ? "-nocommit" : ""); - if (dev_disconnect_nocommit) - dev_suppress_commit = true; + status_peer_debug(id, "dev_disconnect: %s (%s)", dev_disconnect_line, + peer_wire_name(pkt_type)); return dev_disconnect_line[0]; } diff --git a/common/dev_disconnect.h b/common/dev_disconnect.h index 3c0f4b8973d4..e1351478dcae 100644 --- a/common/dev_disconnect.h +++ b/common/dev_disconnect.h @@ -4,15 +4,15 @@ #include #if DEVELOPER +struct node_id; + enum dev_disconnect { /* Do nothing. */ DEV_DISCONNECT_NORMAL = '=', - /* Close connection before sending packet (and fail write). */ + /* Close connection before sending packet. */ DEV_DISCONNECT_BEFORE = '-', /* Close connection after sending packet. */ DEV_DISCONNECT_AFTER = '+', - /* Close connection after dropping packet. */ - DEV_DISCONNECT_DROPPKT = '@', /* Swallow all writes from now on, and do no more reads. */ DEV_DISCONNECT_BLACKHOLE = '0', /* Don't use connection after sending packet, but don't close. */ @@ -20,7 +20,7 @@ enum dev_disconnect { }; /* Force a close fd before or after a certain packet type */ -enum dev_disconnect dev_disconnect(int pkt_type); +enum dev_disconnect dev_disconnect(const struct node_id *id, int pkt_type); /* Make next write on fd fail as if they'd disconnected. */ void dev_sabotage_fd(int fd, bool close_fd); @@ -31,8 +31,6 @@ void dev_blackhole_fd(int fd); /* For debug code to set in daemon. */ void dev_disconnect_init(int fd); -/* Hack for channeld to do DEV_DISCONNECT_SUPPRESS_COMMIT. */ -extern bool dev_suppress_commit; #endif /* DEVELOPER */ #endif /* LIGHTNING_COMMON_DEV_DISCONNECT_H */ diff --git a/common/gossip_store.c b/common/gossip_store.c index bc66cf110811..9056dee01158 100644 --- a/common/gossip_store.c +++ b/common/gossip_store.c @@ -11,40 +11,8 @@ #include #include -void gossip_setup_timestamp_filter(struct per_peer_state *pps, - u32 first_timestamp, - u32 timestamp_range) -{ - /* If this is the first filter, we gossip sync immediately. */ - if (!pps->gs) { - pps->gs = tal(pps, struct gossip_state); - pps->gs->next_gossip = time_mono(); - } - - pps->gs->timestamp_min = first_timestamp; - pps->gs->timestamp_max = first_timestamp + timestamp_range - 1; - /* Make sure we never leave it on an impossible value. */ - if (pps->gs->timestamp_max < pps->gs->timestamp_min) - pps->gs->timestamp_max = UINT32_MAX; - - /* BOLT #7: - * - * The receiver: - * - SHOULD send all gossip messages whose `timestamp` is greater or - * equal to `first_timestamp`, and less than `first_timestamp` plus - * `timestamp_range`. - * - MAY wait for the next outgoing gossip flush to send these. - * ... - * - SHOULD restrict future gossip messages to those whose `timestamp` - * is greater or equal to `first_timestamp`, and less than - * `first_timestamp` plus `timestamp_range`. - */ - - /* Restart just after header. */ - lseek(pps->gossip_store_fd, 1, SEEK_SET); -} - -static bool timestamp_filter(const struct per_peer_state *pps, u32 timestamp) +static bool timestamp_filter(u32 timestamp_min, u32 timestamp_max, + u32 timestamp) { /* BOLT #7: * @@ -53,26 +21,11 @@ static bool timestamp_filter(const struct per_peer_state *pps, u32 timestamp) * `timestamp_range`. */ /* Note that we turn first_timestamp & timestamp_range into an inclusive range */ - return timestamp >= pps->gs->timestamp_min - && timestamp <= pps->gs->timestamp_max; + return timestamp >= timestamp_min + && timestamp <= timestamp_max; } -/* Not all the data we expected was there: rewind file */ -static void failed_read(int fd, int len) -{ - if (len < 0) { - /* Grab errno before lseek overrides it */ - const char *err = strerror(errno); - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "gossip_store: failed read @%"PRIu64": %s", - (u64)lseek(fd, 0, SEEK_CUR), err); - } - - lseek(fd, -len, SEEK_CUR); -} - -static void reopen_gossip_store(struct per_peer_state *pps, - const u8 *msg) +static size_t reopen_gossip_store(int *gossip_store_fd, const u8 *msg) { u64 equivalent_offset; int newfd; @@ -91,83 +44,96 @@ static void reopen_gossip_store(struct per_peer_state *pps, status_debug("gossip_store at end, new fd moved to %"PRIu64, equivalent_offset); - lseek(newfd, equivalent_offset, SEEK_SET); - close(pps->gossip_store_fd); - pps->gossip_store_fd = newfd; + close(*gossip_store_fd); + *gossip_store_fd = newfd; + return equivalent_offset; } -u8 *gossip_store_next(const tal_t *ctx, struct per_peer_state *pps) +u8 *gossip_store_next(const tal_t *ctx, + int *gossip_store_fd, + u32 timestamp_min, u32 timestamp_max, + size_t *off, size_t *end) { u8 *msg = NULL; - /* Don't read until we're initialized. */ - if (!pps->gs) - return NULL; - while (!msg) { struct gossip_hdr hdr; u32 msglen, checksum, timestamp; bool push; int type, r; - r = read(pps->gossip_store_fd, &hdr, sizeof(hdr)); - if (r != sizeof(hdr)) { - /* We expect a 0 read here at EOF */ - if (r != 0) - failed_read(pps->gossip_store_fd, r); - per_peer_state_reset_gossip_timer(pps); + r = pread(*gossip_store_fd, &hdr, sizeof(hdr), *off); + if (r != sizeof(hdr)) return NULL; - } + + msglen = be32_to_cpu(hdr.len); + push = (msglen & GOSSIP_STORE_LEN_PUSH_BIT); + msglen &= GOSSIP_STORE_LEN_MASK; /* Skip any deleted entries. */ if (be32_to_cpu(hdr.len) & GOSSIP_STORE_LEN_DELETED_BIT) { - /* Skip over it. */ - lseek(pps->gossip_store_fd, - be32_to_cpu(hdr.len) & GOSSIP_STORE_LEN_MASK, - SEEK_CUR); + *off += r + msglen; continue; } - msglen = be32_to_cpu(hdr.len); - push = (msglen & GOSSIP_STORE_LEN_PUSH_BIT); - msglen &= GOSSIP_STORE_LEN_MASK; - checksum = be32_to_cpu(hdr.crc); timestamp = be32_to_cpu(hdr.timestamp); msg = tal_arr(ctx, u8, msglen); - r = read(pps->gossip_store_fd, msg, msglen); - if (r != msglen) { - failed_read(pps->gossip_store_fd, r); - per_peer_state_reset_gossip_timer(pps); + r = pread(*gossip_store_fd, msg, msglen, *off + r); + if (r != msglen) return NULL; - } if (checksum != crc32c(be32_to_cpu(hdr.timestamp), msg, msglen)) status_failed(STATUS_FAIL_INTERNAL_ERROR, - "gossip_store: bad checksum offset %" - PRIi64": %s", - (s64)lseek(pps->gossip_store_fd, - 0, SEEK_CUR) - msglen, - tal_hex(tmpctx, msg)); - - /* Don't send back gossip they sent to us! */ - if (gossip_rcvd_filter_del(pps->grf, msg)) { - msg = tal_free(msg); - continue; - } + "gossip_store: bad checksum offset %zu" + ": %s", + *off, tal_hex(tmpctx, msg)); + + /* Definitely processing it now */ + *off += sizeof(hdr) + msglen; + if (*off > *end) + *end = *off; type = fromwire_peektype(msg); - if (type == WIRE_GOSSIP_STORE_ENDED) - reopen_gossip_store(pps, msg); + /* end can go backwards in this case! */ + if (type == WIRE_GOSSIP_STORE_ENDED) { + *off = *end = reopen_gossip_store(gossip_store_fd, msg); /* Ignore gossipd internal messages. */ - else if (type != WIRE_CHANNEL_ANNOUNCEMENT - && type != WIRE_CHANNEL_UPDATE - && type != WIRE_NODE_ANNOUNCEMENT) + } else if (type != WIRE_CHANNEL_ANNOUNCEMENT + && type != WIRE_CHANNEL_UPDATE + && type != WIRE_NODE_ANNOUNCEMENT) { msg = tal_free(msg); - else if (!push && !timestamp_filter(pps, timestamp)) + } else if (!push && + !timestamp_filter(timestamp_min, timestamp_max, + timestamp)) { msg = tal_free(msg); + } } return msg; } + +size_t find_gossip_store_end(int gossip_store_fd, size_t off) +{ + /* We cheat and read first two bytes of message too. */ + struct { + struct gossip_hdr hdr; + be16 type; + } buf; + int r; + + while ((r = read(gossip_store_fd, &buf, + sizeof(buf.hdr) + sizeof(buf.type))) + == sizeof(buf.hdr) + sizeof(buf.type)) { + u32 msglen = be32_to_cpu(buf.hdr.len) & GOSSIP_STORE_LEN_MASK; + + /* Don't swallow end marker! */ + if (buf.type == CPU_TO_BE16(WIRE_GOSSIP_STORE_ENDED)) + break; + + off += sizeof(buf.hdr) + msglen; + lseek(gossip_store_fd, off, SEEK_SET); + } + return off; +} diff --git a/common/gossip_store.h b/common/gossip_store.h index b23e99f43cf6..b5d8fad1905d 100644 --- a/common/gossip_store.h +++ b/common/gossip_store.h @@ -5,7 +5,8 @@ #include #include -struct per_peer_state; +struct gossip_state; +struct gossip_rcvd_filter; /** * gossip_store -- On-disk storage related information @@ -38,15 +39,20 @@ struct gossip_hdr { /** * Direct store accessor: loads gossip msg from store. * - * Returns NULL and resets time_to_next_gossip(pps) if there are no - * more gossip msgs. + * Returns NULL if there are no more gossip msgs. + * Updates *end if the known end of file has moved. + * Updates *gossip_store_fd if file has been compacted. */ -u8 *gossip_store_next(const tal_t *ctx, struct per_peer_state *pps); +u8 *gossip_store_next(const tal_t *ctx, + int *gossip_store_fd, + u32 timestamp_min, u32 timestamp_max, + size_t *off, size_t *end); /** - * Sets up the tiemstamp filter once they told us to set it.( + * Gossipd will be writing to this, and it's not atomic! Safest + * way to find the "end" is to walk through. + * @old_end: 1 if no previous end. */ -void gossip_setup_timestamp_filter(struct per_peer_state *pps, - u32 first_timestamp, - u32 timestamp_range); +size_t find_gossip_store_end(int gossip_store_fd, size_t old_end); + #endif /* LIGHTNING_COMMON_GOSSIP_STORE_H */ diff --git a/common/peer_failed.c b/common/peer_failed.c index 97ec96cfab31..c9c18d84dbe7 100644 --- a/common/peer_failed.c +++ b/common/peer_failed.c @@ -2,9 +2,9 @@ #include #include #include -#include #include #include +#include #include #include #include @@ -19,8 +19,6 @@ peer_fatal_continue(const u8 *msg TAKES, const struct per_peer_state *pps) status_send(msg); status_send_fd(pps->peer_fd); - status_send_fd(pps->gossip_fd); - status_send_fd(pps->gossip_store_fd); exit(0x80 | (reason & 0xFF)); } @@ -38,13 +36,12 @@ peer_failed(struct per_peer_state *pps, } else { msg = towire_errorfmt(desc, channel_id, "%s", desc); } - sync_crypto_write(pps, msg); + peer_write(pps, msg); /* Tell master the error so it can re-xmit. */ msg = towire_status_peer_error(NULL, channel_id, desc, warn, - pps, msg); peer_billboard(true, desc); peer_fatal_continue(take(msg), pps); @@ -87,7 +84,7 @@ void peer_failed_received_errmsg(struct per_peer_state *pps, { u8 *msg; - msg = towire_status_peer_error(NULL, channel_id, desc, warning, pps, + msg = towire_status_peer_error(NULL, channel_id, desc, warning, NULL); peer_billboard(true, "Received %s", desc); peer_fatal_continue(take(msg), pps); diff --git a/common/peer_io.c b/common/peer_io.c new file mode 100644 index 000000000000..587a14901ba4 --- /dev/null +++ b/common/peer_io.c @@ -0,0 +1,34 @@ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void peer_write(struct per_peer_state *pps, const void *msg TAKES) +{ + status_peer_io(LOG_IO_OUT, NULL, msg); + + if (!wire_sync_write(pps->peer_fd, msg)) + peer_failed_connection_lost(); +} + +u8 *peer_read(const tal_t *ctx, struct per_peer_state *pps) +{ + u8 *dec = wire_sync_read(ctx, pps->peer_fd); + if (!dec) + peer_failed_connection_lost(); + + status_peer_io(LOG_IO_IN, NULL, dec); + + return dec; +} diff --git a/common/peer_io.h b/common/peer_io.h new file mode 100644 index 000000000000..621e71db35af --- /dev/null +++ b/common/peer_io.h @@ -0,0 +1,15 @@ +#ifndef LIGHTNING_COMMON_PEER_IO_H +#define LIGHTNING_COMMON_PEER_IO_H +#include "config.h" +#include +#include + +struct per_peer_state; + +/* Exits with peer_failed_connection_lost() if write fails. */ +void peer_write(struct per_peer_state *pps, const void *msg TAKES); + +/* Exits with peer_failed_connection_lost() if can't read packet. */ +u8 *peer_read(const tal_t *ctx, struct per_peer_state *pps); + +#endif /* LIGHTNING_COMMON_PEER_IO_H */ diff --git a/common/peer_status_wire.csv b/common/peer_status_wire.csv index 8162443e2ffb..1fedb7ccc678 100644 --- a/common/peer_status_wire.csv +++ b/common/peer_status_wire.csv @@ -8,6 +8,5 @@ msgdata,status_peer_error,channel,channel_id, msgdata,status_peer_error,desc,wirestring, # Take a deep breath, then try reconnecting to the precious little snowflake. msgdata,status_peer_error,warning,bool, -msgdata,status_peer_error,pps,per_peer_state, msgdata,status_peer_error,len,u16, msgdata,status_peer_error,error_for_them,u8,len diff --git a/common/per_peer_state.c b/common/per_peer_state.c index 18b2472ff173..981e06c07126 100644 --- a/common/per_peer_state.c +++ b/common/per_peer_state.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -13,128 +12,25 @@ static void destroy_per_peer_state(struct per_peer_state *pps) { if (pps->peer_fd != -1) close(pps->peer_fd); - if (pps->gossip_fd != -1) - close(pps->gossip_fd); - if (pps->gossip_store_fd != -1) - close(pps->gossip_store_fd); } -struct per_peer_state *new_per_peer_state(const tal_t *ctx, - const struct crypto_state *cs) +struct per_peer_state *new_per_peer_state(const tal_t *ctx) { struct per_peer_state *pps = tal(ctx, struct per_peer_state); - pps->cs = *cs; - pps->gs = NULL; - pps->peer_fd = pps->gossip_fd = pps->gossip_store_fd = -1; - pps->grf = new_gossip_rcvd_filter(pps); + pps->peer_fd = -1; tal_add_destructor(pps, destroy_per_peer_state); return pps; } -void per_peer_state_set_fds(struct per_peer_state *pps, - int peer_fd, int gossip_fd, int gossip_store_fd) +void per_peer_state_set_fd(struct per_peer_state *pps, int peer_fd) { assert(pps->peer_fd == -1); - assert(pps->gossip_fd == -1); - assert(pps->gossip_store_fd == -1); pps->peer_fd = peer_fd; - pps->gossip_fd = gossip_fd; - pps->gossip_store_fd = gossip_store_fd; -} - -void per_peer_state_set_fds_arr(struct per_peer_state *pps, const int *fds) -{ - /* We expect 3 fds. */ - assert(tal_count(fds) == 3); - per_peer_state_set_fds(pps, fds[0], fds[1], fds[2]); -} - -void towire_gossip_state(u8 **pptr, const struct gossip_state *gs) -{ - towire_u64(pptr, gs->next_gossip.ts.tv_sec); - towire_u64(pptr, gs->next_gossip.ts.tv_nsec); - towire_u32(pptr, gs->timestamp_min); - towire_u32(pptr, gs->timestamp_max); -} - -void fromwire_gossip_state(const u8 **cursor, size_t *max, - struct gossip_state *gs) -{ - gs->next_gossip.ts.tv_sec = fromwire_u64(cursor, max); - gs->next_gossip.ts.tv_nsec = fromwire_u64(cursor, max); - gs->timestamp_min = fromwire_u32(cursor, max); - gs->timestamp_max = fromwire_u32(cursor, max); -} - -void towire_per_peer_state(u8 **pptr, const struct per_peer_state *pps) -{ - towire_crypto_state(pptr, &pps->cs); - towire_bool(pptr, pps->gs != NULL); - if (pps->gs) - towire_gossip_state(pptr, pps->gs); - /* We don't pass the gossip_rcvd_filter: it's merely an optimization */ } void per_peer_state_fdpass_send(int fd, const struct per_peer_state *pps) { assert(pps->peer_fd != -1); - assert(pps->gossip_fd != -1); - assert(pps->gossip_store_fd != -1); fdpass_send(fd, pps->peer_fd); - fdpass_send(fd, pps->gossip_fd); - fdpass_send(fd, pps->gossip_store_fd); -} - -struct per_peer_state *fromwire_per_peer_state(const tal_t *ctx, - const u8 **cursor, size_t *max) -{ - struct crypto_state cs; - struct per_peer_state *pps; - - fromwire_crypto_state(cursor, max, &cs); - pps = new_per_peer_state(ctx, &cs); - if (fromwire_bool(cursor, max)) { - pps->gs = tal(pps, struct gossip_state); - fromwire_gossip_state(cursor, max, pps->gs); - } - return pps; -} - -/* FIXME: Put in ccan/time */ -/* Is a after b? */ -static inline bool timemono_after(struct timemono a, struct timemono b) -{ - return time_greater_(a.ts, b.ts); -} - -bool time_to_next_gossip(const struct per_peer_state *pps, - struct timerel *t) -{ - if (!pps->gs) - return false; - - struct timemono now = time_mono(); - if (timemono_after(now, pps->gs->next_gossip)) - *t = time_from_sec(0); - else - *t = timemono_between(pps->gs->next_gossip, now); - return true; -} - -/* BOLT #7: - * - * A node: - *... - * - SHOULD flush outgoing gossip messages once every 60 seconds, - * independently of the arrival times of the messages. - * - Note: this results in staggered announcements that are unique - * (not duplicated). - */ -void per_peer_state_reset_gossip_timer(struct per_peer_state *pps) -{ - struct timerel t = time_from_sec(GOSSIP_FLUSH_INTERVAL(dev_fast_gossip)); - - pps->gs->next_gossip = timemono_add(time_mono(), t); - gossip_rcvd_filter_age(pps->grf); } diff --git a/common/per_peer_state.h b/common/per_peer_state.h index 45bd1f172a82..0561d8ce2870 100644 --- a/common/per_peer_state.h +++ b/common/per_peer_state.h @@ -6,58 +6,19 @@ #include #include -struct gossip_state { - /* Time for next gossip burst. */ - struct timemono next_gossip; - /* Timestamp filtering for gossip. */ - u32 timestamp_min, timestamp_max; -}; - /* Things we hand between daemons to talk to peers. */ struct per_peer_state { - /* Cryptographic state needed to exchange messages with the peer (as - * featured in BOLT #8) */ - struct crypto_state cs; - /* NULL if it's not initialized yet */ - struct gossip_state *gs; - /* Cache of msgs we have received, to avoid re-xmitting from store */ - struct gossip_rcvd_filter *grf; /* If not -1, closed on freeing */ - int peer_fd, gossip_fd, gossip_store_fd; + int peer_fd; }; /* Allocate a new per-peer state and add destructor to close fds if set; - * sets fds to -1 and ->gs to NULL.. */ -struct per_peer_state *new_per_peer_state(const tal_t *ctx, - const struct crypto_state *cs); + * sets peer_fd to -1. */ +struct per_peer_state *new_per_peer_state(const tal_t *ctx); /* Initialize the fds (must be -1 previous) */ -void per_peer_state_set_fds(struct per_peer_state *pps, - int peer_fd, int gossip_fd, int gossip_store_fd); +void per_peer_state_set_fd(struct per_peer_state *pps, int peer_fd); -/* Array version of above: tal_count(fds) must be 3 */ -void per_peer_state_set_fds_arr(struct per_peer_state *pps, const int *fds); - -/* These routines do *part* of the work: you need to per_peer_state_fdpass_send - * or receive the three fds afterwards! */ -void towire_per_peer_state(u8 **pptr, const struct per_peer_state *pps); void per_peer_state_fdpass_send(int fd, const struct per_peer_state *pps); -struct per_peer_state *fromwire_per_peer_state(const tal_t *ctx, - const u8 **cursor, size_t *max); - -void towire_gossip_state(u8 **pptr, const struct gossip_state *gs); -void fromwire_gossip_state(const u8 **cursor, size_t *max, - struct gossip_state *gs); - -/* How long until we have to check gossip store, if any? */ -bool time_to_next_gossip(const struct per_peer_state *pps, - struct timerel *t); - -/* Reset pps->next_gossip now we've drained gossip_store */ -void per_peer_state_reset_gossip_timer(struct per_peer_state *pps); - -/* Used to speed up gossip iff DEVELOPER*/ -extern bool dev_fast_gossip; - #endif /* LIGHTNING_COMMON_PER_PEER_STATE_H */ diff --git a/common/read_peer_msg.c b/common/read_peer_msg.c index 7fc4b0f05f5b..bda5ae73f455 100644 --- a/common/read_peer_msg.c +++ b/common/read_peer_msg.c @@ -1,10 +1,8 @@ #include "config.h" #include #include -#include -#include -#include #include +#include #include #include #include @@ -14,55 +12,6 @@ #include #include -u8 *peer_or_gossip_sync_read(const tal_t *ctx, - struct per_peer_state *pps, - bool *from_gossipd) -{ - fd_set readfds; - u8 *msg; - - for (;;) { - struct timeval tv, *tptr; - struct timerel trel; - - if (time_to_next_gossip(pps, &trel)) { - tv = timerel_to_timeval(trel); - tptr = &tv; - } else - tptr = NULL; - - FD_ZERO(&readfds); - FD_SET(pps->peer_fd, &readfds); - FD_SET(pps->gossip_fd, &readfds); - - if (select(pps->peer_fd > pps->gossip_fd - ? pps->peer_fd + 1 : pps->gossip_fd + 1, - &readfds, NULL, NULL, tptr) != 0) - break; - - /* We timed out; look in gossip_store. Failure resets timer. */ - msg = gossip_store_next(tmpctx, pps); - if (msg) { - *from_gossipd = true; - return msg; - } - } - - if (FD_ISSET(pps->peer_fd, &readfds)) { - msg = sync_crypto_read(ctx, pps); - *from_gossipd = false; - return msg; - } - - msg = wire_sync_read(ctx, pps->gossip_fd); - if (!msg) - status_failed(STATUS_FAIL_GOSSIP_IO, - "Error reading gossip msg: %s", - strerror(errno)); - *from_gossipd = true; - return msg; -} - bool is_peer_error(const tal_t *ctx, const u8 *msg, const struct channel_id *channel_id, char **desc, bool *warning) @@ -103,106 +52,36 @@ bool is_peer_error(const tal_t *ctx, const u8 *msg, bool is_wrong_channel(const u8 *msg, const struct channel_id *expected, struct channel_id *actual) { - if (!extract_channel_id(msg, actual)) + if (!expected) return false; - return !channel_id_eq(expected, actual); -} - -void handle_gossip_msg(struct per_peer_state *pps, const u8 *msg TAKES) -{ - u8 *gossip; - - /* It's a raw gossip msg: this copies or takes() */ - gossip = tal_dup_talarr(tmpctx, u8, msg); - - /* Gossipd can send us gossip messages, OR warnings */ - if (fromwire_peektype(gossip) == WIRE_WARNING) { - sync_crypto_write(pps, gossip); - peer_failed_connection_lost(); - } else { - sync_crypto_write(pps, gossip); - } -} - -/* takes iff returns true */ -bool handle_timestamp_filter(struct per_peer_state *pps, const u8 *msg TAKES) -{ - struct bitcoin_blkid chain_hash; - u32 first_timestamp, timestamp_range; - - if (!fromwire_gossip_timestamp_filter(msg, &chain_hash, - &first_timestamp, - ×tamp_range)) { + if (!extract_channel_id(msg, actual)) return false; - } - if (!bitcoin_blkid_eq(&chainparams->genesis_blockhash, &chain_hash)) { - sync_crypto_write(pps, - take(towire_warningfmt(NULL, NULL, - "gossip_timestamp_filter" - " for bad chain: %s", - tal_hex(tmpctx, take(msg))))); - return true; - } - - gossip_setup_timestamp_filter(pps, first_timestamp, timestamp_range); - return true; + return !channel_id_eq(expected, actual); } -bool handle_peer_gossip_or_error(struct per_peer_state *pps, - const struct channel_id *channel_id, - bool soft_error, - const u8 *msg TAKES) +bool handle_peer_error(struct per_peer_state *pps, + const struct channel_id *channel_id, + bool soft_error, + const u8 *msg TAKES) { char *err; bool warning; - u8 *pong; - -#if DEVELOPER - /* Any odd-typed unknown message is handled by the caller, so if we - * find one here it's an error. */ - assert(!is_unknown_msg_discardable(msg)); -#else - /* BOLT #1: - * - * A receiving node: - * - upon receiving a message of _odd_, unknown type: - * - MUST ignore the received message. - */ - if (is_unknown_msg_discardable(msg)) - goto handled; -#endif - - if (handle_timestamp_filter(pps, msg)) - return true; - else if (check_ping_make_pong(NULL, msg, &pong)) { - if (pong) - sync_crypto_write(pps, take(pong)); - return true; - } else if (is_msg_for_gossipd(msg)) { - gossip_rcvd_filter_add(pps->grf, msg); - wire_sync_write(pps->gossip_fd, msg); - /* wire_sync_write takes, so don't take again. */ - return true; - } if (is_peer_error(tmpctx, msg, channel_id, &err, &warning)) { /* Ignore unknown channel errors. */ - if (!err) - goto handled; + if (!err) { + if (taken(msg)) + tal_free(msg); + return true; + } /* We hang up when a warning is received. */ peer_failed_received_errmsg(pps, err, channel_id, soft_error || warning); - goto handled; } return false; - -handled: - if (taken(msg)) - tal_free(msg); - return true; } diff --git a/common/read_peer_msg.h b/common/read_peer_msg.h index fbdff761a759..7a4052a0e90e 100644 --- a/common/read_peer_msg.h +++ b/common/read_peer_msg.h @@ -8,25 +8,6 @@ struct crypto_state; struct channel_id; struct per_peer_state; -/** - * peer_or_gossip_sync_read - read a peer message, or maybe a gossip msg. - * @ctx: context to allocate return packet from. - * @pps: the per-peer peer state and fds - * @from_gossipd: true if the msg was from gossipd, otherwise false. - * - * Will call peer_failed_connection_lost() or - * status_failed(STATUS_FAIL_GOSSIP_IO) or return a message. - * - * Usually, you should call handle_gossip_msg if *@from_gossipd is - * true, otherwise if is_peer_error() handle the error, otherwise if - * is_msg_for_gossipd() then send to gossipd, otherwise if is - * is_wrong_channel() send that as a reply. Otherwise it should be - * a valid message. - */ -u8 *peer_or_gossip_sync_read(const tal_t *ctx, - struct per_peer_state *pps, - bool *from_gossipd); - /** * is_peer_error - if it's an error, describe if it applies to this channel. * @ctx: context to allocate return from. @@ -55,28 +36,17 @@ bool is_wrong_channel(const u8 *msg, const struct channel_id *expected, /** - * handle_peer_gossip_or_error - simple handler for all the above cases. + * handle_peer_error - simple handler for errors * @pps: per-peer state. * @channel_id: the channel id of the current channel. * @soft_error: tell lightningd that incoming error is non-fatal. * @msg: the peer message (only taken if returns true). * - * This returns true if it handled the packet: a gossip packet (forwarded - * to gossipd), or an error packet (causes peer_failed_received_errmsg or - * ignored), or a ping (may reply with pong). - */ -bool handle_peer_gossip_or_error(struct per_peer_state *pps, - const struct channel_id *channel_id, - bool soft_error, - const u8 *msg TAKES); - -/** - * handle_timestamp_filter - deal with timestamp filter requests. - * @pps: per-peer state. - * @msg: the peer message (only taken if returns true). + * This returns true if it handled the packet. */ -bool handle_timestamp_filter(struct per_peer_state *pps, const u8 *msg TAKES); +bool handle_peer_error(struct per_peer_state *pps, + const struct channel_id *channel_id, + bool soft_error, + const u8 *msg TAKES); -/* We got this message from gossipd: forward/quit as it asks. */ -void handle_gossip_msg(struct per_peer_state *pps, const u8 *msg TAKES); #endif /* LIGHTNING_COMMON_READ_PEER_MSG_H */ diff --git a/common/socket_close.c b/common/socket_close.c index 3c192e47e38d..7d19ec76814b 100644 --- a/common/socket_close.c +++ b/common/socket_close.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include #include @@ -18,9 +20,15 @@ Simplified (minus all the error checks): close(fd); */ +/* makes read() return EINTR */ +static void break_read(int signum) +{ +} + bool socket_close(int fd) { char unused[64]; + struct sigaction act, old_act; int sys_res; sys_res = shutdown(fd, SHUT_WR); @@ -29,20 +37,22 @@ bool socket_close(int fd) return false; } - for (;;) { - do { - sys_res = read(fd, unused, sizeof(unused)); - } while (sys_res < 0 && errno == EINTR); - if (sys_res < 0) { - close_noerr(fd); - return false; - } - if (sys_res == 0) - break; - } + /* Let's not get too enthusiastic about waiting. */ + memset(&act, 0, sizeof(act)); + act.sa_handler = break_read; + sigaction(SIGALRM, &act, &old_act); - if (close(fd) < 0) + alarm(5); + + while ((sys_res = read(fd, unused, sizeof(unused))) > 0); + + alarm(0); + sigaction(SIGALRM, &old_act, NULL); + + if (sys_res < 0) { + close_noerr(fd); return false; - else - return true; + } + + return close(fd) == 0; } diff --git a/common/subdaemon.c b/common/subdaemon.c index 6ed2e443815a..523a4e3ac3b1 100644 --- a/common/subdaemon.c +++ b/common/subdaemon.c @@ -1,5 +1,4 @@ #include "config.h" -#include #include #include #include @@ -33,14 +32,5 @@ void subdaemon_setup(int argc, char *argv[]) daemon_maybe_debug(argv); -#if DEVELOPER - for (int i = 1; i < argc; i++) { - if (strstarts(argv[i], "--dev-disconnect=")) { - dev_disconnect_init(atoi(argv[i] - + strlen("--dev-disconnect="))); - } - } -#endif - daemon_setup(argv[0], status_backtrace_print, status_backtrace_exit); } diff --git a/common/test/run-blindedpath_enctlv.c b/common/test/run-blindedpath_enctlv.c index a1d32e5a3af3..9c619b7b3fd9 100644 --- a/common/test/run-blindedpath_enctlv.c +++ b/common/test/run-blindedpath_enctlv.c @@ -50,7 +50,7 @@ struct amount_msat fromwire_amount_msat(const u8 **cursor UNNEEDED, size_t *max struct amount_sat fromwire_amount_sat(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_amount_sat called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for fromwire_node_id */ diff --git a/common/test/run-blindedpath_onion.c b/common/test/run-blindedpath_onion.c index 191e157af697..4b51804ea175 100644 --- a/common/test/run-blindedpath_onion.c +++ b/common/test/run-blindedpath_onion.c @@ -56,7 +56,7 @@ struct amount_msat fromwire_amount_msat(const u8 **cursor UNNEEDED, size_t *max struct amount_sat fromwire_amount_sat(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_amount_sat called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for fromwire_node_id */ diff --git a/common/test/run-bolt12_merkle-json.c b/common/test/run-bolt12_merkle-json.c index eb62379cbc7c..ebdd325d5886 100644 --- a/common/test/run-bolt12_merkle-json.c +++ b/common/test/run-bolt12_merkle-json.c @@ -19,7 +19,7 @@ /* AUTOGENERATED MOCKS START */ /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for fromwire_node_id */ diff --git a/common/test/run-bolt12_merkle.c b/common/test/run-bolt12_merkle.c index 1610e3ea8737..83abb27d133a 100644 --- a/common/test/run-bolt12_merkle.c +++ b/common/test/run-bolt12_merkle.c @@ -22,7 +22,7 @@ int features_unsupported(const struct feature_set *our_features UNNEEDED, enum feature_place p UNNEEDED) { fprintf(stderr, "features_unsupported called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for fromwire_onionmsg_path */ diff --git a/common/test/run-gossmap_local.c b/common/test/run-gossmap_local.c index 605c2cb8d54b..1d8d19cc9cf0 100644 --- a/common/test/run-gossmap_local.c +++ b/common/test/run-gossmap_local.c @@ -16,7 +16,7 @@ bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_bigsize called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for towire_bigsize */ diff --git a/common/test/run-route-specific.c b/common/test/run-route-specific.c index e58ef4689afc..a591f16cd5bb 100644 --- a/common/test/run-route-specific.c +++ b/common/test/run-route-specific.c @@ -25,7 +25,7 @@ bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_bigsize called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for fromwire_tlv */ diff --git a/common/test/run-route.c b/common/test/run-route.c index e1fac36ebfe4..ad6fadc8e60e 100644 --- a/common/test/run-route.c +++ b/common/test/run-route.c @@ -18,7 +18,7 @@ bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_bigsize called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for fromwire_tlv */ diff --git a/common/test/run-route_blinding_override_test.c b/common/test/run-route_blinding_override_test.c index 5025c8ff7d2f..b8e2552cb5f2 100644 --- a/common/test/run-route_blinding_override_test.c +++ b/common/test/run-route_blinding_override_test.c @@ -63,7 +63,7 @@ struct amount_msat fromwire_amount_msat(const u8 **cursor UNNEEDED, size_t *max struct amount_sat fromwire_amount_sat(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_amount_sat called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for fromwire_node_id */ diff --git a/common/test/run-route_blinding_test.c b/common/test/run-route_blinding_test.c index d9f141839536..22076d9568b7 100644 --- a/common/test/run-route_blinding_test.c +++ b/common/test/run-route_blinding_test.c @@ -63,7 +63,7 @@ struct amount_msat fromwire_amount_msat(const u8 **cursor UNNEEDED, size_t *max struct amount_sat fromwire_amount_sat(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_amount_sat called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for fromwire_node_id */ diff --git a/common/timeout.c b/common/timeout.c index d4b4b480f1bf..475733e02a45 100644 --- a/common/timeout.c +++ b/common/timeout.c @@ -31,7 +31,24 @@ struct oneshot *new_reltimer_(struct timers *timers, return t; } -void *reltimer_arg(struct oneshot *t) +struct oneshot *new_abstimer_(struct timers *timers, + const tal_t *ctx, + struct timemono expiry, + void (*cb)(void *), void *arg) +{ + struct oneshot *t = tal(ctx, struct oneshot); + + t->cb = cb; + t->arg = arg; + t->timers = timers; + timer_init(&t->timer); + timer_addmono(timers, &t->timer, expiry); + tal_add_destructor(t, destroy_timer); + + return t; +} + +void *oneshot_arg(struct oneshot *t) { return t->arg; } diff --git a/common/timeout.h b/common/timeout.h index 55b1a4b633ac..0277a072323a 100644 --- a/common/timeout.h +++ b/common/timeout.h @@ -15,8 +15,16 @@ struct oneshot *new_reltimer_(struct timers *timers, new_reltimer_((timers), (ctx), (relexpire), \ typesafe_cb(void, void *, (func), (arg)), (arg)) +struct oneshot *new_abstimer_(struct timers *timers, + const tal_t *ctx, + struct timemono expiry, + void (*cb)(void *), void *arg); +#define new_abstimer(timers, ctx, expiry, func, arg) \ + new_abstimer_((timers), (ctx), (expiry), \ + typesafe_cb(void, void *, (func), (arg)), (arg)) + /* Get timer arg. */ -void *reltimer_arg(struct oneshot *t); +void *oneshot_arg(struct oneshot *t); void timer_expired(struct timer *timer); diff --git a/connectd/Makefile b/connectd/Makefile index 76cb7079f7ce..8b1ea8907606 100644 --- a/connectd/Makefile +++ b/connectd/Makefile @@ -5,7 +5,9 @@ CONNECTD_HEADERS := connectd/connectd_wiregen.h \ connectd/connectd.h \ connectd/peer_exchange_initmsg.h \ connectd/handshake.h \ + connectd/multiplex.h \ connectd/netaddress.h \ + connectd/onion_message.h \ connectd/tor_autoservice.h \ connectd/tor.h @@ -40,8 +42,9 @@ CONNECTD_COMMON_OBJS := \ common/bech32_util.o \ common/bigsize.o \ common/bip32.o \ + common/blinding.o \ + common/blindedpath.o \ common/channel_id.o \ - common/crypto_state.o \ common/cryptomsg.o \ common/daemon.o \ common/daemon_conn.o \ @@ -49,17 +52,22 @@ CONNECTD_COMMON_OBJS := \ common/dev_disconnect.o \ common/ecdh_hsmd.o \ common/features.o \ + common/hmac.o \ common/status_wiregen.o \ + common/gossip_store.o \ common/gossip_rcvd_filter.o \ common/key_derive.o \ common/memleak.o \ common/msg_queue.o \ common/node_id.o \ + common/onion.o \ common/onionreply.o \ + common/ping.o \ common/per_peer_state.o \ common/psbt_open.o \ common/pseudorand.o \ common/setup.o \ + common/sphinx.o \ common/status.o \ common/status_wire.o \ common/subdaemon.o \ @@ -71,6 +79,7 @@ CONNECTD_COMMON_OBJS := \ common/wireaddr.o \ common/wire_error.o \ gossipd/gossipd_wiregen.o \ + gossipd/gossip_store_wiregen.o \ wire/onion$(EXP)_wiregen.o lightningd/lightning_connectd: $(CONNECTD_OBJS) $(CONNECTD_COMMON_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(HSMD_CLIENT_OBJS) diff --git a/connectd/connectd.c b/connectd/connectd.c index e855552f9c74..fc52d4733b72 100644 --- a/connectd/connectd.c +++ b/connectd/connectd.c @@ -10,18 +10,18 @@ #include "config.h" #include #include -#include #include -#include #include #include #include #include #include +#include #include +#include +#include #include #include -#include #include #include #include @@ -31,7 +31,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -59,89 +61,6 @@ #define INITIAL_WAIT_SECONDS 1 #define MAX_WAIT_SECONDS 300 -/*~ We keep a hash table (ccan/htable) of public keys, which tells us what - * peers are already connected. The HTABLE_DEFINE_TYPE() macro needs a - * keyof() function to extract the key. For this simple use case, that's the - * identity function: */ -static const struct node_id *node_id_keyof(const struct node_id *pc) -{ - return pc; -} - -/*~ We also need to define a hashing function. siphash24 is a fast yet - * cryptographic hash in ccan/crypto/siphash24; we might be able to get away - * with a slightly faster hash with fewer guarantees, but it's good hygiene to - * use this unless it's a proven bottleneck. siphash_seed() is a function in - * common/pseudorand which sets up a seed for our hashing; it's different - * every time the program is run. */ -static size_t node_id_hash(const struct node_id *id) -{ - return siphash24(siphash_seed(), id->k, sizeof(id->k)); -} - -/*~ This defines 'struct node_set' which contains 'struct node_id' pointers. */ -HTABLE_DEFINE_TYPE(struct node_id, - node_id_keyof, - node_id_hash, - node_id_eq, - node_set); - -/*~ This is the global state, like `struct lightningd *ld` in lightningd. */ -struct daemon { - /* Who am I? */ - struct node_id id; - - /* pubkey equivalent. */ - struct pubkey mykey; - - /* Base for timeout timers, and how long to wait for init msg */ - struct timers timers; - u32 timeout_secs; - - /* Peers that we've handed to `lightningd`, which it hasn't told us - * have disconnected. */ - struct node_set peers; - - /* Peers we are trying to reach */ - struct list_head connecting; - - /* Connection to main daemon. */ - struct daemon_conn *master; - - /* Allow localhost to be considered "public": DEVELOPER-only option, - * but for simplicity we don't #if DEVELOPER-wrap it here. */ - bool dev_allow_localhost; - - /* We support use of a SOCKS5 proxy (e.g. Tor) */ - struct addrinfo *proxyaddr; - - /* They can tell us we must use proxy even for non-Tor addresses. */ - bool always_use_proxy; - - /* There are DNS seeds we can use to look up node addresses as a last - * resort, but doing so leaks our address so can be disabled. */ - bool use_dns; - - /* The address that the broken response returns instead of - * NXDOMAIN. NULL if we have not detected a broken resolver. */ - struct sockaddr *broken_resolver_response; - - /* File descriptors to listen on once we're activated. */ - struct listen_fd *listen_fds; - - /* Allow to define the default behavior of tor services calls*/ - bool use_v3_autotor; - - /* Our features, as lightningd told us */ - struct feature_set *our_features; - - /* Subdaemon to proxy websocket requests. */ - char *websocket_helper; - - /* If non-zero, port to listen for websocket connections. */ - u16 websocket_port; -}; - /* Peers we're trying to reach: we iterate through addrs until we succeed * or fail. */ struct connecting { @@ -290,66 +209,6 @@ static void peer_connected_in(struct daemon *daemon, tal_free(connect); } -/*~ Every per-peer daemon needs a connection to the gossip daemon; this allows - * it to forward gossip to/from the peer. The gossip daemon needs to know a - * few of the features of the peer and its id (for reporting). - * - * Every peer also has read-only access to the gossip_store, which is handed - * out by gossipd too, and also a "gossip_state" indicating where we're up to. - * - * 'features' is a field in the `init` message, indicating properties of the - * node. - */ -static bool get_gossipfds(struct daemon *daemon, - const struct node_id *id, - const u8 *their_features, - struct per_peer_state *pps) -{ - bool gossip_queries_feature, initial_routing_sync, success; - u8 *msg; - - /*~ The way features generally work is that both sides need to offer it; - * we always offer `gossip_queries`, but this check is explicit. */ - gossip_queries_feature - = feature_negotiated(daemon->our_features, their_features, - OPT_GOSSIP_QUERIES); - - /*~ `initial_routing_sync` is supported by every node, since it was in - * the initial lightning specification: it means the peer wants the - * backlog of existing gossip. */ - initial_routing_sync - = feature_offered(their_features, OPT_INITIAL_ROUTING_SYNC); - - /*~ We do this communication sync, since gossipd is our friend and - * it's easier. If gossipd fails, we fail. */ - msg = towire_gossipd_new_peer(NULL, id, gossip_queries_feature, - initial_routing_sync); - if (!wire_sync_write(GOSSIPCTL_FD, take(msg))) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Failed writing to gossipctl: %s", - strerror(errno)); - - msg = wire_sync_read(tmpctx, GOSSIPCTL_FD); - if (!fromwire_gossipd_new_peer_reply(pps, msg, &success, &pps->gs)) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Failed parsing msg gossipctl: %s", - tal_hex(tmpctx, msg)); - - /* Gossipd might run out of file descriptors, so it tells us, and we - * give up on connecting this peer. */ - if (!success) { - status_broken("Gossipd did not give us an fd: losing peer %s", - type_to_string(tmpctx, struct node_id, id)); - return false; - } - - /* Otherwise, the next thing in the socket will be the file descriptors - * for the per-peer daemon. */ - pps->gossip_fd = fdpass_recv(GOSSIPCTL_FD); - pps->gossip_store_fd = fdpass_recv(GOSSIPCTL_FD); - return true; -} - /*~ This is an ad-hoc marshalling structure where we store arguments so we * can call peer_connected again. */ struct peer_reconnected { @@ -414,7 +273,7 @@ static struct io_plan *peer_reconnected(struct io_conn *conn, /*~ ccan/io supports waiting on an address: in this case, the key in * the peer set. When someone calls `io_wake()` on that address, it * will call retry_peer_connected above. */ - return io_wait(conn, node_set_get(&daemon->peers, id), + return io_wait(conn, peer_htable_get(&daemon->peers, id), /*~ The notleak() wrapper is a DEVELOPER-mode hack so * that our memory leak detection doesn't consider 'pr' * (which is not referenced from our code) to be a @@ -422,6 +281,45 @@ static struct io_plan *peer_reconnected(struct io_conn *conn, retry_peer_connected, notleak(pr)); } +/*~ When we free a peer, we remove it from the daemon's hashtable */ +static void destroy_peer(struct peer *peer, struct daemon *daemon) +{ + peer_htable_del(&daemon->peers, peer); +} + +/*~ This is where we create a new peer. */ +static struct peer *new_peer(struct daemon *daemon, + const struct node_id *id, + const struct crypto_state *cs, + const u8 *their_features, + struct io_conn *conn STEALS, + int *fd_for_subd) +{ + struct peer *peer = tal(daemon, struct peer); + + peer->daemon = daemon; + peer->id = *id; + peer->cs = *cs; + peer->final_msg = NULL; + peer->subd_in = NULL; + peer->peer_in = NULL; + peer->sent_to_peer = NULL; + peer->urgent = false; + peer->peer_outq = msg_queue_new(peer); + peer->subd_outq = msg_queue_new(peer); + + /* Aim for connection to shuffle data back and forth: sets up + * peer->to_subd */ + if (!multiplex_subd_setup(peer, fd_for_subd)) + return tal_free(peer); + + peer->to_peer = tal_steal(peer, conn); + peer_htable_add(&daemon->peers, peer); + tal_add_destructor2(peer, destroy_peer, daemon); + + return peer; +} + /*~ Note the lack of static: this is called by peer_exchange_initmsg.c once the * INIT messages are exchanged, and also by the retry code above. */ struct io_plan *peer_connected(struct io_conn *conn, @@ -433,11 +331,14 @@ struct io_plan *peer_connected(struct io_conn *conn, bool incoming) { u8 *msg; - struct per_peer_state *pps; + struct peer *peer; int unsup; size_t depender, missing; + int subd_fd; + bool option_gossip_queries; - if (node_set_get(&daemon->peers, id)) + peer = peer_htable_get(&daemon->peers, id); + if (peer) return peer_reconnected(conn, daemon, id, addr, cs, their_features, incoming); @@ -487,35 +388,33 @@ struct io_plan *peer_connected(struct io_conn *conn, conn, find_connecting(daemon, id)->conn); /* This contains the per-peer state info; gossipd fills in pps->gs */ - pps = new_per_peer_state(tmpctx, cs); - - /* If gossipd can't give us a file descriptor, we give up connecting. */ - if (!get_gossipfds(daemon, id, their_features, pps)) + peer = new_peer(daemon, id, cs, their_features, conn, &subd_fd); + /* Only takes over conn if it succeeds. */ + if (!peer) return io_close(conn); + /* Tell gossipd it can ask query this new peer for gossip */ + option_gossip_queries = feature_negotiated(daemon->our_features, + their_features, + OPT_GOSSIP_QUERIES); + msg = towire_gossipd_new_peer(NULL, id, option_gossip_queries); + daemon_conn_send(daemon->gossipd, take(msg)); + + /* Get ready for streaming gossip from the store */ + setup_peer_gossip_store(peer, daemon->our_features, their_features); + /* Create message to tell master peer has connected. */ msg = towire_connectd_peer_connected(NULL, id, addr, incoming, - pps, their_features); + their_features); /*~ 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 and gossip fds. */ + * we have connected, and give the peer fd. */ daemon_conn_send(daemon->master, take(msg)); - /* io_conn_fd() extracts the fd from ccan/io's io_conn */ - daemon_conn_send_fd(daemon->master, io_conn_fd(conn)); - daemon_conn_send_fd(daemon->master, pps->gossip_fd); - daemon_conn_send_fd(daemon->master, pps->gossip_store_fd); - - /* Don't try to close these on freeing. */ - pps->gossip_store_fd = pps->gossip_fd = -1; - - /*~ Finally, we add it to the set of pubkeys: tal_dup will handle - * take() args for us, by simply tal_steal()ing it. */ - node_set_add(&daemon->peers, tal_dup(daemon, struct node_id, id)); + daemon_conn_send_fd(daemon->master, subd_fd); - /*~ We want to free the connection, but not close the fd (which is - * queued to go to lightningd), so use this variation on io_close: */ - return io_close_taken_fd(conn); + /*~ Now we set up this connection to read/write from subd */ + return multiplex_peer_setup(conn, peer); } /*~ handshake.c's handles setting up the crypto state once we get a connection @@ -525,13 +424,14 @@ static struct io_plan *handshake_in_success(struct io_conn *conn, const struct pubkey *id_key, const struct wireaddr_internal *addr, struct crypto_state *cs, + struct oneshot *timeout, struct daemon *daemon) { struct node_id id; node_id_from_pubkey(&id, id_key); status_peer_debug(&id, "Connect IN"); return peer_exchange_initmsg(conn, daemon, daemon->our_features, - cs, &id, addr, true); + cs, &id, addr, timeout, true); } /*~ If the timer goes off, we simply free everything, which hangs up. */ @@ -591,11 +491,12 @@ static struct io_plan *conn_in(struct io_conn *conn, struct conn_in *conn_in_arg) { struct daemon *daemon = conn_in_arg->daemon; + struct oneshot *timeout; - /* If they don't complete handshake in reasonable time, hang up */ - notleak(new_reltimer(&daemon->timers, conn, - time_from_sec(daemon->timeout_secs), - conn_timeout, conn)); + /* If they don't complete handshake in reasonable time, we hang up */ + timeout = new_reltimer(&daemon->timers, conn, + time_from_sec(daemon->timeout_secs), + conn_timeout, conn); /*~ The crypto handshake differs depending on whether you received or * initiated the socket connection, so there are two entry points. @@ -603,7 +504,7 @@ static struct io_plan *conn_in(struct io_conn *conn, * code from thinking `conn` (which we don't keep a pointer to) is * leaked */ return responder_handshake(notleak(conn), &daemon->mykey, - &conn_in_arg->addr, + &conn_in_arg->addr, timeout, handshake_in_success, daemon); } @@ -723,6 +624,7 @@ static struct io_plan *handshake_out_success(struct io_conn *conn, const struct pubkey *key, const struct wireaddr_internal *addr, struct crypto_state *cs, + struct oneshot *timeout, struct connecting *connect) { struct node_id id; @@ -732,12 +634,13 @@ static struct io_plan *handshake_out_success(struct io_conn *conn, status_peer_debug(&id, "Connect OUT"); return peer_exchange_initmsg(conn, connect->daemon, connect->daemon->our_features, - cs, &id, addr, false); + cs, &id, addr, timeout, false); } struct io_plan *connection_out(struct io_conn *conn, struct connecting *connect) { struct pubkey outkey; + struct oneshot *timeout; /* This shouldn't happen: lightningd should not give invalid ids! */ if (!pubkey_from_node_id(&outkey, &connect->id)) { @@ -748,15 +651,15 @@ struct io_plan *connection_out(struct io_conn *conn, struct connecting *connect) } /* If they don't complete handshake in reasonable time, hang up */ - notleak(new_reltimer(&connect->daemon->timers, conn, - time_from_sec(connect->daemon->timeout_secs), - conn_timeout, conn)); + timeout = new_reltimer(&connect->daemon->timers, conn, + time_from_sec(connect->daemon->timeout_secs), + conn_timeout, conn); status_peer_debug(&connect->id, "Connected out, starting crypto"); connect->connstate = "Cryptographic handshake"; return initiator_handshake(conn, &connect->daemon->mykey, &outkey, &connect->addrs[connect->addrnum], - handshake_out_success, connect); + timeout, handshake_out_success, connect); } /*~ When we've exhausted all addresses without success, we come here. @@ -1537,9 +1440,7 @@ static struct wireaddr_internal *setup_listeners(const tal_t *ctx, /*~ Parse the incoming connect init message from lightningd ("master") and * assign config variables to the daemon; it should be the first message we * get. */ -static struct io_plan *connect_init(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) +static void connect_init(struct daemon *daemon, const u8 *msg) { struct wireaddr *proxyaddr; struct wireaddr_internal *binding; @@ -1547,6 +1448,8 @@ static struct io_plan *connect_init(struct io_conn *conn, enum addr_listen_announce *proposed_listen_announce; struct wireaddr *announcable; char *tor_password; + bool dev_fast_gossip; + bool dev_disconnect; /* Fields which require allocation are allocated off daemon */ if (!fromwire_connectd_init( @@ -1562,12 +1465,19 @@ static struct io_plan *connect_init(struct io_conn *conn, &daemon->use_v3_autotor, &daemon->timeout_secs, &daemon->websocket_helper, - &daemon->websocket_port)) { + &daemon->websocket_port, + &dev_fast_gossip, + &dev_disconnect)) { /* This is a helper which prints the type expected and the actual * message, then exits (it should never be called!). */ master_badmsg(WIRE_CONNECTD_INIT, msg); } +#if DEVELOPER + /*~ Clearly mark this as a developer-only flag! */ + daemon->dev_fast_gossip = dev_fast_gossip; +#endif + if (!pubkey_from_node_id(&daemon->mykey, &daemon->id)) status_failed(STATUS_FAIL_INTERNAL_ERROR, "Invalid id for me %s", @@ -1606,15 +1516,14 @@ static struct io_plan *connect_init(struct io_conn *conn, take(towire_connectd_init_reply(NULL, binding, announcable))); - - /* Read the next message. */ - return daemon_conn_read_next(conn, daemon->master); +#if DEVELOPER + if (dev_disconnect) + dev_disconnect_init(5); +#endif } /*~ lightningd tells us to go! */ -static struct io_plan *connect_activate(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) +static void connect_activate(struct daemon *daemon, const u8 *msg) { bool do_listen; @@ -1645,7 +1554,6 @@ static struct io_plan *connect_activate(struct io_conn *conn, /* OK, we're ready! */ daemon_conn_send(daemon->master, take(towire_connectd_activate_reply(NULL))); - return daemon_conn_read_next(conn, daemon->master); } /* BOLT #10: @@ -1711,37 +1619,19 @@ static void add_seed_addrs(struct wireaddr_internal **addrs, } } -static bool wireaddr_int_equals_wireaddr(struct wireaddr_internal *addr_a, - struct wireaddr *addr_b) +static bool wireaddr_int_equals_wireaddr(const struct wireaddr_internal *addr_a, + const struct wireaddr *addr_b) { if (!addr_a || !addr_b) return false; return wireaddr_eq(&addr_a->u.wireaddr, addr_b); } -/*~ This asks gossipd for any addresses advertized by the node. */ +/*~ Orders the addresses which lightningd gave us. */ static void add_gossip_addrs(struct wireaddr_internal **addrs, - const struct node_id *id, - struct wireaddr_internal *addrhint) + const struct wireaddr *normal_addrs, + const struct wireaddr_internal *addrhint) { - u8 *msg; - struct wireaddr *normal_addrs; - - /* For simplicity, we do this synchronous. */ - msg = towire_gossipd_get_addrs(NULL, id); - if (!wire_sync_write(GOSSIPCTL_FD, take(msg))) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Failed writing to gossipctl: %s", - strerror(errno)); - - /* This returns 'struct wireaddr's since that's what's supported by - * the BOLT #7 protocol. */ - msg = wire_sync_read(tmpctx, GOSSIPCTL_FD); - if (!fromwire_gossipd_get_addrs_reply(tmpctx, msg, &normal_addrs)) - status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Failed parsing get_addrs_reply gossipctl: %s", - tal_hex(tmpctx, msg)); - /* Wrap each one in a wireaddr_internal and add to addrs. */ for (size_t i = 0; i < tal_count(normal_addrs); i++) { /* This is not supported, ignore. */ @@ -1778,14 +1668,15 @@ static void add_gossip_addrs(struct wireaddr_internal **addrs, static void try_connect_peer(struct daemon *daemon, const struct node_id *id, u32 seconds_waited, - struct wireaddr_internal *addrhint) + struct wireaddr *gossip_addrs, + struct wireaddr_internal *addrhint STEALS) { struct wireaddr_internal *addrs; bool use_proxy = daemon->always_use_proxy; struct connecting *connect; /* Already done? May happen with timer. */ - if (node_set_get(&daemon->peers, id)) + if (peer_htable_get(&daemon->peers, id)) return; /* If we're trying to connect it right now, that's OK. */ @@ -1809,7 +1700,7 @@ static void try_connect_peer(struct daemon *daemon, if (addrhint) tal_arr_expand(&addrs, *addrhint); - add_gossip_addrs(&addrs, id, addrhint); + add_gossip_addrs(&addrs, gossip_addrs, addrhint); if (tal_count(addrs) == 0) { /* Don't resolve via DNS seed if we're supposed to use proxy. */ @@ -1861,47 +1752,50 @@ static void try_connect_peer(struct daemon *daemon, } /* lightningd tells us to connect to a peer by id, with optional addr hint. */ -static struct io_plan *connect_to_peer(struct io_conn *conn, - struct daemon *daemon, const u8 *msg) +static void connect_to_peer(struct daemon *daemon, const u8 *msg) { struct node_id id; u32 seconds_waited; struct wireaddr_internal *addrhint; + struct wireaddr *addrs; if (!fromwire_connectd_connect_to_peer(tmpctx, msg, - &id, &seconds_waited, - &addrhint)) + &id, &seconds_waited, + &addrs, &addrhint)) master_badmsg(WIRE_CONNECTD_CONNECT_TO_PEER, msg); - try_connect_peer(daemon, &id, seconds_waited, addrhint); - return daemon_conn_read_next(conn, daemon->master); + try_connect_peer(daemon, &id, seconds_waited, addrs, addrhint); } /* A peer is gone: clean things up. */ static void cleanup_dead_peer(struct daemon *daemon, const struct node_id *id) { - struct node_id *node; + struct peer *peer; /* We should stay in sync with lightningd at all times. */ - node = node_set_get(&daemon->peers, id); - if (!node) + 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)); - node_set_del(&daemon->peers, node); status_peer_debug(id, "disconnect"); + /* Tell gossipd to stop asking this peer gossip queries */ + daemon_conn_send(daemon->gossipd, + take(towire_gossipd_peer_gone(NULL, id))); + /* Wake up in case there's a reconnecting peer waiting in io_wait. */ - io_wake(node); + io_wake(peer); /* Note: deleting from a htable (a-la node_set_del) does not free it: - * htable doesn't assume it's a tal object at all. */ - tal_free(node); + * htable doesn't assume it's a tal object at all. That's why we have + * a destructor attached to peer (called destroy_peer by + * convention). */ + tal_free(peer); } /* lightningd tells us a peer has disconnected. */ -static struct io_plan *peer_disconnected(struct io_conn *conn, - struct daemon *daemon, const u8 *msg) +static void peer_disconnected(struct daemon *daemon, const u8 *msg) { struct node_id id; @@ -1909,75 +1803,30 @@ static struct io_plan *peer_disconnected(struct io_conn *conn, master_badmsg(WIRE_CONNECTD_PEER_DISCONNECTED, msg); cleanup_dead_peer(daemon, &id); - - /* Read the next message from lightningd. */ - return daemon_conn_read_next(conn, daemon->master); -} - -/* lightningd tells us to send a final (usually error) message to peer, then - * disconnect. */ -struct final_msg_data { - struct daemon *daemon; - struct node_id id; -}; - -static void destroy_final_msg_data(struct final_msg_data *f) -{ - cleanup_dead_peer(f->daemon, &f->id); -} - -static struct io_plan *send_final_msg(struct io_conn *conn, u8 *msg) -{ - return io_write(conn, msg, tal_bytelen(msg), io_close_cb, NULL); } /* lightningd tells us to send a msg and disconnect. */ -static struct io_plan *peer_final_msg(struct io_conn *conn, - struct daemon *daemon, const u8 *msg) +static void peer_final_msg(struct io_conn *conn, + struct daemon *daemon, const u8 *msg) { - struct per_peer_state *pps; - struct final_msg_data *f = tal(NULL, struct final_msg_data); + struct peer *peer; + struct node_id id; u8 *finalmsg; - int fds[3]; - f->daemon = daemon; - /* pps is allocated off f, so fds are closed when f freed. */ - if (!fromwire_connectd_peer_final_msg(f, msg, &f->id, &pps, &finalmsg)) + if (!fromwire_connectd_peer_final_msg(tmpctx, msg, &id, &finalmsg)) master_badmsg(WIRE_CONNECTD_PEER_FINAL_MSG, msg); - /* When f is freed, we want to mark node as dead. */ - tal_add_destructor(f, destroy_final_msg_data); - - /* Get the fds for this peer. */ - io_fd_block(io_conn_fd(conn), true); - for (size_t i = 0; i < ARRAY_SIZE(fds); i++) { - fds[i] = fdpass_recv(io_conn_fd(conn)); - if (fds[i] == -1) - status_failed(STATUS_FAIL_MASTER_IO, - "Getting fd %zu after peer_final_msg: %s", - i, strerror(errno)); + /* This can happen if peer hung up on us. */ + peer = peer_htable_get(&daemon->peers, &id); + if (peer) { + /* Log and encrypt message for peer. */ + status_peer_io(LOG_IO_OUT, &id, finalmsg); + multiplex_final_msg(peer, take(finalmsg)); } - io_fd_block(io_conn_fd(conn), false); - - /* We put peer fd into conn, but pps needs to free the rest */ - per_peer_state_set_fds(pps, -1, fds[1], fds[2]); - - /* Log and encrypt message for peer. */ - status_peer_io(LOG_IO_OUT, &f->id, finalmsg); - finalmsg = cryptomsg_encrypt_msg(f, &pps->cs, take(finalmsg)); - - /* Organize io loop to write out that message, it will free f - * once closed */ - tal_steal(io_new_conn(daemon, fds[0], send_final_msg, finalmsg), f); - - /* Read the next message from lightningd. */ - return daemon_conn_read_next(conn, daemon->master); } #if DEVELOPER -static struct io_plan *dev_connect_memleak(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) +static void dev_connect_memleak(struct daemon *daemon, const u8 *msg) { struct htable *memtable; bool found_leak; @@ -1986,12 +1835,12 @@ static struct io_plan *dev_connect_memleak(struct io_conn *conn, /* Now delete daemon and those which it has pointers to. */ memleak_remove_region(memtable, daemon, sizeof(daemon)); + memleak_remove_htable(memtable, &daemon->peers.raw); found_leak = dump_memleak(memtable, memleak_status_broken); daemon_conn_send(daemon->master, take(towire_connectd_dev_memleak_reply(NULL, found_leak))); - return daemon_conn_read_next(conn, daemon->master); } #endif /* DEVELOPER */ @@ -2005,23 +1854,41 @@ static struct io_plan *recv_req(struct io_conn *conn, * connect requests and disconnected messages. */ switch (t) { case WIRE_CONNECTD_INIT: - return connect_init(conn, daemon, msg); + connect_init(daemon, msg); + goto out; case WIRE_CONNECTD_ACTIVATE: - return connect_activate(conn, daemon, msg); + connect_activate(daemon, msg); + goto out; case WIRE_CONNECTD_CONNECT_TO_PEER: - return connect_to_peer(conn, daemon, msg); + connect_to_peer(daemon, msg); + goto out; case WIRE_CONNECTD_PEER_DISCONNECTED: - return peer_disconnected(conn, daemon, msg); + peer_disconnected(daemon, msg); + goto out; case WIRE_CONNECTD_PEER_FINAL_MSG: - return peer_final_msg(conn, daemon, msg); + peer_final_msg(conn, daemon, msg); + goto out; + + case WIRE_CONNECTD_PING: + send_manual_ping(daemon, msg); + goto out; + + case WIRE_CONNECTD_SEND_ONIONMSG: + onionmsg_req(daemon, msg); + goto out; + + case WIRE_CONNECTD_CUSTOMMSG_OUT: + send_custommsg(daemon, msg); + goto out; case WIRE_CONNECTD_DEV_MEMLEAK: #if DEVELOPER - return dev_connect_memleak(conn, daemon, msg); + dev_connect_memleak(daemon, msg); + goto out; #endif /* We send these, we don't receive them */ case WIRE_CONNECTD_INIT_REPLY: @@ -2030,12 +1897,19 @@ static struct io_plan *recv_req(struct io_conn *conn, case WIRE_CONNECTD_RECONNECTED: case WIRE_CONNECTD_CONNECT_FAILED: case WIRE_CONNECTD_DEV_MEMLEAK_REPLY: + case WIRE_CONNECTD_PING_REPLY: + case WIRE_CONNECTD_GOT_ONIONMSG_TO_US: + case WIRE_CONNECTD_CUSTOMMSG_IN: break; } /* Master shouldn't give bad requests. */ status_failed(STATUS_FAIL_MASTER_IO, "%i: %s", t, tal_hex(tmpctx, msg)); + +out: + /* Read the next message. */ + return daemon_conn_read_next(conn, daemon->master); } /*~ UNUSED is defined to an __attribute__ for GCC; at one stage we tried to use @@ -2050,6 +1924,26 @@ static void master_gone(struct daemon_conn *master UNUSED) exit(2); } +/*~ gossipd sends us gossip to send to the peers. */ +static struct io_plan *recv_gossip(struct io_conn *conn, + const u8 *msg, + struct daemon *daemon) +{ + struct node_id dst; + u8 *gossip_msg; + struct peer *peer; + + if (!fromwire_gossipd_send_gossip(msg, msg, &dst, &gossip_msg)) + status_failed(STATUS_FAIL_GOSSIP_IO, "Unknown msg %i", + fromwire_peektype(msg)); + + peer = peer_htable_get(&daemon->peers, &dst); + if (peer) + queue_peer_msg(peer, take(gossip_msg)); + + return daemon_conn_read_next(conn, daemon->gossipd); +} + /*~ This is a hook used by the memleak code (if DEVELOPER=1): it can't see * pointers inside hash tables, so we give it a hint here. */ #if DEVELOPER @@ -2070,11 +1964,13 @@ int main(int argc, char *argv[]) /* Allocate and set up our simple top-level structure. */ daemon = tal(NULL, struct daemon); - node_set_init(&daemon->peers); + peer_htable_init(&daemon->peers); memleak_add_helper(daemon, memleak_daemon_cb); list_head_init(&daemon->connecting); daemon->listen_fds = tal_arr(daemon, struct listen_fd, 0); timers_init(&daemon->timers, time_mono()); + daemon->gossip_store_fd = -1; + /* stdin == control */ daemon->master = daemon_conn_new(daemon, STDIN_FILENO, recv_req, NULL, daemon); @@ -2084,6 +1980,11 @@ int main(int argc, char *argv[]) * our status_ and failed messages. */ status_setup_async(daemon->master); + /* This streams gossip to and from gossipd */ + daemon->gossipd = daemon_conn_new(daemon, GOSSIPCTL_FD, + recv_gossip, NULL, + daemon); + /* Set up ecdh() function so it uses our HSM fd, and calls * status_failed on error. */ ecdh_hsmd_setup(HSM_FD, status_failed); diff --git a/connectd/connectd.h b/connectd/connectd.h index d78fc15c6dbd..93814efc5e3c 100644 --- a/connectd/connectd.h +++ b/connectd/connectd.h @@ -2,14 +2,183 @@ #define LIGHTNING_CONNECTD_CONNECTD_H #include "config.h" #include +#include +#include +#include #include +#include +#include struct io_conn; struct connecting; -struct daemon; -struct node_id; struct wireaddr_internal; +/*~ All the gossip_store related fields are kept together for convenience. */ +struct gossip_state { + /* Is it active right now? */ + bool active; + /* Except with dev override, this fires every 60 seconds */ + struct oneshot *gossip_timer; + /* Timestamp filtering for gossip. */ + u32 timestamp_min, timestamp_max; + /* I think this is called "echo cancellation" */ + struct gossip_rcvd_filter *grf; + /* Offset within the gossip_store file */ + size_t off; +}; + +/*~ We need to know if we were expecting a pong, and why */ +enum pong_expect_type { + /* We weren't expecting a ping reply */ + PONG_UNEXPECTED = 0, + /* We were expecting a ping reply due to ping command */ + PONG_EXPECTED_COMMAND = 1, + /* We were expecting a ping reply due to ping timer */ + PONG_EXPECTED_PROBING = 2, +}; + +/*~ We keep a hash table (ccan/htable) of peers, which tells us what peers are + * already connected (by peer->id). */ +struct peer { + /* Main daemon */ + struct daemon *daemon; + + /* The pubkey of the node */ + struct node_id id; + /* Counters and keys for symmetric crypto */ + struct crypto_state cs; + + /* Connection to the peer */ + struct io_conn *to_peer; + + /* Connection to the subdaemon */ + struct io_conn *to_subd; + + /* Final message to send to peer (and hangup) */ + u8 *final_msg; + + /* When we write something which wants Nagle overridden */ + bool urgent; + + /* Input buffers. */ + u8 *subd_in, *peer_in; + + /* Output buffers. */ + struct msg_queue *subd_outq, *peer_outq; + + /* Peer sent buffer (for freeing after sending) */ + const u8 *sent_to_peer; + + /* We stream from the gossip_store for them, when idle */ + struct gossip_state gs; + + /* Are we expecting a pong? */ + enum pong_expect_type expecting_pong; + + /* Random ping timer, to detect dead connections. */ + struct oneshot *ping_timer; +}; + +/*~ The HTABLE_DEFINE_TYPE() macro needs a keyof() function to extract the key: + */ +static const struct node_id *peer_keyof(const struct peer *peer) +{ + return &peer->id; +} + +/*~ We also need to define a hashing function. siphash24 is a fast yet + * cryptographic hash in ccan/crypto/siphash24; we might be able to get away + * with a slightly faster hash with fewer guarantees, but it's good hygiene to + * use this unless it's a proven bottleneck. siphash_seed() is a function in + * common/pseudorand which sets up a seed for our hashing; it's different + * every time the program is run. */ +static size_t node_id_hash(const struct node_id *id) +{ + return siphash24(siphash_seed(), id->k, sizeof(id->k)); +} + +/*~ We also define an equality function: is this element equal to this key? */ +static bool peer_eq_node_id(const struct peer *peer, + const struct node_id *id) +{ + return node_id_eq(&peer->id, id); +} + +/*~ This defines 'struct peer_htable' which contains 'struct peer' pointers. */ +HTABLE_DEFINE_TYPE(struct peer, + peer_keyof, + node_id_hash, + peer_eq_node_id, + peer_htable); + +/*~ This is the global state, like `struct lightningd *ld` in lightningd. */ +struct daemon { + /* Who am I? */ + struct node_id id; + + /* pubkey equivalent. */ + struct pubkey mykey; + + /* Base for timeout timers, and how long to wait for init msg */ + struct timers timers; + u32 timeout_secs; + + /* Peers that we've handed to `lightningd`, which it hasn't told us + * have disconnected. */ + struct peer_htable peers; + + /* Peers we are trying to reach */ + struct list_head connecting; + + /* Connection to main daemon. */ + struct daemon_conn *master; + + /* Connection to gossip daemon. */ + struct daemon_conn *gossipd; + + /* Allow localhost to be considered "public": DEVELOPER-only option, + * but for simplicity we don't #if DEVELOPER-wrap it here. */ + bool dev_allow_localhost; + + /* We support use of a SOCKS5 proxy (e.g. Tor) */ + struct addrinfo *proxyaddr; + + /* They can tell us we must use proxy even for non-Tor addresses. */ + bool always_use_proxy; + + /* There are DNS seeds we can use to look up node addresses as a last + * resort, but doing so leaks our address so can be disabled. */ + bool use_dns; + + /* The address that the broken response returns instead of + * NXDOMAIN. NULL if we have not detected a broken resolver. */ + struct sockaddr *broken_resolver_response; + + /* File descriptors to listen on once we're activated. */ + struct listen_fd *listen_fds; + + /* Allow to define the default behavior of tor services calls*/ + bool use_v3_autotor; + + /* Our features, as lightningd told us */ + struct feature_set *our_features; + + /* Subdaemon to proxy websocket requests. */ + char *websocket_helper; + + /* If non-zero, port to listen for websocket connections. */ + u16 websocket_port; + + /* The gossip_store */ + int gossip_store_fd; + size_t gossip_store_end; + +#if DEVELOPER + /* Hack to speed up gossip timer */ + bool dev_fast_gossip; +#endif +}; + /* Called by io_tor_connect once it has a connection out. */ struct io_plan *connection_out(struct io_conn *conn, struct connecting *connect); diff --git a/connectd/connectd_gossipd_wire.csv b/connectd/connectd_gossipd_wire.csv index c0d9152c9957..195a73421bb8 100644 --- a/connectd/connectd_gossipd_wire.csv +++ b/connectd/connectd_gossipd_wire.csv @@ -5,20 +5,21 @@ # Communication between gossipd and connectd. msgtype,gossipd_new_peer,4000 msgdata,gossipd_new_peer,id,node_id, -# Did we negotiate LOCAL_GOSSIP_QUERIES? +# Did we negotiate OPT_GOSSIP_QUERIES? msgdata,gossipd_new_peer,gossip_queries_feature,bool, -# Did they offer LOCAL_INITIAL_ROUTING_SYNC? -msgdata,gossipd_new_peer,initial_routing_sync,bool, -# if success: + gossip fd and gossip_store fd -msgtype,gossipd_new_peer_reply,4100 -msgdata,gossipd_new_peer_reply,success,bool, -msgdata,gossipd_new_peer_reply,gs,?gossip_state, +# peer is done +msgtype,gossipd_peer_gone,4101 +msgdata,gossipd_peer_gone,id,node_id, -# Connectd asks gossipd for any known addresses for that node. -msgtype,gossipd_get_addrs,4001 -msgdata,gossipd_get_addrs,id,node_id, +# connectd tells gossipd a gossip msg it received for peer. +msgtype,gossipd_recv_gossip,4002 +msgdata,gossipd_recv_gossip,id,node_id, +msgdata,gossipd_recv_gossip,len,u16, +msgdata,gossipd_recv_gossip,msg,byte,len -msgtype,gossipd_get_addrs_reply,4101 -msgdata,gossipd_get_addrs_reply,num,u16, -msgdata,gossipd_get_addrs_reply,addrs,wireaddr,num +# Gossipd asks connectd to send a gossip msg for peer. +msgtype,gossipd_send_gossip,4102 +msgdata,gossipd_send_gossip,id,node_id, +msgdata,gossipd_send_gossip,len,u16, +msgdata,gossipd_send_gossip,msg,byte,len diff --git a/connectd/connectd_wire.csv b/connectd/connectd_wire.csv index bddaf972af7e..7632a2840e43 100644 --- a/connectd/connectd_wire.csv +++ b/connectd/connectd_wire.csv @@ -2,8 +2,8 @@ #include #include #include -#include #include +#include msgtype,connectd_init,2000 msgdata,connectd_init,chainparams,chainparams, @@ -21,6 +21,9 @@ msgdata,connectd_init,use_v3_autotor,bool, msgdata,connectd_init,timeout_secs,u32, msgdata,connectd_init,websocket_helper,wirestring, msgdata,connectd_init,websocket_port,u16, +msgdata,connectd_init,dev_fast_gossip,bool, +# If this is set, then fd 5 is dev_disconnect_fd. +msgdata,connectd_init,dev_disconnect,bool, # Connectd->master, here are the addresses I bound, can announce. msgtype,connectd_init_reply,2100 @@ -45,6 +48,8 @@ msgdata,connectd_reconnected,id,node_id, msgtype,connectd_connect_to_peer,2001 msgdata,connectd_connect_to_peer,id,node_id, msgdata,connectd_connect_to_peer,seconds_waited,u32, +msgdata,connectd_connect_to_peer,len,u32, +msgdata,connectd_connect_to_peer,addrs,wireaddr,len msgdata,connectd_connect_to_peer,addrhint,?wireaddr_internal, # Connectd->master: connect failed. @@ -55,12 +60,11 @@ 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. Three fds: peer, gossip and gossip_store +# Connectd -> master: we got a peer. Plus fd for peer daemon msgtype,connectd_peer_connected,2002 msgdata,connectd_peer_connected,id,node_id, msgdata,connectd_peer_connected,addr,wireaddr_internal, msgdata,connectd_peer_connected,incoming,bool, -msgdata,connectd_peer_connected,pps,per_peer_state, msgdata,connectd_peer_connected,flen,u16, msgdata,connectd_peer_connected,features,u8,flen @@ -68,10 +72,9 @@ msgdata,connectd_peer_connected,features,u8,flen msgtype,connectd_peer_disconnected,2015 msgdata,connectd_peer_disconnected,id,node_id, -# master -> connectd: give message to peer and disconnect. Three fds: peer, gossip and gossip_store +# master -> connectd: give message to peer and disconnect. msgtype,connectd_peer_final_msg,2003 msgdata,connectd_peer_final_msg,id,node_id, -msgdata,connectd_peer_final_msg,pps,per_peer_state, msgdata,connectd_peer_final_msg,len,u16, msgdata,connectd_peer_final_msg,msg,u8,len @@ -80,3 +83,48 @@ msgtype,connectd_dev_memleak,2033 msgtype,connectd_dev_memleak_reply,2133 msgdata,connectd_dev_memleak_reply,leak,bool, + +# Ping/pong test. Waits for a reply if it expects one. +msgtype,connectd_ping,2030 +msgdata,connectd_ping,id,node_id, +msgdata,connectd_ping,num_pong_bytes,u16, +msgdata,connectd_ping,len,u16, + +msgtype,connectd_ping_reply,2130 +# False if we there was already a ping in progress. +msgdata,connectd_ping_reply,sent,bool, +# 0 == no pong expected, otherwise length of pong. +msgdata,connectd_ping_reply,totlen,u16, + +# We tell lightningd we got an onionmsg +msgtype,connectd_got_onionmsg_to_us,2145 +msgdata,connectd_got_onionmsg_to_us,obs2,bool, +msgdata,connectd_got_onionmsg_to_us,node_alias,pubkey, +msgdata,connectd_got_onionmsg_to_us,self_id,?secret, +msgdata,connectd_got_onionmsg_to_us,reply_blinding,?pubkey, +msgdata,connectd_got_onionmsg_to_us,reply_first_node,?pubkey, +msgdata,connectd_got_onionmsg_to_us,reply_path_len,u16, +msgdata,connectd_got_onionmsg_to_us,reply_path,onionmsg_path,reply_path_len +msgdata,connectd_got_onionmsg_to_us,rawmsg_len,u16, +msgdata,connectd_got_onionmsg_to_us,rawmsg,u8,rawmsg_len + +# Lightningd tells us to send an onion message. +msgtype,connectd_send_onionmsg,2041 +msgdata,connectd_send_onionmsg,obs2,bool, +msgdata,connectd_send_onionmsg,id,node_id, +msgdata,connectd_send_onionmsg,onion_len,u16, +msgdata,connectd_send_onionmsg,onion,u8,onion_len +msgdata,connectd_send_onionmsg,blinding,pubkey, + +# A custom message that we got from a peer and don't know how to handle, so we +# forward it to the master for further handling. +msgtype,connectd_custommsg_in,2110 +msgdata,connectd_custommsg_in,id,node_id, +msgdata,connectd_custommsg_in,msg_len,u16, +msgdata,connectd_custommsg_in,msg,u8,msg_len + +# A custom message that the lightningd tells us to send to the peer. +msgtype,connectd_custommsg_out,2011 +msgdata,connectd_custommsg_out,id,node_id, +msgdata,connectd_custommsg_out,msg_len,u16, +msgdata,connectd_custommsg_out,msg,u8,msg_len diff --git a/connectd/handshake.c b/connectd/handshake.c index 768b4a2a6a6b..1097f6f3d033 100644 --- a/connectd/handshake.c +++ b/connectd/handshake.c @@ -173,11 +173,15 @@ struct handshake { /* Are we initiator or responder. */ enum bolt8_side side; + /* Timeout timer if we take too long. */ + struct oneshot *timeout; + /* Function to call once handshake complete. */ struct io_plan *(*cb)(struct io_conn *conn, const struct pubkey *their_id, const struct wireaddr_internal *wireaddr, struct crypto_state *cs, + struct oneshot *timeout, void *cbarg); void *cbarg; }; @@ -348,10 +352,12 @@ static struct io_plan *handshake_succeeded(struct io_conn *conn, const struct pubkey *their_id, const struct wireaddr_internal *addr, struct crypto_state *cs, + struct oneshot *timeout, void *cbarg); void *cbarg; struct pubkey their_id; struct wireaddr_internal addr; + struct oneshot *timeout; /* BOLT #8: * @@ -377,9 +383,10 @@ static struct io_plan *handshake_succeeded(struct io_conn *conn, cbarg = h->cbarg; their_id = h->their_id; addr = h->addr; + timeout = h->timeout; tal_free(h); - return cb(conn, &their_id, &addr, &cs, cbarg); + return cb(conn, &their_id, &addr, &cs, timeout, cbarg); } static struct handshake *new_handshake(const tal_t *ctx, @@ -956,10 +963,12 @@ static struct io_plan *act_one_responder(struct io_conn *conn, struct io_plan *responder_handshake_(struct io_conn *conn, const struct pubkey *my_id, const struct wireaddr_internal *addr, + struct oneshot *timeout, struct io_plan *(*cb)(struct io_conn *, const struct pubkey *, const struct wireaddr_internal *, struct crypto_state *, + struct oneshot *, void *cbarg), void *cbarg) { @@ -970,6 +979,7 @@ struct io_plan *responder_handshake_(struct io_conn *conn, h->addr = *addr; h->cbarg = cbarg; h->cb = cb; + h->timeout = timeout; return act_one_responder(conn, h); } @@ -978,10 +988,12 @@ struct io_plan *initiator_handshake_(struct io_conn *conn, const struct pubkey *my_id, const struct pubkey *their_id, const struct wireaddr_internal *addr, + struct oneshot *timeout, struct io_plan *(*cb)(struct io_conn *, const struct pubkey *, const struct wireaddr_internal *, struct crypto_state *, + struct oneshot *timeout, void *cbarg), void *cbarg) { @@ -993,6 +1005,7 @@ struct io_plan *initiator_handshake_(struct io_conn *conn, h->addr = *addr; h->cbarg = cbarg; h->cb = cb; + h->timeout = timeout; return act_one_initiator(conn, h); } diff --git a/connectd/handshake.h b/connectd/handshake.h index 733178bee205..facb7f203250 100644 --- a/connectd/handshake.h +++ b/connectd/handshake.h @@ -6,15 +6,17 @@ struct crypto_state; struct io_conn; struct wireaddr_internal; struct pubkey; +struct oneshot; -#define initiator_handshake(conn, my_id, their_id, addr, cb, cbarg) \ - initiator_handshake_((conn), (my_id), (their_id), (addr), \ +#define initiator_handshake(conn, my_id, their_id, addr, timeout, cb, cbarg) \ + initiator_handshake_((conn), (my_id), (their_id), (addr), (timeout), \ typesafe_cb_preargs(struct io_plan *, void *, \ (cb), (cbarg), \ struct io_conn *, \ const struct pubkey *, \ - const struct wireaddr_internal *, \ - struct crypto_state *), \ + const struct wireaddr_internal *, \ + struct crypto_state *, \ + struct oneshot *), \ (cbarg)) @@ -22,31 +24,36 @@ struct io_plan *initiator_handshake_(struct io_conn *conn, const struct pubkey *my_id, const struct pubkey *their_id, const struct wireaddr_internal *addr, + struct oneshot *timeout, struct io_plan *(*cb)(struct io_conn *, const struct pubkey *, const struct wireaddr_internal *, struct crypto_state *, + struct oneshot *timeout, void *cbarg), void *cbarg); -#define responder_handshake(conn, my_id, addr, cb, cbarg) \ - responder_handshake_((conn), (my_id), (addr), \ +#define responder_handshake(conn, my_id, addr, timeout, cb, cbarg) \ + responder_handshake_((conn), (my_id), (addr), (timeout), \ typesafe_cb_preargs(struct io_plan *, void *, \ (cb), (cbarg), \ struct io_conn *, \ const struct pubkey *, \ - const struct wireaddr_internal *, \ - struct crypto_state *), \ + const struct wireaddr_internal *, \ + struct crypto_state *, \ + struct oneshot *), \ (cbarg)) struct io_plan *responder_handshake_(struct io_conn *conn, const struct pubkey *my_id, const struct wireaddr_internal *addr, + struct oneshot *timeout, struct io_plan *(*cb)(struct io_conn *, const struct pubkey *, const struct wireaddr_internal *, struct crypto_state *, + struct oneshot *, void *cbarg), void *cbarg); #endif /* LIGHTNING_CONNECTD_HANDSHAKE_H */ diff --git a/connectd/multiplex.c b/connectd/multiplex.c new file mode 100644 index 000000000000..246efb081998 --- /dev/null +++ b/connectd/multiplex.c @@ -0,0 +1,752 @@ +/*~ This contains all the code to shuffle data between socket to the peer + * itself, and the subdaemons. */ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void queue_peer_msg(struct peer *peer, const u8 *msg TAKES) +{ + msg_enqueue(peer->peer_outq, msg); +} + +/* Send warning, close connection to peer */ +static void send_warning(struct peer *peer, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + status_vfmt(LOG_UNUSUAL, &peer->id, fmt, ap); + va_end(ap); + + /* Close locally, send msg as final warning */ + io_close(peer->to_subd); + + va_start(ap, fmt); + peer->final_msg = towire_warningfmtv(peer, NULL, fmt, ap); + va_end(ap); +} + +/* Kicks off write_to_peer() to look for more gossip to send from store */ +static void wake_gossip(struct peer *peer); + +static struct oneshot *gossip_stream_timer(struct peer *peer) +{ + u32 next; + + /* BOLT #7: + * + * A node: + *... + * - SHOULD flush outgoing gossip messages once every 60 seconds, + * independently of the arrival times of the messages. + * - Note: this results in staggered announcements that are unique + * (not duplicated). + */ + /* We shorten this for dev_fast_gossip! */ + next = GOSSIP_FLUSH_INTERVAL(peer->daemon->dev_fast_gossip); + + return new_reltimer(&peer->daemon->timers, + peer, time_from_sec(next), + wake_gossip, peer); +} + +/* This is called once we need it: otherwise, the gossip_store may not exist, + * since we start at the same time as gossipd itself. */ +static void setup_gossip_store(struct daemon *daemon) +{ + daemon->gossip_store_fd = open(GOSSIP_STORE_FILENAME, O_RDONLY); + if (daemon->gossip_store_fd < 0) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Opening gossip_store %s: %s", + GOSSIP_STORE_FILENAME, strerror(errno)); + /* gossipd will be writing to this, and it's not atomic! Safest + * way to find the "end" is to walk through. */ + daemon->gossip_store_end + = find_gossip_store_end(daemon->gossip_store_fd, 1); +} + +void setup_peer_gossip_store(struct peer *peer, + const struct feature_set *our_features, + const u8 *their_features) +{ + /* Lazy setup */ + if (peer->daemon->gossip_store_fd == -1) + setup_gossip_store(peer->daemon); + + peer->gs.grf = new_gossip_rcvd_filter(peer); + + /* BOLT #7: + * + * A node: + * - if the `gossip_queries` feature is negotiated: + * - MUST NOT relay any gossip messages it did not generate itself, + * unless explicitly requested. + */ + if (feature_negotiated(our_features, their_features, OPT_GOSSIP_QUERIES)) { + status_peer_debug(&peer->id, "gossip_store: deferring"); + + peer->gs.gossip_timer = NULL; + peer->gs.active = false; + peer->gs.off = 1; + return; + } + + peer->gs.gossip_timer = gossip_stream_timer(peer); + peer->gs.active = true; + peer->gs.timestamp_min = 0; + peer->gs.timestamp_max = UINT32_MAX; + + /* BOLT #7: + * + * - upon receiving an `init` message with the + * `initial_routing_sync` flag set to 1: + * - SHOULD send gossip messages for all known channels and + * nodes, as if they were just received. + * - if the `initial_routing_sync` flag is set to 0, OR if the + * initial sync was completed: + * - SHOULD resume normal operation, as specified in the + * following [Rebroadcasting](#rebroadcasting) section. + */ + if (feature_offered(their_features, OPT_INITIAL_ROUTING_SYNC)) { + status_peer_debug(&peer->id, "gossip_store: initial_routing_sync"); + peer->gs.off = 1; + } else { + /* During tests, particularly, we find that the gossip_store + * moves fast, so make sure it really does start at the end. */ + peer->gs.off + = find_gossip_store_end(peer->daemon->gossip_store_fd, + peer->daemon->gossip_store_end); + status_peer_debug(&peer->id, "gossip_store: off = %zu", + peer->gs.off); + } +} + +/* These four function handle subd->peer */ +static struct io_plan *after_final_msg(struct io_conn *peer_conn, + struct peer *peer) +{ + /* io_close will want to free this itself! */ + assert(peer->to_peer == peer_conn); + tal_steal(NULL, peer_conn); + tal_free(peer); + return io_close(peer_conn); +} + +#if DEVELOPER +static struct io_plan *write_to_peer(struct io_conn *peer_conn, + struct peer *peer); + +static struct io_plan *dev_leave_hanging(struct io_conn *peer_conn, + struct peer *peer) +{ + /* We don't tell the peer we're disconnecting, but from now on + * our writes go nowhere, and there's nothing to read. */ + dev_sabotage_fd(io_conn_fd(peer_conn), false); + return write_to_peer(peer_conn, peer); +} +#endif /* DEVELOPER */ + +/* We're happy for the kernel to batch update and gossip messages, but a + * commitment message, for example, should be instantly sent. There's no + * great way of doing this, unfortunately. + * + * Setting TCP_NODELAY on Linux flushes the socket, which really means + * we'd want to toggle on then off it *after* sending. But Linux has + * TCP_CORK. On FreeBSD, it seems (looking at source) not to, so + * there we'd want to set it before the send, and reenable it + * afterwards. Even if this is wrong on other non-Linux platforms, it + * only means one extra packet. + */ +static void set_urgent_flag(struct peer *peer, bool urgent) +{ + int val; + int opt; + const char *optname; + static bool complained = false; + + if (!urgent && !peer->urgent) + return; + +#ifdef TCP_CORK + opt = TCP_CORK; + optname = "TCP_CORK"; +#elif defined(TCP_NODELAY) + opt = TCP_NODELAY; + optname = "TCP_NODELAY"; +#else +#error "Please report platform with neither TCP_CORK nor TCP_NODELAY?" +#endif + + val = urgent; + if (setsockopt(io_conn_fd(peer->to_peer), + IPPROTO_TCP, opt, &val, sizeof(val)) != 0) { + /* This actually happens in testing, where we blackhole the fd */ + if (!complained) { + status_unusual("setsockopt %s=1: %s", + optname, + strerror(errno)); + complained = true; + } + } + peer->urgent = urgent; +} + + +static struct io_plan *encrypt_and_send(struct peer *peer, + const u8 *msg TAKES, + struct io_plan *(*next) + (struct io_conn *peer_conn, + struct peer *peer)) +{ + int type = fromwire_peektype(msg); + +#if DEVELOPER + switch (dev_disconnect(&peer->id, type)) { + case DEV_DISCONNECT_BEFORE: + if (taken(msg)) + tal_free(msg); + return io_close(peer->to_peer); + case DEV_DISCONNECT_AFTER: + next = (void *)io_close_cb; + break; + case DEV_DISCONNECT_BLACKHOLE: + dev_blackhole_fd(io_conn_fd(peer->to_peer)); + break; + case DEV_DISCONNECT_NORMAL: + break; + case DEV_DISCONNECT_DISABLE_AFTER: + next = dev_leave_hanging; + break; + } +#endif + + /* These are critical, and so send without delay. */ + if (type == WIRE_COMMITMENT_SIGNED + || type == WIRE_REVOKE_AND_ACK + || type == WIRE_PING + || type == WIRE_PONG) { + set_urgent_flag(peer, true); + } + + /* We free this and the encrypted version in next write_to_peer */ + peer->sent_to_peer = cryptomsg_encrypt_msg(peer, &peer->cs, msg); + return io_write(peer->to_peer, + peer->sent_to_peer, + tal_bytelen(peer->sent_to_peer), + next, peer); +} + +/* FIXME: Put in ccan/time */ +/* Is a before b? */ +static inline bool timemono_before(struct timemono a, struct timemono b) +{ + return time_less_(a.ts, b.ts); +} + +/* Kicks off write_to_peer() to look for more gossip to send from store */ +static void wake_gossip(struct peer *peer) +{ + peer->gs.active = true; + io_wake(peer->peer_outq); + + /* And go again in 60 seconds (from now, now when we finish!) */ + peer->gs.gossip_timer = gossip_stream_timer(peer); +} + +/* If we are streaming gossip, get something from gossip store */ +static u8 *maybe_from_gossip_store(const tal_t *ctx, struct peer *peer) +{ + u8 *msg; + + /* Not streaming yet? */ + if (!peer->gs.active) + return NULL; + + /* This should be around to kick us every 60 seconds */ + assert(peer->gs.gossip_timer); + +again: + msg = gossip_store_next(ctx, &peer->daemon->gossip_store_fd, + peer->gs.timestamp_min, + peer->gs.timestamp_max, + &peer->gs.off, + &peer->daemon->gossip_store_end); + /* Don't send back gossip they sent to us! */ + if (msg) { + status_peer_debug(&peer->id, + "Sending gossip %s", + peer_wire_name(fromwire_peektype(msg))); + if (gossip_rcvd_filter_del(peer->gs.grf, msg)) { + msg = tal_free(msg); + goto again; + } + status_peer_io(LOG_IO_OUT, &peer->id, msg); + return msg; + } + + peer->gs.active = false; + return NULL; +} + +/* Mutual recursion */ +static void send_ping(struct peer *peer); + +static void set_ping_timer(struct peer *peer) +{ + peer->ping_timer = new_reltimer(&peer->daemon->timers, peer, + time_from_sec(15 + pseudorand(30)), + send_ping, peer); +} + +static void send_ping(struct peer *peer) +{ + /* Already have a ping in flight? */ + if (peer->expecting_pong != PONG_UNEXPECTED) { + status_peer_debug(&peer->id, "Last ping unreturned: hanging up"); + if (peer->to_peer) + io_close(peer->to_peer); + return; + } + + queue_peer_msg(peer, take(make_ping(NULL, 1, 0))); + peer->expecting_pong = PONG_EXPECTED_PROBING; + set_ping_timer(peer); +} + +static void handle_ping_in(struct peer *peer, const u8 *msg) +{ + u8 *pong; + + if (!check_ping_make_pong(NULL, msg, &pong)) { + send_warning(peer, "Invalid ping %s", tal_hex(msg, msg)); + return; + } + + if (pong) + queue_peer_msg(peer, take(pong)); +} + +static void handle_ping_reply(struct peer *peer, const u8 *msg) +{ + u8 *ignored; + size_t i; + + /* We print this out because we asked for pong, so can't spam us... */ + if (!fromwire_pong(msg, msg, &ignored)) + status_peer_unusual(&peer->id, "Got malformed ping reply %s", + tal_hex(tmpctx, msg)); + + /* We print this because dev versions of c-lightning embed + * version here: see check_ping_make_pong! */ + for (i = 0; i < tal_count(ignored); i++) { + if (ignored[i] < ' ' || ignored[i] == 127) + break; + } + status_debug("Got pong %zu bytes (%.*s...)", + tal_count(ignored), (int)i, (char *)ignored); + daemon_conn_send(peer->daemon->master, + take(towire_connectd_ping_reply(NULL, true, + tal_bytelen(msg)))); +} + +static void handle_pong_in(struct peer *peer, const u8 *msg) +{ + switch (peer->expecting_pong) { + case PONG_EXPECTED_COMMAND: + handle_ping_reply(peer, msg); + /* fall thru */ + case PONG_EXPECTED_PROBING: + peer->expecting_pong = PONG_UNEXPECTED; + return; + case PONG_UNEXPECTED: + status_debug("Unexpected pong?"); + return; + } + abort(); +} + +/* Forward to gossipd */ +static void handle_gossip_in(struct peer *peer, const u8 *msg) +{ + u8 *gmsg = towire_gossipd_recv_gossip(NULL, &peer->id, msg); + daemon_conn_send(peer->daemon->gossipd, take(gmsg)); +} + +static void handle_gossip_timetamp_filter_in(struct peer *peer, const u8 *msg) +{ + struct bitcoin_blkid chain_hash; + u32 first_timestamp, timestamp_range; + + if (!fromwire_gossip_timestamp_filter(msg, &chain_hash, + &first_timestamp, + ×tamp_range)) { + send_warning(peer, "gossip_timestamp_filter invalid: %s", + tal_hex(tmpctx, msg)); + return; + } + + if (!bitcoin_blkid_eq(&chainparams->genesis_blockhash, &chain_hash)) { + send_warning(peer, "gossip_timestamp_filter for bad chain: %s", + tal_hex(tmpctx, msg)); + return; + } + + peer->gs.timestamp_min = first_timestamp; + peer->gs.timestamp_max = first_timestamp + timestamp_range - 1; + /* Make sure we never leave it on an impossible value. */ + if (peer->gs.timestamp_max < peer->gs.timestamp_min) + peer->gs.timestamp_max = UINT32_MAX; + + peer->gs.off = 1; + + /* BOLT #7: + * - MAY wait for the next outgoing gossip flush to send these. + */ + /* We send immediately the first time, after that we wait. */ + if (!peer->gs.gossip_timer) + wake_gossip(peer); +} + +/* We handle pings and gossip messages. */ +static bool handle_message_locally(struct peer *peer, const u8 *msg) +{ + enum peer_wire type = fromwire_peektype(msg); + + /* We remember these so we don't rexmit them */ + if (is_msg_gossip_broadcast(msg)) + gossip_rcvd_filter_add(peer->gs.grf, msg); + + if (type == WIRE_GOSSIP_TIMESTAMP_FILTER) { + handle_gossip_timetamp_filter_in(peer, msg); + return true; + } else if (type == WIRE_PING) { + handle_ping_in(peer, msg); + return true; + } else if (type == WIRE_PONG) { + handle_pong_in(peer, msg); + return true; + } else if (type == WIRE_OBS2_ONION_MESSAGE) { + handle_obs2_onion_message(peer->daemon, peer, msg); + return true; + } else if (type == WIRE_ONION_MESSAGE) { + handle_onion_message(peer->daemon, peer, msg); + return true; + } + + /* Do we want to divert to gossipd? */ + if (is_msg_for_gossipd(msg)) { + handle_gossip_in(peer, msg); + return true; + } + + return false; +} + +static struct io_plan *write_to_peer(struct io_conn *peer_conn, + struct peer *peer) +{ + const u8 *msg; + assert(peer->to_peer == peer_conn); + + /* Free last sent one (if any) */ + peer->sent_to_peer = tal_free(peer->sent_to_peer); + + /* Pop tail of send queue */ + msg = msg_dequeue(peer->peer_outq); + + /* Nothing to send? */ + if (!msg) { + /* Send final once subd is not longer connected */ + if (peer->final_msg && !peer->to_subd) { + return encrypt_and_send(peer, + peer->final_msg, + after_final_msg); + } + + /* If they want us to send gossip, do so now. */ + msg = maybe_from_gossip_store(NULL, peer); + if (!msg) { + /* Reset urgent flag, if set. */ + set_urgent_flag(peer, false); + + /* Tell them to read again, */ + io_wake(&peer->subd_in); + + /* Wait for them to wake us */ + return msg_queue_wait(peer_conn, peer->peer_outq, + write_to_peer, peer); + } + } + + return encrypt_and_send(peer, take(msg), write_to_peer); +} + +static struct io_plan *read_from_subd(struct io_conn *subd_conn, + struct peer *peer); +static struct io_plan *read_from_subd_done(struct io_conn *subd_conn, + struct peer *peer) +{ + /* Tell them to encrypt & write. */ + queue_peer_msg(peer, take(peer->subd_in)); + peer->subd_in = NULL; + + /* Wait for them to wake us */ + return io_wait(subd_conn, &peer->subd_in, read_from_subd, peer); +} + +static struct io_plan *read_from_subd(struct io_conn *subd_conn, + struct peer *peer) +{ + return io_read_wire(subd_conn, peer, &peer->subd_in, + read_from_subd_done, peer); +} + +/* These four function handle peer->subd */ +static struct io_plan *write_to_subd(struct io_conn *subd_conn, + struct peer *peer) +{ + const u8 *msg; + assert(peer->to_subd == subd_conn); + + /* Pop tail of send queue */ + msg = msg_dequeue(peer->subd_outq); + + /* Nothing to send? */ + if (!msg) { + /* Tell them to read again. */ + io_wake(&peer->peer_in); + + /* Wait for them to wake us */ + return msg_queue_wait(subd_conn, peer->subd_outq, + write_to_subd, peer); + } + + return io_write_wire(subd_conn, take(msg), write_to_subd, peer); +} + +static struct io_plan *read_hdr_from_peer(struct io_conn *peer_conn, + struct peer *peer); +static struct io_plan *read_body_from_peer_done(struct io_conn *peer_conn, + struct peer *peer) +{ + u8 *decrypted; + + decrypted = cryptomsg_decrypt_body(NULL, &peer->cs, + peer->peer_in); + if (!decrypted) + return io_close(peer_conn); + tal_free(peer->peer_in); + + /* If we swallow this, just try again. */ + if (handle_message_locally(peer, decrypted)) { + tal_free(decrypted); + return read_hdr_from_peer(peer_conn, peer); + } + + /* Tell them to write. */ + msg_enqueue(peer->subd_outq, take(decrypted)); + + /* Wait for them to wake us */ + return io_wait(peer_conn, &peer->peer_in, read_hdr_from_peer, peer); +} + +static struct io_plan *read_body_from_peer(struct io_conn *peer_conn, + struct peer *peer) +{ + u16 len; + + if (!cryptomsg_decrypt_header(&peer->cs, peer->peer_in, &len)) + return io_close(peer_conn); + + tal_resize(&peer->peer_in, (u32)len + CRYPTOMSG_BODY_OVERHEAD); + return io_read(peer_conn, peer->peer_in, tal_count(peer->peer_in), + read_body_from_peer_done, peer); +} + +static struct io_plan *read_hdr_from_peer(struct io_conn *peer_conn, + struct peer *peer) +{ + assert(peer->to_peer == peer_conn); + + /* BOLT #8: + * + * ### Receiving and Decrypting Messages + * + * In order to decrypt the _next_ message in the network + * stream, the following steps are completed: + * + * 1. Read _exactly_ 18 bytes from the network buffer. + */ + peer->peer_in = tal_arr(peer, u8, CRYPTOMSG_HDR_SIZE); + return io_read(peer_conn, peer->peer_in, CRYPTOMSG_HDR_SIZE, + read_body_from_peer, peer); +} + +static struct io_plan *subd_conn_init(struct io_conn *subd_conn, struct peer *peer) +{ + peer->to_subd = subd_conn; + return io_duplex(subd_conn, + read_from_subd(subd_conn, peer), + write_to_subd(subd_conn, peer)); +} + +static void destroy_subd_conn(struct io_conn *subd_conn, struct peer *peer) +{ + assert(subd_conn == peer->to_subd); + peer->to_subd = NULL; + /* In case they were waiting for this to send final_msg */ + if (peer->final_msg) + msg_wake(peer->peer_outq); +} + +bool multiplex_subd_setup(struct peer *peer, int *fd_for_subd) +{ + int fds[2]; + + if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds) != 0) { + status_broken("Failed to create socketpair: %s", + strerror(errno)); + return false; + } + peer->to_subd = io_new_conn(peer, fds[0], subd_conn_init, peer); + tal_add_destructor2(peer->to_subd, destroy_subd_conn, peer); + *fd_for_subd = fds[1]; + return true; +} + +static void destroy_peer_conn(struct io_conn *peer_conn, struct peer *peer) +{ + assert(peer->to_peer == peer_conn); + peer->to_peer = NULL; + + /* Close internal connections if not already. */ + if (peer->to_subd) + io_close(peer->to_subd); +} + +struct io_plan *multiplex_peer_setup(struct io_conn *peer_conn, + struct peer *peer) +{ + /*~ If conn closes, we close the subd connections and wait for + * lightningd to tell us to close with the peer */ + tal_add_destructor2(peer_conn, destroy_peer_conn, peer); + + return io_duplex(peer_conn, + read_hdr_from_peer(peer_conn, peer), + write_to_peer(peer_conn, peer)); +} + +void multiplex_final_msg(struct peer *peer, const u8 *final_msg TAKES) +{ + peer->final_msg = tal_dup_talarr(peer, u8, final_msg); + if (!peer->to_subd) + io_wake(peer->peer_outq); +} + +/* Lightningd says to send a ping */ +void send_manual_ping(struct daemon *daemon, const u8 *msg) +{ + u8 *ping; + struct node_id id; + u16 len, num_pong_bytes; + struct peer *peer; + + if (!fromwire_connectd_ping(msg, &id, &num_pong_bytes, &len)) + master_badmsg(WIRE_CONNECTD_PING, msg); + + peer = peer_htable_get(&daemon->peers, &id); + if (!peer) { + daemon_conn_send(daemon->master, + take(towire_connectd_ping_reply(NULL, + false, 0))); + return; + } + + /* We're not supposed to send another ping until previous replied */ + if (peer->expecting_pong != PONG_UNEXPECTED) { + daemon_conn_send(daemon->master, + take(towire_connectd_ping_reply(NULL, + false, 0))); + return; + } + + /* It should never ask for an oversize ping. */ + ping = make_ping(NULL, num_pong_bytes, len); + if (tal_count(ping) > 65535) + status_failed(STATUS_FAIL_MASTER_IO, "Oversize ping"); + + queue_peer_msg(peer, take(ping)); + + status_debug("sending ping expecting %sresponse", + num_pong_bytes >= 65532 ? "no " : ""); + + /* BOLT #1: + * + * A node receiving a `ping` message: + *... + * - if `num_pong_bytes` is less than 65532: + * - MUST respond by sending a `pong` message, with `byteslen` equal + * to `num_pong_bytes`. + * - otherwise (`num_pong_bytes` is **not** less than 65532): + * - MUST ignore the `ping`. + */ + if (num_pong_bytes >= 65532) { + daemon_conn_send(daemon->master, + take(towire_connectd_ping_reply(NULL, + true, 0))); + return; + } + + /* We'll respond to lightningd once the pong comes in */ + peer->expecting_pong = PONG_EXPECTED_COMMAND; + + /* Since we're doing this manually, kill and restart timer. */ + tal_free(peer->ping_timer); + set_ping_timer(peer); +} + +void send_custommsg(struct daemon *daemon, const u8 *msg) +{ + struct node_id id; + u8 *custommsg; + struct peer *peer; + + if (!fromwire_connectd_custommsg_out(tmpctx, msg, &id, &custommsg)) + master_badmsg(WIRE_CONNECTD_CUSTOMMSG_OUT, msg); + + /* Races can happen: this might be gone by now. */ + peer = peer_htable_get(&daemon->peers, &id); + if (peer) + queue_peer_msg(peer, take(custommsg)); +} diff --git a/connectd/multiplex.h b/connectd/multiplex.h new file mode 100644 index 000000000000..7b8db8bcd209 --- /dev/null +++ b/connectd/multiplex.h @@ -0,0 +1,36 @@ +#ifndef LIGHTNING_CONNECTD_MULTIPLEX_H +#define LIGHTNING_CONNECTD_MULTIPLEX_H +#include "config.h" +#include +#include +#include +#include + +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); + +/* Send this message to peer and disconnect. */ +void multiplex_final_msg(struct peer *peer, + const u8 *final_msg TAKES); + +/* Inject a message into the output stream */ +void queue_peer_msg(struct peer *peer, const u8 *msg TAKES); + +void setup_peer_gossip_store(struct peer *peer, + const struct feature_set *our_features, + const u8 *their_features); + +/* When lightningd says to send a ping */ +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); +#endif /* LIGHTNING_CONNECTD_MULTIPLEX_H */ diff --git a/connectd/onion_message.c b/connectd/onion_message.c new file mode 100644 index 000000000000..f19594899172 --- /dev/null +++ b/connectd/onion_message.c @@ -0,0 +1,345 @@ +/*~ This contains all the code to handle onion messages. */ +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Peer sends obsolete onion msg. */ +void handle_obs2_onion_message(struct daemon *daemon, + struct peer *peer, const u8 *msg) +{ + enum onion_wire badreason; + struct onionpacket *op; + struct pubkey blinding, ephemeral; + struct route_step *rs; + u8 *onion; + struct tlv_obs2_onionmsg_payload *om; + struct secret ss, onion_ss; + const u8 *cursor; + size_t max, maxlen; + + /* Ignore unless explicitly turned on. */ + if (!feature_offered(daemon->our_features->bits[NODE_ANNOUNCE_FEATURE], + OPT_ONION_MESSAGES)) + return; + + /* FIXME: ratelimit! */ + if (!fromwire_obs2_onion_message(msg, msg, &blinding, &onion)) { + queue_peer_msg(peer, + towire_warningfmt(NULL, NULL, + "Bad onion_message")); + return; + } + + /* We unwrap the onion now. */ + op = parse_onionpacket(tmpctx, onion, tal_bytelen(onion), &badreason); + if (!op) { + status_peer_debug(&peer->id, "onion msg: can't parse onionpacket: %s", + onion_wire_name(badreason)); + return; + } + + ephemeral = op->ephemeralkey; + if (!unblind_onion(&blinding, ecdh, &ephemeral, &ss)) { + status_peer_debug(&peer->id, "onion msg: can't unblind onionpacket"); + return; + } + + /* Now get onion shared secret and parse it. */ + ecdh(&ephemeral, &onion_ss); + rs = process_onionpacket(tmpctx, op, &onion_ss, NULL, 0, false); + if (!rs) { + status_peer_debug(&peer->id, + "onion msg: can't process onionpacket ss=%s", + type_to_string(tmpctx, struct secret, &onion_ss)); + return; + } + + /* The raw payload is prepended with length in the modern onion. */ + cursor = rs->raw_payload; + max = tal_bytelen(rs->raw_payload); + maxlen = fromwire_bigsize(&cursor, &max); + if (!cursor) { + status_peer_debug(&peer->id, "onion msg: Invalid hop payload %s", + tal_hex(tmpctx, rs->raw_payload)); + return; + } + if (maxlen > max) { + status_peer_debug(&peer->id, "onion msg: overlong hop payload %s", + tal_hex(tmpctx, rs->raw_payload)); + return; + } + + om = tlv_obs2_onionmsg_payload_new(msg); + if (!fromwire_obs2_onionmsg_payload(&cursor, &maxlen, om)) { + status_peer_debug(&peer->id, "onion msg: invalid onionmsg_payload %s", + tal_hex(tmpctx, rs->raw_payload)); + return; + } + + if (rs->nextcase == ONION_END) { + struct pubkey *reply_blinding, *first_node_id, me, alias; + const struct onionmsg_path **reply_path; + struct secret *self_id; + u8 *omsg; + + if (!pubkey_from_node_id(&me, &daemon->id)) { + status_broken("Failed to convert own id"); + return; + } + + /* Final enctlv is actually optional */ + if (!om->enctlv) { + alias = me; + self_id = NULL; + } else if (!decrypt_obs2_final_enctlv(tmpctx, &blinding, &ss, + om->enctlv, &me, &alias, + &self_id)) { + status_peer_debug(&peer->id, + "onion msg: failed to decrypt enctlv" + " %s", tal_hex(tmpctx, om->enctlv)); + return; + } + + if (om->reply_path) { + first_node_id = &om->reply_path->first_node_id; + reply_blinding = &om->reply_path->blinding; + reply_path = cast_const2(const struct onionmsg_path **, + om->reply_path->path); + } else { + first_node_id = NULL; + reply_blinding = NULL; + reply_path = NULL; + } + + /* We re-marshall here by policy, before handing to lightningd */ + omsg = tal_arr(tmpctx, u8, 0); + towire_tlvstream_raw(&omsg, om->fields); + daemon_conn_send(daemon->master, + take(towire_connectd_got_onionmsg_to_us(NULL, + true, /* obs2 */ + &alias, self_id, + reply_blinding, + first_node_id, + reply_path, + omsg))); + } else { + struct pubkey next_node, next_blinding; + struct peer *next_peer; + struct node_id next_node_id; + + /* This fails as expected if no enctlv. */ + if (!decrypt_obs2_enctlv(&blinding, &ss, om->enctlv, &next_node, + &next_blinding)) { + status_peer_debug(&peer->id, + "onion msg: invalid enctlv %s", + tal_hex(tmpctx, om->enctlv)); + return; + } + + /* Even though lightningd checks for valid ids, there's a race + * where it might vanish before we read this command. */ + node_id_from_pubkey(&next_node_id, &next_node); + next_peer = peer_htable_get(&daemon->peers, &next_node_id); + if (!next_peer) { + status_peer_debug(&peer->id, + "onion msg: unknown next peer %s", + type_to_string(tmpctx, + struct pubkey, + &next_node)); + return; + } + queue_peer_msg(next_peer, + take(towire_obs2_onion_message(NULL, + &next_blinding, + serialize_onionpacket(tmpctx, rs->next)))); + } +} + +void onionmsg_req(struct daemon *daemon, const u8 *msg) +{ + struct node_id id; + u8 *onionmsg; + struct pubkey blinding; + struct peer *peer; + bool obs2; + + if (!fromwire_connectd_send_onionmsg(msg, msg, &obs2, &id, &onionmsg, &blinding)) + master_badmsg(WIRE_CONNECTD_SEND_ONIONMSG, msg); + + /* Even though lightningd checks for valid ids, there's a race + * where it might vanish before we read this command. */ + peer = peer_htable_get(&daemon->peers, &id); + if (peer) { + u8 *omsg; + if (obs2) + omsg = towire_obs2_onion_message(NULL, &blinding, onionmsg); + else + omsg = towire_onion_message(NULL, &blinding, onionmsg); + queue_peer_msg(peer, take(omsg)); + } +} + +/* Peer sends an onion msg. */ +void handle_onion_message(struct daemon *daemon, + struct peer *peer, const u8 *msg) +{ + enum onion_wire badreason; + struct onionpacket *op; + struct pubkey blinding, ephemeral; + struct route_step *rs; + u8 *onion; + struct tlv_onionmsg_payload *om; + struct secret ss, onion_ss; + const u8 *cursor; + size_t max, maxlen; + + /* Ignore unless explicitly turned on. */ + if (!feature_offered(daemon->our_features->bits[NODE_ANNOUNCE_FEATURE], + OPT_ONION_MESSAGES)) + return; + + /* FIXME: ratelimit! */ + if (!fromwire_onion_message(msg, msg, &blinding, &onion)) { + queue_peer_msg(peer, + towire_warningfmt(NULL, NULL, + "Bad onion_message")); + return; + } + + /* We unwrap the onion now. */ + op = parse_onionpacket(tmpctx, onion, tal_bytelen(onion), &badreason); + if (!op) { + status_peer_debug(&peer->id, "onion msg: can't parse onionpacket: %s", + onion_wire_name(badreason)); + return; + } + + ephemeral = op->ephemeralkey; + if (!unblind_onion(&blinding, ecdh, &ephemeral, &ss)) { + status_peer_debug(&peer->id, "onion msg: can't unblind onionpacket"); + return; + } + + /* Now get onion shared secret and parse it. */ + ecdh(&ephemeral, &onion_ss); + rs = process_onionpacket(tmpctx, op, &onion_ss, NULL, 0, false); + if (!rs) { + status_peer_debug(&peer->id, + "onion msg: can't process onionpacket ss=%s", + type_to_string(tmpctx, struct secret, &onion_ss)); + return; + } + + /* The raw payload is prepended with length in the modern onion. */ + cursor = rs->raw_payload; + max = tal_bytelen(rs->raw_payload); + maxlen = fromwire_bigsize(&cursor, &max); + if (!cursor) { + status_peer_debug(&peer->id, "onion msg: Invalid hop payload %s", + tal_hex(tmpctx, rs->raw_payload)); + return; + } + if (maxlen > max) { + status_peer_debug(&peer->id, "onion msg: overlong hop payload %s", + tal_hex(tmpctx, rs->raw_payload)); + return; + } + + om = tlv_onionmsg_payload_new(msg); + if (!fromwire_onionmsg_payload(&cursor, &maxlen, om)) { + status_peer_debug(&peer->id, "onion msg: invalid onionmsg_payload %s", + tal_hex(tmpctx, rs->raw_payload)); + return; + } + + if (rs->nextcase == ONION_END) { + struct pubkey *reply_blinding, *first_node_id, me, alias; + const struct onionmsg_path **reply_path; + struct secret *self_id; + u8 *omsg; + + if (!pubkey_from_node_id(&me, &daemon->id)) { + status_broken("Failed to convert own id"); + return; + } + + /* Final enctlv is actually optional */ + if (!om->encrypted_data_tlv) { + alias = me; + self_id = NULL; + } else if (!decrypt_final_enctlv(tmpctx, &blinding, &ss, + om->encrypted_data_tlv, &me, &alias, + &self_id)) { + status_peer_debug(&peer->id, + "onion msg: failed to decrypt enctlv" + " %s", tal_hex(tmpctx, om->encrypted_data_tlv)); + return; + } + + if (om->reply_path) { + first_node_id = &om->reply_path->first_node_id; + reply_blinding = &om->reply_path->blinding; + reply_path = cast_const2(const struct onionmsg_path **, + om->reply_path->path); + } else { + first_node_id = NULL; + reply_blinding = NULL; + reply_path = NULL; + } + + /* We re-marshall here by policy, before handing to lightningd */ + omsg = tal_arr(tmpctx, u8, 0); + towire_tlvstream_raw(&omsg, om->fields); + daemon_conn_send(daemon->master, + take(towire_connectd_got_onionmsg_to_us(NULL, + false, /* !obs2 */ + &alias, self_id, + reply_blinding, + first_node_id, + reply_path, + omsg))); + } else { + struct pubkey next_node, next_blinding; + struct peer *next_peer; + struct node_id next_node_id; + + /* This fails as expected if no enctlv. */ + if (!decrypt_enctlv(&blinding, &ss, om->encrypted_data_tlv, &next_node, + &next_blinding)) { + status_peer_debug(&peer->id, + "onion msg: invalid enctlv %s", + tal_hex(tmpctx, om->encrypted_data_tlv)); + return; + } + + /* FIXME: Handle short_channel_id! */ + node_id_from_pubkey(&next_node_id, &next_node); + next_peer = peer_htable_get(&daemon->peers, &next_node_id); + if (!next_peer) { + status_peer_debug(&peer->id, + "onion msg: unknown next peer %s", + type_to_string(tmpctx, + struct pubkey, + &next_node)); + return; + } + queue_peer_msg(next_peer, + take(towire_onion_message(NULL, + &next_blinding, + serialize_onionpacket(tmpctx, rs->next)))); + } +} + diff --git a/connectd/onion_message.h b/connectd/onion_message.h new file mode 100644 index 000000000000..22fc9bb8b4a4 --- /dev/null +++ b/connectd/onion_message.h @@ -0,0 +1,15 @@ +#ifndef LIGHTNING_CONNECTD_ONION_MESSAGE_H +#define LIGHTNING_CONNECTD_ONION_MESSAGE_H +#include "config.h" +#include + +/* Various messages come in from peer */ +void handle_obs2_onion_message(struct daemon *daemon, + struct peer *peer, const u8 *msg); +void handle_onion_message(struct daemon *daemon, + struct peer *peer, const u8 *msg); + +/* Lightningd tells us to send an onion message */ +void onionmsg_req(struct daemon *daemon, const u8 *msg); + +#endif /* LIGHTNING_CONNECTD_ONION_MESSAGE_H */ diff --git a/connectd/peer_exchange_initmsg.c b/connectd/peer_exchange_initmsg.c index 9398bb75adad..aa6aa0da8f88 100644 --- a/connectd/peer_exchange_initmsg.c +++ b/connectd/peer_exchange_initmsg.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -10,7 +11,7 @@ #include /* Temporary structure for us to read peer message in */ -struct peer { +struct early_peer { struct daemon *daemon; /* The ID of the peer */ @@ -38,10 +39,10 @@ static bool contains_common_chain(struct bitcoin_blkid *chains) } /* Here in case we need to read another message. */ -static struct io_plan *read_init(struct io_conn *conn, struct peer *peer); +static struct io_plan *read_init(struct io_conn *conn, struct early_peer *peer); static struct io_plan *peer_init_received(struct io_conn *conn, - struct peer *peer) + struct early_peer *peer) { u8 *msg = cryptomsg_decrypt_body(tmpctx, &peer->cs, peer->msg); u8 *globalfeatures, *features; @@ -89,6 +90,9 @@ static struct io_plan *peer_init_received(struct io_conn *conn, * window where it was: combine the two. */ features = featurebits_or(tmpctx, take(features), globalfeatures); + /* We can dispose of peer after next call. */ + tal_steal(tmpctx, peer); + /* Usually return io_close_taken_fd, but may wait for old peer to * be disconnected if it's a reconnect. */ return peer_connected(conn, peer->daemon, &peer->id, @@ -98,7 +102,7 @@ static struct io_plan *peer_init_received(struct io_conn *conn, } static struct io_plan *peer_init_hdr_received(struct io_conn *conn, - struct peer *peer) + struct early_peer *peer) { u16 len; @@ -111,7 +115,7 @@ static struct io_plan *peer_init_hdr_received(struct io_conn *conn, peer_init_received, peer); } -static struct io_plan *read_init(struct io_conn *conn, struct peer *peer) +static struct io_plan *read_init(struct io_conn *conn, struct early_peer *peer) { /* Free our sent init msg. */ tal_free(peer->msg); @@ -128,14 +132,14 @@ static struct io_plan *read_init(struct io_conn *conn, struct peer *peer) #if DEVELOPER static struct io_plan *peer_write_postclose(struct io_conn *conn, - struct peer *peer) + struct early_peer *peer) { dev_sabotage_fd(io_conn_fd(conn), true); return read_init(conn, peer); } static struct io_plan *peer_write_post_sabotage(struct io_conn *conn, - struct peer *peer) + struct early_peer *peer) { dev_sabotage_fd(io_conn_fd(conn), false); return read_init(conn, peer); @@ -148,11 +152,12 @@ struct io_plan *peer_exchange_initmsg(struct io_conn *conn, const struct crypto_state *cs, const struct node_id *id, const struct wireaddr_internal *addr, + struct oneshot *timeout, bool incoming) { /* If conn is closed, forget peer */ - struct peer *peer = tal(conn, struct peer); - struct io_plan *(*next)(struct io_conn *, struct peer *); + struct early_peer *peer = tal(conn, struct early_peer); + struct io_plan *(*next)(struct io_conn *, struct early_peer *); struct tlv_init_tlvs *tlvs; peer->daemon = daemon; @@ -161,6 +166,9 @@ struct io_plan *peer_exchange_initmsg(struct io_conn *conn, peer->cs = *cs; peer->incoming = incoming; + /* Attach timer to early peer, so it gets freed with it. */ + notleak(tal_steal(peer, timeout)); + /* BOLT #1: * * The sending node: @@ -200,12 +208,10 @@ struct io_plan *peer_exchange_initmsg(struct io_conn *conn, next = read_init; #if DEVELOPER - switch (dev_disconnect(WIRE_INIT)) { + switch (dev_disconnect(&peer->id, WIRE_INIT)) { case DEV_DISCONNECT_BEFORE: dev_sabotage_fd(io_conn_fd(conn), true); break; - case DEV_DISCONNECT_DROPPKT: - peer->msg = tal_free(peer->msg); /* FALL THRU */ case DEV_DISCONNECT_AFTER: next = peer_write_postclose; break; diff --git a/connectd/peer_exchange_initmsg.h b/connectd/peer_exchange_initmsg.h index 6a3c8a24397d..eb654aaa73c0 100644 --- a/connectd/peer_exchange_initmsg.h +++ b/connectd/peer_exchange_initmsg.h @@ -8,6 +8,7 @@ struct daemon; struct io_conn; struct node_id; struct wireaddr_internal; +struct oneshot; /* If successful, calls peer_connected() */ struct io_plan *peer_exchange_initmsg(struct io_conn *conn, @@ -16,6 +17,7 @@ struct io_plan *peer_exchange_initmsg(struct io_conn *conn, const struct crypto_state *cs, const struct node_id *id, const struct wireaddr_internal *addr, + struct oneshot *timeout, bool incoming); #endif /* LIGHTNING_CONNECTD_PEER_EXCHANGE_INITMSG_H */ diff --git a/connectd/test/run-initiator-success.c b/connectd/test/run-initiator-success.c index 27bb98bc9e03..73e35875f5ce 100644 --- a/connectd/test/run-initiator-success.c +++ b/connectd/test/run-initiator-success.c @@ -278,6 +278,7 @@ static struct io_plan *success(struct io_conn *conn UNUSED, const struct pubkey *them, const struct wireaddr_internal *addr UNUSED, struct crypto_state *cs, + struct oneshot *timeout UNUSED, void *unused UNUSED) { assert(pubkey_eq(them, &rs_pub)); @@ -320,7 +321,7 @@ int main(int argc, char *argv[]) dummy.itype = ADDR_INTERNAL_WIREADDR; dummy.u.wireaddr.addrlen = 0; - initiator_handshake((void *)tmpctx, &ls_pub, &rs_pub, &dummy, success, NULL); + initiator_handshake((void *)tmpctx, &ls_pub, &rs_pub, &dummy, NULL, success, NULL); /* Should not exit! */ abort(); } diff --git a/connectd/test/run-onion_message.c b/connectd/test/run-onion_message.c new file mode 100644 index 000000000000..ab00545a8c19 --- /dev/null +++ b/connectd/test/run-onion_message.c @@ -0,0 +1,488 @@ +#include "config.h" +#include "../onion_message.c" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } +/* Generated stub for amount_sat */ +struct amount_sat amount_sat(u64 satoshis UNNEEDED) +{ fprintf(stderr, "amount_sat called!\n"); abort(); } +/* Generated stub for amount_sat_add */ + bool amount_sat_add(struct amount_sat *val UNNEEDED, + struct amount_sat a UNNEEDED, + struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_add called!\n"); abort(); } +/* Generated stub for amount_sat_eq */ +bool amount_sat_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_eq called!\n"); abort(); } +/* Generated stub for amount_sat_greater_eq */ +bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_greater_eq called!\n"); abort(); } +/* Generated stub for amount_sat_sub */ + bool amount_sat_sub(struct amount_sat *val UNNEEDED, + struct amount_sat a UNNEEDED, + struct amount_sat b UNNEEDED) +{ fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } +/* Generated stub for amount_tx_fee */ +struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) +{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); } +/* Generated stub for daemon_conn_send */ +void daemon_conn_send(struct daemon_conn *dc UNNEEDED, const u8 *msg UNNEEDED) +{ fprintf(stderr, "daemon_conn_send called!\n"); abort(); } +/* Generated stub for decrypt_enctlv */ +bool decrypt_enctlv(const struct pubkey *blinding UNNEEDED, + const struct secret *ss UNNEEDED, + const u8 *enctlv UNNEEDED, + struct pubkey *next_node UNNEEDED, + struct pubkey *next_blinding) + +{ fprintf(stderr, "decrypt_enctlv called!\n"); abort(); } +/* Generated stub for decrypt_final_enctlv */ +bool decrypt_final_enctlv(const tal_t *ctx UNNEEDED, + const struct pubkey *blinding UNNEEDED, + const struct secret *ss UNNEEDED, + const u8 *enctlv UNNEEDED, + const struct pubkey *my_id UNNEEDED, + struct pubkey *alias UNNEEDED, + struct secret **path_id) + +{ fprintf(stderr, "decrypt_final_enctlv called!\n"); abort(); } +/* Generated stub for decrypt_obs2_enctlv */ +bool decrypt_obs2_enctlv(const struct pubkey *blinding UNNEEDED, + const struct secret *ss UNNEEDED, + const u8 *enctlv UNNEEDED, + struct pubkey *next_node UNNEEDED, + struct pubkey *next_blinding) + +{ fprintf(stderr, "decrypt_obs2_enctlv called!\n"); abort(); } +/* Generated stub for decrypt_obs2_final_enctlv */ +bool decrypt_obs2_final_enctlv(const tal_t *ctx UNNEEDED, + const struct pubkey *blinding UNNEEDED, + const struct secret *ss UNNEEDED, + const u8 *enctlv UNNEEDED, + const struct pubkey *my_id UNNEEDED, + struct pubkey *alias UNNEEDED, + struct secret **self_id) + +{ fprintf(stderr, "decrypt_obs2_final_enctlv called!\n"); abort(); } +/* Generated stub for ecdh */ +void ecdh(const struct pubkey *point UNNEEDED, struct secret *ss UNNEEDED) +{ fprintf(stderr, "ecdh called!\n"); abort(); } +/* Generated stub for fromwire */ +const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED) +{ fprintf(stderr, "fromwire called!\n"); abort(); } +/* Generated stub for fromwire_bigsize */ +bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_bigsize called!\n"); abort(); } +/* Generated stub for fromwire_bool */ +bool fromwire_bool(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_bool called!\n"); abort(); } +/* Generated stub for fromwire_connectd_send_onionmsg */ +bool fromwire_connectd_send_onionmsg(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, bool *obs2 UNNEEDED, struct node_id *id UNNEEDED, u8 **onion UNNEEDED, struct pubkey *blinding UNNEEDED) +{ fprintf(stderr, "fromwire_connectd_send_onionmsg called!\n"); abort(); } +/* Generated stub for fromwire_fail */ +void *fromwire_fail(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_fail called!\n"); abort(); } +/* Generated stub for fromwire_obs2_onion_message */ +bool fromwire_obs2_onion_message(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct pubkey *blinding UNNEEDED, u8 **onionmsg UNNEEDED) +{ fprintf(stderr, "fromwire_obs2_onion_message called!\n"); abort(); } +/* Generated stub for fromwire_obs2_onionmsg_payload */ +bool fromwire_obs2_onionmsg_payload(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, + struct tlv_obs2_onionmsg_payload * record UNNEEDED) +{ fprintf(stderr, "fromwire_obs2_onionmsg_payload called!\n"); abort(); } +/* Generated stub for fromwire_onion_message */ +bool fromwire_onion_message(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct pubkey *blinding UNNEEDED, u8 **onionmsg UNNEEDED) +{ fprintf(stderr, "fromwire_onion_message called!\n"); abort(); } +/* Generated stub for fromwire_onionmsg_payload */ +bool fromwire_onionmsg_payload(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, + struct tlv_onionmsg_payload * record UNNEEDED) +{ fprintf(stderr, "fromwire_onionmsg_payload called!\n"); abort(); } +/* Generated stub for fromwire_secp256k1_ecdsa_signature */ +void fromwire_secp256k1_ecdsa_signature(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, + secp256k1_ecdsa_signature *signature UNNEEDED) +{ fprintf(stderr, "fromwire_secp256k1_ecdsa_signature called!\n"); abort(); } +/* Generated stub for fromwire_sha256 */ +void fromwire_sha256(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct sha256 *sha256 UNNEEDED) +{ fprintf(stderr, "fromwire_sha256 called!\n"); abort(); } +/* Generated stub for fromwire_tal_arrn */ +u8 *fromwire_tal_arrn(const tal_t *ctx UNNEEDED, + const u8 **cursor UNNEEDED, size_t *max UNNEEDED, size_t num UNNEEDED) +{ fprintf(stderr, "fromwire_tal_arrn called!\n"); abort(); } +/* Generated stub for fromwire_u16 */ +u16 fromwire_u16(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_u16 called!\n"); abort(); } +/* Generated stub for fromwire_u32 */ +u32 fromwire_u32(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_u32 called!\n"); abort(); } +/* Generated stub for fromwire_u64 */ +u64 fromwire_u64(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_u64 called!\n"); abort(); } +/* Generated stub for fromwire_u8 */ +u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) +{ fprintf(stderr, "fromwire_u8 called!\n"); abort(); } +/* Generated stub for fromwire_u8_array */ +void fromwire_u8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, u8 *arr UNNEEDED, size_t num UNNEEDED) +{ fprintf(stderr, "fromwire_u8_array called!\n"); abort(); } +/* Generated stub for master_badmsg */ +void master_badmsg(u32 type_expected UNNEEDED, const u8 *msg) +{ fprintf(stderr, "master_badmsg called!\n"); abort(); } +/* Generated stub for node_id_from_pubkey */ +void node_id_from_pubkey(struct node_id *id UNNEEDED, const struct pubkey *key UNNEEDED) +{ fprintf(stderr, "node_id_from_pubkey called!\n"); abort(); } +/* Generated stub for onion_wire_name */ +const char *onion_wire_name(int e UNNEEDED) +{ fprintf(stderr, "onion_wire_name called!\n"); abort(); } +/* Generated stub for parse_onionpacket */ +struct onionpacket *parse_onionpacket(const tal_t *ctx UNNEEDED, + const u8 *src UNNEEDED, + const size_t srclen UNNEEDED, + enum onion_wire *failcode UNNEEDED) +{ fprintf(stderr, "parse_onionpacket called!\n"); abort(); } +/* Generated stub for process_onionpacket */ +struct route_step *process_onionpacket( + const tal_t * ctx UNNEEDED, + const struct onionpacket *packet UNNEEDED, + const struct secret *shared_secret UNNEEDED, + const u8 *assocdata UNNEEDED, + const size_t assocdatalen UNNEEDED, + bool has_realm + ) +{ fprintf(stderr, "process_onionpacket called!\n"); abort(); } +/* Generated stub for pubkey_from_node_id */ +bool pubkey_from_node_id(struct pubkey *key UNNEEDED, const struct node_id *id UNNEEDED) +{ fprintf(stderr, "pubkey_from_node_id called!\n"); abort(); } +/* Generated stub for queue_peer_msg */ +void queue_peer_msg(struct peer *peer UNNEEDED, const u8 *msg TAKES UNNEEDED) +{ fprintf(stderr, "queue_peer_msg called!\n"); abort(); } +/* Generated stub for serialize_onionpacket */ +u8 *serialize_onionpacket( + const tal_t *ctx UNNEEDED, + const struct onionpacket *packet UNNEEDED) +{ fprintf(stderr, "serialize_onionpacket called!\n"); abort(); } +/* Generated stub for status_fmt */ +void status_fmt(enum log_level level UNNEEDED, + const struct node_id *peer UNNEEDED, + const char *fmt UNNEEDED, ...) + +{ fprintf(stderr, "status_fmt called!\n"); abort(); } +/* Generated stub for subkey_from_hmac */ +void subkey_from_hmac(const char *prefix UNNEEDED, + const struct secret *base UNNEEDED, + struct secret *key UNNEEDED) +{ fprintf(stderr, "subkey_from_hmac called!\n"); abort(); } +/* Generated stub for tlv_obs2_onionmsg_payload_new */ +struct tlv_obs2_onionmsg_payload *tlv_obs2_onionmsg_payload_new(const tal_t *ctx UNNEEDED) +{ fprintf(stderr, "tlv_obs2_onionmsg_payload_new called!\n"); abort(); } +/* Generated stub for tlv_onionmsg_payload_new */ +struct tlv_onionmsg_payload *tlv_onionmsg_payload_new(const tal_t *ctx UNNEEDED) +{ fprintf(stderr, "tlv_onionmsg_payload_new called!\n"); abort(); } +/* Generated stub for towire */ +void towire(u8 **pptr UNNEEDED, const void *data UNNEEDED, size_t len UNNEEDED) +{ fprintf(stderr, "towire called!\n"); abort(); } +/* Generated stub for towire_bool */ +void towire_bool(u8 **pptr UNNEEDED, bool v UNNEEDED) +{ fprintf(stderr, "towire_bool called!\n"); abort(); } +/* Generated stub for towire_connectd_got_onionmsg_to_us */ +u8 *towire_connectd_got_onionmsg_to_us(const tal_t *ctx UNNEEDED, bool obs2 UNNEEDED, const struct pubkey *node_alias UNNEEDED, const struct secret *self_id UNNEEDED, const struct pubkey *reply_blinding UNNEEDED, const struct pubkey *reply_first_node UNNEEDED, const struct onionmsg_path **reply_path UNNEEDED, const u8 *rawmsg UNNEEDED) +{ fprintf(stderr, "towire_connectd_got_onionmsg_to_us called!\n"); abort(); } +/* Generated stub for towire_obs2_onion_message */ +u8 *towire_obs2_onion_message(const tal_t *ctx UNNEEDED, const struct pubkey *blinding UNNEEDED, const u8 *onionmsg UNNEEDED) +{ fprintf(stderr, "towire_obs2_onion_message called!\n"); abort(); } +/* Generated stub for towire_onion_message */ +u8 *towire_onion_message(const tal_t *ctx UNNEEDED, const struct pubkey *blinding UNNEEDED, const u8 *onionmsg UNNEEDED) +{ fprintf(stderr, "towire_onion_message called!\n"); abort(); } +/* Generated stub for towire_secp256k1_ecdsa_signature */ +void towire_secp256k1_ecdsa_signature(u8 **pptr UNNEEDED, + const secp256k1_ecdsa_signature *signature UNNEEDED) +{ fprintf(stderr, "towire_secp256k1_ecdsa_signature called!\n"); abort(); } +/* Generated stub for towire_sha256 */ +void towire_sha256(u8 **pptr UNNEEDED, const struct sha256 *sha256 UNNEEDED) +{ fprintf(stderr, "towire_sha256 called!\n"); abort(); } +/* Generated stub for towire_tlvstream_raw */ +void towire_tlvstream_raw(u8 **pptr UNNEEDED, struct tlv_field *fields UNNEEDED) +{ fprintf(stderr, "towire_tlvstream_raw called!\n"); abort(); } +/* Generated stub for towire_u16 */ +void towire_u16(u8 **pptr UNNEEDED, u16 v UNNEEDED) +{ fprintf(stderr, "towire_u16 called!\n"); abort(); } +/* Generated stub for towire_u32 */ +void towire_u32(u8 **pptr UNNEEDED, u32 v UNNEEDED) +{ fprintf(stderr, "towire_u32 called!\n"); abort(); } +/* Generated stub for towire_u64 */ +void towire_u64(u8 **pptr UNNEEDED, u64 v UNNEEDED) +{ fprintf(stderr, "towire_u64 called!\n"); abort(); } +/* Generated stub for towire_u8 */ +void towire_u8(u8 **pptr UNNEEDED, u8 v UNNEEDED) +{ fprintf(stderr, "towire_u8 called!\n"); abort(); } +/* Generated stub for towire_u8_array */ +void towire_u8_array(u8 **pptr UNNEEDED, const u8 *arr UNNEEDED, size_t num UNNEEDED) +{ fprintf(stderr, "towire_u8_array called!\n"); abort(); } +/* Generated stub for towire_warningfmt */ +u8 *towire_warningfmt(const tal_t *ctx UNNEEDED, + const struct channel_id *channel UNNEEDED, + const char *fmt UNNEEDED, ...) +{ fprintf(stderr, "towire_warningfmt called!\n"); abort(); } +/* Generated stub for unblind_onion */ +bool unblind_onion(const struct pubkey *blinding UNNEEDED, + void (*ecdh)(const struct pubkey *point UNNEEDED, struct secret *ss) UNNEEDED, + struct pubkey *onion_key UNNEEDED, + struct secret *ss) + +{ fprintf(stderr, "unblind_onion called!\n"); abort(); } +/* AUTOGENERATED MOCKS END */ + +/* Updated each time, as we pretend to be Alice, Bob, Carol */ +static const struct privkey *mykey; + +static void test_ecdh(const struct pubkey *point, struct secret *ss) +{ + if (secp256k1_ecdh(secp256k1_ctx, ss->data, &point->pubkey, + mykey->secret.data, NULL, NULL) != 1) + abort(); +} + +static void json_strfield(const char *name, const char *val) +{ + printf("\t\"%s\": \"%s\",\n", name, val); +} + +static void json_onionmsg_payload(const struct tlv_obs2_onionmsg_payload *om) +{ + if (om->reply_path) { + printf("\t\"reply_path\": {\n"); + json_strfield("first_node_id", + type_to_string(tmpctx, struct pubkey, + &om->reply_path->first_node_id)); + json_strfield("blinding", + type_to_string(tmpctx, struct pubkey, + &om->reply_path->blinding)); + printf("\t\"path\": [\n"); + for (size_t i = 0; i < tal_count(om->reply_path->path); i++) { + json_strfield("node_id", + type_to_string(tmpctx, struct pubkey, + &om->reply_path->path[i]->node_id)); + json_strfield("encrypted_recipient_data", + tal_hex(tmpctx, + om->reply_path->path[i]->encrypted_recipient_data)); + } + printf("]}\n"); + } + if (om->invoice) + json_strfield("invoice", tal_hex(tmpctx, om->invoice)); + if (om->invoice_request) + json_strfield("invoice_request", + tal_hex(tmpctx, om->invoice_request)); + if (om->invoice_error) + json_strfield("invoice_error", + tal_hex(tmpctx, om->invoice_error)); +} + +/* Return next onion (and updates blinding), or NULL */ +static u8 *json_test(const char *testname, + const u8 *data, + const struct privkey *me, + const struct privkey *blinding_priv, + struct pubkey *blinding) +{ + struct pubkey my_id, next_node; + struct secret ss, onion_ss; + struct pubkey ephemeral; + struct route_step *rs; + const u8 *cursor; + size_t max, maxlen; + struct onionpacket *op; + struct tlv_obs2_onionmsg_payload *om; + + op = parse_onionpacket(tmpctx, data, tal_bytelen(data), NULL); + assert(op); + + pubkey_from_privkey(me, &my_id); + printf("{"); + json_strfield("test name", testname); + json_strfield("reader_privkey", + type_to_string(tmpctx, struct privkey, me)); + json_strfield("reader_id", + type_to_string(tmpctx, struct pubkey, &my_id)); + + if (blinding_priv) + json_strfield("blinding_privkey", + type_to_string(tmpctx, struct privkey, + blinding_priv)); + json_strfield("blinding", + type_to_string(tmpctx, struct pubkey, blinding)); + printf("\"onionmsg\": {\n"); + json_strfield("raw", tal_hex(tmpctx, data)); + json_strfield("version", tal_fmt(tmpctx, "%i", op->version)); + json_strfield("public_key", + type_to_string(tmpctx, struct pubkey, &op->ephemeralkey)); + json_strfield("hop_payloads", + tal_hex(tmpctx, op->routinginfo)); + json_strfield("hmac", + tal_hexstr(tmpctx, &op->hmac, sizeof(op->hmac))); + printf("},\n"); + + ephemeral = op->ephemeralkey; + + /* Set this for test_ecdh */ + mykey = me; + assert(unblind_onion(blinding, test_ecdh, &ephemeral, &ss)); + json_strfield("ECDH shared secret", + type_to_string(tmpctx, struct secret, &ss)); + /* Reproduce internal calc from unblind_onion */ + { + struct secret hmac; + subkey_from_hmac("blinded_node_id", &ss, &hmac); + json_strfield("HMAC256(\\\"blinded_node_id\\\", ss(i)) * k(i)", + type_to_string(tmpctx, struct secret, &hmac)); + } + json_strfield("Tweaked onion pubkey", + type_to_string(tmpctx, struct pubkey, &ephemeral)); + + /* Now get onion shared secret and parse it. */ + test_ecdh(&ephemeral, &onion_ss); + json_strfield("onion shared secret", + type_to_string(tmpctx, struct secret, &onion_ss)); + rs = process_onionpacket(tmpctx, op, &onion_ss, NULL, 0, false); + assert(rs); + + printf("\"onion contents\": {\n"); + json_strfield("raw", tal_hex(tmpctx, rs->raw_payload)); + + cursor = rs->raw_payload; + max = tal_bytelen(rs->raw_payload); + maxlen = fromwire_bigsize(&cursor, &max); + json_strfield("length", tal_fmt(tmpctx, "%zu", maxlen)); + json_strfield("rawtlv", tal_hexstr(tmpctx, cursor, maxlen)); + json_strfield("hmac", tal_hexstr(tmpctx, rs->next->hmac.bytes, + sizeof(rs->next->hmac.bytes))); + om = tlv_obs2_onionmsg_payload_new(tmpctx); + assert(fromwire_obs2_onionmsg_payload(&cursor, &maxlen, om)); + + json_onionmsg_payload(om); + + /* We expect one of these. */ + assert(om->enctlv); + + printf("\t\"encrypted_data_tlv\": {\n"); + json_strfield("raw", tal_hex(tmpctx, om->enctlv)); + + if (rs->nextcase == ONION_END) { + struct secret *self_id; + struct pubkey alias; + assert(decrypt_obs2_final_enctlv(tmpctx, + blinding, &ss, + om->enctlv, + &my_id, &alias, &self_id)); + if (self_id) { + json_strfield("self_id", + type_to_string(tmpctx, struct secret, + self_id)); + } + printf("}\n"); + return NULL; + } else { + assert(decrypt_obs2_enctlv(blinding, &ss, om->enctlv, &next_node, + blinding)); + json_strfield("next_node", + type_to_string(tmpctx, struct pubkey, &next_node)); + json_strfield("next_blinding", + type_to_string(tmpctx, struct pubkey, + blinding)); + printf("}"); + printf("},\n"); + return serialize_onionpacket(tmpctx, rs->next); + } +} + +int main(int argc, char *argv[]) +{ + struct onionpacket *op; + u8 *data; + struct privkey alice, bob, carol, dave, blinding_priv; + struct pubkey alice_id, bob_id, carol_id, dave_id; + struct pubkey blinding; + + common_setup(argv[0]); + + memset(&alice, 'A', sizeof(alice)); + memset(&bob, 'B', sizeof(bob)); + memset(&carol, 'C', sizeof(carol)); + memset(&dave, 'D', sizeof(dave)); + pubkey_from_privkey(&alice, &alice_id); + pubkey_from_privkey(&bob, &bob_id); + pubkey_from_privkey(&carol, &carol_id); + pubkey_from_privkey(&dave, &dave_id); + + /* ThomasH sends via email: + * + * { + * "version":0, + * "public_key": + * "0256b328b30c8bf5839e24058747879408bdb36241dc9c2e7c619faa12b2920967", + * "hop_payloads": + * "37df67dcefdb678725cb8074d3224dfe235ba3f22f71ac8a2c9d1398b1175295b1dd3f14c02d698021e8a8856637306c6f195e01494eb8dc636b4462367533a84786b8592e580086cdf0f1c58b77eb68703a2fb82ecc2e91307a25b6d5e4045174551b1c867264d3905e4f05b2e5bcfed7e7276660bf7e956bce5afa395e7e4c15883b856bc93dd9d6a968838ef51314d38dd41e5ab84b8846dca3c61d87e55780e7a7da336a965a4652263413cdef41daa68f7bb7cd4d566c19a1c4eece369c47e604575f38e7a246a985c3441b60ae33c564395bb7a4bbe28325ccdb07503285dacf90b5e09f4e455fb42459741f9d497000298b99f1e70adc28f59a1be85a96952f27b6a6c5d6a08822b4f5cae05daa6c2ce2f8ca5fdd4e8f0df46b94791b3159fe8eace11bcf8d58be425b49ce2b47c007affefd5cea785c1996ad805f8c8c5ca79f15ab26e2bd4080b1d74328e7ce5bd2a579c71a6bd25f33f2ce475a2cfbe67ed1f4eb8fbd86920f41d573488abe059166aabbc3be187c435423ead6a5473994e0246efe76e419893aa2d7566b2645f3496d97585de9c92b8c5a5226398cc459ce84abc02fe2b45b5ecaf21961730d4a34bbe6fdfe720e71e3d81a494c01080d8039360d534c6ee5a3c47a1874e526969add9126b30d9192f85ba45bcfd7029cc7560f0e25e14b5deaa805360c4967705e85325ac055922863470f5397e8404022488caebf9204acd6cb02a11088aebf7e497b4ff1172f0a9c6bf980914cc4eb42fc78b457add549abf1134f84922b217502938b42d10b35079f44c5168d4c3e9fe7ca8094ef72ed73ef84f1d3530b6b3545f9f4f013e7e8cbcf2619f57754a7380ce6a9532ee14c55990faa43df6c09530a314b5f4ce597f5ec9b776e8597ce258ac47dac43bd3ac9e52788ff3a66b7dc07cd1bc3e6d197339d85fa8d3d6c3054dd1a5e416c714b544de6eb55209e40e3cac412a51748370160d2d73b6d97abd62f7bae70df27cd199c511fa693019c5717d471e934906b98cd974fda4dd1cb5e2d721044a0be2bdf24d0971e09f2f39488fe389fc5230699b4df7cec7447e5be4ea49bd7c3fe1a5ec7358510dc1dd9c1a8da68c0863188d80549e49f7c00f57d2009b2427b2aed1569603fc247734039469f9fdf3ddd3a22fa95c5d8066a468327a02b474c9915419af82c8edc67686984767fe7885207c6820f6c2e57cb8fd0bcb9981ebc8065c74e970a5d593c3b73ee25a0877ca096a9f7edfee6d43bd817c7d415fea9abb6f206c61aa36942df9318762a76b9da26d0d41a0ae9eee042a175f82dc134bf6f2d46a218db358d6852940e6e30df4a58ac6cb409e7ce99afe1e3f42768bd617af4d0a235d0ba0dd5075f9cc091784395d30e7e42d4e006db21bea9b45d1f122b75c051e84e2281573ef54ebad053218fff0cc28ea89a06adc218d4134f407654990592e75462f5ee4a463c1e46425222d48761162da8049613cafd7ecc52ff8024e9d58512b958e3a3d12dede84e1441247700bca0f992875349448b430683c756438fd4e91f3d44f3cf624ed21f3c63cf92615ecc201d0cd3159b1b3fccd8f29d2daba9ac5ba87b1dd2f83323a2b2d3176b803ce9c7bdc4bae615925eb22a213df1eeb2f8ff95586536caf042d565984aacf1425a120a5d8d7a9cbb70bf4852e116b89ff5b198d672220af2be4246372e7c3836cf50d732212a3e3346ff92873ace57fa687b2b1aab3e8dc6cb9f93f865d998cff0a1680d9012a9597c90a070e525f66226cc287814f4ac4157b15a0b25aa110946cd69fd404fafd5656669bfd1d9e509eabc004c5a", + * "hmac": "564bb85911bea8f90d306f4acdafa1c0887619ac72606b11e6b2765734d810ac" + * } + */ + op = tal(tmpctx, struct onionpacket); + op->version = 0; + assert(pubkey_from_hexstr("0256b328b30c8bf5839e24058747879408bdb36241dc9c2e7c619faa12b2920967", strlen("0256b328b30c8bf5839e24058747879408bdb36241dc9c2e7c619faa12b2920967"), &op->ephemeralkey)); + assert(hex_decode("564bb85911bea8f90d306f4acdafa1c0887619ac72606b11e6b2765734d810ac", + strlen("564bb85911bea8f90d306f4acdafa1c0887619ac72606b11e6b2765734d810ac"), + &op->hmac, sizeof(op->hmac))); + op->routinginfo = tal_hexdata(op, "37df67dcefdb678725cb8074d3224dfe235ba3f22f71ac8a2c9d1398b1175295b1dd3f14c02d698021e8a8856637306c6f195e01494eb8dc636b4462367533a84786b8592e580086cdf0f1c58b77eb68703a2fb82ecc2e91307a25b6d5e4045174551b1c867264d3905e4f05b2e5bcfed7e7276660bf7e956bce5afa395e7e4c15883b856bc93dd9d6a968838ef51314d38dd41e5ab84b8846dca3c61d87e55780e7a7da336a965a4652263413cdef41daa68f7bb7cd4d566c19a1c4eece369c47e604575f38e7a246a985c3441b60ae33c564395bb7a4bbe28325ccdb07503285dacf90b5e09f4e455fb42459741f9d497000298b99f1e70adc28f59a1be85a96952f27b6a6c5d6a08822b4f5cae05daa6c2ce2f8ca5fdd4e8f0df46b94791b3159fe8eace11bcf8d58be425b49ce2b47c007affefd5cea785c1996ad805f8c8c5ca79f15ab26e2bd4080b1d74328e7ce5bd2a579c71a6bd25f33f2ce475a2cfbe67ed1f4eb8fbd86920f41d573488abe059166aabbc3be187c435423ead6a5473994e0246efe76e419893aa2d7566b2645f3496d97585de9c92b8c5a5226398cc459ce84abc02fe2b45b5ecaf21961730d4a34bbe6fdfe720e71e3d81a494c01080d8039360d534c6ee5a3c47a1874e526969add9126b30d9192f85ba45bcfd7029cc7560f0e25e14b5deaa805360c4967705e85325ac055922863470f5397e8404022488caebf9204acd6cb02a11088aebf7e497b4ff1172f0a9c6bf980914cc4eb42fc78b457add549abf1134f84922b217502938b42d10b35079f44c5168d4c3e9fe7ca8094ef72ed73ef84f1d3530b6b3545f9f4f013e7e8cbcf2619f57754a7380ce6a9532ee14c55990faa43df6c09530a314b5f4ce597f5ec9b776e8597ce258ac47dac43bd3ac9e52788ff3a66b7dc07cd1bc3e6d197339d85fa8d3d6c3054dd1a5e416c714b544de6eb55209e40e3cac412a51748370160d2d73b6d97abd62f7bae70df27cd199c511fa693019c5717d471e934906b98cd974fda4dd1cb5e2d721044a0be2bdf24d0971e09f2f39488fe389fc5230699b4df7cec7447e5be4ea49bd7c3fe1a5ec7358510dc1dd9c1a8da68c0863188d80549e49f7c00f57d2009b2427b2aed1569603fc247734039469f9fdf3ddd3a22fa95c5d8066a468327a02b474c9915419af82c8edc67686984767fe7885207c6820f6c2e57cb8fd0bcb9981ebc8065c74e970a5d593c3b73ee25a0877ca096a9f7edfee6d43bd817c7d415fea9abb6f206c61aa36942df9318762a76b9da26d0d41a0ae9eee042a175f82dc134bf6f2d46a218db358d6852940e6e30df4a58ac6cb409e7ce99afe1e3f42768bd617af4d0a235d0ba0dd5075f9cc091784395d30e7e42d4e006db21bea9b45d1f122b75c051e84e2281573ef54ebad053218fff0cc28ea89a06adc218d4134f407654990592e75462f5ee4a463c1e46425222d48761162da8049613cafd7ecc52ff8024e9d58512b958e3a3d12dede84e1441247700bca0f992875349448b430683c756438fd4e91f3d44f3cf624ed21f3c63cf92615ecc201d0cd3159b1b3fccd8f29d2daba9ac5ba87b1dd2f83323a2b2d3176b803ce9c7bdc4bae615925eb22a213df1eeb2f8ff95586536caf042d565984aacf1425a120a5d8d7a9cbb70bf4852e116b89ff5b198d672220af2be4246372e7c3836cf50d732212a3e3346ff92873ace57fa687b2b1aab3e8dc6cb9f93f865d998cff0a1680d9012a9597c90a070e525f66226cc287814f4ac4157b15a0b25aa110946cd69fd404fafd5656669bfd1d9e509eabc004c5a", + strlen("37df67dcefdb678725cb8074d3224dfe235ba3f22f71ac8a2c9d1398b1175295b1dd3f14c02d698021e8a8856637306c6f195e01494eb8dc636b4462367533a84786b8592e580086cdf0f1c58b77eb68703a2fb82ecc2e91307a25b6d5e4045174551b1c867264d3905e4f05b2e5bcfed7e7276660bf7e956bce5afa395e7e4c15883b856bc93dd9d6a968838ef51314d38dd41e5ab84b8846dca3c61d87e55780e7a7da336a965a4652263413cdef41daa68f7bb7cd4d566c19a1c4eece369c47e604575f38e7a246a985c3441b60ae33c564395bb7a4bbe28325ccdb07503285dacf90b5e09f4e455fb42459741f9d497000298b99f1e70adc28f59a1be85a96952f27b6a6c5d6a08822b4f5cae05daa6c2ce2f8ca5fdd4e8f0df46b94791b3159fe8eace11bcf8d58be425b49ce2b47c007affefd5cea785c1996ad805f8c8c5ca79f15ab26e2bd4080b1d74328e7ce5bd2a579c71a6bd25f33f2ce475a2cfbe67ed1f4eb8fbd86920f41d573488abe059166aabbc3be187c435423ead6a5473994e0246efe76e419893aa2d7566b2645f3496d97585de9c92b8c5a5226398cc459ce84abc02fe2b45b5ecaf21961730d4a34bbe6fdfe720e71e3d81a494c01080d8039360d534c6ee5a3c47a1874e526969add9126b30d9192f85ba45bcfd7029cc7560f0e25e14b5deaa805360c4967705e85325ac055922863470f5397e8404022488caebf9204acd6cb02a11088aebf7e497b4ff1172f0a9c6bf980914cc4eb42fc78b457add549abf1134f84922b217502938b42d10b35079f44c5168d4c3e9fe7ca8094ef72ed73ef84f1d3530b6b3545f9f4f013e7e8cbcf2619f57754a7380ce6a9532ee14c55990faa43df6c09530a314b5f4ce597f5ec9b776e8597ce258ac47dac43bd3ac9e52788ff3a66b7dc07cd1bc3e6d197339d85fa8d3d6c3054dd1a5e416c714b544de6eb55209e40e3cac412a51748370160d2d73b6d97abd62f7bae70df27cd199c511fa693019c5717d471e934906b98cd974fda4dd1cb5e2d721044a0be2bdf24d0971e09f2f39488fe389fc5230699b4df7cec7447e5be4ea49bd7c3fe1a5ec7358510dc1dd9c1a8da68c0863188d80549e49f7c00f57d2009b2427b2aed1569603fc247734039469f9fdf3ddd3a22fa95c5d8066a468327a02b474c9915419af82c8edc67686984767fe7885207c6820f6c2e57cb8fd0bcb9981ebc8065c74e970a5d593c3b73ee25a0877ca096a9f7edfee6d43bd817c7d415fea9abb6f206c61aa36942df9318762a76b9da26d0d41a0ae9eee042a175f82dc134bf6f2d46a218db358d6852940e6e30df4a58ac6cb409e7ce99afe1e3f42768bd617af4d0a235d0ba0dd5075f9cc091784395d30e7e42d4e006db21bea9b45d1f122b75c051e84e2281573ef54ebad053218fff0cc28ea89a06adc218d4134f407654990592e75462f5ee4a463c1e46425222d48761162da8049613cafd7ecc52ff8024e9d58512b958e3a3d12dede84e1441247700bca0f992875349448b430683c756438fd4e91f3d44f3cf624ed21f3c63cf92615ecc201d0cd3159b1b3fccd8f29d2daba9ac5ba87b1dd2f83323a2b2d3176b803ce9c7bdc4bae615925eb22a213df1eeb2f8ff95586536caf042d565984aacf1425a120a5d8d7a9cbb70bf4852e116b89ff5b198d672220af2be4246372e7c3836cf50d732212a3e3346ff92873ace57fa687b2b1aab3e8dc6cb9f93f865d998cff0a1680d9012a9597c90a070e525f66226cc287814f4ac4157b15a0b25aa110946cd69fd404fafd5656669bfd1d9e509eabc004c5a")); + + data = serialize_onionpacket(tmpctx, op); + printf("[\n"); + + memset(&blinding_priv, 5, sizeof(blinding_priv)); + pubkey_from_privkey(&blinding_priv, &blinding); + + data = json_test("onion message for Alice", + data, + &alice, + &blinding_priv, + &blinding); + + data = json_test("onion message for Bob", + data, + &bob, + NULL, + &blinding); + + data = json_test("onion message for Carol", + data, + &carol, + NULL, + &blinding); + + data = json_test("onion message for Dave", + data, + &dave, + NULL, + &blinding); + + assert(!data); + printf("]\n"); + + common_shutdown(); + return 0; +} diff --git a/connectd/test/run-responder-success.c b/connectd/test/run-responder-success.c index 1bf317e3f328..b5de1da5a9e7 100644 --- a/connectd/test/run-responder-success.c +++ b/connectd/test/run-responder-success.c @@ -277,6 +277,7 @@ static struct io_plan *success(struct io_conn *conn UNUSED, const struct pubkey *them UNUSED, const struct wireaddr_internal *addr UNUSED, struct crypto_state *cs, + struct oneshot *timeout UNUSED, void *unused UNUSED) { assert(secret_eq_str(&cs->sk, expect_sk)); @@ -314,7 +315,7 @@ int main(int argc, char *argv[]) dummy.itype = ADDR_INTERNAL_WIREADDR; dummy.u.wireaddr.addrlen = 0; - responder_handshake((void *)tmpctx, &ls_pub, &dummy, success, NULL); + responder_handshake((void *)tmpctx, &ls_pub, &dummy, NULL, success, NULL); /* Should not exit! */ abort(); } diff --git a/devtools/Makefile b/devtools/Makefile index b4c23f03ac56..5498db4684ce 100644 --- a/devtools/Makefile +++ b/devtools/Makefile @@ -21,7 +21,6 @@ DEVTOOLS_COMMON_OBJS := \ common/bolt11.o \ common/blockheight_states.o \ common/channel_id.o \ - common/crypto_state.o \ common/decode_array.o \ common/features.o \ common/fee_states.o \ @@ -70,7 +69,7 @@ devtools/onion: $(DEVTOOLS_COMMON_OBJS) $(JSMN_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS devtools/blindedpath: $(DEVTOOLS_COMMON_OBJS) $(JSMN_OBJS) $(CCAN_OBJS) common/blinding.o $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o devtools/blindedpath.o common/onion.o common/onionreply.o common/sphinx.o -devtools/gossipwith: $(DEVTOOLS_COMMON_OBJS) $(JSMN_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o wire/peer$(EXP)_wiregen.o devtools/gossipwith.o common/cryptomsg.o common/cryptomsg.o common/crypto_sync.o +devtools/gossipwith: $(DEVTOOLS_COMMON_OBJS) $(JSMN_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o wire/peer$(EXP)_wiregen.o devtools/gossipwith.o common/cryptomsg.o common/cryptomsg.o $(DEVTOOLS_OBJS) $(DEVTOOLS_TOOL_OBJS): wire/wire.h diff --git a/devtools/gossipwith.c b/devtools/gossipwith.c index 0e2093e6764c..3e7f0481a9fd 100644 --- a/devtools/gossipwith.c +++ b/devtools/gossipwith.c @@ -9,12 +9,12 @@ #include #include #include -#include -#include +#include #include #include #include #include +#include #include #include #include @@ -69,23 +69,6 @@ void status_fmt(enum log_level level, { } -#if DEVELOPER -void dev_sabotage_fd(int fd, bool close_fd) -{ - abort(); -} - -void dev_blackhole_fd(int fd) -{ - abort(); -} - -enum dev_disconnect dev_disconnect(int pkt_type) -{ - return DEV_DISCONNECT_NORMAL; -} -#endif - static char *opt_set_network(const char *arg, void *unused) { assert(arg != NULL); @@ -102,11 +85,6 @@ static void opt_show_network(char buf[OPT_SHOW_LEN], const void *unused) snprintf(buf, OPT_SHOW_LEN, "%s", chainparams->network_name); } -void peer_failed_connection_lost(void) -{ - exit(0); -} - void ecdh(const struct pubkey *point, struct secret *ss) { if (secp256k1_ecdh(secp256k1_ctx, ss->data, &point->pubkey, @@ -140,17 +118,60 @@ static struct io_plan *simple_read(struct io_conn *conn, return next(conn, next_arg); } +static void sync_crypto_write(int peer_fd, struct crypto_state *cs, const void *msg TAKES) +{ + u8 *enc; + + enc = cryptomsg_encrypt_msg(NULL, cs, msg); + + if (!write_all(peer_fd, enc, tal_count(enc))) + exit(1); + tal_free(enc); +} + +static u8 *sync_crypto_read(const tal_t *ctx, int peer_fd, struct crypto_state *cs) +{ + u8 hdr[18], *enc, *dec; + u16 len; + + if (!read_all(peer_fd, hdr, sizeof(hdr))) { + status_debug("Failed reading header: %s", strerror(errno)); + exit(0); + } + + if (!cryptomsg_decrypt_header(cs, hdr, &len)) { + status_debug("Failed hdr decrypt with rn=%"PRIu64, + cs->rn-1); + exit(1); + } + + enc = tal_arr(ctx, u8, len + 16); + if (!read_all(peer_fd, enc, tal_count(enc))) { + status_debug("Failed reading body: %s", strerror(errno)); + exit(1); + } + + dec = cryptomsg_decrypt_body(ctx, cs, enc); + tal_free(enc); + if (!dec) + exit(1); + else + status_peer_io(LOG_IO_IN, NULL, dec); + + return dec; +} + static struct io_plan *handshake_success(struct io_conn *conn, const struct pubkey *them, const struct wireaddr_internal *addr, - struct crypto_state *orig_cs, + struct crypto_state *cs, + struct oneshot *timer, char **args) { u8 *msg; - struct per_peer_state *pps = new_per_peer_state(conn, orig_cs); + int peer_fd = io_conn_fd(conn); struct pollfd pollfd[2]; - pps->peer_fd = io_conn_fd(conn); if (initial_sync) set_feature_bit(&features, OPTIONAL_FEATURE(OPT_INITIAL_ROUTING_SYNC)); @@ -164,9 +185,9 @@ static struct io_plan *handshake_success(struct io_conn *conn, } msg = towire_init(NULL, NULL, features, tlvs); - sync_crypto_write(pps, take(msg)); + sync_crypto_write(peer_fd, cs, take(msg)); /* Ignore their init message. */ - tal_free(sync_crypto_read(NULL, pps)); + tal_free(sync_crypto_read(NULL, peer_fd, cs)); tal_free(tlvs); } @@ -175,14 +196,14 @@ static struct io_plan *handshake_success(struct io_conn *conn, else pollfd[0].fd = -1; pollfd[0].events = POLLIN; - pollfd[1].fd = pps->peer_fd; + pollfd[1].fd = peer_fd; pollfd[1].events = POLLIN; while (*args) { u8 *m = tal_hexdata(NULL, *args, strlen(*args)); if (!m) errx(1, "Invalid hexdata '%s'", *args); - sync_crypto_write(pps, take(m)); + sync_crypto_write(peer_fd, cs, take(m)); args++; } @@ -203,10 +224,10 @@ static struct io_plan *handshake_success(struct io_conn *conn, if (!read_all(STDIN_FILENO, msg, tal_bytelen(msg))) err(1, "Only read partial message"); - sync_crypto_write(pps, take(msg)); + sync_crypto_write(peer_fd, cs, take(msg)); } } else if (pollfd[1].revents & POLLIN) { - msg = sync_crypto_read(NULL, pps); + msg = sync_crypto_read(NULL, peer_fd, cs); if (!msg) err(1, "Reading msg"); if (hex) { @@ -351,7 +372,8 @@ int main(int argc, char *argv[]) if (connect(conn->fd, ai->ai_addr, ai->ai_addrlen) != 0) err(1, "Connecting to %s", at+1); - initiator_handshake(conn, &us, &them, &addr, handshake_success, argv+2); + initiator_handshake(conn, &us, &them, &addr, NULL, + handshake_success, argv+2); exit(0); } diff --git a/gossipd/Makefile b/gossipd/Makefile index f31acfe92c0c..6fbb6a7e450c 100644 --- a/gossipd/Makefile +++ b/gossipd/Makefile @@ -34,10 +34,7 @@ GOSSIPD_COMMON_OBJS := \ common/bech32_util.o \ common/bigsize.o \ common/bip32.o \ - common/blinding.o \ - common/blindedpath.o \ common/channel_id.o \ - common/crypto_state.o \ common/cryptomsg.o \ common/daemon.o \ common/daemon_conn.o \ @@ -46,7 +43,6 @@ GOSSIPD_COMMON_OBJS := \ common/dev_disconnect.o \ common/ecdh_hsmd.o \ common/features.o \ - common/hmac.o \ common/status_wiregen.o \ common/gossip_rcvd_filter.o \ common/key_derive.o \ @@ -54,8 +50,6 @@ GOSSIPD_COMMON_OBJS := \ common/memleak.o \ common/msg_queue.o \ common/node_id.o \ - common/onion.o \ - common/onionreply.o \ common/per_peer_state.o \ common/ping.o \ common/psbt_open.o \ @@ -63,7 +57,6 @@ GOSSIPD_COMMON_OBJS := \ common/private_channel_announcement.o \ common/random_select.o \ common/setup.o \ - common/sphinx.o \ common/status.o \ common/status_wire.o \ common/subdaemon.o \ diff --git a/gossipd/gossip_generation.c b/gossipd/gossip_generation.c index 7e71e5b81262..faf01bb7254f 100644 --- a/gossipd/gossip_generation.c +++ b/gossipd/gossip_generation.c @@ -3,6 +3,7 @@ #include "config.h" #include #include +#include #include #include #include @@ -14,7 +15,7 @@ #include #include #include -#include +#include #include #include @@ -307,48 +308,141 @@ void maybe_send_own_node_announce(struct daemon *daemon, bool startup) update_own_node_announcement(daemon, startup); } -/* Our timer callbacks take a single argument, so we marshall everything - * we need into this structure: */ -struct local_cupdate { - struct daemon *daemon; - struct local_chan *local_chan; +/* Fast accessors for channel_update fields */ +static u8 *channel_flags_access(const u8 *channel_update) +{ + /* BOLT #7: + * 1. type: 258 (`channel_update`) + * 2. data: + * * [`signature`:`signature`] + * * [`chain_hash`:`chain_hash`] + * * [`short_channel_id`:`short_channel_id`] + * * [`u32`:`timestamp`] + * * [`byte`:`message_flags`] + * * [`byte`:`channel_flags`] + */ + /* Note: 2 bytes for `type` field */ + return cast_const(u8 *, &channel_update[2 + 64 + 32 + 8 + 4 + 1]); +} - bool disable; - bool even_if_identical; - bool even_if_too_soon; +static u8 *timestamp_access(const u8 *channel_update) +{ + /* BOLT #7: + * 1. type: 258 (`channel_update`) + * 2. data: + * * [`signature`:`signature`] + * * [`chain_hash`:`chain_hash`] + * * [`short_channel_id`:`short_channel_id`] + * * [`u32`:`timestamp`] + * * [`byte`:`message_flags`] + * * [`byte`:`channel_flags`] + */ + /* Note: 2 bytes for `type` field */ + return cast_const(u8 *, &channel_update[2 + 64 + 32 + 8]); +} - u16 cltv_expiry_delta; - struct amount_msat htlc_minimum, htlc_maximum; - u32 fee_base_msat, fee_proportional_millionths; -}; +static bool is_disabled(const u8 *channel_update) +{ + return *channel_flags_access(channel_update) & ROUTING_FLAGS_DISABLED; +} -/* This generates a `channel_update` message for one of our channels. We do - * this here, rather than in `channeld` because we (may) need to do it - * ourselves anyway if channeld dies, or when we refresh it once a week, - * and so we can avoid creating redundant ones. */ -static void update_local_channel(struct local_cupdate *lc /* frees! */) +static bool is_enabled(const u8 *channel_update) { - struct daemon *daemon = lc->daemon; - secp256k1_ecdsa_signature dummy_sig; - u8 *update, *msg; - u32 timestamp = gossip_time_now(daemon->rstate).ts.tv_sec, next; - u8 message_flags, channel_flags; - struct chan *chan = lc->local_chan->chan; - struct half_chan *hc; - const int direction = lc->local_chan->direction; + return !is_disabled(channel_update); +} - /* Discard existing timer. */ - lc->local_chan->channel_update_timer - = tal_free(lc->local_chan->channel_update_timer); - /* So valgrind doesn't complain */ - memset(&dummy_sig, 0, sizeof(dummy_sig)); +static u32 timestamp_for_update(struct daemon *daemon, + const u32 *prev_timestamp, + bool disable) +{ + u32 timestamp = gossip_time_now(daemon->rstate).ts.tv_sec; /* Create an unsigned channel_update: we backdate enables, so * we can always send a disable in an emergency. */ - if (!lc->disable) + if (!disable) timestamp -= GOSSIP_MIN_INTERVAL(daemon->rstate->dev_fast_gossip); + if (prev_timestamp) { + /* Timestamps can't go backwards! */ + if (timestamp < *prev_timestamp) + timestamp = *prev_timestamp + 1; + + /* If we ever use set-based propagation, ensuring the toggle + * the lower bit in consecutive timestamps makes it more + * robust. */ + if ((timestamp & 1) == (*prev_timestamp & 1)) + timestamp++; + } + + return timestamp; +} + +static u8 *sign_and_timestamp_update(const tal_t *ctx, + struct daemon *daemon, + const struct chan *chan, + int direction, + u8 *unsigned_update TAKES) +{ + u8 *msg, *update; + be32 timestamp; + const u32 *prev_timestamp; + const struct half_chan *hc = &chan->half[direction]; + + if (is_halfchan_defined(hc)) + prev_timestamp = &hc->bcast.timestamp; + else + prev_timestamp = NULL; + + /* Get an appropriate timestamp */ + timestamp = cpu_to_be32(timestamp_for_update(daemon, + prev_timestamp, + is_disabled(unsigned_update))); + memcpy(timestamp_access(unsigned_update), ×tamp, sizeof(timestamp)); + + /* Note that we treat the hsmd as synchronous. This is simple (no + * callback hell)!, but may need to change to async if we ever want + * remote HSMs */ + if (!wire_sync_write(HSM_FD, + towire_hsmd_cupdate_sig_req(tmpctx, unsigned_update))) { + status_failed(STATUS_FAIL_HSM_IO, "Writing cupdate_sig_req: %s", + strerror(errno)); + } + + msg = wire_sync_read(tmpctx, HSM_FD); + if (!msg || !fromwire_hsmd_cupdate_sig_reply(ctx, msg, &update)) { + status_failed(STATUS_FAIL_HSM_IO, + "Reading cupdate_sig_req: %s", + strerror(errno)); + } + + if (taken(unsigned_update)) + tal_free(unsigned_update); + + /* Tell lightningd about this immediately (even if we're not actually + * applying it now) */ + msg = towire_gossipd_got_local_channel_update(NULL, &chan->scid, update); + daemon_conn_send(daemon->master, take(msg)); + + return update; +} + +static u8 *create_unsigned_update(const tal_t *ctx, + const struct short_channel_id *scid, + int direction, + bool disable, + u16 cltv_expiry_delta, + struct amount_msat htlc_minimum, + struct amount_msat htlc_maximum, + u32 fee_base_msat, + u32 fee_proportional_millionths) +{ + secp256k1_ecdsa_signature dummy_sig; + u8 message_flags, channel_flags; + + /* So valgrind doesn't complain */ + memset(&dummy_sig, 0, sizeof(dummy_sig)); + /* BOLT #7: * * The `channel_flags` bitfield is used to indicate the direction of @@ -362,7 +456,7 @@ static void update_local_channel(struct local_cupdate *lc /* frees! */) * | 1 | `disable` | Disable the channel. | */ channel_flags = direction; - if (lc->disable) + if (disable) channel_flags |= ROUTING_FLAGS_DISABLED; /* BOLT #7: @@ -376,101 +470,43 @@ static void update_local_channel(struct local_cupdate *lc /* frees! */) */ message_flags = 0 | ROUTING_OPT_HTLC_MAX_MSAT; - /* Convenience variable. */ - hc = &chan->half[direction]; - - /* If we ever use set-based propagation, ensuring the toggle - * the lower bit in consecutive timestamps makes it more - * robust. */ - if (is_halfchan_defined(hc) - && (timestamp & 1) == (hc->bcast.timestamp & 1)) - timestamp++; - - /* We create an update with a dummy signature, and hand to hsmd to get - * it signed. */ - update = towire_channel_update_option_channel_htlc_max(tmpctx, &dummy_sig, + /* We create an update with a dummy signature and timestamp. */ + return towire_channel_update_option_channel_htlc_max(ctx, + &dummy_sig, /* sig set later */ &chainparams->genesis_blockhash, - &chan->scid, - timestamp, + scid, + 0, /* timestamp set later */ message_flags, channel_flags, - lc->cltv_expiry_delta, - lc->htlc_minimum, - lc->fee_base_msat, - lc->fee_proportional_millionths, - lc->htlc_maximum); - - if (is_halfchan_defined(hc)) { - /* Suppress duplicates. */ - if (!lc->even_if_identical - && !cupdate_different(daemon->rstate->gs, hc, update)) { - tal_free(lc); - return; - } - - /* Is it too soon to send another update? */ - next = hc->bcast.timestamp - + GOSSIP_MIN_INTERVAL(daemon->rstate->dev_fast_gossip); - - if (timestamp < next && !lc->even_if_too_soon) { - status_debug("channel_update %s/%u: delaying %u secs", - type_to_string(tmpctx, - struct short_channel_id, - &chan->scid), - direction, - next - timestamp); - lc->local_chan->channel_update_timer - = new_reltimer(&daemon->timers, lc, - time_from_sec(next - timestamp), - update_local_channel, - lc); - /* If local chan vanishes, so does update, and timer. */ - notleak(tal_steal(lc->local_chan, lc)); - return; - } - } - - /* Note that we treat the hsmd as synchronous. This is simple (no - * callback hell)!, but may need to change to async if we ever want - * remote HSMs */ - if (!wire_sync_write(HSM_FD, - towire_hsmd_cupdate_sig_req(tmpctx, update))) { - status_failed(STATUS_FAIL_HSM_IO, "Writing cupdate_sig_req: %s", - strerror(errno)); - } + cltv_expiry_delta, + htlc_minimum, + fee_base_msat, + fee_proportional_millionths, + htlc_maximum); +} - msg = wire_sync_read(tmpctx, HSM_FD); - if (!msg || !fromwire_hsmd_cupdate_sig_reply(tmpctx, msg, &update)) { - status_failed(STATUS_FAIL_HSM_IO, - "Reading cupdate_sig_req: %s", - strerror(errno)); - } +static void apply_update(struct daemon *daemon, + const struct chan *chan, + int direction, + u8 *update TAKES) +{ + u8 *msg; + struct peer *peer = find_peer(daemon, &chan->nodes[!direction]->id); - /* BOLT #7: - * - * The origin node: - *... - * - MAY create a `channel_update` to communicate the channel parameters to the - * channel peer, even though the channel has not yet been announced (i.e. the - * `announce_channel` bit was not set). - */ if (!is_chan_public(chan)) { + /* Save and restore taken state, for handle_channel_update */ + bool update_taken = taken(update); + /* handle_channel_update will not put private updates in the * broadcast list, but we send it direct to the peer (if we * have one connected) now */ - struct peer *peer = find_peer(daemon, - &chan->nodes[!direction]->id); if (peer) queue_peer_msg(peer, update); + + if (update_taken) + take(update); } - /* We feed it into routing.c like any other channel_update; it may - * discard it (eg. non-public channel), but it should not complain - * about it being invalid! __func__ is a magic C constant which - * expands to this function name. */ - msg = handle_channel_update(daemon->rstate, update, - find_peer(daemon, - &chan->nodes[!direction]->id), - NULL, true); + msg = handle_channel_update(daemon->rstate, update, peer, NULL, true); if (msg) status_failed(STATUS_FAIL_INTERNAL_ERROR, "%s: rejected local channel update %s: %s", @@ -481,117 +517,338 @@ static void update_local_channel(struct local_cupdate *lc /* frees! */) * tmpctx, so it's actually OK. */ tal_hex(tmpctx, update), tal_hex(tmpctx, msg)); - - tal_free(lc); } -/* This is a refresh of a local channel: sends an update if one is needed. */ -void refresh_local_channel(struct daemon *daemon, - struct local_chan *local_chan, - bool even_if_identical) +static void sign_timestamp_and_apply_update(struct daemon *daemon, + const struct chan *chan, + int direction, + u8 *update TAKES) { - const struct half_chan *hc; - struct local_cupdate *lc; - u8 *prev; - secp256k1_ecdsa_signature signature; - struct bitcoin_blkid chain_hash; - struct short_channel_id short_channel_id; - u32 timestamp; - u8 message_flags, channel_flags; + update = sign_and_timestamp_update(NULL, daemon, chan, direction, + update); + apply_update(daemon, chan, direction, take(update)); +} - hc = &local_chan->chan->half[local_chan->direction]; +/* We don't want to thrash the gossip network, so we often defer sending an + * update. We track them here. */ +struct deferred_update { + struct daemon *daemon; + /* Off daemon->deferred_updates */ + struct list_node list; + /* Channel it's for (and owner) */ + const struct chan *chan; + int direction; + /* Timer which will fire when it's time to apply. */ + struct oneshot *channel_update_timer; + /* The actual `update_channel` to apply */ + u8 *update; +}; - /* Don't generate a channel_update for an uninitialized channel. */ - if (!is_halfchan_defined(hc)) - return; +static struct deferred_update *find_deferred_update(struct daemon *daemon, + const struct chan *chan) +{ + struct deferred_update *du; - /* If there's an update pending already, force it to apply now. */ - if (local_chan->channel_update_timer) { - lc = reltimer_arg(local_chan->channel_update_timer); - lc->even_if_too_soon = true; - update_local_channel(lc); - /* Free timer */ - local_chan->channel_update_timer - = tal_free(local_chan->channel_update_timer); + list_for_each(&daemon->deferred_updates, du, list) { + if (du->chan == chan) + return du; } + return NULL; +} + +static void destroy_deferred_update(struct deferred_update *du) +{ + list_del(&du->list); +} - lc = tal(NULL, struct local_cupdate); - lc->daemon = daemon; - lc->local_chan = local_chan; - lc->even_if_identical = even_if_identical; - lc->even_if_too_soon = false; +static void apply_deferred_update(struct deferred_update *du) +{ + apply_update(du->daemon, du->chan, du->direction, take(du->update)); + tal_free(du); +} + +static void defer_update(struct daemon *daemon, + u32 delay, + const struct chan *chan, + int direction, + u8 *unsigned_update TAKES) +{ + struct deferred_update *du; + + /* Override any existing one */ + tal_free(find_deferred_update(daemon, chan)); + + /* If chan is gone, so are we. */ + du = tal(chan, struct deferred_update); + du->daemon = daemon; + du->chan = chan; + du->direction = direction; + du->update = sign_and_timestamp_update(du, daemon, chan, direction, + unsigned_update); + if (delay != 0xFFFFFFFF) + du->channel_update_timer = new_reltimer(&daemon->timers, du, + time_from_sec(delay), + apply_deferred_update, + du); + else + du->channel_update_timer = NULL; + list_add_tail(&daemon->deferred_updates, &du->list); + tal_add_destructor(du, destroy_deferred_update); +} + +/* If there is a pending update for this local channel, apply immediately. */ +static bool local_channel_update_latest(struct daemon *daemon, struct chan *chan) +{ + struct deferred_update *du; + + du = find_deferred_update(daemon, chan); + if (!du) + return false; + + /* Frees itself */ + apply_deferred_update(du); + return true; +} + +/* Get previous update. */ +static u8 *prev_update(const tal_t *ctx, + struct daemon *daemon, const struct chan *chan, int direction) +{ + u8 *prev; + + if (!is_halfchan_defined(&chan->half[direction])) + return NULL; prev = cast_const(u8 *, gossip_store_get(tmpctx, daemon->rstate->gs, - local_chan->chan->half[local_chan->direction] - .bcast.index)); + chan->half[direction].bcast.index)); /* If it's a private update, unwrap */ - fromwire_gossip_store_private_update(tmpctx, prev, &prev); + if (!fromwire_gossip_store_private_update(ctx, prev, &prev)) + tal_steal(ctx, prev); + return prev; +} + +/* This is a refresh of a local channel (after 13 days). */ +void refresh_local_channel(struct daemon *daemon, + struct chan *chan, int direction) +{ + u16 cltv_expiry_delta; + struct amount_msat htlc_minimum, htlc_maximum; + u32 fee_base_msat, fee_proportional_millionths, timestamp; + u8 *prev, *update; + u8 message_flags, channel_flags; + secp256k1_ecdsa_signature signature; + struct bitcoin_blkid chain_hash; + struct short_channel_id short_channel_id; + + /* If there's a pending update, apply it and we're done. */ + if (local_channel_update_latest(daemon, chan)) + return; + + prev = prev_update(tmpctx, daemon, chan, direction); + if (!prev) + return; if (!fromwire_channel_update_option_channel_htlc_max(prev, &signature, &chain_hash, &short_channel_id, ×tamp, &message_flags, &channel_flags, - &lc->cltv_expiry_delta, - &lc->htlc_minimum, - &lc->fee_base_msat, - &lc->fee_proportional_millionths, - &lc->htlc_maximum)) { + &cltv_expiry_delta, + &htlc_minimum, + &fee_base_msat, + &fee_proportional_millionths, + &htlc_maximum)) { status_broken("Could not decode local channel_update %s!", tal_hex(tmpctx, prev)); - tal_free(lc); return; } - lc->disable = (channel_flags & ROUTING_FLAGS_DISABLED) - || local_chan->local_disabled; - update_local_channel(lc); + /* BOLT #7: + * + * The `channel_flags` bitfield is used to indicate the direction of + * the channel: it identifies the node that this update originated + * from and signals various options concerning the channel. The + * following table specifies the meaning of its individual bits: + * + * | Bit Position | Name | Meaning | + * | ------------- | ----------- | -------------------------------- | + * | 0 | `direction` | Direction this update refers to. | + * | 1 | `disable` | Disable the channel. | + */ + if (direction != (channel_flags & ROUTING_FLAGS_DIRECTION)) { + status_broken("Wrong channel direction %s!", + tal_hex(tmpctx, prev)); + return; + } + + /* Don't refresh disabled channels. */ + if (channel_flags & ROUTING_FLAGS_DISABLED) + return; + + update = create_unsigned_update(NULL, &short_channel_id, direction, + false, cltv_expiry_delta, + htlc_minimum, htlc_maximum, + fee_base_msat, + fee_proportional_millionths); + sign_timestamp_and_apply_update(daemon, chan, direction, take(update)); } -/* channeld asks us to update the local channel. */ -bool handle_local_channel_update(struct daemon *daemon, - const struct node_id *src, - const u8 *msg) +/* channeld (via lightningd) asks us to update the local channel. */ +void handle_local_channel_update(struct daemon *daemon, const u8 *msg) { + struct node_id id; struct short_channel_id scid; - struct local_cupdate *lc = tal(tmpctx, struct local_cupdate); - - lc->daemon = daemon; - lc->even_if_identical = false; - lc->even_if_too_soon = false; + bool disable; + u16 cltv_expiry_delta; + struct amount_msat htlc_minimum, htlc_maximum; + u32 fee_base_msat, fee_proportional_millionths; + struct chan *chan; + int direction; + u8 *unsigned_update; + const struct half_chan *hc; - /* FIXME: We should get scid from lightningd when setting up the - * connection, so no per-peer daemon can mess with channels other than - * its own! */ if (!fromwire_gossipd_local_channel_update(msg, + &id, &scid, - &lc->disable, - &lc->cltv_expiry_delta, - &lc->htlc_minimum, - &lc->fee_base_msat, - &lc->fee_proportional_millionths, - &lc->htlc_maximum)) { - status_peer_broken(src, "bad local_channel_update %s", - tal_hex(tmpctx, msg)); - return false; + &disable, + &cltv_expiry_delta, + &htlc_minimum, + &fee_base_msat, + &fee_proportional_millionths, + &htlc_maximum)) { + master_badmsg(WIRE_GOSSIPD_LOCAL_CHANNEL_UPDATE, msg); } - lc->local_chan = local_chan_map_get(&daemon->rstate->local_chan_map, - &scid); + chan = get_channel(daemon->rstate, &scid); /* Can theoretically happen if channel just closed. */ - if (!lc->local_chan) { - status_peer_debug(src, "local_channel_update for unknown %s", + if (!chan) { + status_peer_debug(&id, "local_channel_update for unknown %s", type_to_string(tmpctx, struct short_channel_id, &scid)); - return true; + return; } - /* Remove soft local_disabled flag, if they're marking it enabled. */ - if (!lc->disable) - local_enable_chan(daemon->rstate, lc->local_chan->chan); + if (!local_direction(daemon->rstate, chan, &direction)) { + status_peer_broken(&id, "bad local_channel_update chan %s", + type_to_string(tmpctx, + struct short_channel_id, + &scid)); + return; + } - /* Apply the update they told us */ - update_local_channel(tal_steal(NULL, lc)); - return true; + unsigned_update = create_unsigned_update(tmpctx, &scid, direction, + disable, cltv_expiry_delta, + htlc_minimum, htlc_maximum, + fee_base_msat, + fee_proportional_millionths); + + hc = &chan->half[direction]; + + /* Ignore duplicates. */ + if (is_halfchan_defined(hc) + && !cupdate_different(daemon->rstate->gs, hc, unsigned_update)) + return; + + /* Too early? Defer (don't worry if it's unannounced). */ + if (hc && is_chan_public(chan)) { + u32 now = time_now().ts.tv_sec; + u32 next_time = hc->bcast.timestamp + + GOSSIP_MIN_INTERVAL(daemon->rstate->dev_fast_gossip); + if (now < next_time) { + defer_update(daemon, next_time - now, + chan, direction, take(unsigned_update)); + return; + } + } + + sign_timestamp_and_apply_update(daemon, chan, direction, + take(unsigned_update)); +} + +/* Take update, set/unset disabled flag (and update timestamp). + */ +static void set_disable_flag(u8 *channel_update, bool disable) +{ + u8 *channel_flags = channel_flags_access(channel_update); + + if (disable) + *channel_flags |= ROUTING_FLAGS_DISABLED; + else + *channel_flags &= ~ROUTING_FLAGS_DISABLED; +} + +/* We don't immediately disable, to avoid flapping. */ +void local_disable_chan(struct daemon *daemon, const struct chan *chan, int direction) +{ + struct deferred_update *du; + u8 *update = prev_update(tmpctx, daemon, chan, direction); + if (!update) + return; + + du = find_deferred_update(daemon, chan); + + /* Will a deferred update disable it already? OK, nothing to do. */ + if (du && is_disabled(du->update)) + return; + + /* OK, we definitely don't want deferred update to re-enable! */ + tal_free(du); + + /* Is it already disabled? */ + if (is_disabled(update)) + return; + + /* This is deferred indefinitely (flushed if needed though) */ + set_disable_flag(update, true); + defer_update(daemon, 0xFFFFFFFF, chan, direction, take(update)); +} + +/* lightningd tells us it used the local channel update. */ +void handle_used_local_channel_update(struct daemon *daemon, const u8 *msg) +{ + struct short_channel_id scid; + struct chan *chan; + + if (!fromwire_gossipd_used_local_channel_update(msg, &scid)) + master_badmsg(WIRE_GOSSIPD_USED_LOCAL_CHANNEL_UPDATE, msg); + + chan = get_channel(daemon->rstate, &scid); + /* Might have closed in meantime, but v unlikely! */ + if (!chan) { + status_broken("used_local_channel_update on unknown %s", + type_to_string(tmpctx, struct short_channel_id, + &scid)); + return; + } + local_channel_update_latest(daemon, chan); +} + +void local_enable_chan(struct daemon *daemon, const struct chan *chan, int direction) +{ + struct deferred_update *du; + u8 *update = prev_update(tmpctx, daemon, chan, direction); + + + if (!update) + return; + + du = find_deferred_update(daemon, chan); + + /* Will a deferred update enable it? If so, apply immediately. */ + if (du && is_enabled(du->update)) { + apply_deferred_update(du); + return; + } + + /* OK, we definitely don't want deferred update to disable! */ + tal_free(du); + + /* Is it already enabled? */ + if (is_enabled(update)) + return; + + /* Apply this enabling update immediately. */ + set_disable_flag(update, false); + sign_timestamp_and_apply_update(daemon, chan, direction, take(update)); } diff --git a/gossipd/gossip_generation.h b/gossipd/gossip_generation.h index d58f5151e56b..b39cc158b47f 100644 --- a/gossipd/gossip_generation.h +++ b/gossipd/gossip_generation.h @@ -35,14 +35,20 @@ bool nannounce_different(struct gossip_store *gs, /* Should we announce our own node? Called at strategic places. */ void maybe_send_own_node_announce(struct daemon *daemon, bool startup); -/* This is a refresh of a local channel: sends an update if one is needed. */ +/* Disable this local channel (lazily) */ +void local_disable_chan(struct daemon *daemon, const struct chan *chan, int direction); + +/* Re-enable this local channel */ +void local_enable_chan(struct daemon *daemon, const struct chan *chan, int direction); + +/* This is a refresh of a local channel which is > 13 days old. */ void refresh_local_channel(struct daemon *daemon, - struct local_chan *local_chan, - bool even_if_identical); + struct chan *chan, int direction); + +/* channeld (via lightningd) asks us to update the local channel. */ +void handle_local_channel_update(struct daemon *daemon, const u8 *msg); -/* channeld asks us to update the local channel. */ -bool handle_local_channel_update(struct daemon *daemon, - const struct node_id *src, - const u8 *msg); +/* lightningd tells us it used the last channel_update we sent. */ +void handle_used_local_channel_update(struct daemon *daemon, const u8 *msg); #endif /* LIGHTNING_GOSSIPD_GOSSIP_GENERATION_H */ diff --git a/gossipd/gossip_store.c b/gossipd/gossip_store.c index 408e79adfd36..f06c5a876678 100644 --- a/gossipd/gossip_store.c +++ b/gossipd/gossip_store.c @@ -782,14 +782,25 @@ u32 gossip_store_load(struct routing_state *rstate, struct gossip_store *gs) } switch (fromwire_peektype(msg)) { - case WIRE_GOSSIP_STORE_PRIVATE_CHANNEL: - if (!routing_add_private_channel(rstate, NULL, msg, + case WIRE_GOSSIP_STORE_PRIVATE_CHANNEL: { + u8 *chan_ann; + struct amount_sat sat; + if (!fromwire_gossip_store_private_channel(msg, msg, + &sat, + &chan_ann)) { + bad = "Bad private_channel"; + goto badmsg; + } + + if (!routing_add_private_channel(rstate, NULL, + sat, chan_ann, gs->len)) { bad = "Bad add_private_channel"; goto badmsg; } stats[0]++; break; + } case WIRE_GOSSIP_STORE_CHANNEL_AMOUNT: if (!fromwire_gossip_store_channel_amount(msg, &satoshis)) { diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c index 3fc121b83480..720df9b471bf 100644 --- a/gossipd/gossipd.c +++ b/gossipd/gossipd.c @@ -13,14 +13,12 @@ #include "config.h" #include #include -#include -#include #include #include #include #include +#include #include -#include #include #include #include @@ -44,15 +42,32 @@ * whole-channel flag which indicates it's not available; we use this when a * peer disconnects, and generate a `channel_update` to tell the world lazily * when someone asks. */ -static void peer_disable_channels(struct daemon *daemon, struct node *node) +static void peer_disable_channels(struct daemon *daemon, const struct node *node) { /* If this peer had a channel with us, mark it disabled. */ struct chan_map_iter i; - struct chan *c; + const struct chan *c; for (c = first_chan(node, &i); c; c = next_chan(node, &i)) { - if (node_id_eq(&other_node(node, c)->id, &daemon->id)) - local_disable_chan(daemon->rstate, c); + int direction; + if (!local_direction(daemon->rstate, c, &direction)) + continue; + local_disable_chan(daemon, c, direction); + } +} + +/*~ This cancels the soft-disables when the peer reconnects. */ +static void peer_enable_channels(struct daemon *daemon, const struct node *node) +{ + /* If this peer had a channel with us, mark it disabled. */ + struct chan_map_iter i; + const struct chan *c; + + for (c = first_chan(node, &i); c; c = next_chan(node, &i)) { + int direction; + if (!local_direction(daemon->rstate, c, &direction)) + continue; + local_enable_chan(daemon, c, direction); } } @@ -74,12 +89,6 @@ static void destroy_peer(struct peer *peer) node = get_node(peer->daemon->rstate, &peer->id); if (node) peer_disable_channels(peer->daemon, node); - - /* This is tricky: our lifetime is tied to the daemon_conn; it's our - * parent, so we are freed if it is, but we need to free it if we're - * freed manually. tal_free() treats this as a noop if it's already - * being freed */ - tal_free(peer->dc); } /* Search for a peer. */ @@ -100,11 +109,15 @@ void peer_supplied_good_gossip(struct peer *peer, size_t amount) peer->gossip_counter += amount; } -/* Queue a gossip message for the peer: the subdaemon on the other end simply - * forwards it to the peer. */ +/* Queue a gossip message for the peer: connectd simply forwards it to + * the peer. */ void queue_peer_msg(struct peer *peer, const u8 *msg TAKES) { - daemon_conn_send(peer->dc, msg); + u8 *outermsg = towire_gossipd_send_gossip(NULL, &peer->id, msg); + daemon_conn_send(peer->daemon->connectd, take(outermsg)); + + if (taken(msg)) + tal_free(msg); } /*~ We have a helper for messages from the store. */ @@ -259,59 +272,6 @@ static u8 *handle_channel_update_msg(struct peer *peer, const u8 *msg) return NULL; } -/*~ This is when channeld asks us for a channel_update for a local channel. - * It does that to fill in the error field when lightningd fails an HTLC and - * sets the UPDATE bit in the error type. lightningd is too important to - * fetch this itself, so channeld does it (channeld has to talk to us for - * other things anyway, so why not?). */ -static bool handle_get_local_channel_update(struct peer *peer, const u8 *msg) -{ - struct short_channel_id scid; - struct local_chan *local_chan; - struct chan *chan; - const u8 *update; - struct routing_state *rstate = peer->daemon->rstate; - - if (!fromwire_gossipd_get_update(msg, &scid)) { - status_broken("peer %s sent bad gossip_get_update %s", - type_to_string(tmpctx, struct node_id, &peer->id), - tal_hex(tmpctx, msg)); - return false; - } - - /* It's possible that the channel has just closed (though v. unlikely) */ - local_chan = local_chan_map_get(&rstate->local_chan_map, &scid); - if (!local_chan) { - status_unusual("peer %s scid %s: unknown channel", - type_to_string(tmpctx, struct node_id, &peer->id), - type_to_string(tmpctx, struct short_channel_id, - &scid)); - update = NULL; - goto out; - } - - chan = local_chan->chan; - - /* Since we're going to send it out, make sure it's up-to-date. */ - refresh_local_channel(peer->daemon, local_chan, false); - - /* It's possible this is zero, if we've never sent a channel_update - * for that channel. */ - if (!is_halfchan_defined(&chan->half[local_chan->direction])) - update = NULL; - else - update = gossip_store_get(tmpctx, rstate->gs, - chan->half[local_chan->direction].bcast.index); -out: - status_peer_debug(&peer->id, "schanid %s: %s update", - type_to_string(tmpctx, struct short_channel_id, &scid), - update ? "got" : "no"); - - msg = towire_gossipd_get_update_reply(NULL, update); - daemon_conn_send(peer->dc, take(msg)); - return true; -} - static u8 *handle_node_announce(struct peer *peer, const u8 *msg) { bool was_unknown = false; @@ -324,395 +284,192 @@ static u8 *handle_node_announce(struct peer *peer, const u8 *msg) return err; } -static bool handle_local_channel_announcement(struct daemon *daemon, - struct peer *peer, - const u8 *msg) +static void handle_local_channel_announcement(struct daemon *daemon, const u8 *msg) { u8 *cannouncement; const u8 *err; + struct node_id id; + struct peer *peer; if (!fromwire_gossipd_local_channel_announcement(msg, msg, - &cannouncement)) { - status_broken("peer %s bad local_channel_announcement %s", - type_to_string(tmpctx, struct node_id, &peer->id), - tal_hex(tmpctx, msg)); - return false; - } + &id, + &cannouncement)) + master_badmsg(WIRE_GOSSIPD_LOCAL_CHANNEL_ANNOUNCEMENT, msg); + + /* We treat it OK even if peer has disconnected since (unlikely though!) */ + peer = find_peer(daemon, &id); + if (!peer) + status_broken("Unknown peer %s for local_channel_announcement", + type_to_string(tmpctx, struct node_id, &id)); err = handle_channel_announcement_msg(daemon, peer, cannouncement); if (err) { status_broken("peer %s invalid local_channel_announcement %s (%s)", - type_to_string(tmpctx, struct node_id, &peer->id), + type_to_string(tmpctx, struct node_id, &id), tal_hex(tmpctx, msg), tal_hex(tmpctx, err)); - return false; } - - return true; } -/* Peer sends obsolete onion msg. */ -static u8 *handle_obs2_onion_message(struct peer *peer, const u8 *msg) -{ - enum onion_wire badreason; - struct onionpacket *op; - struct pubkey blinding, ephemeral; - struct route_step *rs; - u8 *onion; - struct tlv_obs2_onionmsg_payload *om; - struct secret ss, onion_ss; - const u8 *cursor; - size_t max, maxlen; - - /* Ignore unless explicitly turned on. */ - if (!feature_offered(peer->daemon->our_features->bits[NODE_ANNOUNCE_FEATURE], - OPT_ONION_MESSAGES)) - return NULL; - - /* FIXME: ratelimit! */ - if (!fromwire_obs2_onion_message(msg, msg, &blinding, &onion)) - return towire_warningfmt(peer, NULL, "Bad onion_message"); - - /* We unwrap the onion now. */ - op = parse_onionpacket(tmpctx, onion, tal_bytelen(onion), &badreason); - if (!op) { - status_peer_debug(&peer->id, "onion msg: can't parse onionpacket: %s", - onion_wire_name(badreason)); - return NULL; - } - ephemeral = op->ephemeralkey; - if (!unblind_onion(&blinding, ecdh, &ephemeral, &ss)) { - status_peer_debug(&peer->id, "onion msg: can't unblind onionpacket"); - return NULL; +/* channeld (via lightningd) tells us about (as-yet?) unannounce channel. + * It needs us to put it in gossip_store. */ +static void handle_local_private_channel(struct daemon *daemon, const u8 *msg) +{ + struct node_id id; + struct amount_sat capacity; + u8 *features; + struct short_channel_id scid; + const u8 *cannounce; + + if (!fromwire_gossipd_local_private_channel(msg, msg, + &id, &capacity, &scid, + &features)) + master_badmsg(WIRE_GOSSIPD_LOCAL_PRIVATE_CHANNEL, msg); + + cannounce = private_channel_announcement(tmpctx, + &scid, + &daemon->id, + &id, + features); + + if (!routing_add_private_channel(daemon->rstate, &id, capacity, + cannounce, 0)) { + status_peer_broken(&id, "bad add_private_channel %s", + tal_hex(tmpctx, cannounce)); } +} - /* Now get onion shared secret and parse it. */ - ecdh(&ephemeral, &onion_ss); - rs = process_onionpacket(tmpctx, op, &onion_ss, NULL, 0, false); - if (!rs) { - status_peer_debug(&peer->id, - "onion msg: can't process onionpacket ss=%s", - type_to_string(tmpctx, struct secret, &onion_ss)); - return NULL; - } +/*~ This is where connectd tells us about a new peer we might want to + * gossip with. */ +static void connectd_new_peer(struct daemon *daemon, const u8 *msg) +{ + struct peer *peer = tal(daemon, struct peer); + struct node *node; - /* The raw payload is prepended with length in the modern onion. */ - cursor = rs->raw_payload; - max = tal_bytelen(rs->raw_payload); - maxlen = fromwire_bigsize(&cursor, &max); - if (!cursor) { - status_peer_debug(&peer->id, "onion msg: Invalid hop payload %s", - tal_hex(tmpctx, rs->raw_payload)); - return NULL; - } - if (maxlen > max) { - status_peer_debug(&peer->id, "onion msg: overlong hop payload %s", - tal_hex(tmpctx, rs->raw_payload)); - return NULL; + if (!fromwire_gossipd_new_peer(msg, &peer->id, + &peer->gossip_queries_feature)) { + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Bad new_peer msg from connectd: %s", + tal_hex(tmpctx, msg)); } - om = tlv_obs2_onionmsg_payload_new(msg); - if (!fromwire_obs2_onionmsg_payload(&cursor, &maxlen, om)) { - status_peer_debug(&peer->id, "onion msg: invalid onionmsg_payload %s", - tal_hex(tmpctx, rs->raw_payload)); - return NULL; + if (find_peer(daemon, &peer->id)) { + status_broken("Peer %s already here?", + type_to_string(tmpctx, struct node_id, &peer->id)); + tal_free(find_peer(daemon, &peer->id)); } - if (rs->nextcase == ONION_END) { - struct pubkey *reply_blinding, *first_node_id, me, alias; - const struct onionmsg_path **reply_path; - struct secret *self_id; - u8 *omsg; - - if (!pubkey_from_node_id(&me, &peer->daemon->id)) { - status_broken("Failed to convert own id"); - return NULL; - } - - /* Final enctlv is actually optional */ - if (!om->enctlv) { - alias = me; - self_id = NULL; - } else if (!decrypt_obs2_final_enctlv(tmpctx, &blinding, &ss, - om->enctlv, &me, &alias, - &self_id)) { - status_peer_debug(&peer->id, - "onion msg: failed to decrypt enctlv" - " %s", tal_hex(tmpctx, om->enctlv)); - return NULL; - } - - if (om->reply_path) { - first_node_id = &om->reply_path->first_node_id; - reply_blinding = &om->reply_path->blinding; - reply_path = cast_const2(const struct onionmsg_path **, - om->reply_path->path); - } else { - first_node_id = NULL; - reply_blinding = NULL; - reply_path = NULL; - } + /* Populate the rest of the peer info. */ + peer->daemon = daemon; + peer->gossip_counter = 0; + peer->scid_queries = NULL; + peer->scid_query_idx = 0; + peer->scid_query_nodes = NULL; + peer->scid_query_nodes_idx = 0; + peer->scid_query_outstanding = false; + peer->range_replies = NULL; + peer->query_channel_range_cb = NULL; - /* We re-marshall here by policy, before handing to lightningd */ - omsg = tal_arr(tmpctx, u8, 0); - towire_tlvstream_raw(&omsg, om->fields); - daemon_conn_send(peer->daemon->master, - take(towire_gossipd_got_onionmsg_to_us(NULL, - true, /* obs2 */ - &alias, self_id, - reply_blinding, - first_node_id, - reply_path, - omsg))); - } else { - struct pubkey next_node, next_blinding; - struct peer *next_peer; - struct node_id next_node_id; - - /* This fails as expected if no enctlv. */ - if (!decrypt_obs2_enctlv(&blinding, &ss, om->enctlv, &next_node, - &next_blinding)) { - status_peer_debug(&peer->id, - "onion msg: invalid enctlv %s", - tal_hex(tmpctx, om->enctlv)); - return NULL; - } + /* We keep a list so we can find peer by id */ + list_add_tail(&peer->daemon->peers, &peer->list); + tal_add_destructor(peer, destroy_peer); - /* Even though lightningd checks for valid ids, there's a race - * where it might vanish before we read this command. */ - node_id_from_pubkey(&next_node_id, &next_node); - next_peer = find_peer(peer->daemon, &next_node_id); - if (!next_peer) { - status_peer_debug(&peer->id, - "onion msg: unknown next peer %s", - type_to_string(tmpctx, - struct pubkey, - &next_node)); - return NULL; - } - queue_peer_msg(next_peer, - take(towire_obs2_onion_message(NULL, - &next_blinding, - serialize_onionpacket(tmpctx, rs->next)))); - } + node = get_node(daemon->rstate, &peer->id); + if (node) + peer_enable_channels(daemon, node); - return NULL; + /* This sends the initial timestamp filter. */ + seeker_setup_peer_gossip(daemon->seeker, peer); } -static struct io_plan *onionmsg_req(struct io_conn *conn, struct daemon *daemon, - const u8 *msg) +static void connectd_peer_gone(struct daemon *daemon, const u8 *msg) { struct node_id id; - u8 *onionmsg; - struct pubkey blinding; struct peer *peer; - bool obs2; - if (!fromwire_gossipd_send_onionmsg(msg, msg, &obs2, &id, &onionmsg, &blinding)) - master_badmsg(WIRE_GOSSIPD_SEND_ONIONMSG, msg); + if (!fromwire_gossipd_peer_gone(msg, &id)) { + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Bad peer_gone msg from connectd: %s", + tal_hex(tmpctx, msg)); + } - /* Even though lightningd checks for valid ids, there's a race - * where it might vanish before we read this command. */ peer = find_peer(daemon, &id); - if (peer) { - u8 *omsg; - if (obs2) - omsg = towire_obs2_onion_message(NULL, &blinding, onionmsg); - else - omsg = towire_onion_message(NULL, &blinding, onionmsg); - queue_peer_msg(peer, take(omsg)); - } - return daemon_conn_read_next(conn, daemon->master); + if (!peer) + status_broken("Peer %s already gone?", + type_to_string(tmpctx, struct node_id, &id)); + tal_free(peer); } -/* Peer sends an onion msg. */ -static u8 *handle_onion_message(struct peer *peer, const u8 *msg) +/*~ lightningd asks us if we know any addresses for a given id. */ +static struct io_plan *handle_get_address(struct io_conn *conn, + struct daemon *daemon, + const u8 *msg) { - enum onion_wire badreason; - struct onionpacket *op; - struct pubkey blinding, ephemeral; - struct route_step *rs; - u8 *onion; - struct tlv_onionmsg_payload *om; - struct secret ss, onion_ss; - const u8 *cursor; - size_t max, maxlen; - - /* Ignore unless explicitly turned on. */ - if (!feature_offered(peer->daemon->our_features->bits[NODE_ANNOUNCE_FEATURE], - OPT_ONION_MESSAGES)) - return NULL; - - /* FIXME: ratelimit! */ - if (!fromwire_onion_message(msg, msg, &blinding, &onion)) - return towire_warningfmt(peer, NULL, "Bad onion_message"); - - /* We unwrap the onion now. */ - op = parse_onionpacket(tmpctx, onion, tal_bytelen(onion), &badreason); - if (!op) { - status_peer_debug(&peer->id, "onion msg: can't parse onionpacket: %s", - onion_wire_name(badreason)); - return NULL; - } - - ephemeral = op->ephemeralkey; - if (!unblind_onion(&blinding, ecdh, &ephemeral, &ss)) { - status_peer_debug(&peer->id, "onion msg: can't unblind onionpacket"); - return NULL; - } - - /* Now get onion shared secret and parse it. */ - ecdh(&ephemeral, &onion_ss); - rs = process_onionpacket(tmpctx, op, &onion_ss, NULL, 0, false); - if (!rs) { - status_peer_debug(&peer->id, - "onion msg: can't process onionpacket ss=%s", - type_to_string(tmpctx, struct secret, &onion_ss)); - return NULL; - } - - /* The raw payload is prepended with length in the modern onion. */ - cursor = rs->raw_payload; - max = tal_bytelen(rs->raw_payload); - maxlen = fromwire_bigsize(&cursor, &max); - if (!cursor) { - status_peer_debug(&peer->id, "onion msg: Invalid hop payload %s", - tal_hex(tmpctx, rs->raw_payload)); - return NULL; - } - if (maxlen > max) { - status_peer_debug(&peer->id, "onion msg: overlong hop payload %s", - tal_hex(tmpctx, rs->raw_payload)); - return NULL; - } - - om = tlv_onionmsg_payload_new(msg); - if (!fromwire_onionmsg_payload(&cursor, &maxlen, om)) { - status_peer_debug(&peer->id, "onion msg: invalid onionmsg_payload %s", - tal_hex(tmpctx, rs->raw_payload)); - return NULL; - } - - if (rs->nextcase == ONION_END) { - struct pubkey *reply_blinding, *first_node_id, me, alias; - const struct onionmsg_path **reply_path; - struct secret *self_id; - u8 *omsg; - - if (!pubkey_from_node_id(&me, &peer->daemon->id)) { - status_broken("Failed to convert own id"); - return NULL; - } - - /* Final enctlv is actually optional */ - if (!om->encrypted_data_tlv) { - alias = me; - self_id = NULL; - } else if (!decrypt_final_enctlv(tmpctx, &blinding, &ss, - om->encrypted_data_tlv, &me, &alias, - &self_id)) { - status_peer_debug(&peer->id, - "onion msg: failed to decrypt enctlv" - " %s", tal_hex(tmpctx, om->encrypted_data_tlv)); - return NULL; - } - - if (om->reply_path) { - first_node_id = &om->reply_path->first_node_id; - reply_blinding = &om->reply_path->blinding; - reply_path = cast_const2(const struct onionmsg_path **, - om->reply_path->path); - } else { - first_node_id = NULL; - reply_blinding = NULL; - reply_path = NULL; - } + struct node_id id; + u8 rgb_color[3]; + u8 alias[32]; + u8 *features; + struct wireaddr *addrs; + struct lease_rates *rates; - /* We re-marshall here by policy, before handing to lightningd */ - omsg = tal_arr(tmpctx, u8, 0); - towire_tlvstream_raw(&omsg, om->fields); - daemon_conn_send(peer->daemon->master, - take(towire_gossipd_got_onionmsg_to_us(NULL, - false, /* !obs2 */ - &alias, self_id, - reply_blinding, - first_node_id, - reply_path, - omsg))); - } else { - struct pubkey next_node, next_blinding; - struct peer *next_peer; - struct node_id next_node_id; - - /* This fails as expected if no enctlv. */ - if (!decrypt_enctlv(&blinding, &ss, om->encrypted_data_tlv, &next_node, - &next_blinding)) { - status_peer_debug(&peer->id, - "onion msg: invalid enctlv %s", - tal_hex(tmpctx, om->encrypted_data_tlv)); - return NULL; - } + if (!fromwire_gossipd_get_addrs(msg, &id)) + master_badmsg(WIRE_GOSSIPD_GET_ADDRS, msg); - /* FIXME: Handle short_channel_id! */ - node_id_from_pubkey(&next_node_id, &next_node); - next_peer = find_peer(peer->daemon, &next_node_id); - if (!next_peer) { - status_peer_debug(&peer->id, - "onion msg: unknown next peer %s", - type_to_string(tmpctx, - struct pubkey, - &next_node)); - return NULL; - } - queue_peer_msg(next_peer, - take(towire_onion_message(NULL, - &next_blinding, - serialize_onionpacket(tmpctx, rs->next)))); - } + if (!get_node_announcement_by_id(tmpctx, daemon, &id, + rgb_color, alias, &features, &addrs, + &rates)) + addrs = NULL; - return NULL; + daemon_conn_send(daemon->master, + take(towire_gossipd_get_addrs_reply(NULL, addrs))); + return daemon_conn_read_next(conn, daemon->master); } -/*~ This is where the per-peer daemons send us messages. It's either forwarded - * gossip, or a request for information. We deliberately use non-overlapping - * message types so we can distinguish them. */ -static struct io_plan *peer_msg_in(struct io_conn *conn, - const u8 *msg, - struct peer *peer) +static void handle_recv_gossip(struct daemon *daemon, const u8 *outermsg) { + struct node_id id; + u8 *msg; const u8 *err; - bool ok; + struct peer *peer; + + if (!fromwire_gossipd_recv_gossip(outermsg, outermsg, &id, &msg)) { + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Bad gossipd_recv_gossip msg from connectd: %s", + tal_hex(tmpctx, outermsg)); + } + + peer = find_peer(daemon, &id); + if (!peer) { + status_broken("connectd sent gossip msg %s for unknown peer %s", + peer_wire_name(fromwire_peektype(msg)), + type_to_string(tmpctx, struct node_id, &id)); + return; + } /* These are messages relayed from peer */ switch ((enum peer_wire)fromwire_peektype(msg)) { case WIRE_CHANNEL_ANNOUNCEMENT: err = handle_channel_announcement_msg(peer->daemon, peer, msg); - goto handled_relay; + goto handled_msg; case WIRE_CHANNEL_UPDATE: err = handle_channel_update_msg(peer, msg); - goto handled_relay; + goto handled_msg; case WIRE_NODE_ANNOUNCEMENT: err = handle_node_announce(peer, msg); - goto handled_relay; + goto handled_msg; case WIRE_QUERY_CHANNEL_RANGE: err = handle_query_channel_range(peer, msg); - goto handled_relay; + goto handled_msg; case WIRE_REPLY_CHANNEL_RANGE: err = handle_reply_channel_range(peer, msg); - goto handled_relay; + goto handled_msg; case WIRE_QUERY_SHORT_CHANNEL_IDS: err = handle_query_short_channel_ids(peer, msg); - goto handled_relay; + goto handled_msg; case WIRE_REPLY_SHORT_CHANNEL_IDS_END: err = handle_reply_short_channel_ids_end(peer, msg); - goto handled_relay; - case WIRE_OBS2_ONION_MESSAGE: - err = handle_obs2_onion_message(peer, msg); - goto handled_relay; - case WIRE_ONION_MESSAGE: - err = handle_onion_message(peer, msg); - goto handled_relay; + goto handled_msg; /* These are non-gossip messages (!is_msg_for_gossipd()) */ case WIRE_WARNING: @@ -748,198 +505,22 @@ static struct io_plan *peer_msg_in(struct io_conn *conn, case WIRE_ACCEPT_CHANNEL2: case WIRE_INIT_RBF: case WIRE_ACK_RBF: + case WIRE_OBS2_ONION_MESSAGE: + case WIRE_ONION_MESSAGE: #if EXPERIMENTAL_FEATURES case WIRE_STFU: #endif - status_broken("peer %s: relayed unexpected msg of type %s", - type_to_string(tmpctx, struct node_id, &peer->id), - peer_wire_name(fromwire_peektype(msg))); - return io_close(conn); - } - - /* Must be a gossipd_peerd_wire_type asking us to do something. */ - switch ((enum gossipd_peerd_wire)fromwire_peektype(msg)) { - case WIRE_GOSSIPD_GET_UPDATE: - ok = handle_get_local_channel_update(peer, msg); - goto handled_cmd; - case WIRE_GOSSIPD_LOCAL_CHANNEL_UPDATE: - ok = handle_local_channel_update(peer->daemon, &peer->id, msg); - goto handled_cmd; - case WIRE_GOSSIPD_LOCAL_CHANNEL_ANNOUNCEMENT: - ok = handle_local_channel_announcement(peer->daemon, peer, msg); - goto handled_cmd; - - /* These are the ones we send, not them */ - case WIRE_GOSSIPD_GET_UPDATE_REPLY: break; } - if (fromwire_peektype(msg) == WIRE_GOSSIP_STORE_PRIVATE_CHANNEL) { - ok = routing_add_private_channel(peer->daemon->rstate, peer, - msg, 0); - goto handled_cmd; - } + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "connectd sent unexpected gossip msg %s for peer %s", + peer_wire_name(fromwire_peektype(msg)), + type_to_string(tmpctx, struct node_id, &peer->id)); - /* Anything else should not have been sent to us: close on it */ - status_peer_broken(&peer->id, "unexpected cmd of type %i %s", - fromwire_peektype(msg), - gossipd_peerd_wire_name(fromwire_peektype(msg))); - return io_close(conn); - - /* Commands should always be OK. */ -handled_cmd: - if (!ok) - return io_close(conn); - goto done; - - /* Forwarded messages may be bad, so we have error which the per-peer - * daemon will forward to the peer. */ -handled_relay: +handled_msg: if (err) queue_peer_msg(peer, take(err)); -done: - return daemon_conn_read_next(conn, peer->dc); -} - -/*~ This is where connectd tells us about a new peer, and we hand back an fd for - * it to send us messages via peer_msg_in above */ -static struct io_plan *connectd_new_peer(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) -{ - struct peer *peer = tal(conn, struct peer); - int fds[2]; - int gossip_store_fd; - struct gossip_state *gs; - - if (!fromwire_gossipd_new_peer(msg, &peer->id, - &peer->gossip_queries_feature, - &peer->initial_routing_sync_feature)) { - status_broken("Bad new_peer msg from connectd: %s", - tal_hex(tmpctx, msg)); - return io_close(conn); - } - - gossip_store_fd = gossip_store_readonly_fd(daemon->rstate->gs);; - if (gossip_store_fd < 0) { - status_broken("Failed to get readonly store fd: %s", - strerror(errno)); - daemon_conn_send(daemon->connectd, - take(towire_gossipd_new_peer_reply(NULL, - false, - NULL))); - goto done; - } - - /* This can happen: we handle it gracefully, returning a `failed` msg. */ - if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds) != 0) { - status_broken("Failed to create socketpair: %s", - strerror(errno)); - close(gossip_store_fd); - daemon_conn_send(daemon->connectd, - take(towire_gossipd_new_peer_reply(NULL, - false, - NULL))); - goto done; - } - - /* We might not have noticed old peer is dead; kill it now. */ - tal_free(find_peer(daemon, &peer->id)); - - /* Populate the rest of the peer info. */ - peer->daemon = daemon; - peer->gossip_counter = 0; - peer->scid_queries = NULL; - peer->scid_query_idx = 0; - peer->scid_query_nodes = NULL; - peer->scid_query_nodes_idx = 0; - peer->scid_query_outstanding = false; - peer->range_replies = NULL; - peer->query_channel_range_cb = NULL; - - /* We keep a list so we can find peer by id */ - list_add_tail(&peer->daemon->peers, &peer->list); - tal_add_destructor(peer, destroy_peer); - - /* This is the new connection: calls maybe_send_query_responses when - * nothing else to send. */ - peer->dc = daemon_conn_new(daemon, fds[0], - peer_msg_in, - maybe_send_query_responses, peer); - /* Free peer if conn closed (destroy_peer closes conn if peer freed) */ - tal_steal(peer->dc, peer); - - /* This sends the initial timestamp filter. */ - seeker_setup_peer_gossip(daemon->seeker, peer); - - /* BOLT #7: - * - * A node: - * - if the `gossip_queries` feature is negotiated: - * - MUST NOT relay any gossip messages it did not generate itself, - * unless explicitly requested. - */ - if (peer->gossip_queries_feature) { - gs = NULL; - } else { - /* BOLT #7: - * - * - upon receiving an `init` message with the - * `initial_routing_sync` flag set to 1: - * - SHOULD send gossip messages for all known channels and - * nodes, as if they were just received. - * - if the `initial_routing_sync` flag is set to 0, OR if the - * initial sync was completed: - * - SHOULD resume normal operation, as specified in the - * following [Rebroadcasting](#rebroadcasting) section. - */ - gs = tal(tmpctx, struct gossip_state); - gs->timestamp_min = 0; - gs->timestamp_max = UINT32_MAX; - - /* If they don't want initial sync, start at end of store */ - if (!peer->initial_routing_sync_feature) - lseek(gossip_store_fd, 0, SEEK_END); - - gs->next_gossip = time_mono(); - } - - /* Reply with success, and the new fd and gossip_state. */ - daemon_conn_send(daemon->connectd, - take(towire_gossipd_new_peer_reply(NULL, true, gs))); - daemon_conn_send_fd(daemon->connectd, fds[1]); - daemon_conn_send_fd(daemon->connectd, gossip_store_fd); - -done: - return daemon_conn_read_next(conn, daemon->connectd); -} - -/*~ connectd can also ask us if we know any addresses for a given id. */ -static struct io_plan *connectd_get_address(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) -{ - struct node_id id; - u8 rgb_color[3]; - u8 alias[32]; - u8 *features; - struct wireaddr *addrs; - struct lease_rates *rates; - - if (!fromwire_gossipd_get_addrs(msg, &id)) { - status_broken("Bad gossipd_get_addrs msg from connectd: %s", - tal_hex(tmpctx, msg)); - return io_close(conn); - } - - if (!get_node_announcement_by_id(tmpctx, daemon, &id, - rgb_color, alias, &features, &addrs, - &rates)) - addrs = NULL; - - daemon_conn_send(daemon->connectd, - take(towire_gossipd_get_addrs_reply(NULL, addrs))); - return daemon_conn_read_next(conn, daemon->connectd); } /*~ connectd's input handler is very simple. */ @@ -950,40 +531,30 @@ static struct io_plan *connectd_req(struct io_conn *conn, enum connectd_gossipd_wire t = fromwire_peektype(msg); switch (t) { + case WIRE_GOSSIPD_RECV_GOSSIP: + handle_recv_gossip(daemon, msg); + goto handled; + case WIRE_GOSSIPD_NEW_PEER: - return connectd_new_peer(conn, daemon, msg); + connectd_new_peer(daemon, msg); + goto handled; - case WIRE_GOSSIPD_GET_ADDRS: - return connectd_get_address(conn, daemon, msg); + case WIRE_GOSSIPD_PEER_GONE: + connectd_peer_gone(daemon, msg); + goto handled; /* We send these, don't receive them. */ - case WIRE_GOSSIPD_NEW_PEER_REPLY: - case WIRE_GOSSIPD_GET_ADDRS_REPLY: + case WIRE_GOSSIPD_SEND_GOSSIP: break; } - status_broken("Bad msg from connectd: %s", - tal_hex(tmpctx, msg)); - return io_close(conn); -} + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "Bad msg from connectd2: %s", tal_hex(tmpctx, msg)); -/*~ This is our 13-day timer callback for refreshing our channels. This - * was added to the spec because people abandoned their channels without - * closing them. */ -static void gossip_send_keepalive_update(struct daemon *daemon, - struct local_chan *local_chan) -{ - status_debug("Sending keepalive channel_update for %s/%u", - type_to_string(tmpctx, struct short_channel_id, - &local_chan->chan->scid), - local_chan->direction); - - /* As a side-effect, this will create an update which matches the - * local_disabled state */ - refresh_local_channel(daemon, local_chan, true); +handled: + return daemon_conn_read_next(conn, daemon->connectd); } - /* BOLT #7: * * A node: @@ -1016,11 +587,13 @@ static void gossip_refresh_network(struct daemon *daemon) struct chan *c; for (c = first_chan(n, &i); c; c = next_chan(n, &i)) { - struct local_chan *local_chan; struct half_chan *hc; + int direction; + + if (!local_direction(daemon->rstate, c, &direction)) + continue; - local_chan = is_local_chan(daemon->rstate, c); - hc = &c->half[local_chan->direction]; + hc = &c->half[direction]; if (!is_halfchan_defined(hc)) { /* Connection is not announced yet, so don't even @@ -1033,12 +606,12 @@ static void gossip_refresh_network(struct daemon *daemon) continue; } - if (is_chan_local_disabled(daemon->rstate, c)) { - /* Only send keepalives for active connections */ - continue; - } - - gossip_send_keepalive_update(daemon, local_chan); + status_debug("Sending keepalive channel_update" + " for %s/%u", + type_to_string(tmpctx, + struct short_channel_id, + &c->scid), direction); + refresh_local_channel(daemon, c, direction); } } @@ -1060,7 +633,7 @@ static void gossip_disable_local_channels(struct daemon *daemon) return; for (c = first_chan(local_node, &i); c; c = next_chan(local_node, &i)) - local_disable_chan(daemon->rstate, c); + local_disable_chan(daemon, c, half_chan_idx(local_node, c)); } struct peer *random_peer(struct daemon *daemon, @@ -1086,9 +659,7 @@ struct peer *random_peer(struct daemon *daemon, } /*~ Parse init message from lightningd: starts the daemon properly. */ -static struct io_plan *gossip_init(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) +static void gossip_init(struct daemon *daemon, const u8 *msg) { u32 *dev_gossip_time; bool dev_fast_gossip, dev_fast_gossip_prune; @@ -1139,19 +710,17 @@ static struct io_plan *gossip_init(struct io_conn *conn, /* Fire up the seeker! */ daemon->seeker = new_seeker(daemon); - /* connectd is already started, and uses this fd to ask us things. */ + /* connectd is already started, and uses this fd to feed/recv gossip. */ daemon->connectd = daemon_conn_new(daemon, CONNECTD_FD, - connectd_req, NULL, daemon); + connectd_req, + maybe_send_query_responses, daemon); /* OK, we are ready. */ daemon_conn_send(daemon->master, take(towire_gossipd_init_reply(NULL))); - return daemon_conn_read_next(conn, daemon->master); } -static struct io_plan *new_blockheight(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) +static void new_blockheight(struct daemon *daemon, const u8 *msg) { if (!fromwire_gossipd_new_blockheight(msg, &daemon->current_blockheight)) master_badmsg(WIRE_GOSSIPD_NEW_BLOCKHEIGHT, msg); @@ -1172,27 +741,20 @@ static struct io_plan *new_blockheight(struct io_conn *conn, tal_arr_remove(&daemon->deferred_txouts, i); i--; } - - return daemon_conn_read_next(conn, daemon->master); } #if DEVELOPER /* Another testing hack */ -static struct io_plan *dev_gossip_suppress(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) +static void dev_gossip_suppress(struct daemon *daemon, const u8 *msg) { if (!fromwire_gossipd_dev_suppress(msg)) master_badmsg(WIRE_GOSSIPD_DEV_SUPPRESS, msg); status_unusual("Suppressing all gossip"); dev_suppress_gossip = true; - return daemon_conn_read_next(conn, daemon->master); } -static struct io_plan *dev_gossip_memleak(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) +static void dev_gossip_memleak(struct daemon *daemon, const u8 *msg) { struct htable *memtable; bool found_leak; @@ -1206,24 +768,18 @@ static struct io_plan *dev_gossip_memleak(struct io_conn *conn, daemon_conn_send(daemon->master, take(towire_gossipd_dev_memleak_reply(NULL, found_leak))); - return daemon_conn_read_next(conn, daemon->master); } -static struct io_plan *dev_compact_store(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) +static void dev_compact_store(struct daemon *daemon, const u8 *msg) { bool done = gossip_store_compact(daemon->rstate->gs); daemon_conn_send(daemon->master, take(towire_gossipd_dev_compact_store_reply(NULL, done))); - return daemon_conn_read_next(conn, daemon->master); } -static struct io_plan *dev_gossip_set_time(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) +static void dev_gossip_set_time(struct daemon *daemon, const u8 *msg) { u32 time; @@ -1233,55 +789,12 @@ static struct io_plan *dev_gossip_set_time(struct io_conn *conn, daemon->rstate->gossip_time = tal(daemon->rstate, struct timeabs); daemon->rstate->gossip_time->ts.tv_sec = time; daemon->rstate->gossip_time->ts.tv_nsec = 0; - - return daemon_conn_read_next(conn, daemon->master); } #endif /* DEVELOPER */ -/*~ lightningd: so, get me the latest update for this local channel, - * so I can include it in an error message. */ -static struct io_plan *get_stripped_cupdate(struct io_conn *conn, - struct daemon *daemon, const u8 *msg) -{ - struct short_channel_id scid; - struct local_chan *local_chan; - const u8 *stripped_update; - - if (!fromwire_gossipd_get_stripped_cupdate(msg, &scid)) - master_badmsg(WIRE_GOSSIPD_GET_STRIPPED_CUPDATE, msg); - - local_chan = local_chan_map_get(&daemon->rstate->local_chan_map, &scid); - if (!local_chan) { - status_debug("Failed to resolve local channel %s", - type_to_string(tmpctx, struct short_channel_id, &scid)); - stripped_update = NULL; - } else { - const struct half_chan *hc; - - /* Since we're going to use it, make sure it's up-to-date. */ - refresh_local_channel(daemon, local_chan, false); - - hc = &local_chan->chan->half[local_chan->direction]; - if (is_halfchan_defined(hc)) { - const u8 *update; - - update = gossip_store_get(tmpctx, daemon->rstate->gs, - hc->bcast.index); - stripped_update = tal_dup_arr(tmpctx, u8, update + 2, - tal_count(update) - 2, 0); - } else - stripped_update = NULL; - } - daemon_conn_send(daemon->master, - take(towire_gossipd_get_stripped_cupdate_reply(NULL, - stripped_update))); - return daemon_conn_read_next(conn, daemon->master); -} - /*~ We queue incoming channel_announcement pending confirmation from lightningd * that it really is an unspent output. Here's its reply. */ -static struct io_plan *handle_txout_reply(struct io_conn *conn, - struct daemon *daemon, const u8 *msg) +static void handle_txout_reply(struct daemon *daemon, const u8 *msg) { struct short_channel_id scid; u8 *outscript; @@ -1301,16 +814,12 @@ static struct io_plan *handle_txout_reply(struct io_conn *conn, /* Anywhere we might have announced a channel, we check if it's time to * announce ourselves (ie. if we just announced our own first channel) */ maybe_send_own_node_announce(daemon, false); - - return daemon_conn_read_next(conn, daemon->master); } /*~ lightningd tells us when about a gossip message directly, when told to by * the addgossip RPC call. That's usually used when a plugin gets an update * returned in an payment error. */ -static struct io_plan *inject_gossip(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) +static void inject_gossip(struct daemon *daemon, const u8 *msg) { u8 *goss; const u8 *errmsg; @@ -1349,12 +858,9 @@ static struct io_plan *inject_gossip(struct io_conn *conn, err_extracted: daemon_conn_send(daemon->master, take(towire_gossipd_addgossip_reply(NULL, err))); - return daemon_conn_read_next(conn, daemon->master); } -static struct io_plan *handle_new_lease_rates(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) +static void handle_new_lease_rates(struct daemon *daemon, const u8 *msg) { struct lease_rates *rates = tal(daemon, struct lease_rates); @@ -1369,15 +875,11 @@ static struct io_plan *handle_new_lease_rates(struct io_conn *conn, /* Send the update over to the peer */ maybe_send_own_node_announce(daemon, false); - - return daemon_conn_read_next(conn, daemon->master); } /*~ This is where lightningd tells us that a channel's funding transaction has * been spent. */ -static struct io_plan *handle_outpoint_spent(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) +static void handle_outpoint_spent(struct daemon *daemon, const u8 *msg) { struct short_channel_id scid; struct chan *chan; @@ -1399,8 +901,6 @@ static struct io_plan *handle_outpoint_spent(struct io_conn *conn, * the channel */ free_chan(rstate, chan); } - - return daemon_conn_read_next(conn, daemon->master); } /*~ This is sent by lightningd when it kicks off 'closingd': we disable it @@ -1412,9 +912,7 @@ static struct io_plan *handle_outpoint_spent(struct io_conn *conn, * channels. This does not send out updates since that's triggered by the peer * connection closing. */ -static struct io_plan *handle_local_channel_close(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) +static void handle_local_channel_close(struct daemon *daemon, const u8 *msg) { struct short_channel_id scid; struct chan *chan; @@ -1423,9 +921,18 @@ static struct io_plan *handle_local_channel_close(struct io_conn *conn, master_badmsg(WIRE_GOSSIPD_LOCAL_CHANNEL_CLOSE, msg); chan = get_channel(rstate, &scid); - if (chan) - local_disable_chan(rstate, chan); - return daemon_conn_read_next(conn, daemon->master); + if (chan) { + int direction; + + if (!local_direction(rstate, chan, &direction)) { + status_broken("Non-local channel close %s", + type_to_string(tmpctx, + struct short_channel_id, + &scid)); + } else { + local_disable_chan(daemon, chan, direction); + } + } } /*~ This routine handles all the commands from lightningd. */ @@ -1437,40 +944,67 @@ static struct io_plan *recv_req(struct io_conn *conn, switch (t) { case WIRE_GOSSIPD_INIT: - return gossip_init(conn, daemon, msg); - - case WIRE_GOSSIPD_GET_STRIPPED_CUPDATE: - return get_stripped_cupdate(conn, daemon, msg); + gossip_init(daemon, msg); + goto done; case WIRE_GOSSIPD_GET_TXOUT_REPLY: - return handle_txout_reply(conn, daemon, msg); + handle_txout_reply(daemon, msg); + goto done; case WIRE_GOSSIPD_OUTPOINT_SPENT: - return handle_outpoint_spent(conn, daemon, msg); + handle_outpoint_spent(daemon, msg); + goto done; case WIRE_GOSSIPD_LOCAL_CHANNEL_CLOSE: - return handle_local_channel_close(conn, daemon, msg); + handle_local_channel_close(daemon, msg); + goto done; case WIRE_GOSSIPD_NEW_BLOCKHEIGHT: - return new_blockheight(conn, daemon, msg); + new_blockheight(daemon, msg); + goto done; case WIRE_GOSSIPD_ADDGOSSIP: - return inject_gossip(conn, daemon, msg); + inject_gossip(daemon, msg); + goto done; case WIRE_GOSSIPD_NEW_LEASE_RATES: - return handle_new_lease_rates(conn, daemon, msg); + handle_new_lease_rates(daemon, msg); + goto done; + + case WIRE_GOSSIPD_GET_ADDRS: + return handle_get_address(conn, daemon, msg); + + case WIRE_GOSSIPD_USED_LOCAL_CHANNEL_UPDATE: + handle_used_local_channel_update(daemon, msg); + goto done; + case WIRE_GOSSIPD_LOCAL_CHANNEL_UPDATE: + handle_local_channel_update(daemon, msg); + goto done; + + case WIRE_GOSSIPD_LOCAL_CHANNEL_ANNOUNCEMENT: + handle_local_channel_announcement(daemon, msg); + goto done; + + case WIRE_GOSSIPD_LOCAL_PRIVATE_CHANNEL: + handle_local_private_channel(daemon, msg); + goto done; #if DEVELOPER case WIRE_GOSSIPD_DEV_SET_MAX_SCIDS_ENCODE_SIZE: - return dev_set_max_scids_encode_size(conn, daemon, msg); + dev_set_max_scids_encode_size(daemon, msg); + goto done; case WIRE_GOSSIPD_DEV_SUPPRESS: - return dev_gossip_suppress(conn, daemon, msg); + dev_gossip_suppress(daemon, msg); + goto done; case WIRE_GOSSIPD_DEV_MEMLEAK: - return dev_gossip_memleak(conn, daemon, msg); + dev_gossip_memleak(daemon, msg); + goto done; case WIRE_GOSSIPD_DEV_COMPACT_STORE: - return dev_compact_store(conn, daemon, msg); + dev_compact_store(daemon, msg); + goto done; case WIRE_GOSSIPD_DEV_SET_TIME: - return dev_gossip_set_time(conn, daemon, msg); + dev_gossip_set_time(daemon, msg); + goto done; #else case WIRE_GOSSIPD_DEV_SET_MAX_SCIDS_ENCODE_SIZE: case WIRE_GOSSIPD_DEV_SUPPRESS: @@ -1480,23 +1014,23 @@ static struct io_plan *recv_req(struct io_conn *conn, break; #endif /* !DEVELOPER */ - case WIRE_GOSSIPD_SEND_ONIONMSG: - return onionmsg_req(conn, daemon, msg); - /* We send these, we don't receive them */ case WIRE_GOSSIPD_INIT_REPLY: - case WIRE_GOSSIPD_GET_STRIPPED_CUPDATE_REPLY: case WIRE_GOSSIPD_GET_TXOUT: case WIRE_GOSSIPD_DEV_MEMLEAK_REPLY: case WIRE_GOSSIPD_DEV_COMPACT_STORE_REPLY: - case WIRE_GOSSIPD_GOT_ONIONMSG_TO_US: case WIRE_GOSSIPD_ADDGOSSIP_REPLY: + case WIRE_GOSSIPD_GET_ADDRS_REPLY: + case WIRE_GOSSIPD_GOT_LOCAL_CHANNEL_UPDATE: break; } /* Master shouldn't give bad requests. */ status_failed(STATUS_FAIL_MASTER_IO, "%i: %s", t, tal_hex(tmpctx, msg)); + +done: + return daemon_conn_read_next(conn, daemon->master); } /* This is called when lightningd closes its connection to us. We simply @@ -1522,6 +1056,7 @@ int main(int argc, char *argv[]) daemon->node_announce_timer = NULL; daemon->current_blockheight = 0; /* i.e. unknown */ daemon->rates = NULL; + list_head_init(&daemon->deferred_updates); /* Tell the ecdh() function how to talk to hsmd */ ecdh_hsmd_setup(HSM_FD, status_failed); diff --git a/gossipd/gossipd.h b/gossipd/gossipd.h index fe2082c74b26..a84d5765eb71 100644 --- a/gossipd/gossipd.h +++ b/gossipd/gossipd.h @@ -9,6 +9,7 @@ #define HSM_FD 3 /* connectd asks us for help finding nodes, and gossip fds for new peers */ #define CONNECTD_FD 4 +#define CONNECTD2_FD 5 struct chan; struct channel_update_timestamps; @@ -60,6 +61,9 @@ struct daemon { /* The channel lease rates we're advertising */ const struct lease_rates *rates; + + /* Any of our channel_updates we're deferring. */ + struct list_head deferred_updates; }; struct range_query_reply { @@ -104,9 +108,6 @@ struct peer { void (*query_channel_range_cb)(struct peer *peer, u32 first_blocknum, u32 number_of_blocks, const struct range_query_reply *replies); - - /* The daemon_conn used to queue messages to/from the peer. */ - struct daemon_conn *dc; }; /* Search for a peer. */ diff --git a/gossipd/gossipd_peerd_wire.csv b/gossipd/gossipd_peerd_wire.csv index 10c48adeaf89..282712beb4bc 100644 --- a/gossipd/gossipd_peerd_wire.csv +++ b/gossipd/gossipd_peerd_wire.csv @@ -2,27 +2,3 @@ #include #include -# Channel daemon can ask for updates for a specific channel, for sending -# errors. -msgtype,gossipd_get_update,3501 -msgdata,gossipd_get_update,short_channel_id,short_channel_id, - -# If channel isn't known, update will be empty. -msgtype,gossipd_get_update_reply,3601 -msgdata,gossipd_get_update_reply,len,u16, -msgdata,gossipd_get_update_reply,update,u8,len - -# Send this channel_update. -msgtype,gossipd_local_channel_update,3504 -msgdata,gossipd_local_channel_update,short_channel_id,short_channel_id, -msgdata,gossipd_local_channel_update,disable,bool, -msgdata,gossipd_local_channel_update,cltv_expiry_delta,u16, -msgdata,gossipd_local_channel_update,htlc_minimum_msat,amount_msat, -msgdata,gossipd_local_channel_update,fee_base_msat,u32, -msgdata,gossipd_local_channel_update,fee_proportional_millionths,u32, -msgdata,gossipd_local_channel_update,htlc_maximum_msat,amount_msat, - -# Send this channel_announcement -msgtype,gossipd_local_channel_announcement,3506 -msgdata,gossipd_local_channel_announcement,len,u16, -msgdata,gossipd_local_channel_announcement,cannount,u8,len diff --git a/gossipd/gossipd_wire.csv b/gossipd/gossipd_wire.csv index 8f49421d0312..712aee5c52ff 100644 --- a/gossipd/gossipd_wire.csv +++ b/gossipd/gossipd_wire.csv @@ -27,14 +27,6 @@ msgdata,gossipd_dev_set_time,dev_gossip_time,u32, msgtype,gossipd_dev_set_max_scids_encode_size,3030 msgdata,gossipd_dev_set_max_scids_encode_size,max,u32, -# Given a short_channel_id, return the latest (stripped) update for error msg. -msgtype,gossipd_get_stripped_cupdate,3010 -msgdata,gossipd_get_stripped_cupdate,channel_id,short_channel_id, - -msgtype,gossipd_get_stripped_cupdate_reply,3110 -msgdata,gossipd_get_stripped_cupdate_reply,stripped_update_len,u16, -msgdata,gossipd_get_stripped_cupdate_reply,stripped_update,u8,stripped_update_len - # gossipd->master: we're closing this channel. msgtype,gossipd_local_channel_close,3027 msgdata,gossipd_local_channel_close,short_channel_id,short_channel_id, @@ -74,25 +66,6 @@ msgdata,gossipd_dev_compact_store_reply,success,bool, msgtype,gossipd_new_blockheight,3026 msgdata,gossipd_new_blockheight,blockheight,u32, -msgtype,gossipd_got_onionmsg_to_us,3145 -msgdata,gossipd_got_onionmsg_to_us,obs2,bool, -msgdata,gossipd_got_onionmsg_to_us,node_alias,pubkey, -msgdata,gossipd_got_onionmsg_to_us,self_id,?secret, -msgdata,gossipd_got_onionmsg_to_us,reply_blinding,?pubkey, -msgdata,gossipd_got_onionmsg_to_us,reply_first_node,?pubkey, -msgdata,gossipd_got_onionmsg_to_us,reply_path_len,u16, -msgdata,gossipd_got_onionmsg_to_us,reply_path,onionmsg_path,reply_path_len -msgdata,gossipd_got_onionmsg_to_us,rawmsg_len,u16, -msgdata,gossipd_got_onionmsg_to_us,rawmsg,u8,rawmsg_len - -# Lightningd tells us to send an onion message. -msgtype,gossipd_send_onionmsg,3041 -msgdata,gossipd_send_onionmsg,obs2,bool, -msgdata,gossipd_send_onionmsg,id,node_id, -msgdata,gossipd_send_onionmsg,onion_len,u16, -msgdata,gossipd_send_onionmsg,onion,u8,onion_len -msgdata,gossipd_send_onionmsg,blinding,pubkey, - # Lightningd tells us to inject a gossip message (for addgossip RPC) msgtype,gossipd_addgossip,3044 msgdata,gossipd_addgossip,len,u16, @@ -105,3 +78,47 @@ msgdata,gossipd_addgossip_reply,err,wirestring, # Updated lease rates available msgtype,gossipd_new_lease_rates,3046 msgdata,gossipd_new_lease_rates,rates,lease_rates, + +# Lightningd asks gossipd for any known addresses for that node. +msgtype,gossipd_get_addrs,3050 +msgdata,gossipd_get_addrs,id,node_id, + +msgtype,gossipd_get_addrs_reply,3150 +msgdata,gossipd_get_addrs_reply,num,u16, +msgdata,gossipd_get_addrs_reply,addrs,wireaddr,num + +# Tell master a local channel update (so it can serve errors). +msgtype,gossipd_got_local_channel_update,3151 +msgdata,gossipd_got_local_channel_update,scid,short_channel_id, +msgdata,gossipd_got_local_channel_update,len,u16, +msgdata,gossipd_got_local_channel_update,channel_update,u8,len + +# Send this channel_update. +msgtype,gossipd_local_channel_update,3004 +msgdata,gossipd_local_channel_update,id,node_id, +msgdata,gossipd_local_channel_update,short_channel_id,short_channel_id, +msgdata,gossipd_local_channel_update,disable,bool, +msgdata,gossipd_local_channel_update,cltv_expiry_delta,u16, +msgdata,gossipd_local_channel_update,htlc_minimum_msat,amount_msat, +msgdata,gossipd_local_channel_update,fee_base_msat,u32, +msgdata,gossipd_local_channel_update,fee_proportional_millionths,u32, +msgdata,gossipd_local_channel_update,htlc_maximum_msat,amount_msat, + +# Send this channel_announcement +msgtype,gossipd_local_channel_announcement,3006 +msgdata,gossipd_local_channel_announcement,id,node_id, +msgdata,gossipd_local_channel_announcement,len,u16, +msgdata,gossipd_local_channel_announcement,cannounce,u8,len + +# Tell gossipd about a private channel (to put it in the store) +# cannounce has same structure, dummy sigs. +msgtype,gossipd_local_private_channel,3008 +msgdata,gossipd_local_private_channel,id,node_id, +msgdata,gossipd_local_private_channel,capacity,amount_sat, +msgdata,gossipd_local_private_channel,scid,short_channel_id, +msgdata,gossipd_local_private_channel,len,u16, +msgdata,gossipd_local_private_channel,features,u8,len + +# Tell gossipd we used the channel update (in case it was deferred) +msgtype,gossipd_used_local_channel_update,3052 +msgdata,gossipd_used_local_channel_update,scid,short_channel_id, diff --git a/gossipd/queries.c b/gossipd/queries.c index b46a683b9a8e..436ee9b2c4b4 100644 --- a/gossipd/queries.c +++ b/gossipd/queries.c @@ -335,8 +335,8 @@ const u8 *handle_query_short_channel_ids(struct peer *peer, const u8 *msg) peer->scid_query_idx = 0; peer->scid_query_nodes = tal_arr(peer, struct node_id, 0); - /* Notify the daemon_conn-write loop to invoke create_next_scid_reply */ - daemon_conn_wake(peer->dc); + /* Notify the daemon_conn-write loop to invoke maybe_send_query_responses_peer */ + daemon_conn_wake(peer->daemon->connectd); return NULL; } @@ -985,7 +985,7 @@ static void uniquify_node_ids(struct node_id **ids) /* We are fairly careful to avoid the peer DoSing us with channel queries: * this routine sends information about a single short_channel_id, unless * it's finished all of them. */ -void maybe_send_query_responses(struct peer *peer) +static bool maybe_send_query_responses_peer(struct peer *peer) { struct routing_state *rstate = peer->daemon->rstate; size_t i, num; @@ -1119,6 +1119,22 @@ void maybe_send_query_responses(struct peer *peer) peer->scid_query_nodes = tal_free(peer->scid_query_nodes); peer->scid_query_nodes_idx = 0; } + return sent; +} + +void maybe_send_query_responses(struct daemon *daemon) +{ + /* Rotate through, so we don't favor a single peer. */ + struct list_head used; + struct peer *p; + + list_head_init(&used); + while ((p = list_pop(&daemon->peers, struct peer, list)) != NULL) { + list_add(&used, &p->list); + if (maybe_send_query_responses_peer(p)) + break; + } + list_append_list(&daemon->peers, &used); } bool query_channel_range(struct daemon *daemon, @@ -1163,15 +1179,12 @@ bool query_channel_range(struct daemon *daemon, #if DEVELOPER /* This is a testing hack to allow us to artificially lower the maximum bytes * of short_channel_ids we'll encode, using dev_set_max_scids_encode_size. */ -struct io_plan *dev_set_max_scids_encode_size(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg) +void dev_set_max_scids_encode_size(struct daemon *daemon, const u8 *msg) { if (!fromwire_gossipd_dev_set_max_scids_encode_size(msg, &dev_max_encoding_bytes)) master_badmsg(WIRE_GOSSIPD_DEV_SET_MAX_SCIDS_ENCODE_SIZE, msg); status_debug("Set max_scids_encode_bytes to %u", dev_max_encoding_bytes); - return daemon_conn_read_next(conn, daemon->master); } #endif /* DEVELOPER */ diff --git a/gossipd/queries.h b/gossipd/queries.h index 67fbca0c30ee..1e4019f11115 100644 --- a/gossipd/queries.h +++ b/gossipd/queries.h @@ -16,8 +16,8 @@ const u8 *handle_reply_short_channel_ids_end(struct peer *peer, const u8 *msg); const u8 *handle_query_channel_range(struct peer *peer, const u8 *msg); const u8 *handle_reply_channel_range(struct peer *peer, const u8 *msg); -/* This called when the peer is idle. */ -void maybe_send_query_responses(struct peer *peer); +/* This called when the connectd is idle. */ +void maybe_send_query_responses(struct daemon *daemon); /* BOLT #7: * @@ -62,9 +62,7 @@ struct io_plan *dev_query_channel_range(struct io_conn *conn, /* This is a testing hack to allow us to artificially lower the maximum bytes * of short_channel_ids we'll encode, using dev_set_max_scids_encode_size. */ -struct io_plan *dev_set_max_scids_encode_size(struct io_conn *conn, - struct daemon *daemon, - const u8 *msg); +void dev_set_max_scids_encode_size(struct daemon *daemon, const u8 *msg); #endif /* DEVELOPER */ #endif /* LIGHTNING_GOSSIPD_QUERIES_H */ diff --git a/gossipd/routing.c b/gossipd/routing.c index d246b2ee53fc..947ab0e86b08 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -198,7 +198,6 @@ static void destroy_routing_state(struct routing_state *rstate) /* Free up our htables */ pending_cannouncement_map_clear(&rstate->pending_cannouncements); - local_chan_map_clear(&rstate->local_chan_map); } /* We don't check this when loading from the gossip_store: that would break @@ -226,7 +225,6 @@ static void memleak_help_routing_tables(struct htable *memtable, memleak_remove_htable(memtable, &rstate->nodes->raw); memleak_remove_htable(memtable, &rstate->pending_node_map->raw); memleak_remove_htable(memtable, &rstate->pending_cannouncements.raw); - memleak_remove_htable(memtable, &rstate->local_chan_map.raw); memleak_remove_uintmap(memtable, &rstate->unupdated_chanmap); for (n = node_map_first(rstate->nodes, &nit); @@ -295,7 +293,6 @@ struct routing_state *new_routing_state(const tal_t *ctx, uintmap_init(&rstate->chanmap); uintmap_init(&rstate->unupdated_chanmap); - local_chan_map_init(&rstate->local_chan_map); rstate->num_txout_failures = 0; uintmap_init(&rstate->txout_failures); uintmap_init(&rstate->txout_failures_old); @@ -524,36 +521,6 @@ static void bad_gossip_order(const u8 *msg, details); } -static void destroy_local_chan(struct local_chan *local_chan, - struct routing_state *rstate) -{ - if (!local_chan_map_del(&rstate->local_chan_map, local_chan)) - abort(); -} - -static void maybe_add_local_chan(struct routing_state *rstate, - struct chan *chan) -{ - int direction; - struct local_chan *local_chan; - - if (node_id_eq(&chan->nodes[0]->id, &rstate->local_id)) - direction = 0; - else if (node_id_eq(&chan->nodes[1]->id, &rstate->local_id)) - direction = 1; - else - return; - - local_chan = tal(chan, struct local_chan); - local_chan->chan = chan; - local_chan->direction = direction; - local_chan->local_disabled = false; - local_chan->channel_update_timer = NULL; - - local_chan_map_add(&rstate->local_chan_map, local_chan); - tal_add_destructor2(local_chan, destroy_local_chan, rstate); -} - struct chan *new_chan(struct routing_state *rstate, const struct short_channel_id *scid, const struct node_id *id1, @@ -595,8 +562,6 @@ struct chan *new_chan(struct routing_state *rstate, uintmap_add(&rstate->chanmap, scid->u64, chan); - /* Initialize shadow structure if it's local */ - maybe_add_local_chan(rstate, chan); return chan; } @@ -795,13 +760,6 @@ static void destroy_pending_cannouncement(struct pending_cannouncement *pending, pending_cannouncement_map_del(&rstate->pending_cannouncements, pending); } -static bool is_local_channel(const struct routing_state *rstate, - const struct chan *chan) -{ - return node_id_eq(&chan->nodes[0]->id, &rstate->local_id) - || node_id_eq(&chan->nodes[1]->id, &rstate->local_id); -} - static void add_channel_announce_to_broadcast(struct routing_state *rstate, struct chan *chan, const u8 *channel_announce, @@ -809,7 +767,7 @@ static void add_channel_announce_to_broadcast(struct routing_state *rstate, u32 index) { u8 *addendum = towire_gossip_store_channel_amount(tmpctx, chan->sat); - bool is_local = is_local_channel(rstate, chan); + bool is_local = local_direction(rstate, chan, NULL); chan->bcast.timestamp = timestamp; /* 0, unless we're loading from store */ @@ -1381,7 +1339,7 @@ bool routing_add_channel_update(struct routing_state *rstate, } else if (!is_chan_public(chan)) { /* For private channels, we get updates without an announce: don't * broadcast them! But save local ones to store anyway. */ - assert(is_local_channel(rstate, chan)); + assert(local_direction(rstate, chan, NULL)); /* Don't save if we're loading from store */ if (!index) { hc->bcast.index @@ -1399,7 +1357,7 @@ bool routing_add_channel_update(struct routing_state *rstate, hc->bcast.index = gossip_store_add(rstate->gs, update, hc->bcast.timestamp, - is_local_channel(rstate, chan), + local_direction(rstate, chan, NULL), NULL); if (hc->bcast.timestamp > rstate->last_timestamp && hc->bcast.timestamp < time_now().ts.tv_sec) @@ -1863,23 +1821,18 @@ void route_prune(struct routing_state *rstate) } bool routing_add_private_channel(struct routing_state *rstate, - const struct peer *peer, - const u8 *msg, u64 index) + const struct node_id *id, + struct amount_sat capacity, + const u8 *chan_ann, u64 index) { struct short_channel_id scid; struct node_id node_id[2]; struct pubkey ignorekey; - struct amount_sat sat; struct chan *chan; - u8 *features, *chan_ann; + u8 *features; secp256k1_ecdsa_signature ignoresig; struct bitcoin_blkid chain_hash; - if (!fromwire_gossip_store_private_channel(tmpctx, msg, - &sat, &chan_ann)) - return false; - - if (!fromwire_channel_announcement(tmpctx, chan_ann, &ignoresig, &ignoresig, @@ -1894,21 +1847,46 @@ bool routing_add_private_channel(struct routing_state *rstate, &ignorekey)) return false; - /* Can happen on channeld restart. */ - if (get_channel(rstate, &scid)) { - status_peer_debug(peer ? &peer->id : NULL, - "Attempted to local_add_channel a known channel"); + /* Happens on channeld restart. */ + if (get_channel(rstate, &scid)) return true; - } - status_peer_debug(peer ? &peer->id : NULL, - "local_add_channel %s", - type_to_string(tmpctx, struct short_channel_id, &scid)); + /* Make sure this id (if any) was allowed to create this */ + if (id) { + struct node_id expected[2]; + int cmp = node_id_cmp(&rstate->local_id, id); + + if (cmp < 0) { + expected[0] = rstate->local_id; + expected[1] = *id; + } else if (cmp > 0) { + expected[0] = *id; + expected[1] = rstate->local_id; + } else { + /* lightningd sets id, so this is fatal */ + status_failed(STATUS_FAIL_MASTER_IO, + "private_channel peer was us?"); + } + + if (!node_id_eq(&node_id[0], &expected[0]) + || !node_id_eq(&node_id[1], &expected[1])) { + status_peer_broken(id, "private channel %s<->%s invalid", + type_to_string(tmpctx, struct node_id, + &node_id[0]), + type_to_string(tmpctx, struct node_id, + &node_id[1])); + return false; + } + } /* Create new (unannounced) channel */ - chan = new_chan(rstate, &scid, &node_id[0], &node_id[1], sat); - if (!index) + chan = new_chan(rstate, &scid, &node_id[0], &node_id[1], capacity); + if (!index) { + u8 *msg = towire_gossip_store_private_channel(tmpctx, + capacity, + chan_ann); index = gossip_store_add(rstate->gs, msg, 0, false, NULL); + } chan->bcast.index = index; return true; } diff --git a/gossipd/routing.h b/gossipd/routing.h index a0ec756f09fe..1641284bb667 100644 --- a/gossipd/routing.h +++ b/gossipd/routing.h @@ -94,22 +94,6 @@ static inline bool chan_eq_scid(const struct chan *c, HTABLE_DEFINE_TYPE(struct chan, chan_map_scid, hash_scid, chan_eq_scid, chan_map); -/* Container for local channel pointers. */ -static inline const struct short_channel_id *local_chan_map_scid(const struct local_chan *local_chan) -{ - return &local_chan->chan->scid; -} - -static inline bool local_chan_eq_scid(const struct local_chan *local_chan, - const struct short_channel_id *scid) -{ - return short_channel_id_eq(scid, &local_chan->chan->scid); -} - -HTABLE_DEFINE_TYPE(struct local_chan, - local_chan_map_scid, hash_scid, local_chan_eq_scid, - local_chan_map); - /* For a small number of channels (by far the most common) we use a simple * array, with empty buckets NULL. For larger, we use a proper hash table, * with the extra allocation that implies. */ @@ -191,33 +175,13 @@ HTABLE_DEFINE_TYPE(struct pending_cannouncement, panding_cannouncement_map_scid, struct pending_node_map; struct unupdated_channel; -/* Fast versions: if you know n is one end of the channel */ -static inline struct node *other_node(const struct node *n, - const struct chan *chan) -{ - int idx = (chan->nodes[1] == n); - - assert(chan->nodes[0] == n || chan->nodes[1] == n); - return chan->nodes[!idx]; -} - -/* If you know n is one end of the channel, get connection src == n */ -static inline struct half_chan *half_chan_from(const struct node *n, - struct chan *chan) -{ - int idx = (chan->nodes[1] == n); - - assert(chan->nodes[0] == n || chan->nodes[1] == n); - return &chan->half[idx]; -} - -/* If you know n is one end of the channel, get index dst == n */ -static inline int half_chan_to(const struct node *n, const struct chan *chan) +/* If you know n is one end of the channel, get index of src == n */ +static inline int half_chan_idx(const struct node *n, const struct chan *chan) { int idx = (chan->nodes[1] == n); assert(chan->nodes[0] == n || chan->nodes[1] == n); - return !idx; + return idx; } struct routing_state { @@ -255,9 +219,6 @@ struct routing_state { UINTMAP(bool) txout_failures, txout_failures_old; struct oneshot *txout_failure_timer; - /* A map of local channels by short_channel_ids */ - struct local_chan_map local_chan_map; - /* Highest timestamp of gossip we accepted (before now) */ u32 last_timestamp; @@ -273,6 +234,21 @@ struct routing_state { #endif }; +/* Which direction are we? False if neither. */ +static inline bool local_direction(struct routing_state *rstate, + const struct chan *chan, + int *direction) +{ + for (int dir = 0; dir <= 1; (dir)++) { + if (node_id_eq(&chan->nodes[dir]->id, &rstate->local_id)) { + if (direction) + *direction = dir; + return true; + } + } + return false; +} + static inline struct chan * get_channel(const struct routing_state *rstate, const struct short_channel_id *scid) @@ -402,8 +378,9 @@ bool routing_add_node_announcement(struct routing_state *rstate, * `announce_depth`. */ bool routing_add_private_channel(struct routing_state *rstate, - const struct peer *peer, - const u8 *msg, u64 index); + const struct node_id *id, + struct amount_sat sat, + const u8 *chan_ann, u64 index); /** * Get the local time. @@ -412,41 +389,11 @@ bool routing_add_private_channel(struct routing_state *rstate, */ struct timeabs gossip_time_now(const struct routing_state *rstate); -static inline struct local_chan *is_local_chan(struct routing_state *rstate, - const struct chan *chan) -{ - return local_chan_map_get(&rstate->local_chan_map, &chan->scid); -} - /* Would we ratelimit a channel_update with this timestamp? */ bool would_ratelimit_cupdate(struct routing_state *rstate, const struct half_chan *hc, u32 timestamp); -/* Because we can have millions of channels, and we only want a local_disable - * flag on ones connected to us, we keep a separate hashtable for that flag. - */ -static inline bool is_chan_local_disabled(struct routing_state *rstate, - const struct chan *chan) -{ - struct local_chan *local_chan = is_local_chan(rstate, chan); - return local_chan && local_chan->local_disabled; -} - -static inline void local_disable_chan(struct routing_state *rstate, - const struct chan *chan) -{ - struct local_chan *local_chan = is_local_chan(rstate, chan); - local_chan->local_disabled = true; -} - -static inline void local_enable_chan(struct routing_state *rstate, - const struct chan *chan) -{ - struct local_chan *local_chan = is_local_chan(rstate, chan); - local_chan->local_disabled = false; -} - /* Remove channel from store: announcement and any updates. */ void remove_channel_from_store(struct routing_state *rstate, struct chan *chan); diff --git a/gossipd/test/run-check_channel_announcement.c b/gossipd/test/run-check_channel_announcement.c index 28b29a341031..827bbdd63ebd 100644 --- a/gossipd/test/run-check_channel_announcement.c +++ b/gossipd/test/run-check_channel_announcement.c @@ -144,6 +144,10 @@ void *notleak_(void *ptr UNNEEDED, bool plus_children UNNEEDED) /* Generated stub for peer_supplied_good_gossip */ void peer_supplied_good_gossip(struct peer *peer UNNEEDED, size_t amount UNNEEDED) { fprintf(stderr, "peer_supplied_good_gossip called!\n"); abort(); } +/* Generated stub for status_failed */ +void status_failed(enum status_failreason code UNNEEDED, + const char *fmt UNNEEDED, ...) +{ fprintf(stderr, "status_failed called!\n"); abort(); } /* Generated stub for status_fmt */ void status_fmt(enum log_level level UNNEEDED, const struct node_id *peer UNNEEDED, diff --git a/gossipd/test/run-check_node_announcement.c b/gossipd/test/run-check_node_announcement.c index ca982558b22f..25fcdda7abd2 100644 --- a/gossipd/test/run-check_node_announcement.c +++ b/gossipd/test/run-check_node_announcement.c @@ -24,6 +24,9 @@ bool blinding_next_pubkey(const struct pubkey *pk UNNEEDED, const struct sha256 *h UNNEEDED, struct pubkey *next UNNEEDED) { fprintf(stderr, "blinding_next_pubkey called!\n"); abort(); } +/* Generated stub for daemon_conn_send */ +void daemon_conn_send(struct daemon_conn *dc UNNEEDED, const u8 *msg UNNEEDED) +{ fprintf(stderr, "daemon_conn_send called!\n"); abort(); } /* Generated stub for ecdh */ void ecdh(const struct pubkey *point UNNEEDED, struct secret *ss UNNEEDED) { fprintf(stderr, "ecdh called!\n"); abort(); } @@ -34,8 +37,11 @@ struct peer *find_peer(struct daemon *daemon UNNEEDED, const struct node_id *id char *fmt_wireaddr_without_port(const tal_t *ctx UNNEEDED, const struct wireaddr *a UNNEEDED) { fprintf(stderr, "fmt_wireaddr_without_port called!\n"); abort(); } /* Generated stub for fromwire_gossipd_local_channel_update */ -bool fromwire_gossipd_local_channel_update(const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, bool *disable UNNEEDED, u16 *cltv_expiry_delta UNNEEDED, struct amount_msat *htlc_minimum_msat UNNEEDED, u32 *fee_base_msat UNNEEDED, u32 *fee_proportional_millionths UNNEEDED, struct amount_msat *htlc_maximum_msat UNNEEDED) +bool fromwire_gossipd_local_channel_update(const void *p UNNEEDED, struct node_id *id UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, bool *disable UNNEEDED, u16 *cltv_expiry_delta UNNEEDED, struct amount_msat *htlc_minimum_msat UNNEEDED, u32 *fee_base_msat UNNEEDED, u32 *fee_proportional_millionths UNNEEDED, struct amount_msat *htlc_maximum_msat UNNEEDED) { fprintf(stderr, "fromwire_gossipd_local_channel_update called!\n"); abort(); } +/* Generated stub for fromwire_gossipd_used_local_channel_update */ +bool fromwire_gossipd_used_local_channel_update(const void *p UNNEEDED, struct short_channel_id *scid UNNEEDED) +{ fprintf(stderr, "fromwire_gossipd_used_local_channel_update called!\n"); abort(); } /* Generated stub for fromwire_hsmd_cupdate_sig_reply */ bool fromwire_hsmd_cupdate_sig_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **cu UNNEEDED) { fprintf(stderr, "fromwire_hsmd_cupdate_sig_reply called!\n"); abort(); } @@ -75,6 +81,9 @@ void json_object_end(struct json_stream *js UNNEEDED) /* Generated stub for json_object_start */ void json_object_start(struct json_stream *ks UNNEEDED, const char *fieldname UNNEEDED) { fprintf(stderr, "json_object_start called!\n"); abort(); } +/* Generated stub for master_badmsg */ +void master_badmsg(u32 type_expected UNNEEDED, const u8 *msg) +{ fprintf(stderr, "master_badmsg called!\n"); abort(); } /* Generated stub for new_onionreply */ struct onionreply *new_onionreply(const tal_t *ctx UNNEEDED, const u8 *contents TAKES UNNEEDED) { fprintf(stderr, "new_onionreply called!\n"); abort(); } @@ -84,15 +93,9 @@ 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 notleak_ */ -void *notleak_(void *ptr UNNEEDED, bool plus_children UNNEEDED) -{ fprintf(stderr, "notleak_ called!\n"); abort(); } /* Generated stub for queue_peer_msg */ void queue_peer_msg(struct peer *peer UNNEEDED, const u8 *msg TAKES UNNEEDED) { fprintf(stderr, "queue_peer_msg called!\n"); abort(); } -/* Generated stub for reltimer_arg */ -void *reltimer_arg(struct oneshot *t UNNEEDED) -{ fprintf(stderr, "reltimer_arg called!\n"); abort(); } /* Generated stub for status_failed */ void status_failed(enum status_failreason code UNNEEDED, const char *fmt UNNEEDED, ...) @@ -103,6 +106,9 @@ void status_fmt(enum log_level level UNNEEDED, const char *fmt UNNEEDED, ...) { fprintf(stderr, "status_fmt called!\n"); abort(); } +/* Generated stub for towire_gossipd_got_local_channel_update */ +u8 *towire_gossipd_got_local_channel_update(const tal_t *ctx UNNEEDED, const struct short_channel_id *scid UNNEEDED, const u8 *channel_update UNNEEDED) +{ fprintf(stderr, "towire_gossipd_got_local_channel_update called!\n"); abort(); } /* Generated stub for towire_hsmd_cupdate_sig_req */ u8 *towire_hsmd_cupdate_sig_req(const tal_t *ctx UNNEEDED, const u8 *cu UNNEEDED) { fprintf(stderr, "towire_hsmd_cupdate_sig_req called!\n"); abort(); } diff --git a/gossipd/test/run-crc32_of_update.c b/gossipd/test/run-crc32_of_update.c index 87e6094b2aaa..47a1250a35c9 100644 --- a/gossipd/test/run-crc32_of_update.c +++ b/gossipd/test/run-crc32_of_update.c @@ -28,10 +28,9 @@ bool blinding_next_pubkey(const struct pubkey *pk UNNEEDED, const struct sha256 *h UNNEEDED, struct pubkey *next UNNEEDED) { fprintf(stderr, "blinding_next_pubkey called!\n"); abort(); } -/* Generated stub for daemon_conn_read_next */ -struct io_plan *daemon_conn_read_next(struct io_conn *conn UNNEEDED, - struct daemon_conn *dc UNNEEDED) -{ fprintf(stderr, "daemon_conn_read_next called!\n"); abort(); } +/* Generated stub for daemon_conn_send */ +void daemon_conn_send(struct daemon_conn *dc UNNEEDED, const u8 *msg UNNEEDED) +{ fprintf(stderr, "daemon_conn_send called!\n"); abort(); } /* Generated stub for daemon_conn_wake */ void daemon_conn_wake(struct daemon_conn *dc UNNEEDED) { fprintf(stderr, "daemon_conn_wake called!\n"); abort(); } @@ -59,8 +58,11 @@ char *fmt_wireaddr_without_port(const tal_t *ctx UNNEEDED, const struct wireaddr bool fromwire_gossipd_dev_set_max_scids_encode_size(const void *p UNNEEDED, u32 *max UNNEEDED) { fprintf(stderr, "fromwire_gossipd_dev_set_max_scids_encode_size called!\n"); abort(); } /* Generated stub for fromwire_gossipd_local_channel_update */ -bool fromwire_gossipd_local_channel_update(const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, bool *disable UNNEEDED, u16 *cltv_expiry_delta UNNEEDED, struct amount_msat *htlc_minimum_msat UNNEEDED, u32 *fee_base_msat UNNEEDED, u32 *fee_proportional_millionths UNNEEDED, struct amount_msat *htlc_maximum_msat UNNEEDED) +bool fromwire_gossipd_local_channel_update(const void *p UNNEEDED, struct node_id *id UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, bool *disable UNNEEDED, u16 *cltv_expiry_delta UNNEEDED, struct amount_msat *htlc_minimum_msat UNNEEDED, u32 *fee_base_msat UNNEEDED, u32 *fee_proportional_millionths UNNEEDED, struct amount_msat *htlc_maximum_msat UNNEEDED) { fprintf(stderr, "fromwire_gossipd_local_channel_update called!\n"); abort(); } +/* Generated stub for fromwire_gossipd_used_local_channel_update */ +bool fromwire_gossipd_used_local_channel_update(const void *p UNNEEDED, struct short_channel_id *scid UNNEEDED) +{ fprintf(stderr, "fromwire_gossipd_used_local_channel_update called!\n"); abort(); } /* Generated stub for fromwire_hsmd_cupdate_sig_reply */ bool fromwire_hsmd_cupdate_sig_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **cu UNNEEDED) { fprintf(stderr, "fromwire_hsmd_cupdate_sig_reply called!\n"); abort(); } @@ -117,9 +119,6 @@ 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 notleak_ */ -void *notleak_(void *ptr UNNEEDED, bool plus_children UNNEEDED) -{ fprintf(stderr, "notleak_ called!\n"); abort(); } /* Generated stub for peer_supplied_good_gossip */ void peer_supplied_good_gossip(struct peer *peer UNNEEDED, size_t amount UNNEEDED) { fprintf(stderr, "peer_supplied_good_gossip called!\n"); abort(); } @@ -130,9 +129,6 @@ void queue_peer_from_store(struct peer *peer UNNEEDED, /* Generated stub for queue_peer_msg */ void queue_peer_msg(struct peer *peer UNNEEDED, const u8 *msg TAKES UNNEEDED) { fprintf(stderr, "queue_peer_msg called!\n"); abort(); } -/* Generated stub for reltimer_arg */ -void *reltimer_arg(struct oneshot *t UNNEEDED) -{ fprintf(stderr, "reltimer_arg called!\n"); abort(); } /* Generated stub for status_failed */ void status_failed(enum status_failreason code UNNEEDED, const char *fmt UNNEEDED, ...) @@ -143,6 +139,9 @@ void status_fmt(enum log_level level UNNEEDED, const char *fmt UNNEEDED, ...) { fprintf(stderr, "status_fmt called!\n"); abort(); } +/* Generated stub for towire_gossipd_got_local_channel_update */ +u8 *towire_gossipd_got_local_channel_update(const tal_t *ctx UNNEEDED, const struct short_channel_id *scid UNNEEDED, const u8 *channel_update UNNEEDED) +{ fprintf(stderr, "towire_gossipd_got_local_channel_update called!\n"); abort(); } /* Generated stub for towire_hsmd_cupdate_sig_req */ u8 *towire_hsmd_cupdate_sig_req(const tal_t *ctx UNNEEDED, const u8 *cu UNNEEDED) { fprintf(stderr, "towire_hsmd_cupdate_sig_req called!\n"); abort(); } diff --git a/gossipd/test/run-extended-info.c b/gossipd/test/run-extended-info.c index bf0d460a82ed..8e5ad79cd38c 100644 --- a/gossipd/test/run-extended-info.c +++ b/gossipd/test/run-extended-info.c @@ -33,10 +33,6 @@ bool blinding_next_pubkey(const struct pubkey *pk UNNEEDED, const struct sha256 *h UNNEEDED, struct pubkey *next UNNEEDED) { fprintf(stderr, "blinding_next_pubkey called!\n"); abort(); } -/* Generated stub for daemon_conn_read_next */ -struct io_plan *daemon_conn_read_next(struct io_conn *conn UNNEEDED, - struct daemon_conn *dc UNNEEDED) -{ fprintf(stderr, "daemon_conn_read_next called!\n"); abort(); } /* Generated stub for daemon_conn_wake */ void daemon_conn_wake(struct daemon_conn *dc UNNEEDED) { fprintf(stderr, "daemon_conn_wake called!\n"); abort(); } diff --git a/gossipd/test/run-onion_message.c b/gossipd/test/run-onion_message.c deleted file mode 100644 index 473554f3f720..000000000000 --- a/gossipd/test/run-onion_message.c +++ /dev/null @@ -1,581 +0,0 @@ -#include "config.h" -int unused_main(int argc, char *argv[]); -#define main unused_main -#include "../gossipd.c" -#undef main -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if DEVELOPER -bool dev_suppress_gossip; - -/* Generated stub for dev_set_max_scids_encode_size */ -struct io_plan *dev_set_max_scids_encode_size(struct io_conn *conn UNNEEDED, - struct daemon *daemon UNNEEDED, - const u8 *msg UNNEEDED) -{ fprintf(stderr, "dev_set_max_scids_encode_size called!\n"); abort(); } -/* Generated stub for dump_memleak */ -bool dump_memleak(struct htable *memtable UNNEEDED, - void (*print)(const char *fmt UNNEEDED, ...)) -{ fprintf(stderr, "dump_memleak called!\n"); abort(); } -/* Generated stub for memleak_status_broken */ -void memleak_status_broken(const char *fmt UNNEEDED, ...) -{ fprintf(stderr, "memleak_status_broken called!\n"); abort(); } -#endif - -/* AUTOGENERATED MOCKS START */ -/* Generated stub for add_to_txout_failures */ -void add_to_txout_failures(struct routing_state *rstate UNNEEDED, - const struct short_channel_id *scid UNNEEDED) -{ fprintf(stderr, "add_to_txout_failures called!\n"); abort(); } -/* Generated stub for daemon_conn_new_ */ -struct daemon_conn *daemon_conn_new_(const tal_t *ctx UNNEEDED, int fd UNNEEDED, - struct io_plan *(*recv)(struct io_conn * UNNEEDED, - const u8 * UNNEEDED, - void *) UNNEEDED, - void (*outq_empty)(void *) UNNEEDED, - void *arg UNNEEDED) -{ fprintf(stderr, "daemon_conn_new_ called!\n"); abort(); } -/* Generated stub for daemon_conn_read_next */ -struct io_plan *daemon_conn_read_next(struct io_conn *conn UNNEEDED, - struct daemon_conn *dc UNNEEDED) -{ fprintf(stderr, "daemon_conn_read_next called!\n"); abort(); } -/* Generated stub for daemon_conn_send */ -void daemon_conn_send(struct daemon_conn *dc UNNEEDED, const u8 *msg UNNEEDED) -{ fprintf(stderr, "daemon_conn_send called!\n"); abort(); } -/* Generated stub for daemon_conn_send_fd */ -void daemon_conn_send_fd(struct daemon_conn *dc UNNEEDED, int fd UNNEEDED) -{ fprintf(stderr, "daemon_conn_send_fd called!\n"); abort(); } -/* Generated stub for daemon_shutdown */ -void daemon_shutdown(void) -{ fprintf(stderr, "daemon_shutdown called!\n"); abort(); } -/* Generated stub for ecdh */ -void ecdh(const struct pubkey *point UNNEEDED, struct secret *ss UNNEEDED) -{ fprintf(stderr, "ecdh called!\n"); abort(); } -/* Generated stub for ecdh_hsmd_setup */ -void ecdh_hsmd_setup(int hsm_fd UNNEEDED, - void (*failed)(enum status_failreason UNNEEDED, - const char *fmt UNNEEDED, ...)) -{ fprintf(stderr, "ecdh_hsmd_setup called!\n"); abort(); } -/* Generated stub for first_chan */ -struct chan *first_chan(const struct node *node UNNEEDED, struct chan_map_iter *i UNNEEDED) -{ fprintf(stderr, "first_chan called!\n"); abort(); } -/* Generated stub for fmt_wireaddr_without_port */ -char *fmt_wireaddr_without_port(const tal_t *ctx UNNEEDED, const struct wireaddr *a UNNEEDED) -{ fprintf(stderr, "fmt_wireaddr_without_port called!\n"); abort(); } -/* Generated stub for free_chan */ -void free_chan(struct routing_state *rstate UNNEEDED, struct chan *chan UNNEEDED) -{ fprintf(stderr, "free_chan called!\n"); abort(); } -/* Generated stub for fromwire_gossipd_addgossip */ -bool fromwire_gossipd_addgossip(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **msg UNNEEDED) -{ fprintf(stderr, "fromwire_gossipd_addgossip called!\n"); abort(); } -/* Generated stub for fromwire_gossipd_dev_set_time */ -bool fromwire_gossipd_dev_set_time(const void *p UNNEEDED, u32 *dev_gossip_time UNNEEDED) -{ fprintf(stderr, "fromwire_gossipd_dev_set_time called!\n"); abort(); } -/* Generated stub for fromwire_gossipd_dev_suppress */ -bool fromwire_gossipd_dev_suppress(const void *p UNNEEDED) -{ fprintf(stderr, "fromwire_gossipd_dev_suppress called!\n"); abort(); } -/* Generated stub for fromwire_gossipd_get_addrs */ -bool fromwire_gossipd_get_addrs(const void *p UNNEEDED, struct node_id *id UNNEEDED) -{ fprintf(stderr, "fromwire_gossipd_get_addrs called!\n"); abort(); } -/* Generated stub for fromwire_gossipd_get_stripped_cupdate */ -bool fromwire_gossipd_get_stripped_cupdate(const void *p UNNEEDED, struct short_channel_id *channel_id UNNEEDED) -{ fprintf(stderr, "fromwire_gossipd_get_stripped_cupdate called!\n"); abort(); } -/* Generated stub for fromwire_gossipd_get_txout_reply */ -bool fromwire_gossipd_get_txout_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, struct amount_sat *satoshis UNNEEDED, u8 **outscript UNNEEDED) -{ fprintf(stderr, "fromwire_gossipd_get_txout_reply called!\n"); abort(); } -/* Generated stub for fromwire_gossipd_get_update */ -bool fromwire_gossipd_get_update(const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED) -{ fprintf(stderr, "fromwire_gossipd_get_update called!\n"); abort(); } -/* Generated stub for fromwire_gossipd_init */ -bool fromwire_gossipd_init(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, const struct chainparams **chainparams UNNEEDED, struct feature_set **our_features UNNEEDED, struct node_id *id UNNEEDED, u8 rgb[3] UNNEEDED, u8 alias[32] UNNEEDED, struct wireaddr **announcable UNNEEDED, u32 **dev_gossip_time UNNEEDED, bool *dev_fast_gossip UNNEEDED, bool *dev_fast_gossip_prune UNNEEDED) -{ fprintf(stderr, "fromwire_gossipd_init called!\n"); abort(); } -/* Generated stub for fromwire_gossipd_local_channel_announcement */ -bool fromwire_gossipd_local_channel_announcement(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **cannount UNNEEDED) -{ fprintf(stderr, "fromwire_gossipd_local_channel_announcement called!\n"); abort(); } -/* Generated stub for fromwire_gossipd_local_channel_close */ -bool fromwire_gossipd_local_channel_close(const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED) -{ fprintf(stderr, "fromwire_gossipd_local_channel_close called!\n"); abort(); } -/* Generated stub for fromwire_gossipd_new_blockheight */ -bool fromwire_gossipd_new_blockheight(const void *p UNNEEDED, u32 *blockheight UNNEEDED) -{ fprintf(stderr, "fromwire_gossipd_new_blockheight called!\n"); abort(); } -/* Generated stub for fromwire_gossipd_new_lease_rates */ -bool fromwire_gossipd_new_lease_rates(const void *p UNNEEDED, struct lease_rates *rates UNNEEDED) -{ fprintf(stderr, "fromwire_gossipd_new_lease_rates called!\n"); abort(); } -/* Generated stub for fromwire_gossipd_new_peer */ -bool fromwire_gossipd_new_peer(const void *p UNNEEDED, struct node_id *id UNNEEDED, bool *gossip_queries_feature UNNEEDED, bool *initial_routing_sync UNNEEDED) -{ fprintf(stderr, "fromwire_gossipd_new_peer called!\n"); abort(); } -/* Generated stub for fromwire_gossipd_outpoint_spent */ -bool fromwire_gossipd_outpoint_spent(const void *p UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED) -{ fprintf(stderr, "fromwire_gossipd_outpoint_spent called!\n"); abort(); } -/* Generated stub for fromwire_gossipd_send_onionmsg */ -bool fromwire_gossipd_send_onionmsg(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, bool *obs2 UNNEEDED, struct node_id *id UNNEEDED, u8 **onion UNNEEDED, struct pubkey *blinding UNNEEDED) -{ fprintf(stderr, "fromwire_gossipd_send_onionmsg called!\n"); abort(); } -/* Generated stub for fromwire_wireaddr_array */ -struct wireaddr *fromwire_wireaddr_array(const tal_t *ctx UNNEEDED, const u8 *ser UNNEEDED) -{ fprintf(stderr, "fromwire_wireaddr_array called!\n"); abort(); } -/* Generated stub for get_node */ -struct node *get_node(struct routing_state *rstate UNNEEDED, - const struct node_id *id UNNEEDED) -{ fprintf(stderr, "get_node called!\n"); abort(); } -/* Generated stub for gossip_store_compact */ -bool gossip_store_compact(struct gossip_store *gs UNNEEDED) -{ fprintf(stderr, "gossip_store_compact called!\n"); abort(); } -/* Generated stub for gossip_store_get */ -const u8 *gossip_store_get(const tal_t *ctx UNNEEDED, - struct gossip_store *gs UNNEEDED, - u64 offset UNNEEDED) -{ fprintf(stderr, "gossip_store_get called!\n"); abort(); } -/* Generated stub for gossip_store_load */ -u32 gossip_store_load(struct routing_state *rstate UNNEEDED, struct gossip_store *gs UNNEEDED) -{ fprintf(stderr, "gossip_store_load called!\n"); abort(); } -/* Generated stub for gossip_store_readonly_fd */ -int gossip_store_readonly_fd(struct gossip_store *gs UNNEEDED) -{ fprintf(stderr, "gossip_store_readonly_fd called!\n"); abort(); } -/* Generated stub for gossip_time_now */ -struct timeabs gossip_time_now(const struct routing_state *rstate UNNEEDED) -{ fprintf(stderr, "gossip_time_now called!\n"); abort(); } -/* Generated stub for gossipd_peerd_wire_name */ -const char *gossipd_peerd_wire_name(int e UNNEEDED) -{ fprintf(stderr, "gossipd_peerd_wire_name called!\n"); abort(); } -/* Generated stub for handle_channel_announcement */ -u8 *handle_channel_announcement(struct routing_state *rstate UNNEEDED, - const u8 *announce TAKES UNNEEDED, - u32 current_blockheight UNNEEDED, - const struct short_channel_id **scid UNNEEDED, - struct peer *peer UNNEEDED) -{ fprintf(stderr, "handle_channel_announcement called!\n"); abort(); } -/* Generated stub for handle_channel_update */ -u8 *handle_channel_update(struct routing_state *rstate UNNEEDED, const u8 *update TAKES UNNEEDED, - struct peer *peer UNNEEDED, - struct short_channel_id *unknown_scid UNNEEDED, - bool force UNNEEDED) -{ fprintf(stderr, "handle_channel_update called!\n"); abort(); } -/* Generated stub for handle_local_channel_update */ -bool handle_local_channel_update(struct daemon *daemon UNNEEDED, - const struct node_id *src UNNEEDED, - const u8 *msg UNNEEDED) -{ fprintf(stderr, "handle_local_channel_update called!\n"); abort(); } -/* Generated stub for handle_node_announcement */ -u8 *handle_node_announcement(struct routing_state *rstate UNNEEDED, const u8 *node UNNEEDED, - struct peer *peer UNNEEDED, bool *was_unknown UNNEEDED) -{ fprintf(stderr, "handle_node_announcement called!\n"); abort(); } -/* Generated stub for handle_pending_cannouncement */ -bool handle_pending_cannouncement(struct daemon *daemon UNNEEDED, - struct routing_state *rstate UNNEEDED, - const struct short_channel_id *scid UNNEEDED, - const struct amount_sat sat UNNEEDED, - const u8 *txscript UNNEEDED) -{ fprintf(stderr, "handle_pending_cannouncement called!\n"); abort(); } -/* Generated stub for handle_query_channel_range */ -const u8 *handle_query_channel_range(struct peer *peer UNNEEDED, const u8 *msg UNNEEDED) -{ fprintf(stderr, "handle_query_channel_range called!\n"); abort(); } -/* Generated stub for handle_query_short_channel_ids */ -const u8 *handle_query_short_channel_ids(struct peer *peer UNNEEDED, const u8 *msg UNNEEDED) -{ fprintf(stderr, "handle_query_short_channel_ids called!\n"); abort(); } -/* Generated stub for handle_reply_channel_range */ -const u8 *handle_reply_channel_range(struct peer *peer UNNEEDED, const u8 *msg UNNEEDED) -{ fprintf(stderr, "handle_reply_channel_range called!\n"); abort(); } -/* Generated stub for handle_reply_short_channel_ids_end */ -const u8 *handle_reply_short_channel_ids_end(struct peer *peer UNNEEDED, const u8 *msg UNNEEDED) -{ fprintf(stderr, "handle_reply_short_channel_ids_end called!\n"); abort(); } -/* Generated stub for json_add_member */ -void json_add_member(struct json_stream *js UNNEEDED, - const char *fieldname UNNEEDED, - bool quote UNNEEDED, - const char *fmt UNNEEDED, ...) -{ fprintf(stderr, "json_add_member called!\n"); abort(); } -/* Generated stub for json_member_direct */ -char *json_member_direct(struct json_stream *js UNNEEDED, - const char *fieldname UNNEEDED, size_t extra UNNEEDED) -{ fprintf(stderr, "json_member_direct called!\n"); abort(); } -/* Generated stub for json_object_end */ -void json_object_end(struct json_stream *js UNNEEDED) -{ fprintf(stderr, "json_object_end called!\n"); abort(); } -/* Generated stub for json_object_start */ -void json_object_start(struct json_stream *ks UNNEEDED, const char *fieldname UNNEEDED) -{ fprintf(stderr, "json_object_start called!\n"); abort(); } -/* Generated stub for master_badmsg */ -void master_badmsg(u32 type_expected UNNEEDED, const u8 *msg) -{ fprintf(stderr, "master_badmsg called!\n"); abort(); } -/* Generated stub for maybe_send_own_node_announce */ -void maybe_send_own_node_announce(struct daemon *daemon UNNEEDED, bool startup UNNEEDED) -{ fprintf(stderr, "maybe_send_own_node_announce called!\n"); abort(); } -/* Generated stub for maybe_send_query_responses */ -void maybe_send_query_responses(struct peer *peer UNNEEDED) -{ fprintf(stderr, "maybe_send_query_responses called!\n"); abort(); } -/* Generated stub for memleak_find_allocations */ -struct htable *memleak_find_allocations(const tal_t *ctx UNNEEDED, - const void *exclude1 UNNEEDED, - const void *exclude2 UNNEEDED) -{ fprintf(stderr, "memleak_find_allocations called!\n"); abort(); } -/* Generated stub for memleak_remove_region */ -void memleak_remove_region(struct htable *memtable UNNEEDED, - const void *p UNNEEDED, size_t bytelen UNNEEDED) -{ fprintf(stderr, "memleak_remove_region called!\n"); abort(); } -/* Generated stub for new_onionreply */ -struct onionreply *new_onionreply(const tal_t *ctx UNNEEDED, const u8 *contents TAKES UNNEEDED) -{ fprintf(stderr, "new_onionreply called!\n"); abort(); } -/* Generated stub for new_reltimer_ */ -struct oneshot *new_reltimer_(struct timers *timers UNNEEDED, - const tal_t *ctx UNNEEDED, - struct timerel expire UNNEEDED, - void (*cb)(void *) UNNEEDED, void *arg UNNEEDED) -{ fprintf(stderr, "new_reltimer_ called!\n"); abort(); } -/* Generated stub for new_routing_state */ -struct routing_state *new_routing_state(const tal_t *ctx UNNEEDED, - const struct node_id *local_id UNNEEDED, - struct list_head *peers UNNEEDED, - struct timers *timers UNNEEDED, - const u32 *dev_gossip_time TAKES UNNEEDED, - bool dev_fast_gossip UNNEEDED, - bool dev_fast_gossip_prune UNNEEDED) -{ fprintf(stderr, "new_routing_state called!\n"); abort(); } -/* Generated stub for new_seeker */ -struct seeker *new_seeker(struct daemon *daemon UNNEEDED) -{ fprintf(stderr, "new_seeker called!\n"); abort(); } -/* Generated stub for next_chan */ -struct chan *next_chan(const struct node *node UNNEEDED, struct chan_map_iter *i UNNEEDED) -{ fprintf(stderr, "next_chan called!\n"); abort(); } -/* Generated stub for notleak_ */ -void *notleak_(void *ptr UNNEEDED, bool plus_children UNNEEDED) -{ fprintf(stderr, "notleak_ called!\n"); abort(); } -/* Generated stub for query_unknown_channel */ -void query_unknown_channel(struct daemon *daemon UNNEEDED, - struct peer *peer UNNEEDED, - const struct short_channel_id *id UNNEEDED) -{ fprintf(stderr, "query_unknown_channel called!\n"); abort(); } -/* Generated stub for query_unknown_node */ -void query_unknown_node(struct seeker *seeker UNNEEDED, struct peer *peer UNNEEDED) -{ fprintf(stderr, "query_unknown_node called!\n"); abort(); } -/* Generated stub for refresh_local_channel */ -void refresh_local_channel(struct daemon *daemon UNNEEDED, - struct local_chan *local_chan UNNEEDED, - bool even_if_identical UNNEEDED) -{ fprintf(stderr, "refresh_local_channel called!\n"); abort(); } -/* Generated stub for remove_channel_from_store */ -void remove_channel_from_store(struct routing_state *rstate UNNEEDED, - struct chan *chan UNNEEDED) -{ fprintf(stderr, "remove_channel_from_store called!\n"); abort(); } -/* Generated stub for remove_unknown_scid */ -bool remove_unknown_scid(struct seeker *seeker UNNEEDED, - const struct short_channel_id *scid UNNEEDED, - bool found UNNEEDED) -{ fprintf(stderr, "remove_unknown_scid called!\n"); abort(); } -/* Generated stub for route_prune */ -void route_prune(struct routing_state *rstate UNNEEDED) -{ fprintf(stderr, "route_prune called!\n"); abort(); } -/* Generated stub for routing_add_private_channel */ -bool routing_add_private_channel(struct routing_state *rstate UNNEEDED, - const struct peer *peer UNNEEDED, - const u8 *msg UNNEEDED, u64 index UNNEEDED) -{ fprintf(stderr, "routing_add_private_channel called!\n"); abort(); } -/* Generated stub for sanitize_error */ -char *sanitize_error(const tal_t *ctx UNNEEDED, const u8 *errmsg UNNEEDED, - struct channel_id *channel_id UNNEEDED) -{ fprintf(stderr, "sanitize_error called!\n"); abort(); } -/* Generated stub for seeker_setup_peer_gossip */ -void seeker_setup_peer_gossip(struct seeker *seeker UNNEEDED, struct peer *peer UNNEEDED) -{ fprintf(stderr, "seeker_setup_peer_gossip called!\n"); abort(); } -/* Generated stub for status_failed */ -void status_failed(enum status_failreason code UNNEEDED, - const char *fmt UNNEEDED, ...) -{ fprintf(stderr, "status_failed called!\n"); abort(); } -/* Generated stub for status_fmt */ -void status_fmt(enum log_level level UNNEEDED, - const struct node_id *peer UNNEEDED, - const char *fmt UNNEEDED, ...) - -{ fprintf(stderr, "status_fmt called!\n"); abort(); } -/* Generated stub for status_setup_async */ -void status_setup_async(struct daemon_conn *master UNNEEDED) -{ fprintf(stderr, "status_setup_async called!\n"); abort(); } -/* Generated stub for subdaemon_setup */ -void subdaemon_setup(int argc UNNEEDED, char *argv[]) -{ fprintf(stderr, "subdaemon_setup called!\n"); abort(); } -/* Generated stub for timer_expired */ -void timer_expired(struct timer *timer UNNEEDED) -{ fprintf(stderr, "timer_expired called!\n"); abort(); } -/* Generated stub for towire_gossipd_addgossip_reply */ -u8 *towire_gossipd_addgossip_reply(const tal_t *ctx UNNEEDED, const wirestring *err UNNEEDED) -{ fprintf(stderr, "towire_gossipd_addgossip_reply called!\n"); abort(); } -/* Generated stub for towire_gossipd_dev_compact_store_reply */ -u8 *towire_gossipd_dev_compact_store_reply(const tal_t *ctx UNNEEDED, bool success UNNEEDED) -{ fprintf(stderr, "towire_gossipd_dev_compact_store_reply called!\n"); abort(); } -/* Generated stub for towire_gossipd_dev_memleak_reply */ -u8 *towire_gossipd_dev_memleak_reply(const tal_t *ctx UNNEEDED, bool leak UNNEEDED) -{ fprintf(stderr, "towire_gossipd_dev_memleak_reply called!\n"); abort(); } -/* Generated stub for towire_gossipd_get_addrs_reply */ -u8 *towire_gossipd_get_addrs_reply(const tal_t *ctx UNNEEDED, const struct wireaddr *addrs UNNEEDED) -{ fprintf(stderr, "towire_gossipd_get_addrs_reply called!\n"); abort(); } -/* Generated stub for towire_gossipd_get_stripped_cupdate_reply */ -u8 *towire_gossipd_get_stripped_cupdate_reply(const tal_t *ctx UNNEEDED, const u8 *stripped_update UNNEEDED) -{ fprintf(stderr, "towire_gossipd_get_stripped_cupdate_reply called!\n"); abort(); } -/* Generated stub for towire_gossipd_get_txout */ -u8 *towire_gossipd_get_txout(const tal_t *ctx UNNEEDED, const struct short_channel_id *short_channel_id UNNEEDED) -{ fprintf(stderr, "towire_gossipd_get_txout called!\n"); abort(); } -/* Generated stub for towire_gossipd_get_update_reply */ -u8 *towire_gossipd_get_update_reply(const tal_t *ctx UNNEEDED, const u8 *update UNNEEDED) -{ fprintf(stderr, "towire_gossipd_get_update_reply called!\n"); abort(); } -/* Generated stub for towire_gossipd_got_onionmsg_to_us */ -u8 *towire_gossipd_got_onionmsg_to_us(const tal_t *ctx UNNEEDED, bool obs2 UNNEEDED, const struct pubkey *node_alias UNNEEDED, const struct secret *self_id UNNEEDED, const struct pubkey *reply_blinding UNNEEDED, const struct pubkey *reply_first_node UNNEEDED, const struct onionmsg_path **reply_path UNNEEDED, const u8 *rawmsg UNNEEDED) -{ fprintf(stderr, "towire_gossipd_got_onionmsg_to_us called!\n"); abort(); } -/* Generated stub for towire_gossipd_init_reply */ -u8 *towire_gossipd_init_reply(const tal_t *ctx UNNEEDED) -{ fprintf(stderr, "towire_gossipd_init_reply called!\n"); abort(); } -/* Generated stub for towire_gossipd_new_peer_reply */ -u8 *towire_gossipd_new_peer_reply(const tal_t *ctx UNNEEDED, bool success UNNEEDED, const struct gossip_state *gs UNNEEDED) -{ fprintf(stderr, "towire_gossipd_new_peer_reply called!\n"); abort(); } -/* Generated stub for towire_warningfmt */ -u8 *towire_warningfmt(const tal_t *ctx UNNEEDED, - const struct channel_id *channel UNNEEDED, - const char *fmt UNNEEDED, ...) -{ fprintf(stderr, "towire_warningfmt called!\n"); abort(); } -/* AUTOGENERATED MOCKS END */ - -/* Updated each time, as we pretend to be Alice, Bob, Carol */ -static const struct privkey *mykey; - -static void test_ecdh(const struct pubkey *point, struct secret *ss) -{ - if (secp256k1_ecdh(secp256k1_ctx, ss->data, &point->pubkey, - mykey->secret.data, NULL, NULL) != 1) - abort(); -} - -static void json_strfield(const char *name, const char *val) -{ - printf("\t\"%s\": \"%s\",\n", name, val); -} - -static void json_onionmsg_payload(const struct tlv_obs2_onionmsg_payload *om) -{ - if (om->reply_path) { - printf("\t\"reply_path\": {\n"); - json_strfield("first_node_id", - type_to_string(tmpctx, struct pubkey, - &om->reply_path->first_node_id)); - json_strfield("blinding", - type_to_string(tmpctx, struct pubkey, - &om->reply_path->blinding)); - printf("\t\"path\": [\n"); - for (size_t i = 0; i < tal_count(om->reply_path->path); i++) { - json_strfield("node_id", - type_to_string(tmpctx, struct pubkey, - &om->reply_path->path[i]->node_id)); - json_strfield("encrypted_recipient_data", - tal_hex(tmpctx, - om->reply_path->path[i]->encrypted_recipient_data)); - } - printf("]}\n"); - } - if (om->invoice) - json_strfield("invoice", tal_hex(tmpctx, om->invoice)); - if (om->invoice_request) - json_strfield("invoice_request", - tal_hex(tmpctx, om->invoice_request)); - if (om->invoice_error) - json_strfield("invoice_error", - tal_hex(tmpctx, om->invoice_error)); -} - -/* Return next onion (and updates blinding), or NULL */ -static u8 *json_test(const char *testname, - const u8 *data, - const struct privkey *me, - const struct privkey *blinding_priv, - struct pubkey *blinding) -{ - struct pubkey my_id, next_node; - struct secret ss, onion_ss; - struct pubkey ephemeral; - struct route_step *rs; - const u8 *cursor; - size_t max, maxlen; - struct onionpacket *op; - struct tlv_obs2_onionmsg_payload *om; - - op = parse_onionpacket(tmpctx, data, tal_bytelen(data), NULL); - assert(op); - - pubkey_from_privkey(me, &my_id); - printf("{"); - json_strfield("test name", testname); - json_strfield("reader_privkey", - type_to_string(tmpctx, struct privkey, me)); - json_strfield("reader_id", - type_to_string(tmpctx, struct pubkey, &my_id)); - - if (blinding_priv) - json_strfield("blinding_privkey", - type_to_string(tmpctx, struct privkey, - blinding_priv)); - json_strfield("blinding", - type_to_string(tmpctx, struct pubkey, blinding)); - printf("\"onionmsg\": {\n"); - json_strfield("raw", tal_hex(tmpctx, data)); - json_strfield("version", tal_fmt(tmpctx, "%i", op->version)); - json_strfield("public_key", - type_to_string(tmpctx, struct pubkey, &op->ephemeralkey)); - json_strfield("hop_payloads", - tal_hex(tmpctx, op->routinginfo)); - json_strfield("hmac", - tal_hexstr(tmpctx, &op->hmac, sizeof(op->hmac))); - printf("},\n"); - - ephemeral = op->ephemeralkey; - - /* Set this for test_ecdh */ - mykey = me; - assert(unblind_onion(blinding, test_ecdh, &ephemeral, &ss)); - json_strfield("ECDH shared secret", - type_to_string(tmpctx, struct secret, &ss)); - /* Reproduce internal calc from unblind_onion */ - { - struct secret hmac; - subkey_from_hmac("blinded_node_id", &ss, &hmac); - json_strfield("HMAC256(\\\"blinded_node_id\\\", ss(i)) * k(i)", - type_to_string(tmpctx, struct secret, &hmac)); - } - json_strfield("Tweaked onion pubkey", - type_to_string(tmpctx, struct pubkey, &ephemeral)); - - /* Now get onion shared secret and parse it. */ - test_ecdh(&ephemeral, &onion_ss); - json_strfield("onion shared secret", - type_to_string(tmpctx, struct secret, &onion_ss)); - rs = process_onionpacket(tmpctx, op, &onion_ss, NULL, 0, false); - assert(rs); - - printf("\"onion contents\": {\n"); - json_strfield("raw", tal_hex(tmpctx, rs->raw_payload)); - - cursor = rs->raw_payload; - max = tal_bytelen(rs->raw_payload); - maxlen = fromwire_bigsize(&cursor, &max); - json_strfield("length", tal_fmt(tmpctx, "%zu", maxlen)); - json_strfield("rawtlv", tal_hexstr(tmpctx, cursor, maxlen)); - json_strfield("hmac", tal_hexstr(tmpctx, rs->next->hmac.bytes, - sizeof(rs->next->hmac.bytes))); - om = tlv_obs2_onionmsg_payload_new(tmpctx); - assert(fromwire_obs2_onionmsg_payload(&cursor, &maxlen, om)); - - json_onionmsg_payload(om); - - /* We expect one of these. */ - assert(om->enctlv); - - printf("\t\"encrypted_data_tlv\": {\n"); - json_strfield("raw", tal_hex(tmpctx, om->enctlv)); - - if (rs->nextcase == ONION_END) { - struct secret *self_id; - struct pubkey alias; - assert(decrypt_obs2_final_enctlv(tmpctx, - blinding, &ss, - om->enctlv, - &my_id, &alias, &self_id)); - if (self_id) { - json_strfield("self_id", - type_to_string(tmpctx, struct secret, - self_id)); - } - printf("}\n"); - return NULL; - } else { - assert(decrypt_obs2_enctlv(blinding, &ss, om->enctlv, &next_node, - blinding)); - json_strfield("next_node", - type_to_string(tmpctx, struct pubkey, &next_node)); - json_strfield("next_blinding", - type_to_string(tmpctx, struct pubkey, - blinding)); - printf("}"); - printf("},\n"); - return serialize_onionpacket(tmpctx, rs->next); - } -} - -int main(int argc, char *argv[]) -{ - struct onionpacket *op; - u8 *data; - struct privkey alice, bob, carol, dave, blinding_priv; - struct pubkey alice_id, bob_id, carol_id, dave_id; - struct pubkey blinding; - - common_setup(argv[0]); - - memset(&alice, 'A', sizeof(alice)); - memset(&bob, 'B', sizeof(bob)); - memset(&carol, 'C', sizeof(carol)); - memset(&dave, 'D', sizeof(dave)); - pubkey_from_privkey(&alice, &alice_id); - pubkey_from_privkey(&bob, &bob_id); - pubkey_from_privkey(&carol, &carol_id); - pubkey_from_privkey(&dave, &dave_id); - - /* ThomasH sends via email: - * - * { - * "version":0, - * "public_key": - * "0256b328b30c8bf5839e24058747879408bdb36241dc9c2e7c619faa12b2920967", - * "hop_payloads": - * "37df67dcefdb678725cb8074d3224dfe235ba3f22f71ac8a2c9d1398b1175295b1dd3f14c02d698021e8a8856637306c6f195e01494eb8dc636b4462367533a84786b8592e580086cdf0f1c58b77eb68703a2fb82ecc2e91307a25b6d5e4045174551b1c867264d3905e4f05b2e5bcfed7e7276660bf7e956bce5afa395e7e4c15883b856bc93dd9d6a968838ef51314d38dd41e5ab84b8846dca3c61d87e55780e7a7da336a965a4652263413cdef41daa68f7bb7cd4d566c19a1c4eece369c47e604575f38e7a246a985c3441b60ae33c564395bb7a4bbe28325ccdb07503285dacf90b5e09f4e455fb42459741f9d497000298b99f1e70adc28f59a1be85a96952f27b6a6c5d6a08822b4f5cae05daa6c2ce2f8ca5fdd4e8f0df46b94791b3159fe8eace11bcf8d58be425b49ce2b47c007affefd5cea785c1996ad805f8c8c5ca79f15ab26e2bd4080b1d74328e7ce5bd2a579c71a6bd25f33f2ce475a2cfbe67ed1f4eb8fbd86920f41d573488abe059166aabbc3be187c435423ead6a5473994e0246efe76e419893aa2d7566b2645f3496d97585de9c92b8c5a5226398cc459ce84abc02fe2b45b5ecaf21961730d4a34bbe6fdfe720e71e3d81a494c01080d8039360d534c6ee5a3c47a1874e526969add9126b30d9192f85ba45bcfd7029cc7560f0e25e14b5deaa805360c4967705e85325ac055922863470f5397e8404022488caebf9204acd6cb02a11088aebf7e497b4ff1172f0a9c6bf980914cc4eb42fc78b457add549abf1134f84922b217502938b42d10b35079f44c5168d4c3e9fe7ca8094ef72ed73ef84f1d3530b6b3545f9f4f013e7e8cbcf2619f57754a7380ce6a9532ee14c55990faa43df6c09530a314b5f4ce597f5ec9b776e8597ce258ac47dac43bd3ac9e52788ff3a66b7dc07cd1bc3e6d197339d85fa8d3d6c3054dd1a5e416c714b544de6eb55209e40e3cac412a51748370160d2d73b6d97abd62f7bae70df27cd199c511fa693019c5717d471e934906b98cd974fda4dd1cb5e2d721044a0be2bdf24d0971e09f2f39488fe389fc5230699b4df7cec7447e5be4ea49bd7c3fe1a5ec7358510dc1dd9c1a8da68c0863188d80549e49f7c00f57d2009b2427b2aed1569603fc247734039469f9fdf3ddd3a22fa95c5d8066a468327a02b474c9915419af82c8edc67686984767fe7885207c6820f6c2e57cb8fd0bcb9981ebc8065c74e970a5d593c3b73ee25a0877ca096a9f7edfee6d43bd817c7d415fea9abb6f206c61aa36942df9318762a76b9da26d0d41a0ae9eee042a175f82dc134bf6f2d46a218db358d6852940e6e30df4a58ac6cb409e7ce99afe1e3f42768bd617af4d0a235d0ba0dd5075f9cc091784395d30e7e42d4e006db21bea9b45d1f122b75c051e84e2281573ef54ebad053218fff0cc28ea89a06adc218d4134f407654990592e75462f5ee4a463c1e46425222d48761162da8049613cafd7ecc52ff8024e9d58512b958e3a3d12dede84e1441247700bca0f992875349448b430683c756438fd4e91f3d44f3cf624ed21f3c63cf92615ecc201d0cd3159b1b3fccd8f29d2daba9ac5ba87b1dd2f83323a2b2d3176b803ce9c7bdc4bae615925eb22a213df1eeb2f8ff95586536caf042d565984aacf1425a120a5d8d7a9cbb70bf4852e116b89ff5b198d672220af2be4246372e7c3836cf50d732212a3e3346ff92873ace57fa687b2b1aab3e8dc6cb9f93f865d998cff0a1680d9012a9597c90a070e525f66226cc287814f4ac4157b15a0b25aa110946cd69fd404fafd5656669bfd1d9e509eabc004c5a", - * "hmac": "564bb85911bea8f90d306f4acdafa1c0887619ac72606b11e6b2765734d810ac" - * } - */ - op = tal(tmpctx, struct onionpacket); - op->version = 0; - assert(pubkey_from_hexstr("0256b328b30c8bf5839e24058747879408bdb36241dc9c2e7c619faa12b2920967", strlen("0256b328b30c8bf5839e24058747879408bdb36241dc9c2e7c619faa12b2920967"), &op->ephemeralkey)); - assert(hex_decode("564bb85911bea8f90d306f4acdafa1c0887619ac72606b11e6b2765734d810ac", - strlen("564bb85911bea8f90d306f4acdafa1c0887619ac72606b11e6b2765734d810ac"), - &op->hmac, sizeof(op->hmac))); - op->routinginfo = tal_hexdata(op, "37df67dcefdb678725cb8074d3224dfe235ba3f22f71ac8a2c9d1398b1175295b1dd3f14c02d698021e8a8856637306c6f195e01494eb8dc636b4462367533a84786b8592e580086cdf0f1c58b77eb68703a2fb82ecc2e91307a25b6d5e4045174551b1c867264d3905e4f05b2e5bcfed7e7276660bf7e956bce5afa395e7e4c15883b856bc93dd9d6a968838ef51314d38dd41e5ab84b8846dca3c61d87e55780e7a7da336a965a4652263413cdef41daa68f7bb7cd4d566c19a1c4eece369c47e604575f38e7a246a985c3441b60ae33c564395bb7a4bbe28325ccdb07503285dacf90b5e09f4e455fb42459741f9d497000298b99f1e70adc28f59a1be85a96952f27b6a6c5d6a08822b4f5cae05daa6c2ce2f8ca5fdd4e8f0df46b94791b3159fe8eace11bcf8d58be425b49ce2b47c007affefd5cea785c1996ad805f8c8c5ca79f15ab26e2bd4080b1d74328e7ce5bd2a579c71a6bd25f33f2ce475a2cfbe67ed1f4eb8fbd86920f41d573488abe059166aabbc3be187c435423ead6a5473994e0246efe76e419893aa2d7566b2645f3496d97585de9c92b8c5a5226398cc459ce84abc02fe2b45b5ecaf21961730d4a34bbe6fdfe720e71e3d81a494c01080d8039360d534c6ee5a3c47a1874e526969add9126b30d9192f85ba45bcfd7029cc7560f0e25e14b5deaa805360c4967705e85325ac055922863470f5397e8404022488caebf9204acd6cb02a11088aebf7e497b4ff1172f0a9c6bf980914cc4eb42fc78b457add549abf1134f84922b217502938b42d10b35079f44c5168d4c3e9fe7ca8094ef72ed73ef84f1d3530b6b3545f9f4f013e7e8cbcf2619f57754a7380ce6a9532ee14c55990faa43df6c09530a314b5f4ce597f5ec9b776e8597ce258ac47dac43bd3ac9e52788ff3a66b7dc07cd1bc3e6d197339d85fa8d3d6c3054dd1a5e416c714b544de6eb55209e40e3cac412a51748370160d2d73b6d97abd62f7bae70df27cd199c511fa693019c5717d471e934906b98cd974fda4dd1cb5e2d721044a0be2bdf24d0971e09f2f39488fe389fc5230699b4df7cec7447e5be4ea49bd7c3fe1a5ec7358510dc1dd9c1a8da68c0863188d80549e49f7c00f57d2009b2427b2aed1569603fc247734039469f9fdf3ddd3a22fa95c5d8066a468327a02b474c9915419af82c8edc67686984767fe7885207c6820f6c2e57cb8fd0bcb9981ebc8065c74e970a5d593c3b73ee25a0877ca096a9f7edfee6d43bd817c7d415fea9abb6f206c61aa36942df9318762a76b9da26d0d41a0ae9eee042a175f82dc134bf6f2d46a218db358d6852940e6e30df4a58ac6cb409e7ce99afe1e3f42768bd617af4d0a235d0ba0dd5075f9cc091784395d30e7e42d4e006db21bea9b45d1f122b75c051e84e2281573ef54ebad053218fff0cc28ea89a06adc218d4134f407654990592e75462f5ee4a463c1e46425222d48761162da8049613cafd7ecc52ff8024e9d58512b958e3a3d12dede84e1441247700bca0f992875349448b430683c756438fd4e91f3d44f3cf624ed21f3c63cf92615ecc201d0cd3159b1b3fccd8f29d2daba9ac5ba87b1dd2f83323a2b2d3176b803ce9c7bdc4bae615925eb22a213df1eeb2f8ff95586536caf042d565984aacf1425a120a5d8d7a9cbb70bf4852e116b89ff5b198d672220af2be4246372e7c3836cf50d732212a3e3346ff92873ace57fa687b2b1aab3e8dc6cb9f93f865d998cff0a1680d9012a9597c90a070e525f66226cc287814f4ac4157b15a0b25aa110946cd69fd404fafd5656669bfd1d9e509eabc004c5a", - strlen("37df67dcefdb678725cb8074d3224dfe235ba3f22f71ac8a2c9d1398b1175295b1dd3f14c02d698021e8a8856637306c6f195e01494eb8dc636b4462367533a84786b8592e580086cdf0f1c58b77eb68703a2fb82ecc2e91307a25b6d5e4045174551b1c867264d3905e4f05b2e5bcfed7e7276660bf7e956bce5afa395e7e4c15883b856bc93dd9d6a968838ef51314d38dd41e5ab84b8846dca3c61d87e55780e7a7da336a965a4652263413cdef41daa68f7bb7cd4d566c19a1c4eece369c47e604575f38e7a246a985c3441b60ae33c564395bb7a4bbe28325ccdb07503285dacf90b5e09f4e455fb42459741f9d497000298b99f1e70adc28f59a1be85a96952f27b6a6c5d6a08822b4f5cae05daa6c2ce2f8ca5fdd4e8f0df46b94791b3159fe8eace11bcf8d58be425b49ce2b47c007affefd5cea785c1996ad805f8c8c5ca79f15ab26e2bd4080b1d74328e7ce5bd2a579c71a6bd25f33f2ce475a2cfbe67ed1f4eb8fbd86920f41d573488abe059166aabbc3be187c435423ead6a5473994e0246efe76e419893aa2d7566b2645f3496d97585de9c92b8c5a5226398cc459ce84abc02fe2b45b5ecaf21961730d4a34bbe6fdfe720e71e3d81a494c01080d8039360d534c6ee5a3c47a1874e526969add9126b30d9192f85ba45bcfd7029cc7560f0e25e14b5deaa805360c4967705e85325ac055922863470f5397e8404022488caebf9204acd6cb02a11088aebf7e497b4ff1172f0a9c6bf980914cc4eb42fc78b457add549abf1134f84922b217502938b42d10b35079f44c5168d4c3e9fe7ca8094ef72ed73ef84f1d3530b6b3545f9f4f013e7e8cbcf2619f57754a7380ce6a9532ee14c55990faa43df6c09530a314b5f4ce597f5ec9b776e8597ce258ac47dac43bd3ac9e52788ff3a66b7dc07cd1bc3e6d197339d85fa8d3d6c3054dd1a5e416c714b544de6eb55209e40e3cac412a51748370160d2d73b6d97abd62f7bae70df27cd199c511fa693019c5717d471e934906b98cd974fda4dd1cb5e2d721044a0be2bdf24d0971e09f2f39488fe389fc5230699b4df7cec7447e5be4ea49bd7c3fe1a5ec7358510dc1dd9c1a8da68c0863188d80549e49f7c00f57d2009b2427b2aed1569603fc247734039469f9fdf3ddd3a22fa95c5d8066a468327a02b474c9915419af82c8edc67686984767fe7885207c6820f6c2e57cb8fd0bcb9981ebc8065c74e970a5d593c3b73ee25a0877ca096a9f7edfee6d43bd817c7d415fea9abb6f206c61aa36942df9318762a76b9da26d0d41a0ae9eee042a175f82dc134bf6f2d46a218db358d6852940e6e30df4a58ac6cb409e7ce99afe1e3f42768bd617af4d0a235d0ba0dd5075f9cc091784395d30e7e42d4e006db21bea9b45d1f122b75c051e84e2281573ef54ebad053218fff0cc28ea89a06adc218d4134f407654990592e75462f5ee4a463c1e46425222d48761162da8049613cafd7ecc52ff8024e9d58512b958e3a3d12dede84e1441247700bca0f992875349448b430683c756438fd4e91f3d44f3cf624ed21f3c63cf92615ecc201d0cd3159b1b3fccd8f29d2daba9ac5ba87b1dd2f83323a2b2d3176b803ce9c7bdc4bae615925eb22a213df1eeb2f8ff95586536caf042d565984aacf1425a120a5d8d7a9cbb70bf4852e116b89ff5b198d672220af2be4246372e7c3836cf50d732212a3e3346ff92873ace57fa687b2b1aab3e8dc6cb9f93f865d998cff0a1680d9012a9597c90a070e525f66226cc287814f4ac4157b15a0b25aa110946cd69fd404fafd5656669bfd1d9e509eabc004c5a")); - - data = serialize_onionpacket(tmpctx, op); - printf("[\n"); - - memset(&blinding_priv, 5, sizeof(blinding_priv)); - pubkey_from_privkey(&blinding_priv, &blinding); - - data = json_test("onion message for Alice", - data, - &alice, - &blinding_priv, - &blinding); - - data = json_test("onion message for Bob", - data, - &bob, - NULL, - &blinding); - - data = json_test("onion message for Carol", - data, - &carol, - NULL, - &blinding); - - data = json_test("onion message for Dave", - data, - &dave, - NULL, - &blinding); - - assert(!data); - printf("]\n"); - - common_shutdown(); - return 0; -} diff --git a/gossipd/test/run-txout_failure.c b/gossipd/test/run-txout_failure.c index ba7791c329a3..1acfd534d210 100644 --- a/gossipd/test/run-txout_failure.c +++ b/gossipd/test/run-txout_failure.c @@ -109,6 +109,10 @@ void peer_supplied_good_gossip(struct peer *peer UNNEEDED, size_t amount UNNEEDE char *sanitize_error(const tal_t *ctx UNNEEDED, const u8 *errmsg UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "sanitize_error called!\n"); abort(); } +/* Generated stub for status_failed */ +void status_failed(enum status_failreason code UNNEEDED, + const char *fmt UNNEEDED, ...) +{ fprintf(stderr, "status_failed called!\n"); abort(); } /* Generated stub for status_fmt */ void status_fmt(enum log_level level UNNEEDED, const struct node_id *peer UNNEEDED, diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index 96c76ef4e8a3..a7342a2e1a0e 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -97,10 +97,6 @@ static bool is_lightningd(const struct client *client) return client == dbid_zero_clients[0]; } -/* FIXME: This is used by debug.c. Doesn't apply to us, but lets us link. */ -extern void dev_disconnect_init(int fd); -void dev_disconnect_init(int fd UNUSED) { } - /* Pre-declare this, due to mutual recursion */ static struct io_plan *handle_client(struct io_conn *conn, struct client *c); @@ -618,6 +614,9 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) { enum hsmd_wire t = fromwire_peektype(c->msg_in); + if (!is_lightningd(c)) + status_peer_debug(&c->id, "Got %s", hsmd_wire_name(t)); + /* Before we do anything else, is this client allowed to do * what he asks for? */ if (!hsmd_check_client_capabilities(c->hsmd_client, t)) diff --git a/lightningd/Makefile b/lightningd/Makefile index 2cdb6b0d00b7..f9d4e7396cbf 100644 --- a/lightningd/Makefile +++ b/lightningd/Makefile @@ -30,7 +30,6 @@ LIGHTNINGD_SRC := \ lightningd/pay.c \ lightningd/peer_control.c \ lightningd/peer_htlcs.c \ - lightningd/ping.c \ lightningd/plugin.c \ lightningd/plugin_control.c \ lightningd/plugin_hook.c \ @@ -41,6 +40,7 @@ LIGHTNINGD_SRC := \ LIGHTNINGD_SRC_NOHDR := \ lightningd/datastore.c \ + lightningd/ping.c \ lightningd/offer.c \ lightningd/signmessage.c @@ -81,7 +81,6 @@ LIGHTNINGD_COMMON_OBJS := \ common/channel_type.o \ common/coin_mvt.o \ common/configdir.o \ - common/crypto_state.o \ common/daemon.o \ common/derive_basepoints.o \ common/ecdh_hsmd.o \ diff --git a/lightningd/channel.c b/lightningd/channel.c index 617b89ad9589..c98d8864b159 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -254,6 +254,7 @@ struct channel *new_unsaved_channel(struct peer *peer, = CLOSING_FEE_NEGOTIATION_STEP_UNIT_PERCENTAGE; channel->shutdown_wrong_funding = NULL; channel->closing_feerate_range = NULL; + channel->channel_update = NULL; /* Channel is connected! */ channel->connected = true; @@ -462,6 +463,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, channel->lease_chan_max_msat = lease_chan_max_msat; channel->lease_chan_max_ppt = lease_chan_max_ppt; channel->blockheight_states = dup_height_states(channel, height_states); + channel->channel_update = NULL; list_add_tail(&peer->channels, &channel->list); channel->rr_number = peer->ld->rr_counter++; @@ -824,7 +826,7 @@ void channel_internal_error(struct channel *channel, const char *fmt, ...) channel_cleanup_commands(channel, why); if (channel_unsaved(channel)) { - subd_release_channel(channel->owner, channel); + channel_set_owner(channel, NULL); delete_channel(channel); tal_free(why); return; @@ -875,10 +877,10 @@ static void err_and_reconnect(struct channel *channel, channel_set_owner(channel, NULL); /* Their address only useful if we connected to them */ - delay_then_reconnect(channel, seconds_before_reconnect, - channel->peer->connected_incoming - ? NULL - : &channel->peer->addr); + try_reconnect(channel, seconds_before_reconnect, + channel->peer->connected_incoming + ? NULL + : &channel->peer->addr); } void channel_fail_reconnect_later(struct channel *channel, const char *fmt, ...) diff --git a/lightningd/channel.h b/lightningd/channel.h index 76a73d5b47ae..774e146ac010 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -233,6 +233,9 @@ struct channel { u32 lease_chan_max_msat; /* Lease commited max part per thousandth channel fee (ppm * 1000) */ u16 lease_chan_max_ppt; + + /* Latest channel_update, for use in error messages. */ + u8 *channel_update; }; /* For v2 opens, a channel that has not yet been committed/saved to disk */ @@ -466,4 +469,6 @@ void channel_set_billboard(struct channel *channel, bool perm, struct htlc_in *channel_has_htlc_in(struct channel *channel); struct htlc_out *channel_has_htlc_out(struct channel *channel); +const u8 *get_channel_update(struct channel *channel); + #endif /* LIGHTNING_LIGHTNINGD_CHANNEL_H */ diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index e6fb0af00ab0..3680f8f71a03 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -17,11 +17,10 @@ #include #include #include +#include #include #include #include -#include -#include static void update_feerates(struct lightningd *ld, struct channel *channel) { @@ -348,17 +347,14 @@ static void peer_start_closingd_after_shutdown(struct channel *channel, const u8 *msg, const int *fds) { - struct per_peer_state *pps; - - if (!fromwire_channeld_shutdown_complete(tmpctx, msg, &pps)) { + if (!fromwire_channeld_shutdown_complete(msg)) { channel_internal_error(channel, "bad shutdown_complete: %s", tal_hex(msg, msg)); return; } - per_peer_state_set_fds_arr(pps, fds); /* This sets channel->owner, closes down channeld. */ - peer_start_closingd(channel, pps); + peer_start_closingd(channel, fds[0]); /* We might have reconnected, so already be here. */ if (!channel_closed(channel) @@ -404,6 +400,23 @@ static void handle_error_channel(struct channel *channel, forget(channel); } +static void handle_local_private_channel(struct channel *channel, const u8 *msg) +{ + struct amount_sat capacity; + u8 *features; + + if (!fromwire_channeld_local_private_channel(msg, msg, &capacity, + &features)) { + channel_internal_error(channel, + "bad channeld_local_private_channel %s", + tal_hex(channel, msg)); + return; + } + + tell_gossipd_local_private_channel(channel->peer->ld, channel, + capacity, features); +} + static void forget_channel(struct channel *channel, const char *why) { channel->error = towire_errorfmt(channel, &channel->cid, "%s", why); @@ -482,9 +495,9 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) peer_got_shutdown(sd->channel, msg); break; case WIRE_CHANNELD_SHUTDOWN_COMPLETE: - /* We expect 3 fds. */ + /* We expect 1 fd. */ if (!fds) - return 3; + return 1; peer_start_closingd_after_shutdown(sd->channel, msg, fds); break; case WIRE_CHANNELD_FAIL_FALLEN_BEHIND: @@ -493,8 +506,18 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNELD_SEND_ERROR_REPLY: handle_error_channel(sd->channel, msg); break; - case WIRE_CHANNELD_PING_REPLY: - ping_reply(sd, msg); + case WIRE_CHANNELD_USED_CHANNEL_UPDATE: + /* This tells gossipd we used it. */ + get_channel_update(sd->channel); + break; + case WIRE_CHANNELD_LOCAL_CHANNEL_UPDATE: + tell_gossipd_local_channel_update(sd->ld, sd->channel, msg); + break; + case WIRE_CHANNELD_LOCAL_CHANNEL_ANNOUNCEMENT: + tell_gossipd_local_channel_announce(sd->ld, sd->channel, msg); + break; + case WIRE_CHANNELD_LOCAL_PRIVATE_CHANNEL: + handle_local_private_channel(sd->channel, msg); break; #if EXPERIMENTAL_FEATURES case WIRE_CHANNELD_UPGRADED: @@ -517,6 +540,7 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNELD_FEERATES: case WIRE_CHANNELD_BLOCKHEIGHT: case WIRE_CHANNELD_SPECIFIC_FEERATES: + case WIRE_CHANNELD_CHANNEL_UPDATE: case WIRE_CHANNELD_DEV_MEMLEAK: case WIRE_CHANNELD_DEV_QUIESCE: /* Replies go to requests. */ @@ -525,16 +549,6 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) case WIRE_CHANNELD_DEV_MEMLEAK_REPLY: case WIRE_CHANNELD_SEND_ERROR: case WIRE_CHANNELD_DEV_QUIESCE_REPLY: - case WIRE_CHANNELD_PING: - break; - } - - switch ((enum common_wire)t) { - case WIRE_CUSTOMMSG_IN: - handle_custommsg_in(sd->ld, sd->node_id, msg); - break; - /* We send these. */ - case WIRE_CUSTOMMSG_OUT: break; } @@ -542,7 +556,7 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds) } void peer_start_channeld(struct channel *channel, - struct per_peer_state *pps, + int peer_fd, const u8 *fwd_msg, bool reconnected, const u8 *reestablish_only) @@ -577,9 +591,7 @@ void peer_start_channeld(struct channel *channel, channel_msg, channel_errmsg, channel_set_billboard, - take(&pps->peer_fd), - take(&pps->gossip_fd), - take(&pps->gossip_store_fd), + take(&peer_fd), take(&hsmfd), NULL)); if (!channel->owner) { @@ -646,68 +658,72 @@ void peer_start_channeld(struct channel *channel, tmpctx, channel->peer->ld->wallet, channel->dbid); initmsg = towire_channeld_init(tmpctx, - chainparams, - ld->our_features, - &channel->cid, - &channel->funding, - channel->funding_sats, - channel->minimum_depth, - get_block_height(ld->topology), - channel->blockheight_states, - channel->lease_expiry, - &channel->our_config, - &channel->channel_info.their_config, - channel->fee_states, - feerate_min(ld, NULL), - feerate_max(ld, NULL), - try_get_feerate(ld->topology, FEERATE_PENALTY), - &channel->last_sig, - pps, - &channel->channel_info.remote_fundingkey, - &channel->channel_info.theirbase, - &channel->channel_info.remote_per_commit, - &channel->channel_info.old_remote_per_commit, - channel->opener, - channel->feerate_base, - channel->feerate_ppm, - channel->our_msat, - &channel->local_basepoints, - &channel->local_funding_pubkey, - &ld->id, - &channel->peer->id, - cfg->commit_time_ms, - cfg->cltv_expiry_delta, - channel->last_was_revoke, - channel->last_sent_commit, - channel->next_index[LOCAL], - channel->next_index[REMOTE], - num_revocations, - channel->next_htlc_id, - htlcs, - channel->scid != NULL, - channel->remote_funding_locked, - &scid, - reconnected, + chainparams, + ld->our_features, + &channel->cid, + &channel->funding, + channel->funding_sats, + channel->minimum_depth, + get_block_height(ld->topology), + channel->blockheight_states, + channel->lease_expiry, + &channel->our_config, + &channel->channel_info.their_config, + channel->fee_states, + feerate_min(ld, NULL), + feerate_max(ld, NULL), + try_get_feerate(ld->topology, FEERATE_PENALTY), + &channel->last_sig, + &channel->channel_info.remote_fundingkey, + &channel->channel_info.theirbase, + &channel->channel_info.remote_per_commit, + &channel->channel_info.old_remote_per_commit, + channel->opener, + channel->feerate_base, + channel->feerate_ppm, + channel->our_msat, + &channel->local_basepoints, + &channel->local_funding_pubkey, + &ld->id, + &channel->peer->id, + cfg->commit_time_ms, + cfg->cltv_expiry_delta, + channel->last_was_revoke, + channel->last_sent_commit, + channel->next_index[LOCAL], + channel->next_index[REMOTE], + num_revocations, + channel->next_htlc_id, + htlcs, + channel->scid != NULL, + channel->remote_funding_locked, + &scid, + reconnected, /* Anything that indicates we are or have * shut down */ - channel->state == CHANNELD_SHUTTING_DOWN + channel->state == CHANNELD_SHUTTING_DOWN || channel->state == CLOSINGD_SIGEXCHANGE || channel_closed(channel), - channel->shutdown_scriptpubkey[REMOTE] != NULL, - channel->shutdown_scriptpubkey[LOCAL], - channel->channel_flags, - fwd_msg, - reached_announce_depth, - &last_remote_per_commit_secret, - channel->peer->their_features, - channel->remote_upfront_shutdown_script, - remote_ann_node_sig, - remote_ann_bitcoin_sig, - channel->type, - IFDEV(ld->dev_fast_gossip, false), - IFDEV(dev_fail_process_onionpacket, false), - pbases, - reestablish_only); + channel->shutdown_scriptpubkey[REMOTE] != NULL, + channel->shutdown_scriptpubkey[LOCAL], + channel->channel_flags, + fwd_msg, + reached_announce_depth, + &last_remote_per_commit_secret, + channel->peer->their_features, + channel->remote_upfront_shutdown_script, + remote_ann_node_sig, + remote_ann_bitcoin_sig, + channel->type, + IFDEV(ld->dev_fast_gossip, false), + IFDEV(dev_fail_process_onionpacket, false), + IFDEV(ld->dev_disable_commit == -1 + ? NULL + : (u32 *)&ld->dev_disable_commit, + NULL), + pbases, + reestablish_only, + channel->channel_update); /* We don't expect a response: we are triggered by funding_depth_cb. */ subd_send_msg(channel->owner, take(initmsg)); @@ -998,6 +1014,20 @@ struct command_result *cancel_channel_before_broadcast(struct command *cmd, return command_still_pending(cmd); } +void channel_replace_update(struct channel *channel, u8 *update TAKES) +{ + tal_free(channel->channel_update); + channel->channel_update = tal_dup_talarr(channel, u8, update); + + /* Keep channeld up-to-date */ + if (!channel->owner || !streq(channel->owner->name, "channeld")) + return; + + subd_send_msg(channel->owner, + take(towire_channeld_channel_update(NULL, + channel->channel_update))); +} + #if DEVELOPER static struct command_result *json_dev_feerate(struct command *cmd, const char *buffer, diff --git a/lightningd/channel_control.h b/lightningd/channel_control.h index ce91cf68bcfc..cd90c248d9f9 100644 --- a/lightningd/channel_control.h +++ b/lightningd/channel_control.h @@ -7,11 +7,10 @@ struct channel; struct crypto_state; struct lightningd; -struct per_peer_state; struct peer; void peer_start_channeld(struct channel *channel, - struct per_peer_state *pps, + int peer_fd, const u8 *fwd_msg, bool reconnected, const u8 *reestablish_only); @@ -39,4 +38,8 @@ void channel_record_open(struct channel *channel); /* A channel has unrecoverably fallen behind */ void channel_fallen_behind(struct channel *channel, const u8 *msg); + +/* Fresh channel_update for this channel. */ +void channel_replace_update(struct channel *channel, u8 *update TAKES); + #endif /* LIGHTNING_LIGHTNINGD_CHANNEL_CONTROL_H */ diff --git a/lightningd/closing_control.c b/lightningd/closing_control.c index 96f600c7889a..ae49eef40a62 100644 --- a/lightningd/closing_control.c +++ b/lightningd/closing_control.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -38,7 +37,6 @@ #include #include #include -#include struct close_command { /* Inside struct lightningd close_commands. */ @@ -336,20 +334,10 @@ static unsigned closing_msg(struct subd *sd, const u8 *msg, const int *fds UNUSE break; } - switch ((enum common_wire)t) { - case WIRE_CUSTOMMSG_IN: - handle_custommsg_in(sd->ld, sd->node_id, msg); - break; - /* We send these. */ - case WIRE_CUSTOMMSG_OUT: - break; - } - return 0; } -void peer_start_closingd(struct channel *channel, - struct per_peer_state *pps) +void peer_start_closingd(struct channel *channel, int peer_fd) { u8 *initmsg; u32 min_feerate, feerate, *max_feerate; @@ -361,6 +349,7 @@ void peer_start_closingd(struct channel *channel, bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS); if (!channel->shutdown_scriptpubkey[REMOTE]) { + close(peer_fd); channel_internal_error(channel, "Can't start closing: no remote info"); return; @@ -378,9 +367,7 @@ void peer_start_closingd(struct channel *channel, closingd_wire_name, closing_msg, channel_errmsg, channel_set_billboard, - take(&pps->peer_fd), - take(&pps->gossip_fd), - take(&pps->gossip_store_fd), + take(&peer_fd), take(&hsmfd), NULL)); @@ -455,7 +442,6 @@ void peer_start_closingd(struct channel *channel, initmsg = towire_closingd_init(tmpctx, chainparams, - pps, &channel->cid, &channel->funding, channel->funding_sats, @@ -476,7 +462,6 @@ void peer_start_closingd(struct channel *channel, && channel->closing_fee_negotiation_step_unit == CLOSING_FEE_NEGOTIATION_STEP_UNIT_PERCENTAGE) /* Always use quickclose with anchors */ || option_anchor_outputs, - IFDEV(ld->dev_fast_gossip, false), channel->shutdown_wrong_funding); /* We don't expect a response: it will give us feedback on diff --git a/lightningd/closing_control.h b/lightningd/closing_control.h index 8991b44439bc..4d1e0364242c 100644 --- a/lightningd/closing_control.h +++ b/lightningd/closing_control.h @@ -6,12 +6,10 @@ struct channel; struct lightningd; -struct per_peer_state; void resolve_close_command(struct lightningd *ld, struct channel *channel, bool cooperative); -void peer_start_closingd(struct channel *channel, - struct per_peer_state *pps); +void peer_start_closingd(struct channel *channel, int peer_fd); #endif /* LIGHTNING_LIGHTNINGD_CLOSING_CONTROL_H */ diff --git a/lightningd/connect_control.c b/lightningd/connect_control.c index a01366d5a1a8..2ecfd5c82993 100644 --- a/lightningd/connect_control.c +++ b/lightningd/connect_control.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -17,8 +18,10 @@ #include #include #include +#include #include #include +#include struct connect { struct list_node list; @@ -69,6 +72,14 @@ static struct command_result *connect_cmd_succeed(struct command *cmd, return command_success(cmd, response); } +/* FIXME: Reorder! */ +static void try_connect(const tal_t *ctx, + struct lightningd *ld, + const struct node_id *id, + struct channel *channel, + u32 seconds_delay, + const struct wireaddr_internal *addrhint); + static struct command_result *json_connect(struct command *cmd, const char *buffer, const jsmntok_t *obj UNNEEDED, @@ -82,7 +93,6 @@ static struct command_result *json_connect(struct command *cmd, char *ataddr = NULL; const char *name; struct wireaddr_internal *addr; - u8 *msg; const char *err_msg; struct peer *peer; @@ -165,8 +175,7 @@ static struct command_result *json_connect(struct command *cmd, } else addr = NULL; - msg = towire_connectd_connect_to_peer(NULL, &id, 0, addr); - subd_send_msg(cmd->ld->connectd, take(msg)); + try_connect(cmd, cmd->ld, &id, NULL, 0, addr); /* Leave this here for peer_connected or connect_failed. */ new_connect(cmd->ld, &id, cmd); @@ -182,36 +191,65 @@ static const struct json_command connect_command = { }; AUTODATA(json_command, &connect_command); +/* We actually use this even if we don't need a delay, while we talk to + * gossipd to get the addresses. */ struct delayed_reconnect { + struct lightningd *ld; + struct node_id id; + /* May be unset if there's no associated channel */ struct channel *channel; u32 seconds_delayed; struct wireaddr_internal *addrhint; }; -static void maybe_reconnect(struct delayed_reconnect *d) +static void gossipd_got_addrs(struct subd *subd, + const u8 *msg, + const int *fds, + struct delayed_reconnect *d) { - struct peer *peer = d->channel->peer; - - /* Might have gone onchain since we started timer. */ - if (channel_active(d->channel)) { - u8 *msg = towire_connectd_connect_to_peer(NULL, &peer->id, - d->seconds_delayed, - d->addrhint); - subd_send_msg(peer->ld->connectd, take(msg)); + struct wireaddr *addrs; + u8 *connectmsg; + + if (!fromwire_gossipd_get_addrs_reply(tmpctx, msg, &addrs)) + fatal("Gossipd gave bad GOSSIPD_GET_ADDRS_REPLY %s", + tal_hex(msg, msg)); + + /* Might have gone onchain (if it was actually freed, we were too). */ + if (d->channel && !channel_active(d->channel)) { + tal_free(d); + return; } + + connectmsg = towire_connectd_connect_to_peer(NULL, + &d->id, + d->seconds_delayed, + addrs, + d->addrhint); + subd_send_msg(d->ld->connectd, take(connectmsg)); tal_free(d); } -void delay_then_reconnect(struct channel *channel, u32 seconds_delay, - const struct wireaddr_internal *addrhint) +/* We might be off a delay timer. Now ask gossipd about public addresses. */ +static void do_connect(struct delayed_reconnect *d) { - struct delayed_reconnect *d; - struct lightningd *ld = channel->peer->ld; + u8 *msg = towire_gossipd_get_addrs(NULL, &d->id); - if (!ld->reconnect) - return; + subd_req(d, d->ld->gossip, take(msg), -1, 0, gossipd_got_addrs, d); +} - d = tal(channel, struct delayed_reconnect); +/* channel may be NULL here */ +static void try_connect(const tal_t *ctx, + struct lightningd *ld, + const struct node_id *id, + struct channel *channel, + u32 seconds_delay, + const struct wireaddr_internal *addrhint) +{ + struct delayed_reconnect *d; + + d = tal(ctx, struct delayed_reconnect); + d->ld = ld; + d->id = *id; d->channel = channel; d->seconds_delayed = seconds_delay; if (addrhint) @@ -219,6 +257,17 @@ void delay_then_reconnect(struct channel *channel, u32 seconds_delay, else d->addrhint = NULL; + if (!seconds_delay) { + do_connect(d); + return; + } + + /* We never have a delay when connecting without a channel */ + assert(channel); + channel_set_billboard(channel, false, + tal_fmt(tmpctx, + "Will attempt reconnect " + "in %u seconds", seconds_delay)); log_debug(channel->log, "Will try reconnect in %u seconds", seconds_delay); @@ -227,7 +276,22 @@ void delay_then_reconnect(struct channel *channel, u32 seconds_delay, notleak(new_reltimer(ld->timers, d, timerel_add(time_from_sec(seconds_delay), time_from_usec(pseudorand(1000000))), - maybe_reconnect, d)); + do_connect, d)); +} + +void try_reconnect(struct channel *channel, + u32 seconds_delay, + const struct wireaddr_internal *addrhint) +{ + if (!channel->peer->ld->reconnect) + return; + + try_connect(channel, + channel->peer->ld, + &channel->peer->id, + channel, + seconds_delay, + addrhint); } static void connect_failed(struct lightningd *ld, const u8 *msg) @@ -254,7 +318,7 @@ static void connect_failed(struct lightningd *ld, const u8 *msg) /* If we have an active channel, then reconnect. */ channel = active_channel_by_id(ld, &id, NULL); if (channel) - delay_then_reconnect(channel, seconds_to_delay, addrhint); + try_reconnect(channel, seconds_to_delay, addrhint); } void connect_succeeded(struct lightningd *ld, const struct peer *peer, @@ -292,6 +356,63 @@ static void peer_please_disconnect(struct lightningd *ld, const u8 *msg) } } +struct custommsg_payload { + struct node_id peer_id; + u8 *msg; +}; + +static bool custommsg_cb(struct custommsg_payload *payload, + const char *buffer, const jsmntok_t *toks) +{ + const jsmntok_t *t_res; + + if (!toks || !buffer) + return true; + + t_res = json_get_member(buffer, toks, "result"); + + /* fail */ + if (!t_res || !json_tok_streq(buffer, t_res, "continue")) + fatal("Plugin returned an invalid response to the " + "custommsg hook: %s", buffer); + + /* call next hook */ + return true; +} + +static void custommsg_final(struct custommsg_payload *payload STEALS) +{ + tal_steal(tmpctx, payload); +} + +static void custommsg_payload_serialize(struct custommsg_payload *payload, + struct json_stream *stream, + struct plugin *plugin) +{ + json_add_hex_talarr(stream, "payload", payload->msg); + json_add_node_id(stream, "peer_id", &payload->peer_id); +} + +REGISTER_PLUGIN_HOOK(custommsg, + custommsg_cb, + custommsg_final, + custommsg_payload_serialize, + struct custommsg_payload *); + +static void handle_custommsg_in(struct lightningd *ld, const u8 *msg) +{ + struct custommsg_payload *p = tal(NULL, struct custommsg_payload); + + if (!fromwire_connectd_custommsg_in(p, msg, &p->peer_id, &p->msg)) { + log_broken(ld->log, "Malformed custommsg: %s", + tal_hex(tmpctx, msg)); + tal_free(p); + return; + } + + plugin_hook_call_custommsg(ld, p); +} + static unsigned connectd_msg(struct subd *connectd, const u8 *msg, const int *fds) { enum connectd_wire t = fromwire_peektype(msg); @@ -304,10 +425,14 @@ static unsigned connectd_msg(struct subd *connectd, const u8 *msg, const int *fd case WIRE_CONNECTD_PEER_DISCONNECTED: case WIRE_CONNECTD_DEV_MEMLEAK: case WIRE_CONNECTD_PEER_FINAL_MSG: + case WIRE_CONNECTD_PING: + case WIRE_CONNECTD_SEND_ONIONMSG: + case WIRE_CONNECTD_CUSTOMMSG_OUT: /* This is a reply, so never gets through to here. */ case WIRE_CONNECTD_INIT_REPLY: case WIRE_CONNECTD_ACTIVATE_REPLY: case WIRE_CONNECTD_DEV_MEMLEAK_REPLY: + case WIRE_CONNECTD_PING_REPLY: break; case WIRE_CONNECTD_RECONNECTED: @@ -315,14 +440,22 @@ static unsigned connectd_msg(struct subd *connectd, const u8 *msg, const int *fd break; case WIRE_CONNECTD_PEER_CONNECTED: - if (tal_count(fds) != 3) - return 3; - peer_connected(connectd->ld, msg, fds[0], fds[1], fds[2]); + if (tal_count(fds) != 1) + return 1; + peer_connected(connectd->ld, msg, fds[0]); break; case WIRE_CONNECTD_CONNECT_FAILED: connect_failed(connectd->ld, msg); break; + + case WIRE_CONNECTD_GOT_ONIONMSG_TO_US: + handle_onionmsg_to_us(connectd->ld, msg); + break; + + case WIRE_CONNECTD_CUSTOMMSG_IN: + handle_custommsg_in(connectd->ld, msg); + break; } return 0; } @@ -363,7 +496,13 @@ int connectd_init(struct lightningd *ld) ld->connectd = new_global_subd(ld, "lightning_connectd", connectd_wire_name, connectd_msg, - take(&hsmfd), take(&fds[1]), NULL); + take(&hsmfd), take(&fds[1]), +#if DEVELOPER + /* Not take(): we share it */ + ld->dev_disconnect_fd >= 0 ? + &ld->dev_disconnect_fd : NULL, +#endif + NULL); if (!ld->connectd) err(1, "Could not subdaemon connectd"); @@ -388,7 +527,9 @@ int connectd_init(struct lightningd *ld) ld->config.use_v3_autotor, ld->config.connection_timeout_secs, websocket_helper_path, - ld->websocket_port); + ld->websocket_port, + IFDEV(ld->dev_fast_gossip, false), + IFDEV(ld->dev_disconnect_fd >= 0, false)); subd_req(ld->connectd, ld->connectd, take(msg), -1, 0, connect_init_done, NULL); @@ -419,3 +560,81 @@ void connectd_activate(struct lightningd *ld) io_loop(NULL, NULL); } +static struct command_result *json_sendcustommsg(struct command *cmd, + const char *buffer, + const jsmntok_t *obj UNNEEDED, + const jsmntok_t *params) +{ + struct json_stream *response; + struct node_id *dest; + struct peer *peer; + u8 *msg; + int type; + + if (!param(cmd, buffer, params, + p_req("node_id", param_node_id, &dest), + p_req("msg", param_bin_from_hex, &msg), + NULL)) + return command_param_failed(); + + type = fromwire_peektype(msg); + if (peer_wire_is_defined(type)) { + return command_fail( + cmd, JSONRPC2_INVALID_REQUEST, + "Cannot send messages of type %d (%s). It is not possible " + "to send messages that have a type managed internally " + "since that might cause issues with the internal state " + "tracking.", + type, peer_wire_name(type)); + } + + if (type % 2 == 0) { + return command_fail( + cmd, JSONRPC2_INVALID_REQUEST, + "Cannot send even-typed %d custom message. Currently " + "custom messages are limited to odd-numbered message " + "types, as even-numbered types might result in " + "disconnections.", + type); + } + + peer = peer_by_id(cmd->ld, dest); + if (!peer) { + return command_fail(cmd, JSONRPC2_INVALID_REQUEST, + "No such peer: %s", + type_to_string(cmd, struct node_id, dest)); + } + + subd_send_msg(cmd->ld->connectd, + take(towire_connectd_custommsg_out(cmd, dest, msg))); + + response = json_stream_success(cmd); + json_add_string(response, "status", + "Message sent to connectd for delivery"); + + return command_success(cmd, response); +} + +static const struct json_command sendcustommsg_command = { + "sendcustommsg", + "utility", + json_sendcustommsg, + "Send a custom message to the peer with the given {node_id}", + .verbose = "sendcustommsg node_id hexcustommsg", +}; + +AUTODATA(json_command, &sendcustommsg_command); + +#ifdef COMPAT_V0100 +#ifdef DEVELOPER +static const struct json_command dev_sendcustommsg_command = { + "dev-sendcustommsg", + "utility", + json_sendcustommsg, + "Send a custom message to the peer with the given {node_id}", + .verbose = "dev-sendcustommsg node_id hexcustommsg", +}; + +AUTODATA(json_command, &dev_sendcustommsg_command); +#endif /* DEVELOPER */ +#endif /* COMPAT_V0100 */ diff --git a/lightningd/connect_control.h b/lightningd/connect_control.h index 830332b3d37c..67beb003782b 100644 --- a/lightningd/connect_control.h +++ b/lightningd/connect_control.h @@ -10,8 +10,8 @@ struct wireaddr_internal; int connectd_init(struct lightningd *ld); void connectd_activate(struct lightningd *ld); -void delay_then_reconnect(struct channel *channel, u32 seconds_delay, - const struct wireaddr_internal *addrhint TAKES); +void try_reconnect(struct channel *channel, u32 seconds_delay, + const struct wireaddr_internal *addrhint TAKES); void connect_succeeded(struct lightningd *ld, const struct peer *peer, bool incoming, const struct wireaddr_internal *addr); diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c index a53c38be9214..2daae9b2b88b 100644 --- a/lightningd/dual_open_control.c +++ b/lightningd/dual_open_control.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -29,7 +30,6 @@ #include #include #include -#include struct commit_rcvd { struct channel *channel; @@ -1329,22 +1329,17 @@ static void handle_channel_closed(struct subd *dualopend, const int *fds, const u8 *msg) { - struct per_peer_state *pps; struct channel *channel = dualopend->channel; - if (!fromwire_dualopend_shutdown_complete(tmpctx, msg, &pps)) { + if (!fromwire_dualopend_shutdown_complete(msg)) { channel_internal_error(dualopend->channel, "Bad DUALOPEND_SHUTDOWN_COMPLETE: %s", tal_hex(msg, msg)); close(fds[0]); - close(fds[1]); - close(fds[2]); return; } - per_peer_state_set_fds_arr(pps, fds); - - peer_start_closingd(channel, pps); + peer_start_closingd(channel, fds[0]); channel_set_state(channel, CHANNELD_SHUTTING_DOWN, CLOSINGD_SIGEXCHANGE, @@ -1352,6 +1347,24 @@ static void handle_channel_closed(struct subd *dualopend, "Start closingd"); } +static void handle_local_private_channel(struct subd *dualopend, + const u8 *msg) +{ + struct amount_sat capacity; + u8 *features; + + if (!fromwire_dualopend_local_private_channel(msg, msg, &capacity, + &features)) { + channel_internal_error(dualopend->channel, + "bad dualopend_local_private_channel %s", + tal_hex(msg, msg)); + return; + } + + tell_gossipd_local_private_channel(dualopend->ld, dualopend->channel, + capacity, features); +} + struct channel_send { const struct wally_tx *wtx; struct channel *channel; @@ -1612,15 +1625,13 @@ static void handle_channel_locked(struct subd *dualopend, const u8 *msg) { struct channel *channel = dualopend->channel; - struct per_peer_state *pps; - if (!fromwire_dualopend_channel_locked(tmpctx, msg, &pps)) { + if (!fromwire_dualopend_channel_locked(msg)) { channel_internal_error(channel, "Bad WIRE_DUALOPEND_CHANNEL_LOCKED: %s", tal_hex(msg, msg)); return; } - per_peer_state_set_fds_arr(pps, fds); assert(channel->scid); assert(channel->remote_funding_locked); @@ -1641,7 +1652,7 @@ static void handle_channel_locked(struct subd *dualopend, wallet_channel_clear_inflights(dualopend->ld->wallet, channel); /* FIXME: LND sigs/update_fee msgs? */ - peer_start_channeld(channel, pps, NULL, false, NULL); + peer_start_channeld(channel, fds[0], NULL, false, NULL); return; } @@ -2957,22 +2968,24 @@ static unsigned int dual_opend_msg(struct subd *dualopend, handle_dry_run_finished(dualopend, msg); return 0; case WIRE_DUALOPEND_CHANNEL_LOCKED: - if (tal_count(fds) != 3) - return 3; + if (tal_count(fds) != 1) + return 1; handle_channel_locked(dualopend, fds, msg); return 0; case WIRE_DUALOPEND_GOT_SHUTDOWN: handle_peer_wants_to_close(dualopend, msg); return 0; case WIRE_DUALOPEND_SHUTDOWN_COMPLETE: - if (tal_count(fds) != 3) - return 3; + if (tal_count(fds) != 1) + return 1; handle_channel_closed(dualopend, fds, msg); return 0; case WIRE_DUALOPEND_FAIL_FALLEN_BEHIND: channel_fail_fallen_behind(dualopend, msg); return 0; - + case WIRE_DUALOPEND_LOCAL_PRIVATE_CHANNEL: + handle_local_private_channel(dualopend, msg); + return 0; /* Messages we send */ case WIRE_DUALOPEND_INIT: case WIRE_DUALOPEND_REINIT: @@ -2990,15 +3003,6 @@ static unsigned int dual_opend_msg(struct subd *dualopend, break; } - switch ((enum common_wire)t) { - case WIRE_CUSTOMMSG_IN: - handle_custommsg_in(dualopend->ld, dualopend->node_id, msg); - return 0; - /* We send these. */ - case WIRE_CUSTOMMSG_OUT: - break; - } - log_broken(dualopend->log, "Unexpected msg %s: %s", dualopend_wire_name(t), tal_hex(tmpctx, msg)); tal_free(dualopend); @@ -3177,7 +3181,7 @@ AUTODATA(json_command, &openchannel_bump_command); AUTODATA(json_command, &openchannel_abort_command); static void start_fresh_dualopend(struct peer *peer, - struct per_peer_state *pps, + int peer_fd, struct channel *channel) { int hsmfd; @@ -3199,9 +3203,7 @@ static void start_fresh_dualopend(struct peer *peer, dual_opend_msg, channel_errmsg, channel_set_billboard, - take(&pps->peer_fd), - take(&pps->gossip_fd), - take(&pps->gossip_store_fd), + take(&peer_fd), take(&hsmfd), NULL); if (!channel->owner) { @@ -3230,7 +3232,7 @@ static void start_fresh_dualopend(struct peer *peer, &channel->our_config, max_to_self_delay, min_effective_htlc_capacity, - pps, &channel->local_basepoints, + &channel->local_basepoints, &channel->local_funding_pubkey, channel->minimum_depth); subd_send_msg(channel->owner, take(msg)); @@ -3238,7 +3240,7 @@ static void start_fresh_dualopend(struct peer *peer, } void peer_restart_dualopend(struct peer *peer, - struct per_peer_state *pps, + int peer_fd, struct channel *channel) { u32 max_to_self_delay, blockheight; @@ -3250,7 +3252,7 @@ void peer_restart_dualopend(struct peer *peer, u8 *msg; if (channel_unsaved(channel)) { - start_fresh_dualopend(peer, pps, channel); + start_fresh_dualopend(peer, peer_fd, channel); return; } hsmfd = hsm_get_client_fd(peer->ld, &peer->id, channel->dbid, @@ -3267,9 +3269,7 @@ void peer_restart_dualopend(struct peer *peer, dual_opend_msg, channel_errmsg, channel_set_billboard, - take(&pps->peer_fd), - take(&pps->gossip_fd), - take(&pps->gossip_store_fd), + take(&peer_fd), take(&hsmfd), NULL)); if (!channel->owner) { log_broken(channel->log, "Could not subdaemon channel: %s", @@ -3311,7 +3311,6 @@ void peer_restart_dualopend(struct peer *peer, &channel->cid, max_to_self_delay, min_effective_htlc_capacity, - pps, &channel->local_basepoints, &channel->local_funding_pubkey, &channel->channel_info.remote_fundingkey, @@ -3344,7 +3343,7 @@ void peer_restart_dualopend(struct peer *peer, subd_send_msg(channel->owner, take(msg)); } -void peer_start_dualopend(struct peer *peer, struct per_peer_state *pps) +void peer_start_dualopend(struct peer *peer, int peer_fd) { struct channel *channel; @@ -3354,5 +3353,5 @@ void peer_start_dualopend(struct peer *peer, struct per_peer_state *pps) peer->ld->config.fee_base, peer->ld->config.fee_per_satoshi); - start_fresh_dualopend(peer, pps, channel); + start_fresh_dualopend(peer, peer_fd, channel); } diff --git a/lightningd/dual_open_control.h b/lightningd/dual_open_control.h index 8657a40a6b1b..479aca10074e 100644 --- a/lightningd/dual_open_control.h +++ b/lightningd/dual_open_control.h @@ -4,12 +4,10 @@ #include "config.h" #include -struct per_peer_state; - -void peer_start_dualopend(struct peer *peer, struct per_peer_state *pps); +void peer_start_dualopend(struct peer *peer, int peer_fd); void peer_restart_dualopend(struct peer *peer, - struct per_peer_state *pps, + int peer_fd, struct channel *channel); void dualopen_tell_depth(struct subd *dualopend, diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index d64575220a04..2e445880fc30 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -1,18 +1,21 @@ #include "config.h" #include +#include #include #include #include #include +#include #include #include #include #include +#include +#include #include #include #include #include -#include #include #include @@ -106,6 +109,42 @@ static void get_txout(struct subd *gossip, const u8 *msg) } } +static void handle_local_channel_update(struct lightningd *ld, const u8 *msg) +{ + struct short_channel_id scid; + u8 *update; + struct channel *channel; + + if (!fromwire_gossipd_got_local_channel_update(msg, msg, + &scid, &update)) { + fatal("Gossip gave bad GOSSIP_GOT_LOCAL_CHANNEL_UPDATE %s", + tal_hex(msg, msg)); + } + + /* In theory this could vanish before gossipd gets around to telling + * us. */ + channel = any_channel_by_scid(ld, &scid); + if (!channel) { + log_broken(ld->log, "Local update for bad scid %s", + type_to_string(tmpctx, struct short_channel_id, + &scid)); + return; + } + + channel_replace_update(channel, take(update)); +} + +const u8 *get_channel_update(struct channel *channel) +{ + /* Tell gossipd we're using it (if shutting down, might be NULL) */ + if (channel->channel_update && channel->peer->ld->gossip) { + subd_send_msg(channel->peer->ld->gossip, + take(towire_gossipd_used_local_channel_update + (NULL, channel->scid))); + } + return channel->channel_update; +} + static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) { enum gossipd_wire t = fromwire_peektype(msg); @@ -113,7 +152,6 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) switch (t) { /* These are messages we send, not them. */ case WIRE_GOSSIPD_INIT: - case WIRE_GOSSIPD_GET_STRIPPED_CUPDATE: case WIRE_GOSSIPD_GET_TXOUT_REPLY: case WIRE_GOSSIPD_OUTPOINT_SPENT: case WIRE_GOSSIPD_NEW_LEASE_RATES: @@ -124,22 +162,26 @@ static unsigned gossip_msg(struct subd *gossip, const u8 *msg, const int *fds) case WIRE_GOSSIPD_DEV_COMPACT_STORE: case WIRE_GOSSIPD_DEV_SET_TIME: case WIRE_GOSSIPD_NEW_BLOCKHEIGHT: - case WIRE_GOSSIPD_SEND_ONIONMSG: case WIRE_GOSSIPD_ADDGOSSIP: + case WIRE_GOSSIPD_GET_ADDRS: + case WIRE_GOSSIPD_USED_LOCAL_CHANNEL_UPDATE: + case WIRE_GOSSIPD_LOCAL_CHANNEL_UPDATE: + case WIRE_GOSSIPD_LOCAL_CHANNEL_ANNOUNCEMENT: + case WIRE_GOSSIPD_LOCAL_PRIVATE_CHANNEL: /* This is a reply, so never gets through to here. */ case WIRE_GOSSIPD_INIT_REPLY: case WIRE_GOSSIPD_DEV_MEMLEAK_REPLY: case WIRE_GOSSIPD_DEV_COMPACT_STORE_REPLY: - case WIRE_GOSSIPD_GET_STRIPPED_CUPDATE_REPLY: case WIRE_GOSSIPD_ADDGOSSIP_REPLY: + case WIRE_GOSSIPD_GET_ADDRS_REPLY: break; - case WIRE_GOSSIPD_GOT_ONIONMSG_TO_US: - handle_onionmsg_to_us(gossip->ld, msg); - break; case WIRE_GOSSIPD_GET_TXOUT: get_txout(gossip, msg); break; + case WIRE_GOSSIPD_GOT_LOCAL_CHANNEL_UPDATE: + handle_local_channel_update(gossip->ld, msg); + break; } return 0; } @@ -215,6 +257,85 @@ void gossipd_notify_spend(struct lightningd *ld, subd_send_msg(ld->gossip, msg); } +/* We unwrap, add the peer id, and send to gossipd. */ +void tell_gossipd_local_channel_update(struct lightningd *ld, + struct channel *channel, + const u8 *msg) +{ + struct short_channel_id scid; + bool disable; + u16 cltv_expiry_delta; + struct amount_msat htlc_minimum_msat; + u32 fee_base_msat, fee_proportional_millionths; + struct amount_msat htlc_maximum_msat; + + if (!fromwire_channeld_local_channel_update(msg, &scid, &disable, + &cltv_expiry_delta, + &htlc_minimum_msat, + &fee_base_msat, + &fee_proportional_millionths, + &htlc_maximum_msat)) { + channel_internal_error(channel, + "bad channeld_local_channel_update %s", + tal_hex(channel, msg)); + return; + } + + /* As we're shutting down, ignore */ + if (!ld->gossip) + return; + + subd_send_msg(ld->gossip, + take(towire_gossipd_local_channel_update + (NULL, + &channel->peer->id, + &scid, + disable, + cltv_expiry_delta, + htlc_minimum_msat, + fee_base_msat, + fee_proportional_millionths, htlc_maximum_msat))); +} + +void tell_gossipd_local_channel_announce(struct lightningd *ld, + struct channel *channel, + const u8 *msg) +{ + u8 *ann; + if (!fromwire_channeld_local_channel_announcement(msg, msg, &ann)) { + channel_internal_error(channel, + "bad channeld_local_channel_announcement" + " %s", + tal_hex(channel, msg)); + return; + } + + /* As we're shutting down, ignore */ + if (!ld->gossip) + return; + + subd_send_msg(ld->gossip, + take(towire_gossipd_local_channel_announcement + (NULL, &channel->peer->id, ann))); +} + +void tell_gossipd_local_private_channel(struct lightningd *ld, + struct channel *channel, + struct amount_sat capacity, + const u8 *features) +{ + /* As we're shutting down, ignore */ + if (!ld->gossip) + return; + + subd_send_msg(ld->gossip, + take(towire_gossipd_local_private_channel + (NULL, &channel->peer->id, + capacity, + channel->scid, + features))); +} + static struct command_result *json_setleaserates(struct command *cmd, const char *buffer, const jsmntok_t *obj UNNEEDED, diff --git a/lightningd/gossip_control.h b/lightningd/gossip_control.h index 7d6254e291bb..c1d587902158 100644 --- a/lightningd/gossip_control.h +++ b/lightningd/gossip_control.h @@ -5,6 +5,7 @@ #include #include +struct channel; struct lightningd; void gossip_init(struct lightningd *ld, int connectd_fd); @@ -14,4 +15,16 @@ void gossipd_notify_spend(struct lightningd *ld, void gossip_notify_new_block(struct lightningd *ld, u32 blockheight); +/* channeld tells us stuff, we tell gossipd. */ +void tell_gossipd_local_channel_update(struct lightningd *ld, + struct channel *channel, + const u8 *msg); +void tell_gossipd_local_channel_announce(struct lightningd *ld, + struct channel *channel, + const u8 *msg); +void tell_gossipd_local_private_channel(struct lightningd *ld, + struct channel *channel, + struct amount_sat capacity, + const u8 *features); + #endif /* LIGHTNING_LIGHTNINGD_GOSSIP_CONTROL_H */ diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index f406e68d04b9..3700816625ea 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -133,6 +133,7 @@ static struct lightningd *new_lightningd(const tal_t *ctx) ld->dev_max_funding_unconfirmed = 2016; ld->dev_ignore_modern_onion = false; ld->dev_ignore_obsolete_onion = false; + ld->dev_disable_commit = -1; #endif /*~ These are CCAN lists: an embedded double-linked list. It's not @@ -525,6 +526,8 @@ static void shutdown_subdaemons(struct lightningd *ld) /*~ The three "global" daemons, which we shutdown explicitly: we * give them 10 seconds to exit gracefully before killing them. */ ld->connectd = subd_shutdown(ld->connectd, 10); + ld->gossip = subd_shutdown(ld->gossip, 10); + ld->hsm = subd_shutdown(ld->hsm, 10); /* Now we free all the HTLCs */ free_htlcs(ld, NULL); @@ -557,11 +560,6 @@ static void shutdown_subdaemons(struct lightningd *ld) tal_free(p); } - /*~ Now they're all dead, we can stop gossipd: doing it before HTLCs is - * problematic because local_fail_in_htlc_needs_update() asks gossipd */ - ld->gossip = subd_shutdown(ld->gossip, 10); - ld->hsm = subd_shutdown(ld->hsm, 10); - /*~ Commit the transaction. Note that the db is actually * single-threaded, so commits never fail and we don't need * spin-and-retry logic everywhere. */ @@ -1026,11 +1024,6 @@ int main(int argc, char *argv[]) * socket pair, and gives us the other */ connectd_gossipd_fd = connectd_init(ld); - /*~ The gossip daemon looks after the routing gossip; - * channel_announcement, channel_update, node_announcement and gossip - * queries. */ - gossip_init(ld, connectd_gossipd_fd); - /*~ We do every database operation within a transaction; usually this * is covered by the infrastructure (eg. opening a transaction before * handling a message or expiring a timer), but for startup we do this @@ -1077,6 +1070,12 @@ int main(int argc, char *argv[]) unconnected_htlcs_in = load_channels_from_wallet(ld); db_commit_transaction(ld->wallet->db); + /*~ The gossip daemon looks after the routing gossip; + * channel_announcement, channel_update, node_announcement and gossip + * queries. It also hands us the latest channel_updates for our + * channels. */ + gossip_init(ld, connectd_gossipd_fd); + /*~ Create RPC socket: now lightning-cli can send us JSON RPC commands * over a UNIX domain socket specified by `ld->rpc_filename`. */ jsonrpc_listen(ld->jsonrpc, ld); diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h index 8fabc615076a..884b2f921744 100644 --- a/lightningd/lightningd.h +++ b/lightningd/lightningd.h @@ -250,6 +250,9 @@ struct lightningd { /* Special switches to test onion compatibility */ bool dev_ignore_modern_onion, dev_ignore_obsolete_onion; + + /* Tell channeld to disable commits after this many. */ + int dev_disable_commit; #endif /* DEVELOPER */ /* tor support */ diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index da24e6c4c2db..2531a01bedba 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -571,7 +571,7 @@ static unsigned int onchain_msg(struct subd *sd, const u8 *msg, const int *fds U /* Only error onchaind can get is if it dies. */ static void onchain_error(struct channel *channel, - struct per_peer_state *pps UNUSED, + int peer_fd UNUSED, const struct channel_id *channel_id UNUSED, const char *desc, bool warning UNUSED, diff --git a/lightningd/onion_message.c b/lightningd/onion_message.c index e6e51f5ebccd..fec95b7ca547 100644 --- a/lightningd/onion_message.c +++ b/lightningd/onion_message.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -150,7 +150,7 @@ void handle_onionmsg_to_us(struct lightningd *ld, const u8 *msg) payload = tal(tmpctx, struct onion_message_hook_payload); payload->our_alias = tal(payload, struct pubkey); - if (!fromwire_gossipd_got_onionmsg_to_us(payload, msg, + if (!fromwire_connectd_got_onionmsg_to_us(payload, msg, &obs2, payload->our_alias, &self_id, @@ -198,7 +198,7 @@ void handle_onionmsg_to_us(struct lightningd *ld, const u8 *msg) } tal_free(submsg); - /* Make sure gossipd gets this right. */ + /* Make sure connectd gets this right. */ if (payload->reply_path && (!payload->reply_blinding || !payload->reply_first_node)) { log_broken(ld->log, @@ -277,7 +277,7 @@ static struct command_result *json_sendonionmessage2(struct command *cmd, return command_fail(cmd, LIGHTNINGD, "experimental-onion-messages not enabled"); - /* Sanity check first; gossipd doesn't bother telling us if peer + /* Sanity check first; connectd doesn't bother telling us if peer * can't be reached. */ if (!peer_by_id(cmd->ld, first_id)) return command_fail(cmd, LIGHTNINGD, "Unknown first peer"); @@ -300,8 +300,8 @@ static struct command_result *json_sendonionmessage2(struct command *cmd, return command_fail(cmd, JSONRPC2_INVALID_PARAMS, "Creating onion failed (tlvs too long?)"); - subd_send_msg(cmd->ld->gossip, - take(towire_gossipd_send_onionmsg(NULL, obs2, first_id, + subd_send_msg(cmd->ld->connectd, + take(towire_connectd_send_onionmsg(NULL, obs2, first_id, serialize_onionpacket(tmpctx, op), blinding))); diff --git a/lightningd/opening_common.c b/lightningd/opening_common.c index 635aaeef5975..90a134f685ec 100644 --- a/lightningd/opening_common.c +++ b/lightningd/opening_common.c @@ -17,8 +17,9 @@ static void destroy_uncommitted_channel(struct uncommitted_channel *uc) { - if (uc->open_daemon) { - struct subd *open_daemon= uc->open_daemon; + struct subd *open_daemon = uc->open_daemon; + + if (open_daemon) { uc->open_daemon = NULL; subd_release_channel(open_daemon, uc); } @@ -74,14 +75,14 @@ new_uncommitted_channel(struct peer *peer) } void opend_channel_errmsg(struct uncommitted_channel *uc, - struct per_peer_state *pps, + int peer_fd, const struct channel_id *channel_id UNUSED, const char *desc, bool warning UNUSED, const u8 *err_for_them UNUSED) { /* Close fds, if any. */ - tal_free(pps); + close(peer_fd); uncommitted_channel_disconnect(uc, LOG_INFORM, desc); tal_free(uc); } @@ -115,10 +116,6 @@ void kill_uncommitted_channel(struct uncommitted_channel *uc, { log_info(uc->log, "Killing opening daemon: %s", why); - /* Close opend daemon. */ - subd_release_channel(uc->open_daemon, uc); - uc->open_daemon = NULL; - uncommitted_channel_disconnect(uc, LOG_INFORM, why); tal_free(uc); } @@ -171,7 +168,7 @@ void handle_reestablish(struct lightningd *ld, const struct node_id *peer_id, const struct channel_id *channel_id, const u8 *reestablish, - struct per_peer_state *pps) + int peer_fd) { struct peer *peer; struct channel *c; @@ -187,7 +184,8 @@ void handle_reestablish(struct lightningd *ld, if (c && channel_closed(c)) { log_debug(c->log, "Reestablish on %s channel: using channeld to reply", channel_state_name(c)); - peer_start_channeld(c, pps, NULL, true, reestablish); + peer_start_channeld(c, peer_fd, NULL, true, + reestablish); } else { const u8 *err = towire_errorfmt(tmpctx, channel_id, "Unknown channel for reestablish"); @@ -195,15 +193,8 @@ void handle_reestablish(struct lightningd *ld, type_to_string(tmpctx, struct channel_id, channel_id)); subd_send_msg(ld->connectd, take(towire_connectd_peer_final_msg(NULL, peer_id, - pps, err))); - subd_send_fd(ld->connectd, pps->peer_fd); - subd_send_fd(ld->connectd, pps->gossip_fd); - subd_send_fd(ld->connectd, pps->gossip_store_fd); - /* Don't close those fds! */ - pps->peer_fd - = pps->gossip_fd - = pps->gossip_store_fd - = -1; + err))); + close(peer_fd); } } diff --git a/lightningd/opening_common.h b/lightningd/opening_common.h index 8def23c573de..9e60d30c46e6 100644 --- a/lightningd/opening_common.h +++ b/lightningd/opening_common.h @@ -89,17 +89,13 @@ struct funding_channel { /* Any commands trying to cancel us. */ struct command **cancels; - - /* Place to stash the per-peer-state while we wait - * for them to get back to us with signatures */ - struct per_peer_state *pps; }; struct uncommitted_channel * new_uncommitted_channel(struct peer *peer); void opend_channel_errmsg(struct uncommitted_channel *uc, - struct per_peer_state *pps, + int peer_fd, const struct channel_id *channel_id UNUSED, const char *desc, bool warning UNUSED, @@ -125,7 +121,7 @@ void handle_reestablish(struct lightningd *ld, const struct node_id *peer_id, const struct channel_id *channel_id, const u8 *reestablish, - struct per_peer_state *pps); + int peer_fd); #if DEVELOPER struct command; diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index dd378219f90c..ed717fc840e1 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -27,7 +27,6 @@ #include #include #include -#include void json_add_uncommitted_channel(struct json_stream *response, const struct uncommitted_channel *uc) @@ -319,9 +318,7 @@ static void opening_funder_start_replied(struct subd *openingd, const u8 *resp, return; failed: - subd_release_channel(openingd, fc->uc); - fc->uc->open_daemon = NULL; - /* Frees fc too, and tmpctx */ + /* Frees fc too */ tal_free(fc->uc); } @@ -338,7 +335,6 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, struct channel *channel; struct lightningd *ld = openingd->ld; u8 *remote_upfront_shutdown_script; - struct per_peer_state *pps; struct penalty_base *pbase; struct channel_type *type; @@ -350,7 +346,6 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, &remote_commit, &pbase, &remote_commit_sig, - &pps, &channel_info.theirbase.revocation, &channel_info.theirbase.payment, &channel_info.theirbase.htlc, @@ -372,7 +367,6 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, goto cleanup; } remote_commit->chainparams = chainparams; - per_peer_state_set_fds_arr(pps, fds); log_debug(ld->log, "%s", type_to_string(tmpctx, struct pubkey, @@ -411,12 +405,10 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, wallet_penalty_base_add(ld->wallet, channel->dbid, pbase); funding_success(channel); - peer_start_channeld(channel, pps, NULL, false, NULL); + peer_start_channeld(channel, fds[0], NULL, false, NULL); cleanup: - subd_release_channel(openingd, fc->uc); - fc->uc->open_daemon = NULL; - /* Frees fc too, and tmpctx */ + /* Frees fc too */ tal_free(fc->uc); } @@ -438,7 +430,6 @@ static void opening_fundee_finished(struct subd *openingd, u8 channel_flags; struct channel *channel; u8 *remote_upfront_shutdown_script, *local_upfront_shutdown_script; - struct per_peer_state *pps; struct penalty_base *pbase; struct channel_type *type; @@ -452,7 +443,6 @@ static void opening_fundee_finished(struct subd *openingd, &remote_commit, &pbase, &remote_commit_sig, - &pps, &channel_info.theirbase.revocation, &channel_info.theirbase.payment, &channel_info.theirbase.htlc, @@ -477,7 +467,6 @@ static void opening_fundee_finished(struct subd *openingd, } remote_commit->chainparams = chainparams; - per_peer_state_set_fds_arr(pps, fds); /* openingd should never accept them funding channel in this case. */ if (peer_active_channel(uc->peer)) { @@ -526,17 +515,13 @@ static void opening_fundee_finished(struct subd *openingd, wallet_penalty_base_add(ld->wallet, channel->dbid, pbase); /* On to normal operation! */ - peer_start_channeld(channel, pps, fwd_msg, false, NULL); + peer_start_channeld(channel, fds[0], fwd_msg, false, NULL); - subd_release_channel(openingd, uc); - uc->open_daemon = NULL; tal_free(uc); return; failed: close(fds[0]); - close(fds[1]); - close(fds[3]); tal_free(uc); } @@ -809,28 +794,27 @@ static void opening_got_offer(struct subd *openingd, } static void opening_got_reestablish(struct subd *openingd, const u8 *msg, - const int fds[3], + const int fds[1], struct uncommitted_channel *uc) { struct lightningd *ld = openingd->ld; struct node_id peer_id = uc->peer->id; struct channel_id channel_id; u8 *reestablish; - struct per_peer_state *pps; if (!fromwire_openingd_got_reestablish(tmpctx, msg, &channel_id, - &reestablish, &pps)) { + &reestablish)) { log_broken(openingd->log, "Malformed opening_got_reestablish %s", tal_hex(tmpctx, msg)); tal_free(openingd); + close(fds[0]); return; } - per_peer_state_set_fds_arr(pps, fds); /* This could free peer */ tal_free(uc); - handle_reestablish(ld, &peer_id, &channel_id, reestablish, pps); + handle_reestablish(ld, &peer_id, &channel_id, reestablish, fds[0]); } static unsigned int openingd_msg(struct subd *openingd, @@ -847,8 +831,8 @@ static unsigned int openingd_msg(struct subd *openingd, tal_free(openingd); return 0; } - if (tal_count(fds) != 3) - return 3; + if (tal_count(fds) != 1) + return 1; opening_funder_finished(openingd, msg, fds, uc->fc); return 0; case WIRE_OPENINGD_FUNDER_START_REPLY: @@ -871,8 +855,8 @@ static unsigned int openingd_msg(struct subd *openingd, return 0; case WIRE_OPENINGD_FUNDEE: - if (tal_count(fds) != 3) - return 3; + if (tal_count(fds) != 1) + return 1; opening_fundee_finished(openingd, msg, fds, uc); return 0; @@ -881,8 +865,8 @@ static unsigned int openingd_msg(struct subd *openingd, return 0; case WIRE_OPENINGD_GOT_REESTABLISH: - if (tal_count(fds) != 3) - return 3; + if (tal_count(fds) != 1) + return 1; opening_got_reestablish(openingd, msg, fds, uc); return 0; @@ -898,22 +882,13 @@ static unsigned int openingd_msg(struct subd *openingd, break; } - switch ((enum common_wire)t) { - case WIRE_CUSTOMMSG_IN: - handle_custommsg_in(openingd->ld, openingd->node_id, msg); - return 0; - /* We send these. */ - case WIRE_CUSTOMMSG_OUT: - break; - } - log_broken(openingd->log, "Unexpected msg %s: %s", openingd_wire_name(t), tal_hex(tmpctx, msg)); tal_free(openingd); return 0; } -void peer_start_openingd(struct peer *peer, struct per_peer_state *pps) +void peer_start_openingd(struct peer *peer, int peer_fd) { int hsmfd; u32 max_to_self_delay; @@ -936,9 +911,7 @@ void peer_start_openingd(struct peer *peer, struct per_peer_state *pps) openingd_msg, opend_channel_errmsg, opend_channel_set_billboard, - take(&pps->peer_fd), - take(&pps->gossip_fd), - take(&pps->gossip_store_fd), + take(&peer_fd), take(&hsmfd), NULL); if (!uc->open_daemon) { uncommitted_channel_disconnect(uc, LOG_BROKEN, @@ -968,13 +941,12 @@ void peer_start_openingd(struct peer *peer, struct per_peer_state *pps) &uc->our_config, max_to_self_delay, min_effective_htlc_capacity, - pps, &uc->local_basepoints, + &uc->local_basepoints, &uc->local_funding_pubkey, uc->minimum_depth, feerate_min(peer->ld, NULL), feerate_max(peer->ld, NULL), - IFDEV(peer->ld->dev_force_tmp_channel_id, NULL), - IFDEV(peer->ld->dev_fast_gossip, false)); + IFDEV(peer->ld->dev_force_tmp_channel_id, NULL)); subd_send_msg(uc->open_daemon, take(msg)); } diff --git a/lightningd/opening_control.h b/lightningd/opening_control.h index 3c5f3343afc1..76db459912c0 100644 --- a/lightningd/opening_control.h +++ b/lightningd/opening_control.h @@ -8,14 +8,12 @@ struct channel_id; struct crypto_state; struct json_stream; struct lightningd; -struct per_peer_state; struct uncommitted_channel; void json_add_uncommitted_channel(struct json_stream *response, const struct uncommitted_channel *uc); -void peer_start_openingd(struct peer *peer, - struct per_peer_state *pps); +void peer_start_openingd(struct peer *peer, int peer_fd); struct subd *peer_get_owning_subd(struct peer *peer); diff --git a/lightningd/options.c b/lightningd/options.c index 146fbee7e248..a1f263a0e139 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -697,6 +697,10 @@ static void dev_register_opts(struct lightningd *ld) opt_register_noarg("--dev-no-obsolete-onion", opt_set_bool, &ld->dev_ignore_obsolete_onion, "Ignore obsolete onion messages"); + opt_register_arg("--dev-disable-commit-after", + opt_set_intval, opt_show_intval, + &ld->dev_disable_commit, + "Disable commit timer after this many commits"); } #endif /* DEVELOPER */ diff --git a/lightningd/pay.c b/lightningd/pay.c index f4db4fc527f5..3b198355c4be 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -536,7 +536,7 @@ void payment_store(struct lightningd *ld, struct wallet_payment *payment TAKES) } void payment_failed(struct lightningd *ld, const struct htlc_out *hout, - const char *localfail, const u8 *failmsg_needs_update) + const char *localfail) { struct wallet_payment *payment; struct routing_failure* fail = NULL; @@ -569,10 +569,7 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout, if (localfail) { /* Use temporary_channel_failure if failmsg has it */ enum onion_wire failcode; - if (failmsg_needs_update) - failcode = fromwire_peektype(failmsg_needs_update); - else - failcode = fromwire_peektype(hout->failmsg); + failcode = fromwire_peektype(hout->failmsg); fail = local_routing_failure(tmpctx, ld, hout, failcode, payment); @@ -782,13 +779,12 @@ static const u8 *send_onion(const tal_t *ctx, struct lightningd *ld, { const u8 *onion; unsigned int base_expiry; - bool dont_care_about_channel_update; + base_expiry = get_block_height(ld->topology) + 1; onion = serialize_onionpacket(tmpctx, packet); return send_htlc_out(ctx, channel, first_hop->amount, base_expiry + first_hop->delay, payment_hash, - blinding, partid, groupid, onion, NULL, hout, - &dont_care_about_channel_update); + blinding, partid, groupid, onion, NULL, hout); } static struct command_result *check_offer_usage(struct command *cmd, diff --git a/lightningd/pay.h b/lightningd/pay.h index 1aace68bbc99..7c933877418d 100644 --- a/lightningd/pay.h +++ b/lightningd/pay.h @@ -15,10 +15,9 @@ struct routing_failure; void payment_succeeded(struct lightningd *ld, struct htlc_out *hout, const struct preimage *rval); -/* failmsg_needs_update is if we actually wanted to temporary_channel_failure - * but we haven't got the update msg yet */ +/* hout->failmsg or hout->failonion must be set. */ void payment_failed(struct lightningd *ld, const struct htlc_out *hout, - const char *localfail, const u8 *failmsg_needs_update); + const char *localfail); /* Inform payment system to save the payment. */ void payment_store(struct lightningd *ld, struct wallet_payment *payment); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 415b4d69f467..40a2b4c38b6a 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -65,7 +64,6 @@ #include #include #include -#include #include #include @@ -281,7 +279,7 @@ void drop_to_chain(struct lightningd *ld, struct channel *channel, } void channel_errmsg(struct channel *channel, - struct per_peer_state *pps, + int peer_fd, const struct channel_id *channel_id UNUSED, const char *desc, bool warning, @@ -299,8 +297,8 @@ void channel_errmsg(struct channel *channel, return; } - /* No per_peer_state means a subd crash or disconnection. */ - if (!pps) { + /* No peer_fd means a subd crash or disconnection. */ + if (peer_fd < 0) { /* If the channel is unsaved, we forget it */ channel_fail_reconnect(channel, "%s: %s", channel->owner->name, desc); @@ -931,7 +929,7 @@ struct peer_connected_hook_payload { struct wireaddr_internal addr; bool incoming; struct peer *peer; - struct per_peer_state *pps; + int peer_fd; u8 *error; }; @@ -1011,7 +1009,9 @@ 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_restart_dualopend(peer, payload->pps, channel); + peer_restart_dualopend(peer, + payload->peer_fd, + channel); return; case CHANNELD_AWAITING_LOCKIN: case CHANNELD_NORMAL: @@ -1020,7 +1020,9 @@ 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->pps, NULL, true, + peer_start_channeld(channel, + payload->peer_fd, + NULL, true, NULL); return; } @@ -1039,11 +1041,13 @@ static void peer_connected_hook_final(struct peer_connected_hook_payload *payloa || channel->state == AWAITING_UNILATERAL); channel->peer->addr = addr; channel->peer->connected_incoming = payload->incoming; - peer_restart_dualopend(peer, payload->pps, channel); + peer_restart_dualopend(peer, + payload->peer_fd, + channel); } else - peer_start_dualopend(peer, payload->pps); + peer_start_dualopend(peer, payload->peer_fd); } else - peer_start_openingd(peer, payload->pps); + peer_start_openingd(peer, payload->peer_fd); return; send_error: @@ -1052,15 +1056,8 @@ static void peer_connected_hook_final(struct peer_connected_hook_payload *payloa /* Get connectd to send error and close. */ subd_send_msg(ld->connectd, take(towire_connectd_peer_final_msg(NULL, &peer->id, - payload->pps, error))); - subd_send_fd(ld->connectd, payload->pps->peer_fd); - subd_send_fd(ld->connectd, payload->pps->gossip_fd); - subd_send_fd(ld->connectd, payload->pps->gossip_store_fd); - /* Don't close those fds! */ - payload->pps->peer_fd - = payload->pps->gossip_fd - = payload->pps->gossip_store_fd - = -1; + error))); + close(payload->peer_fd); } static bool @@ -1116,8 +1113,7 @@ REGISTER_PLUGIN_HOOK(peer_connected, /* 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, int gossip_fd, int gossip_store_fd) +void peer_connected(struct lightningd *ld, const u8 *msg, int peer_fd) { struct node_id id; u8 *their_features; @@ -1130,13 +1126,11 @@ void peer_connected(struct lightningd *ld, const u8 *msg, if (!fromwire_connectd_peer_connected(hook_payload, msg, &id, &hook_payload->addr, &hook_payload->incoming, - &hook_payload->pps, &their_features)) fatal("Connectd gave bad CONNECT_PEER_CONNECTED message %s", tal_hex(msg, msg)); - per_peer_state_set_fds(hook_payload->pps, - peer_fd, gossip_fd, gossip_store_fd); + hook_payload->peer_fd = peer_fd; /* If we're already dealing with this peer, hand off to correct * subdaemon. Otherwise, we'll hand to openingd to wait there. */ @@ -1532,7 +1526,6 @@ command_find_channel(struct command *cmd, static void activate_peer(struct peer *peer, u32 delay) { - u8 *msg; struct channel *channel; struct channel_inflight *inflight; struct lightningd *ld = peer->ld; @@ -1540,28 +1533,8 @@ static void activate_peer(struct peer *peer, u32 delay) /* We can only have one active channel: make sure connectd * knows to try reconnecting. */ channel = peer_active_channel(peer); - if (channel && ld->reconnect) { - if (delay > 0) { - channel_set_billboard(channel, false, - tal_fmt(tmpctx, - "Will attempt reconnect " - "in %u seconds", - delay)); - delay_then_reconnect(channel, delay, - peer->connected_incoming - ? NULL - : &peer->addr); - } else { - msg = towire_connectd_connect_to_peer(NULL, - &peer->id, 0, - peer->connected_incoming - ? NULL - : &peer->addr); - subd_send_msg(ld->connectd, take(msg)); - channel_set_billboard(channel, false, - "Attempting to reconnect"); - } - } + if (channel) + try_reconnect(channel, delay, &peer->addr); list_for_each(&peer->channels, channel, list) { if (channel_unsaved(channel)) @@ -2429,167 +2402,4 @@ void peer_dev_memleak(struct command *cmd) { peer_memleak_req_next(cmd, NULL); } - #endif /* DEVELOPER */ - -struct custommsg_payload { - struct node_id peer_id; - const u8 *msg; -}; - -static bool custommsg_cb(struct custommsg_payload *payload, - const char *buffer, const jsmntok_t *toks) -{ - const jsmntok_t *t_res; - - if (!toks || !buffer) - return true; - - t_res = json_get_member(buffer, toks, "result"); - - /* fail */ - if (!t_res || !json_tok_streq(buffer, t_res, "continue")) - fatal("Plugin returned an invalid response to the " - "custommsg hook: %s", buffer); - - /* call next hook */ - return true; -} - -static void custommsg_final(struct custommsg_payload *payload STEALS) -{ - tal_steal(tmpctx, payload); -} - -static void custommsg_payload_serialize(struct custommsg_payload *payload, - struct json_stream *stream, - struct plugin *plugin) -{ - json_add_hex_talarr(stream, "payload", payload->msg); - json_add_node_id(stream, "peer_id", &payload->peer_id); -} - -REGISTER_PLUGIN_HOOK(custommsg, - custommsg_cb, - custommsg_final, - custommsg_payload_serialize, - struct custommsg_payload *); - -void handle_custommsg_in(struct lightningd *ld, const struct node_id *peer_id, - const u8 *msg) -{ - struct custommsg_payload *p = tal(NULL, struct custommsg_payload); - u8 *custommsg; - - if (!fromwire_custommsg_in(NULL, msg, &custommsg)) { - log_broken(ld->log, "Malformed custommsg from peer %s: %s", - type_to_string(tmpctx, struct node_id, peer_id), - tal_hex(tmpctx, msg)); - return; - } - - p->peer_id = *peer_id; - p->msg = tal_steal(p, custommsg); - plugin_hook_call_custommsg(ld, p); -} - -static struct command_result *json_sendcustommsg(struct command *cmd, - const char *buffer, - const jsmntok_t *obj UNNEEDED, - const jsmntok_t *params) -{ - struct json_stream *response; - struct node_id *dest; - struct peer *peer; - struct subd *owner; - u8 *msg; - int type; - - if (!param(cmd, buffer, params, - p_req("node_id", param_node_id, &dest), - p_req("msg", param_bin_from_hex, &msg), - NULL)) - return command_param_failed(); - - type = fromwire_peektype(msg); - if (peer_wire_is_defined(type)) { - return command_fail( - cmd, JSONRPC2_INVALID_REQUEST, - "Cannot send messages of type %d (%s). It is not possible " - "to send messages that have a type managed internally " - "since that might cause issues with the internal state " - "tracking.", - type, peer_wire_name(type)); - } - - if (type % 2 == 0) { - return command_fail( - cmd, JSONRPC2_INVALID_REQUEST, - "Cannot send even-typed %d custom message. Currently " - "custom messages are limited to odd-numbered message " - "types, as even-numbered types might result in " - "disconnections.", - type); - } - - peer = peer_by_id(cmd->ld, dest); - if (!peer) { - return command_fail(cmd, JSONRPC2_INVALID_REQUEST, - "No such peer: %s", - type_to_string(cmd, struct node_id, dest)); - } - - owner = peer_get_owning_subd(peer); - if (owner == NULL) { - return command_fail(cmd, JSONRPC2_INVALID_REQUEST, - "Peer is not connected: %s", - type_to_string(cmd, struct node_id, dest)); - } - - /* Only a couple of subdaemons have the ability to send custom - * messages. We whitelist those, and error if the current owner is not - * in the whitelist. The reason is that some subdaemons do not handle - * spontaneous messages from the master well (I'm looking at you - * `closingd`...). */ - if (!streq(owner->name, "channeld") && - !streq(owner->name, "openingd")) { - return command_fail(cmd, JSONRPC2_INVALID_REQUEST, - "Peer is currently owned by %s which does " - "not support injecting custom messages.", - owner->name); - } - - subd_send_msg(owner, take(towire_custommsg_out(cmd, msg))); - - response = json_stream_success(cmd); - json_add_string(response, "status", - tal_fmt(cmd, - "Message sent to subdaemon %s for delivery", - owner->name)); - - return command_success(cmd, response); -} - -static const struct json_command sendcustommsg_command = { - "sendcustommsg", - "utility", - json_sendcustommsg, - "Send a custom message to the peer with the given {node_id}", - .verbose = "sendcustommsg node_id hexcustommsg", -}; - -AUTODATA(json_command, &sendcustommsg_command); - -#ifdef COMPAT_V0100 -#ifdef DEVELOPER -static const struct json_command dev_sendcustommsg_command = { - "dev-sendcustommsg", - "utility", - json_sendcustommsg, - "Send a custom message to the peer with the given {node_id}", - .verbose = "dev-sendcustommsg node_id hexcustommsg", -}; - -AUTODATA(json_command, &dev_sendcustommsg_command); -#endif /* DEVELOPER */ -#endif /* COMPAT_V0100 */ diff --git a/lightningd/peer_control.h b/lightningd/peer_control.h index 97d96753bad6..57dfd3824a68 100644 --- a/lightningd/peer_control.h +++ b/lightningd/peer_control.h @@ -11,7 +11,6 @@ #include #include -struct per_peer_state; struct wally_psbt; struct peer { @@ -64,14 +63,13 @@ 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, int gossip_fd, int gossip_store_fd); +void peer_connected(struct lightningd *ld, const u8 *msg, int peer_fd); /* Could be configurable. */ #define OUR_CHANNEL_FLAGS CHANNEL_FLAGS_ANNOUNCE_CHANNEL void channel_errmsg(struct channel *channel, - struct per_peer_state *pps, + int peer_fd, const struct channel_id *channel_id, const char *desc, bool warning, @@ -98,9 +96,6 @@ struct htlc_in_map *load_channels_from_wallet(struct lightningd *ld); void peer_dev_memleak(struct command *cmd); #endif /* DEVELOPER */ -void handle_custommsg_in(struct lightningd *ld, const struct node_id *peer_id, - const u8 *msg); - /* Triggered at each new block. */ void waitblockheight_notify_new_block(struct lightningd *ld, u32 block_height); diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 5914deb25829..babb126745c8 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -138,58 +138,6 @@ static void tell_channeld_htlc_failed(const struct htlc_in *hin, take(towire_channeld_fail_htlc(NULL, failed_htlc))); } -struct failmsg_update_cbdata { - struct htlc_in *hin; - const u8 *failmsg_needs_update; -}; - -static void failmsg_update_reply(struct subd *gossipd, - const u8 *msg, - const int *unused, - struct failmsg_update_cbdata *cbdata) -{ - u8 *failmsg; - u8 *stripped_update; - struct failed_htlc *failed_htlc; - - /* This can happen because channel never got properly announced.*/ - if (!fromwire_gossipd_get_stripped_cupdate_reply(msg, msg, - &stripped_update) - || !tal_count(stripped_update)) { - failmsg = towire_temporary_node_failure(NULL); - } else { - /* End of failmsg is two zero bytes (empty update). */ - assert(tal_count(cbdata->failmsg_needs_update) >= 2); - failmsg = tal_dup_arr(msg, u8, - cbdata->failmsg_needs_update, - tal_count(cbdata->failmsg_needs_update)-2, - 0); - towire_u16(&failmsg, tal_count(stripped_update)); - towire_u8_array(&failmsg, - stripped_update, tal_count(stripped_update)); - } - - /* Now we replace dummy failonion with this real one */ - tal_free(cbdata->hin->failonion); - cbdata->hin->failonion - = create_onionreply(cbdata->hin, - cbdata->hin->shared_secret, - failmsg); - - bool we_filled = false; - wallet_htlc_update(gossipd->ld->wallet, - cbdata->hin->dbid, cbdata->hin->hstate, - cbdata->hin->preimage, - max_unsigned(cbdata->hin->key.channel->next_index[LOCAL], - cbdata->hin->key.channel->next_index[REMOTE]), - cbdata->hin->badonion, - cbdata->hin->failonion, NULL, &we_filled); - - failed_htlc = mk_failed_htlc(tmpctx, - cbdata->hin, cbdata->hin->failonion); - tell_channeld_htlc_failed(cbdata->hin, failed_htlc); -} - static void fail_in_htlc(struct htlc_in *hin, const struct onionreply *failonion TAKES) { @@ -211,6 +159,15 @@ static void fail_in_htlc(struct htlc_in *hin, #endif failed_htlc = mk_failed_htlc(tmpctx, hin, hin->failonion); + bool we_filled = false; + wallet_htlc_update(hin->key.channel->peer->ld->wallet, + hin->dbid, hin->hstate, + hin->preimage, + max_unsigned(hin->key.channel->next_index[LOCAL], + hin->key.channel->next_index[REMOTE]), + hin->badonion, + hin->failonion, NULL, &we_filled); + tell_channeld_htlc_failed(hin, failed_htlc); } @@ -244,34 +201,6 @@ void local_fail_in_htlc(struct htlc_in *hin, const u8 *failmsg TAKES) fail_in_htlc(hin, take(failonion)); } -/* This is used for cases where we can immediately fail the HTLC, but - * need to append a channel_update. */ -void local_fail_in_htlc_needs_update(struct htlc_in *hin, - const u8 *failmsg_needs_update TAKES, - const struct short_channel_id *failmsg_scid) -{ - struct failmsg_update_cbdata *cbdata; - - /* To avoid the state where we have no failonion, we use a temporary - * one, and update once we get the reply from gossipd. */ - assert(!hin->preimage); - - hin->failonion = create_onionreply(hin, - hin->shared_secret, - towire_temporary_node_failure(tmpctx)); - /* We update state now to signal it's in progress, for persistence. */ - htlc_in_update_state(hin->key.channel, hin, SENT_REMOVE_HTLC); - htlc_in_check(hin, __func__); - - cbdata = tal(hin, struct failmsg_update_cbdata); - cbdata->hin = hin; - cbdata->failmsg_needs_update - = tal_dup_talarr(cbdata, u8, failmsg_needs_update); - subd_req(cbdata, hin->key.channel->peer->ld->gossip, - take(towire_gossipd_get_stripped_cupdate(NULL, failmsg_scid)), - -1, 0, failmsg_update_reply, cbdata); -} - /* Helper to create (common) WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS */ const u8 *failmsg_incorrect_or_unknown_(const tal_t *ctx, struct lightningd *ld, @@ -286,39 +215,27 @@ const u8 *failmsg_incorrect_or_unknown_(const tal_t *ctx, } /* localfail are for handing to the local payer if it's local. */ -static void fail_out_htlc(struct htlc_out *hout, - const char *localfail, - const u8 *failmsg_needs_update TAKES) +static void fail_out_htlc(struct htlc_out *hout, const char *localfail) { htlc_out_check(hout, __func__); assert(hout->failmsg || hout->failonion); if (hout->am_origin) { - payment_failed(hout->key.channel->peer->ld, hout, localfail, - failmsg_needs_update); - if (taken(failmsg_needs_update)) - tal_free(failmsg_needs_update); + payment_failed(hout->key.channel->peer->ld, hout, localfail); } else if (hout->in) { - if (failmsg_needs_update) { - local_fail_in_htlc_needs_update(hout->in, - failmsg_needs_update, - hout->key.channel->scid); - } else { - const struct onionreply *failonion; + const struct onionreply *failonion; - /* If we have an onion, simply copy it. */ - if (hout->failonion) - failonion = hout->failonion; - /* Otherwise, we need to onionize this local error. */ - else - failonion = create_onionreply(hout, - hout->in->shared_secret, - hout->failmsg); - fail_in_htlc(hout->in, failonion); - } + /* If we have an onion, simply copy it. */ + if (hout->failonion) + failonion = hout->failonion; + /* Otherwise, we need to onionize this local error. */ + else + failonion = create_onionreply(hout, + hout->in->shared_secret, + hout->failmsg); + fail_in_htlc(hout->in, failonion); } else { - if (taken(failmsg_needs_update)) - tal_free(failmsg_needs_update); + log_broken(hout->key.channel->log, "Neither origin nor in?"); } } @@ -530,8 +447,8 @@ static void destroy_hout_subd_died(struct htlc_out *hout) "Failing HTLC %"PRIu64" due to peer death", hout->key.id); - /* This isn't really used, except as sanity check */ - hout->failmsg = towire_temporary_node_failure(hout); + hout->failmsg = towire_temporary_channel_failure(hout, + get_channel_update(hout->key.channel)); /* Assign a temporary state (we're about to free it!) so checks * are happy that it has a failure message */ @@ -541,8 +458,7 @@ static void destroy_hout_subd_died(struct htlc_out *hout) if (!have_tx) db_begin_transaction(db); - fail_out_htlc(hout, "Outgoing subdaemon died", - take(towire_temporary_channel_failure(NULL, NULL))); + fail_out_htlc(hout, "Outgoing subdaemon died"); if (!have_tx) db_commit_transaction(db); @@ -573,7 +489,7 @@ static void rcvd_htlc_reply(struct subd *subd, const u8 *msg, const int *fds UNU char *localfail = tal_fmt(msg, "%s: %s", onion_wire_name(fromwire_peektype(failmsg)), failurestr); - payment_failed(ld, hout, localfail, NULL); + payment_failed(ld, hout, localfail); } else if (hout->in) { struct onionreply *failonion; @@ -644,13 +560,11 @@ const u8 *send_htlc_out(const tal_t *ctx, u64 groupid, const u8 *onion_routing_packet, struct htlc_in *in, - struct htlc_out **houtp, - bool *needs_update_appended) + struct htlc_out **houtp) { u8 *msg; *houtp = NULL; - *needs_update_appended = false; if (!channel_can_add_htlc(out)) { log_info(out->log, "Attempt to send HTLC but not ready (%s)", @@ -661,8 +575,8 @@ const u8 *send_htlc_out(const tal_t *ctx, if (!out->owner) { log_info(out->log, "Attempt to send HTLC but unowned (%s)", channel_state_name(out)); - *needs_update_appended = true; - return towire_temporary_channel_failure(ctx, NULL); + return towire_temporary_channel_failure(ctx, + get_channel_update(out)); } if (!topology_synced(out->peer->ld->topology)) { @@ -706,7 +620,6 @@ static void forward_htlc(struct htlc_in *hin, struct lightningd *ld = hin->key.channel->peer->ld; struct channel *next = active_channel_by_scid(ld, scid); struct htlc_out *hout = NULL; - bool needs_update_appended; /* Unknown peer, or peer not ready. */ if (!next || !next->scid) { @@ -732,9 +645,8 @@ static void forward_htlc(struct htlc_in *hin, || !check_fwd_amount(hin, amt_to_forward, hin->msat, next->old_feerate_base, next->old_feerate_ppm)) { - needs_update_appended = true; failmsg = towire_fee_insufficient(tmpctx, hin->msat, - NULL); + get_channel_update(next)); goto fail; } log_info(hin->key.channel->log, @@ -743,9 +655,8 @@ static void forward_htlc(struct htlc_in *hin, if (!check_cltv(hin, cltv_expiry, outgoing_cltv_value, ld->config.cltv_expiry_delta)) { - needs_update_appended = true; failmsg = towire_incorrect_cltv_expiry(tmpctx, cltv_expiry, - NULL); + get_channel_update(next)); goto fail; } @@ -763,8 +674,8 @@ static void forward_htlc(struct htlc_in *hin, "Expiry cltv %u too close to current %u", outgoing_cltv_value, get_block_height(ld->topology)); - needs_update_appended = true; - failmsg = towire_expiry_too_soon(tmpctx, NULL); + failmsg = towire_expiry_too_soon(tmpctx, + get_channel_update(next)); goto fail; } @@ -780,7 +691,6 @@ static void forward_htlc(struct htlc_in *hin, outgoing_cltv_value, get_block_height(ld->topology), ld->config.locktime_max); - needs_update_appended = false; failmsg = towire_expiry_too_far(tmpctx); goto fail; } @@ -788,15 +698,12 @@ static void forward_htlc(struct htlc_in *hin, failmsg = send_htlc_out(tmpctx, next, amt_to_forward, outgoing_cltv_value, &hin->payment_hash, next_blinding, 0 /* partid */, 0 /* groupid */, - next_onion, hin, &hout, &needs_update_appended); + next_onion, hin, &hout); if (!failmsg) return; fail: - if (needs_update_appended) - local_fail_in_htlc_needs_update(hin, failmsg, next->scid); - else - local_fail_in_htlc(hin, failmsg); + local_fail_in_htlc(hin, failmsg); wallet_forwarded_payment_add(ld->wallet, hin, next->scid, hout, FORWARD_LOCAL_FAILED, @@ -1494,7 +1401,7 @@ void onchain_failed_our_htlc(const struct channel *channel, char *localfail = tal_fmt(channel, "%s: %s", onion_wire_name(WIRE_PERMANENT_CHANNEL_FAILURE), why); - payment_failed(ld, hout, localfail, NULL); + payment_failed(ld, hout, localfail); tal_free(localfail); } else if (hout->in) { local_fail_in_htlc(hout->in, @@ -1567,7 +1474,7 @@ static void remove_htlc_out(struct channel *channel, struct htlc_out *hout) /* If it's failed, now we can forward since it's completely locked-in */ if (!hout->preimage) { - fail_out_htlc(hout, NULL, NULL); + fail_out_htlc(hout, NULL); } else { const struct channel_coin_mvt *mvt; struct amount_msat oldamt = channel->our_msat; diff --git a/lightningd/peer_htlcs.h b/lightningd/peer_htlcs.h index 50618a7499d1..8c0daf2ab764 100644 --- a/lightningd/peer_htlcs.h +++ b/lightningd/peer_htlcs.h @@ -39,7 +39,7 @@ void peer_got_revoke(struct channel *channel, const u8 *msg); void update_per_commit_point(struct channel *channel, const struct pubkey *per_commitment_point); -/* Returns NULL on success, otherwise failmsg (and sets *needs_update_appended)*/ +/* Returns NULL on success, otherwise failmsg*/ const u8 *send_htlc_out(const tal_t *ctx, struct channel *out, struct amount_msat amount, u32 cltv, @@ -49,8 +49,7 @@ const u8 *send_htlc_out(const tal_t *ctx, u64 groupid, const u8 *onion_routing_packet, struct htlc_in *in, - struct htlc_out **houtp, - bool *needs_update_appended); + struct htlc_out **houtp); void onchain_failed_our_htlc(const struct channel *channel, const struct htlc_stub *htlc, diff --git a/lightningd/ping.c b/lightningd/ping.c index e97351595ae7..144dbe8fac47 100644 --- a/lightningd/ping.c +++ b/lightningd/ping.c @@ -1,83 +1,39 @@ #include "config.h" -#include #include #include #include +#include #include #include #include #include -#include #include -struct ping_command { - struct list_node list; - struct node_id id; - struct command *cmd; -}; - -static struct ping_command *find_ping_cmd(struct lightningd *ld, - const struct node_id *id) -{ - struct ping_command *i; - - list_for_each(&ld->ping_commands, i, list) { - if (node_id_eq(id, &i->id)) - return i; - } - return NULL; -} - -static void destroy_ping_command(struct ping_command *pc) -{ - list_del(&pc->list); -} - -static struct ping_command *new_ping_command(const tal_t *ctx, - struct lightningd *ld, - const struct node_id *peer_id, - struct command *cmd) -{ - struct ping_command *pc = tal(ctx, struct ping_command); - - pc->id = *peer_id; - pc->cmd = cmd; - list_add_tail(&ld->ping_commands, &pc->list); - tal_add_destructor(pc, destroy_ping_command); - - return pc; -} - -void ping_reply(struct subd *channeld, const u8 *msg) +static void ping_reply(struct subd *connectd, + const u8 *msg, const int *fds, + struct command *cmd) { u16 totlen; bool sent; - struct ping_command *pc; - struct channel *c = channeld->channel; - log_debug(channeld->log, "Got ping reply!"); - pc = find_ping_cmd(channeld->ld, &c->peer->id); - if (!pc) { - log_broken(channeld->log, "Unexpected ping reply?"); - return; - } + log_debug(connectd->log, "Got ping reply!"); - if (!fromwire_channeld_ping_reply(msg, &sent, &totlen)) { - log_broken(channeld->log, "Malformed ping reply %s", + if (!fromwire_connectd_ping_reply(msg, &sent, &totlen)) { + log_broken(connectd->log, "Malformed ping reply %s", tal_hex(tmpctx, msg)); - was_pending(command_fail(pc->cmd, LIGHTNINGD, + was_pending(command_fail(cmd, LIGHTNINGD, "Bad reply message")); return; } if (!sent) - was_pending(command_fail(pc->cmd, LIGHTNINGD, + was_pending(command_fail(cmd, LIGHTNINGD, "Ping already pending")); else { - struct json_stream *response = json_stream_success(pc->cmd); + struct json_stream *response = json_stream_success(cmd); json_add_num(response, "totlen", totlen); - was_pending(command_success(pc->cmd, response)); + was_pending(command_success(cmd, response)); } } @@ -88,8 +44,6 @@ static struct command_result *json_ping(struct command *cmd, { unsigned int *len, *pongbytes; struct node_id *id; - struct peer *peer; - struct channel *channel; u8 *msg; if (!param(cmd, buffer, params, @@ -124,19 +78,11 @@ static struct command_result *json_ping(struct command *cmd, "pongbytes %u > 65535", *pongbytes); } - peer = peer_by_id(cmd->ld, id); - if (!peer) + if (!peer_by_id(cmd->ld, id)) return command_fail(cmd, LIGHTNINGD, "Peer not connected"); - channel = peer_active_channel(peer); - if (!channel || !channel->owner || channel->state != CHANNELD_NORMAL) - return command_fail(cmd, LIGHTNINGD, "Peer bad state"); - - /* parent is cmd, so when we complete cmd, we free this. */ - new_ping_command(cmd, cmd->ld, id, cmd); - - msg = towire_channeld_ping(NULL, *pongbytes, *len); - subd_send_msg(channel->owner, take(msg)); + msg = towire_connectd_ping(NULL, id, *pongbytes, *len); + subd_req(cmd, cmd->ld->connectd, take(msg), -1, 0, ping_reply, cmd); return command_still_pending(cmd); } diff --git a/lightningd/ping.h b/lightningd/ping.h deleted file mode 100644 index fec5c90ee242..000000000000 --- a/lightningd/ping.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef LIGHTNING_LIGHTNINGD_PING_H -#define LIGHTNING_LIGHTNINGD_PING_H -#include "config.h" -#include - -struct subd; -void ping_reply(struct subd *subd, const u8 *msg); - -#endif /* LIGHTNING_LIGHTNINGD_PING_H */ diff --git a/lightningd/subd.c b/lightningd/subd.c index ee9d0d79d4b9..37ce776b2ba1 100644 --- a/lightningd/subd.c +++ b/lightningd/subd.c @@ -17,7 +17,6 @@ #include #include #include -#include #include /* Carefully move fd *@from to @to: on success *from set to to */ @@ -188,7 +187,7 @@ static void close_taken_fds(va_list *ap) /* We use sockets, not pipes, because fds are bidir. */ static int subd(const char *path, const char *name, const char *debug_subdaemon, - int *msgfd, int dev_disconnect_fd, + int *msgfd, bool io_logging, va_list *ap) { @@ -212,7 +211,7 @@ static int subd(const char *path, const char *name, if (childpid == 0) { size_t num_args; - char *args[] = { NULL, NULL, NULL, NULL, NULL }; + char *args[] = { NULL, NULL, NULL, NULL }; int **fds = tal_arr(tmpctx, int *, 3); int stdoutfd = STDOUT_FILENO, stderrfd = STDERR_FILENO; @@ -230,10 +229,6 @@ static int subd(const char *path, const char *name, tal_arr_expand(&fds, fd); } - /* If we have a dev_disconnect_fd, add it after. */ - if (dev_disconnect_fd != -1) - tal_arr_expand(&fds, &dev_disconnect_fd); - /* Finally, the fd to report exec errors on */ tal_arr_expand(&fds, &execfail[1]); @@ -241,15 +236,13 @@ static int subd(const char *path, const char *name, goto child_errno_fail; /* Make (fairly!) sure all other fds are closed. */ - closefrom(tal_count(fds) + 1); + closefrom(tal_count(fds)); num_args = 0; args[num_args++] = tal_strdup(NULL, path); if (io_logging) args[num_args++] = "--log-io"; #if DEVELOPER - if (dev_disconnect_fd != -1) - args[num_args++] = tal_fmt(NULL, "--dev-disconnect=%i", dev_disconnect_fd); if (debug_subdaemon && strends(name, debug_subdaemon)) args[num_args++] = "--debugger"; #endif @@ -410,25 +403,24 @@ static bool log_status_fail(struct subd *sd, const u8 *msg) return true; } -static bool handle_peer_error(struct subd *sd, const u8 *msg, int fds[3]) +static bool handle_peer_error(struct subd *sd, const u8 *msg, int fds[1]) { void *channel = sd->channel; struct channel_id channel_id; char *desc; - struct per_peer_state *pps; u8 *err_for_them; bool warning; if (!fromwire_status_peer_error(msg, msg, &channel_id, &desc, &warning, - &pps, &err_for_them)) + &err_for_them)) { + close(fds[0]); return false; - - per_peer_state_set_fds_arr(pps, fds); + } /* Don't free sd; we may be about to free channel. */ sd->channel = NULL; - sd->errcb(channel, pps, &channel_id, desc, warning, err_for_them); + sd->errcb(channel, fds[0], &channel_id, desc, warning, err_for_them); return true; } @@ -529,11 +521,11 @@ static struct io_plan *sd_msg_read(struct io_conn *conn, struct subd *sd) if (sd->channel) { switch ((enum peer_status_wire)type) { case WIRE_STATUS_PEER_ERROR: - /* We expect 3 fds after this */ + /* We expect 1 fd after this */ if (!sd->fds_in) { /* Don't free msg_in: we go around again. */ tal_steal(sd, sd->msg_in); - plan = sd_collect_fds(conn, sd, 3); + plan = sd_collect_fds(conn, sd, 1); goto out; } if (!handle_peer_error(sd, sd->msg_in, sd->fds_in)) @@ -631,7 +623,7 @@ static void destroy_subd(struct subd *sd) if (!outer_transaction) db_begin_transaction(db); if (sd->errcb) - sd->errcb(channel, NULL, NULL, + sd->errcb(channel, -1, NULL, tal_fmt(sd, "Owning subdaemon %s died (%i)", sd->name, status), false, NULL); @@ -687,7 +679,7 @@ static struct subd *new_subd(struct lightningd *ld, unsigned int (*msgcb)(struct subd *, const u8 *, const int *fds), void (*errcb)(void *channel, - struct per_peer_state *pps, + int peer_fd, const struct channel_id *channel_id, const char *desc, bool warning, @@ -700,7 +692,6 @@ static struct subd *new_subd(struct lightningd *ld, struct subd *sd = tal(ld, struct subd); int msg_fd; const char *debug_subd = NULL; - int disconnect_fd = -1; const char *shortname; assert(name != NULL); @@ -720,13 +711,12 @@ static struct subd *new_subd(struct lightningd *ld, #if DEVELOPER debug_subd = ld->dev_debug_subprocess; - disconnect_fd = ld->dev_disconnect_fd; #endif /* DEVELOPER */ const char *path = subdaemon_path(tmpctx, ld, name); sd->pid = subd(path, name, debug_subd, - &msg_fd, disconnect_fd, + &msg_fd, /* We only turn on subdaemon io logging if we're going * to print it: too stressful otherwise! */ log_print_level(sd->log) < LOG_DBG, @@ -799,7 +789,7 @@ struct subd *new_channel_subd_(struct lightningd *ld, unsigned int (*msgcb)(struct subd *, const u8 *, const int *fds), void (*errcb)(void *channel, - struct per_peer_state *pps, + int peer_fd, const struct channel_id *channel_id, const char *desc, bool warning, @@ -823,8 +813,7 @@ void subd_send_msg(struct subd *sd, const u8 *msg_out) u16 type = fromwire_peektype(msg_out); /* FIXME: We should use unique upper bits for each daemon, then * have generate-wire.py add them, just assert here. */ - assert(!strstarts(common_wire_name(type), "INVALID") || - !strstarts(sd->msgname(type), "INVALID")); + assert(!strstarts(sd->msgname(type), "INVALID")); msg_enqueue(sd->outq, msg_out); } @@ -888,7 +877,7 @@ struct subd *subd_shutdown(struct subd *sd, unsigned int seconds) return tal_free(sd); } -void subd_release_channel(struct subd *owner, void *channel) +void subd_release_channel(struct subd *owner, const void *channel) { /* If owner is a per-peer-daemon, and not already freeing itself... */ if (owner->channel) { diff --git a/lightningd/subd.h b/lightningd/subd.h index 94fabf9e3a32..5257a468e3f7 100644 --- a/lightningd/subd.h +++ b/lightningd/subd.h @@ -47,7 +47,7 @@ struct subd { * sufficient information to hand back to gossipd, including the * error message we sent them if any. */ void (*errcb)(void *channel, - struct per_peer_state *pps, + int peer_fd, const struct channel_id *channel_id, const char *desc, bool warning, @@ -124,7 +124,7 @@ struct subd *new_channel_subd_(struct lightningd *ld, unsigned int (*msgcb)(struct subd *, const u8 *, const int *fds), void (*errcb)(void *channel, - struct per_peer_state *pps, + int peer_fd, const struct channel_id *channel_id, const char *desc, bool warning, @@ -141,7 +141,7 @@ struct subd *new_channel_subd_(struct lightningd *ld, (msgname), (msgcb), \ typesafe_cb_postargs(void, void *, (errcb), \ (channel), \ - struct per_peer_state *, \ + int, \ const struct channel_id *, \ const char *, bool, const u8 *), \ typesafe_cb_postargs(void, void *, (billboardcb), \ @@ -197,9 +197,10 @@ void subd_req_(const tal_t *ctx, * @channel: channel to release. * * If the subdaemon is not already shutting down, and it is a per-channel - * subdaemon, this shuts it down. + * subdaemon, this shuts it down. Don't call this directly, use + * channel_set_owner() or uncommitted_channel_release_subd(). */ -void subd_release_channel(struct subd *owner, void *channel); +void subd_release_channel(struct subd *owner, const void *channel); /** * subd_shutdown - try to politely shut down a subdaemon. diff --git a/lightningd/test/run-find_my_abspath.c b/lightningd/test/run-find_my_abspath.c index 24e53c97abad..b0a2469d946a 100644 --- a/lightningd/test/run-find_my_abspath.c +++ b/lightningd/test/run-find_my_abspath.c @@ -76,7 +76,7 @@ void free_htlcs(struct lightningd *ld UNNEEDED, const struct channel *channel UN bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_bigsize called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for fromwire_node_id */ @@ -89,7 +89,7 @@ bool fromwire_status_fail(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, enu bool fromwire_status_peer_billboard(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, bool *perm UNNEEDED, wirestring **happenings UNNEEDED) { fprintf(stderr, "fromwire_status_peer_billboard called!\n"); abort(); } /* Generated stub for fromwire_status_peer_error */ -bool fromwire_status_peer_error(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct channel_id *channel UNNEEDED, wirestring **desc UNNEEDED, bool *warning UNNEEDED, struct per_peer_state **pps UNNEEDED, u8 **error_for_them UNNEEDED) +bool fromwire_status_peer_error(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct channel_id *channel UNNEEDED, wirestring **desc UNNEEDED, bool *warning UNNEEDED, u8 **error_for_them UNNEEDED) { fprintf(stderr, "fromwire_status_peer_error called!\n"); abort(); } /* Generated stub for fromwire_status_version */ bool fromwire_status_version(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, wirestring **version UNNEEDED) @@ -176,9 +176,6 @@ struct chain_topology *new_topology(struct lightningd *ld UNNEEDED, struct log * /* Generated stub for onchaind_replay_channels */ void onchaind_replay_channels(struct lightningd *ld UNNEEDED) { fprintf(stderr, "onchaind_replay_channels called!\n"); abort(); } -/* Generated stub for per_peer_state_set_fds_arr */ -void per_peer_state_set_fds_arr(struct per_peer_state *pps UNNEEDED, const int *fds UNNEEDED) -{ fprintf(stderr, "per_peer_state_set_fds_arr called!\n"); abort(); } /* Generated stub for plugins_config */ void plugins_config(struct plugins *plugins UNNEEDED) { fprintf(stderr, "plugins_config called!\n"); abort(); } diff --git a/lightningd/test/run-invoice-select-inchan.c b/lightningd/test/run-invoice-select-inchan.c index 242b8b689de5..be7cc6a62483 100644 --- a/lightningd/test/run-invoice-select-inchan.c +++ b/lightningd/test/run-invoice-select-inchan.c @@ -94,10 +94,6 @@ void channel_internal_error(struct channel *channel UNNEEDED, const char *fmt UN /* Generated stub for channel_last_funding_feerate */ u32 channel_last_funding_feerate(const struct channel *channel UNNEEDED) { fprintf(stderr, "channel_last_funding_feerate called!\n"); abort(); } -/* Generated stub for channel_set_billboard */ -void channel_set_billboard(struct channel *channel UNNEEDED, bool perm UNNEEDED, - const char *str TAKES UNNEEDED) -{ fprintf(stderr, "channel_set_billboard called!\n"); abort(); } /* Generated stub for channel_set_last_tx */ void channel_set_last_tx(struct channel *channel UNNEEDED, struct bitcoin_tx *tx UNNEEDED, @@ -164,10 +160,6 @@ void db_begin_transaction_(struct db *db UNNEEDED, const char *location UNNEEDED /* Generated stub for db_commit_transaction */ void db_commit_transaction(struct db *db UNNEEDED) { fprintf(stderr, "db_commit_transaction called!\n"); abort(); } -/* Generated stub for delay_then_reconnect */ -void delay_then_reconnect(struct channel *channel UNNEEDED, u32 seconds_delay UNNEEDED, - const struct wireaddr_internal *addrhint TAKES UNNEEDED) -{ fprintf(stderr, "delay_then_reconnect called!\n"); abort(); } /* Generated stub for delete_channel */ void delete_channel(struct channel *channel STEALS UNNEEDED) { fprintf(stderr, "delete_channel called!\n"); abort(); } @@ -203,14 +195,14 @@ void fixup_htlcs_out(struct lightningd *ld UNNEEDED) bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_bigsize called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* 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_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, bool *incoming UNNEEDED, struct per_peer_state **pps UNNEEDED, u8 **features UNNEEDED) +bool fromwire_connectd_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id *id UNNEEDED, struct wireaddr_internal *addr UNNEEDED, bool *incoming UNNEEDED, u8 **features UNNEEDED) { fprintf(stderr, "fromwire_connectd_peer_connected called!\n"); abort(); } /* Generated stub for fromwire_hsmd_sign_bolt12_reply */ bool fromwire_hsmd_sign_bolt12_reply(const void *p UNNEEDED, struct bip340sig *sig UNNEEDED) @@ -488,11 +480,6 @@ struct command_result *param_array(struct command *cmd UNNEEDED, const char *nam const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, const jsmntok_t **arr UNNEEDED) { fprintf(stderr, "param_array called!\n"); abort(); } -/* Generated stub for param_bin_from_hex */ -struct command_result *param_bin_from_hex(struct command *cmd UNNEEDED, const char *name UNNEEDED, - const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, - u8 **bin UNNEEDED) -{ fprintf(stderr, "param_bin_from_hex called!\n"); abort(); } /* Generated stub for param_bool */ struct command_result *param_bool(struct command *cmd UNNEEDED, const char *name UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, @@ -566,9 +553,6 @@ struct command_result *param_u64(struct command *cmd UNNEEDED, const char *name /* Generated stub for peer_active_channel */ struct channel *peer_active_channel(struct peer *peer UNNEEDED) { fprintf(stderr, "peer_active_channel called!\n"); abort(); } -/* Generated stub for peer_get_owning_subd */ -struct subd *peer_get_owning_subd(struct peer *peer UNNEEDED) -{ fprintf(stderr, "peer_get_owning_subd called!\n"); abort(); } /* Generated stub for peer_memleak_done */ void peer_memleak_done(struct command *cmd UNNEEDED, struct subd *leaker UNNEEDED) { fprintf(stderr, "peer_memleak_done called!\n"); abort(); } @@ -577,30 +561,25 @@ struct channel *peer_normal_channel(struct peer *peer UNNEEDED) { fprintf(stderr, "peer_normal_channel called!\n"); abort(); } /* Generated stub for peer_restart_dualopend */ void peer_restart_dualopend(struct peer *peer UNNEEDED, - struct per_peer_state *pps UNNEEDED, + int peer_fd UNNEEDED, struct channel *channel UNNEEDED) { fprintf(stderr, "peer_restart_dualopend called!\n"); abort(); } /* Generated stub for peer_start_channeld */ void peer_start_channeld(struct channel *channel UNNEEDED, - struct per_peer_state *pps UNNEEDED, + int peer_fd UNNEEDED, const u8 *fwd_msg UNNEEDED, bool reconnected 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 per_peer_state *pps UNNEEDED) +void peer_start_dualopend(struct peer *peer UNNEEDED, int peer_fd UNNEEDED) { fprintf(stderr, "peer_start_dualopend called!\n"); abort(); } /* Generated stub for peer_start_openingd */ -void peer_start_openingd(struct peer *peer UNNEEDED, - struct per_peer_state *pps UNNEEDED) +void peer_start_openingd(struct peer *peer UNNEEDED, int peer_fd UNNEEDED) { fprintf(stderr, "peer_start_openingd called!\n"); abort(); } /* Generated stub for peer_unsaved_channel */ struct channel *peer_unsaved_channel(struct peer *peer UNNEEDED) { fprintf(stderr, "peer_unsaved_channel called!\n"); abort(); } -/* Generated stub for per_peer_state_set_fds */ -void per_peer_state_set_fds(struct per_peer_state *pps UNNEEDED, - int peer_fd UNNEEDED, int gossip_fd UNNEEDED, int gossip_store_fd UNNEEDED) -{ fprintf(stderr, "per_peer_state_set_fds called!\n"); abort(); } /* Generated stub for plugin_hook_call_ */ bool plugin_hook_call_(struct lightningd *ld UNNEEDED, const struct plugin_hook *hook UNNEEDED, tal_t *cb_arg STEALS UNNEEDED) @@ -642,11 +621,8 @@ u8 *towire_channeld_dev_reenable_commit(const tal_t *ctx UNNEEDED) /* Generated stub for towire_channeld_specific_feerates */ u8 *towire_channeld_specific_feerates(const tal_t *ctx UNNEEDED, u32 feerate_base UNNEEDED, u32 feerate_ppm UNNEEDED) { fprintf(stderr, "towire_channeld_specific_feerates called!\n"); abort(); } -/* Generated stub for towire_connectd_connect_to_peer */ -u8 *towire_connectd_connect_to_peer(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED, u32 seconds_waited UNNEEDED, const struct wireaddr_internal *addrhint UNNEEDED) -{ fprintf(stderr, "towire_connectd_connect_to_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 struct per_peer_state *pps UNNEEDED, const u8 *msg UNNEEDED) +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_errorfmt */ u8 *towire_errorfmt(const tal_t *ctx UNNEEDED, @@ -673,6 +649,10 @@ u8 *towire_warningfmt(const tal_t *ctx UNNEEDED, const struct channel_id *channel UNNEEDED, const char *fmt UNNEEDED, ...) { fprintf(stderr, "towire_warningfmt called!\n"); abort(); } +/* Generated stub for try_reconnect */ +void try_reconnect(struct channel *channel UNNEEDED, u32 seconds_delay UNNEEDED, + const struct wireaddr_internal *addrhint TAKES UNNEEDED) +{ fprintf(stderr, "try_reconnect called!\n"); abort(); } /* Generated stub for version */ const char *version(void) { fprintf(stderr, "version called!\n"); abort(); } diff --git a/lightningd/test/run-jsonrpc.c b/lightningd/test/run-jsonrpc.c index 1479612d1138..01806dadf442 100644 --- a/lightningd/test/run-jsonrpc.c +++ b/lightningd/test/run-jsonrpc.c @@ -22,7 +22,7 @@ const char *feerate_name(enum feerate feerate UNNEEDED) bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_bigsize called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for fromwire_node_id */ diff --git a/lightningd/test/run-log-pruning.c b/lightningd/test/run-log-pruning.c index 6bda5f337c18..3db0a81dc676 100644 --- a/lightningd/test/run-log-pruning.c +++ b/lightningd/test/run-log-pruning.c @@ -21,7 +21,7 @@ struct command_result *command_success(struct command *cmd UNNEEDED, bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_bigsize called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for fromwire_node_id */ diff --git a/lightningd/test/run-shuffle_fds.c b/lightningd/test/run-shuffle_fds.c index 7f9a3806036c..651f49b6484f 100644 --- a/lightningd/test/run-shuffle_fds.c +++ b/lightningd/test/run-shuffle_fds.c @@ -57,7 +57,7 @@ void fatal(const char *fmt UNNEEDED, ...) bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_bigsize called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for fromwire_node_id */ @@ -70,7 +70,7 @@ bool fromwire_status_fail(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, enu bool fromwire_status_peer_billboard(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, bool *perm UNNEEDED, wirestring **happenings UNNEEDED) { fprintf(stderr, "fromwire_status_peer_billboard called!\n"); abort(); } /* Generated stub for fromwire_status_peer_error */ -bool fromwire_status_peer_error(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct channel_id *channel UNNEEDED, wirestring **desc UNNEEDED, bool *warning UNNEEDED, struct per_peer_state **pps UNNEEDED, u8 **error_for_them UNNEEDED) +bool fromwire_status_peer_error(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct channel_id *channel UNNEEDED, wirestring **desc UNNEEDED, bool *warning UNNEEDED, u8 **error_for_them UNNEEDED) { fprintf(stderr, "fromwire_status_peer_error called!\n"); abort(); } /* Generated stub for fromwire_status_version */ bool fromwire_status_version(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, wirestring **version UNNEEDED) @@ -108,9 +108,6 @@ struct log *new_log(const tal_t *ctx UNNEEDED, struct log_book *record UNNEEDED, const struct node_id *default_node_id UNNEEDED, const char *fmt UNNEEDED, ...) { fprintf(stderr, "new_log called!\n"); abort(); } -/* Generated stub for per_peer_state_set_fds_arr */ -void per_peer_state_set_fds_arr(struct per_peer_state *pps UNNEEDED, const int *fds UNNEEDED) -{ fprintf(stderr, "per_peer_state_set_fds_arr called!\n"); abort(); } /* Generated stub for subdaemon_path */ const char *subdaemon_path(const tal_t *ctx UNNEEDED, const struct lightningd *ld UNNEEDED, const char *name UNNEEDED) { fprintf(stderr, "subdaemon_path called!\n"); abort(); } diff --git a/onchaind/Makefile b/onchaind/Makefile index a57e2bcf9ca2..1da287a5635b 100644 --- a/onchaind/Makefile +++ b/onchaind/Makefile @@ -41,7 +41,6 @@ ONCHAIND_COMMON_OBJS := \ common/daemon.o \ common/daemon_conn.o \ common/derive_basepoints.o \ - common/dev_disconnect.o \ common/status_wiregen.o \ common/htlc_tx.o \ common/htlc_wire.o \ diff --git a/openingd/Makefile b/openingd/Makefile index 091f51ca1790..608268399655 100644 --- a/openingd/Makefile +++ b/openingd/Makefile @@ -41,17 +41,12 @@ OPENINGD_COMMON_OBJS := \ common/channel_config.o \ common/channel_id.o \ common/channel_type.o \ - common/crypto_state.o \ - common/crypto_sync.o \ common/cryptomsg.o \ common/daemon.o \ common/daemon_conn.o \ common/derive_basepoints.o \ - common/dev_disconnect.o \ common/features.o \ common/fee_states.o \ - common/status_wiregen.o \ - common/peer_status_wiregen.o \ common/gossip_rcvd_filter.o \ common/gossip_store.o \ common/htlc_state.o \ @@ -65,10 +60,12 @@ OPENINGD_COMMON_OBJS := \ common/msg_queue.o \ common/node_id.o \ common/onionreply.o \ - common/penalty_base.o \ - common/per_peer_state.o \ common/peer_billboard.o \ common/peer_failed.o \ + common/peer_io.o \ + common/peer_status_wiregen.o \ + common/penalty_base.o \ + common/per_peer_state.o \ common/permute_tx.o \ common/ping.o \ common/psbt_internal.o \ @@ -79,6 +76,7 @@ OPENINGD_COMMON_OBJS := \ common/shutdown_scriptpubkey.o \ common/status.o \ common/status_wire.o \ + common/status_wiregen.o \ common/subdaemon.o \ common/type_to_string.o \ common/utils.o \ diff --git a/openingd/dualopend.c b/openingd/dualopend.c index 7711f6224da2..8134bd0e2de9 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -28,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -41,12 +42,11 @@ #include #include #include -#include #include -/* stdin == lightningd, 3 == peer, 4 == gossipd, 5 = gossip_store, 6 = hsmd */ +/* stdin == lightningd, 3 == peer, 4 = hsmd */ #define REQ_FD STDIN_FILENO -#define HSM_FD 6 +#define HSM_FD 4 /* tx_add_input, tx_add_output, tx_rm_input, tx_rm_output */ #define NUM_TX_MSGS (TX_RM_OUTPUT + 1) @@ -293,7 +293,7 @@ static u8 *psbt_changeset_get_next(const tal_t *ctx, static void shutdown(struct state *state) { - u8 *msg = towire_dualopend_shutdown_complete(state, state->pps); + u8 *msg = towire_dualopend_shutdown_complete(state); wire_sync_write(REQ_FD, msg); per_peer_state_fdpass_send(REQ_FD, state->pps); @@ -392,7 +392,7 @@ static void send_shutdown(struct state *state, const u8 *final_scriptpubkey) /* FIXME: send wrong_funding */ msg = towire_shutdown(NULL, &state->channel_id, final_scriptpubkey, NULL); - sync_crypto_write(state->pps, take(msg)); + peer_write(state->pps, take(msg)); state->shutdown_sent[LOCAL] = true; } @@ -890,17 +890,6 @@ static void dualopend_dev_memleak(struct state *state) } #endif /* DEVELOPER */ -/* We were told to send a custommsg to the peer by `lightningd`. All the - * verification is done on the side of `lightningd` so we should be good to - * just forward it here. */ -static void dualopend_send_custommsg(struct state *state, const u8 *msg) -{ - u8 *inner; - if (!fromwire_custommsg_out(tmpctx, msg, &inner)) - master_badmsg(WIRE_CUSTOMMSG_OUT, msg); - sync_crypto_write(state->pps, take(inner)); -} - static u8 *psbt_to_tx_sigs_msg(const tal_t *ctx, struct state *state, const struct wally_psbt *psbt) @@ -1037,7 +1026,7 @@ static void handle_send_tx_sigs(struct state *state, const u8 *msg) /* Send our sigs to peer */ msg = psbt_to_tx_sigs_msg(tmpctx, state, tx_state->psbt); - sync_crypto_write(state->pps, take(msg)); + peer_write(state->pps, take(msg)); /* Notify lightningd that we've sent sigs */ wire_sync_write(REQ_FD, take(towire_dualopend_tx_sigs_sent(NULL))); @@ -1109,7 +1098,7 @@ static bool send_next(struct state *state, } sendmsg: - sync_crypto_write(state->pps, msg); + peer_write(state->pps, msg); return !finished; } @@ -1156,7 +1145,7 @@ static u8 *handle_funding_locked(struct state *state, u8 *msg) billboard_update(state); if (state->funding_locked[LOCAL]) - return towire_dualopend_channel_locked(state, state->pps); + return towire_dualopend_channel_locked(state); return NULL; } @@ -1169,7 +1158,6 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state) * form, but we use it in a very limited way. */ for (;;) { u8 *msg; - bool from_gossipd; char *err; bool warning; struct channel_id actual; @@ -1180,21 +1168,7 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state) clean_tmpctx(); /* This helper routine polls both the peer and gossipd. */ - msg = peer_or_gossip_sync_read(ctx, state->pps, &from_gossipd); - - /* Use standard helper for gossip msgs (forwards, if it's an - * error, exits). */ - if (from_gossipd) { - handle_gossip_msg(state->pps, take(msg)); - continue; - } - - /* Some messages go straight to gossipd. */ - if (is_msg_for_gossipd(msg)) { - gossip_rcvd_filter_add(state->pps->grf, msg); - wire_sync_write(state->pps->gossip_fd, take(msg)); - continue; - } + msg = peer_read(ctx, state->pps); /* BOLT #1: * @@ -1205,10 +1179,6 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state) if (is_unknown_msg_discardable(msg)) continue; - /* Might be a timestamp filter request: handle. */ - if (handle_timestamp_filter(state->pps, msg)) - continue; - /* A helper which decodes an error. */ if (is_peer_error(tmpctx, msg, &state->channel_id, &err, &warning)) { @@ -1242,10 +1212,10 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state) peer_wire_name(fromwire_peektype(msg)), type_to_string(tmpctx, struct channel_id, &actual)); - sync_crypto_write(state->pps, - take(towire_errorfmt(NULL, &actual, - "Multiple channels" - " unsupported"))); + peer_write(state->pps, + take(towire_errorfmt(NULL, &actual, + "Multiple channels" + " unsupported"))); tal_free(msg); continue; } @@ -1971,10 +1941,10 @@ static u8 *accepter_commits(struct state *state, master_badmsg(WIRE_DUALOPEND_SEND_TX_SIGS, msg); /* Send our commitment sigs over now */ - sync_crypto_write(state->pps, - take(towire_commitment_signed(NULL, - &state->channel_id, - &local_sig.s, NULL))); + peer_write(state->pps, + take(towire_commitment_signed(NULL, + &state->channel_id, + &local_sig.s, NULL))); return msg; } @@ -2331,7 +2301,7 @@ static void accepter_start(struct state *state, const u8 *oc2_msg) &state->our_points.revocation, &state->their_points.revocation); - sync_crypto_write(state->pps, msg); + peer_write(state->pps, msg); peer_billboard(false, "channel open: accept sent, waiting for reply"); /* This is unused in this flow. We re-use @@ -2534,7 +2504,7 @@ static u8 *opener_commits(struct state *state, msg = towire_commitment_signed(tmpctx, &state->channel_id, &local_sig.s, NULL); - sync_crypto_write(state->pps, msg); + peer_write(state->pps, msg); peer_billboard(false, "channel open: commitment sent, waiting for reply"); /* Wait for the peer to send us our commitment tx signature */ @@ -2735,7 +2705,7 @@ static void opener_start(struct state *state, u8 *msg) state->channel_flags, open_tlv); - sync_crypto_write(state->pps, take(msg)); + peer_write(state->pps, take(msg)); /* This is usually a very transient state... */ peer_billboard(false, "channel open: offered, waiting for" @@ -3153,7 +3123,7 @@ static void rbf_local_start(struct state *state, u8 *msg) tx_state->tx_locktime, tx_state->feerate_per_kw_funding); - sync_crypto_write(state->pps, take(msg)); + peer_write(state->pps, take(msg)); /* ... since their reply should be immediate. */ msg = opening_negotiate_msg(tmpctx, state); @@ -3362,7 +3332,7 @@ static void rbf_remote_start(struct state *state, const u8 *rbf_msg) state->our_role == TX_INITIATOR ? tx_state->opener_funding : tx_state->accepter_funding); - sync_crypto_write(state->pps, msg); + peer_write(state->pps, msg); peer_billboard(false, "channel rbf: ack sent, waiting for reply"); /* We merge with RBF's we've initiated now */ @@ -3396,12 +3366,44 @@ static void send_funding_locked(struct state *state) msg = towire_funding_locked(NULL, &state->channel_id, &next_local_per_commit); - sync_crypto_write(state->pps, take(msg)); + peer_write(state->pps, take(msg)); state->funding_locked[LOCAL] = true; billboard_update(state); } +/* FIXME: Maybe cache this? */ +static struct amount_sat channel_size(struct state *state) +{ + u32 funding_outnum; + const u8 *funding_wscript = + bitcoin_redeem_2of2(tmpctx, + &state->our_funding_pubkey, + &state->their_funding_pubkey); + + if (!find_txout(state->tx_state->psbt, + scriptpubkey_p2wsh(tmpctx, funding_wscript), + &funding_outnum)) { + open_err_fatal(state, "Cannot fund txout"); + } + + return psbt_output_get_amount(state->tx_state->psbt, funding_outnum); +} + +static void tell_gossipd_new_channel(struct state *state) +{ + u8 *msg; + const u8 *annfeatures = get_agreed_channelfeatures(tmpctx, + state->our_features, + state->their_features); + + /* Tell lightningd about local channel. */ + msg = towire_dualopend_local_private_channel(NULL, + channel_size(state), + annfeatures); + wire_sync_write(REQ_FD, take(msg)); +} + static u8 *handle_funding_depth(struct state *state, u8 *msg) { u32 depth; @@ -3416,52 +3418,16 @@ static u8 *handle_funding_depth(struct state *state, u8 *msg) /* We check this before we arrive here, but for sanity */ assert(state->minimum_depth <= depth); + /* Tell gossipd the new channel exists before we tell peer. */ + tell_gossipd_new_channel(state); + send_funding_locked(state); if (state->funding_locked[REMOTE]) - return towire_dualopend_channel_locked(state, - state->pps); + return towire_dualopend_channel_locked(state); return NULL; } -/*~ If we see the gossip_fd readable, we read a whole message. Sure, we might - * block, but we trust gossipd. */ -static void handle_gossip_in(struct state *state) -{ - u8 *msg = wire_sync_read(NULL, state->pps->gossip_fd); - - if (!msg) - status_failed(STATUS_FAIL_GOSSIP_IO, - "Reading gossip: %s", strerror(errno)); - - handle_gossip_msg(state->pps, take(msg)); -} - -static void try_read_gossip_store(struct state *state) -{ - u8 *msg = gossip_store_next(tmpctx, state->pps); - - if (msg) - sync_crypto_write(state->pps, take(msg)); -} - -/* Try to handle a custommsg Returns true if it was a custom message and has - * been handled, false if the message was not handled. - */ -static bool dualopend_handle_custommsg(const u8 *msg) -{ - enum peer_wire type = fromwire_peektype(msg); - if (type % 2 == 1 && !peer_wire_is_defined(type)) { - /* The message is not part of the messages we know how to - * handle. Assuming this is a custommsg, we just forward it to the - * master. */ - wire_sync_write(REQ_FD, take(towire_custommsg_in(NULL, msg))); - return true; - } else { - return false; - } -} - /* BOLT #2: * * A receiving node: @@ -3552,7 +3518,7 @@ static void do_reconnect_dance(struct state *state) , tlvs #endif ); - sync_crypto_write(state->pps, take(msg)); + peer_write(state->pps, take(msg)); peer_billboard(false, "Sent reestablish, waiting for theirs"); bool soft_error = state->funding_locked[REMOTE] @@ -3563,11 +3529,10 @@ static void do_reconnect_dance(struct state *state) * before we've reestablished channel). */ do { clean_tmpctx(); - msg = sync_crypto_read(tmpctx, state->pps); - } while (dualopend_handle_custommsg(msg) - || handle_peer_gossip_or_error(state->pps, - &state->channel_id, - soft_error, msg)); + msg = peer_read(tmpctx, state->pps); + } while (handle_peer_error(state->pps, + &state->channel_id, + soft_error, msg)); if (!fromwire_channel_reestablish (msg, &cid, @@ -3618,7 +3583,7 @@ static void do_reconnect_dance(struct state *state) if (psbt_side_finalized(tx_state->psbt, state->our_role) && !state->funding_locked[REMOTE]) { msg = psbt_to_tx_sigs_msg(NULL, state, tx_state->psbt); - sync_crypto_write(state->pps, take(msg)); + peer_write(state->pps, take(msg)); } if (state->funding_locked[LOCAL]) { @@ -3682,18 +3647,9 @@ static u8 *handle_master_in(struct state *state) case WIRE_DUALOPEND_FAIL_FALLEN_BEHIND: case WIRE_DUALOPEND_DRY_RUN: case WIRE_DUALOPEND_VALIDATE_LEASE: + case WIRE_DUALOPEND_LOCAL_PRIVATE_CHANNEL: break; } - - /* Now handle common messages. */ - switch ((enum common_wire)t) { - case WIRE_CUSTOMMSG_OUT: - dualopend_send_custommsg(state, msg); - /* We send these. */ - case WIRE_CUSTOMMSG_IN: - break; - } - status_failed(STATUS_FAIL_MASTER_IO, "Unknown msg %s", tal_hex(tmpctx, msg)); } @@ -3703,7 +3659,7 @@ static u8 *handle_master_in(struct state *state) * surprise. */ static u8 *handle_peer_in(struct state *state) { - u8 *msg = sync_crypto_read(tmpctx, state->pps); + u8 *msg = peer_read(tmpctx, state->pps); enum peer_wire t = fromwire_peektype(msg); struct channel_id channel_id; @@ -3771,29 +3727,18 @@ static u8 *handle_peer_in(struct state *state) break; } - /* Handle custommsgs */ - enum peer_wire type = fromwire_peektype(msg); - if (type % 2 == 1 && !peer_wire_is_defined(type)) { - /* The message is not part of the messages we know how to - * handle. Assuming this is a custommsg, we just - * forward it to master. */ - wire_sync_write(REQ_FD, take(towire_custommsg_in(NULL, msg))); + /* Handles errors. */ + if (handle_peer_error(state->pps, &state->channel_id, false, msg)) return NULL; - } - /* Handles standard cases, and legal unknown ones. */ - if (handle_peer_gossip_or_error(state->pps, - &state->channel_id, false, msg)) - return NULL; - - sync_crypto_write(state->pps, - take(towire_warningfmt(NULL, - extract_channel_id(msg, - &channel_id) ? - &channel_id : NULL, - "Unexpected message %s: %s", - peer_wire_name(t), - tal_hex(tmpctx, msg)))); + peer_write(state->pps, + take(towire_warningfmt(NULL, + extract_channel_id(msg, + &channel_id) ? + &channel_id : NULL, + "Unexpected message %s: %s", + peer_wire_name(t), + tal_hex(tmpctx, msg)))); /* FIXME: We don't actually want master to try to send an * error, since peer is transient. This is a hack. @@ -3806,7 +3751,7 @@ int main(int argc, char *argv[]) { common_setup(argv[0]); - struct pollfd pollfd[3]; + struct pollfd pollfd[2]; struct state *state = tal(NULL, struct state); struct secret *none; struct fee_states *fee_states; @@ -3834,7 +3779,6 @@ int main(int argc, char *argv[]) &state->tx_state->localconf, &state->max_to_self_delay, &state->min_effective_htlc_capacity, - &state->pps, &state->our_points, &state->our_funding_pubkey, &state->minimum_depth)) { @@ -3866,7 +3810,6 @@ int main(int argc, char *argv[]) &state->channel_id, &state->max_to_self_delay, &state->min_effective_htlc_capacity, - &state->pps, &state->our_points, &state->our_funding_pubkey, &state->their_funding_pubkey, @@ -3934,8 +3877,9 @@ int main(int argc, char *argv[]) - /* 3 == peer, 4 == gossipd, 5 = gossip_store, 6 = hsmd */ - per_peer_state_set_fds(state->pps, 3, 4, 5); + /* 3 == peer, 4 = hsmd */ + state->pps = new_per_peer_state(state); + per_peer_state_set_fd(state->pps, 3); /*~ We need an initial per-commitment point whether we're funding or * they are, and lightningd has reserved a unique dbid for us already, @@ -3959,10 +3903,8 @@ int main(int argc, char *argv[]) /*~ We manually run a little poll() loop here. With only three fds */ pollfd[0].fd = REQ_FD; pollfd[0].events = POLLIN; - pollfd[1].fd = state->pps->gossip_fd; + pollfd[1].fd = state->pps->peer_fd; pollfd[1].events = POLLIN; - pollfd[2].fd = state->pps->peer_fd; - pollfd[2].events = POLLIN; /* Do reconnect, if need be */ if (state->channel) { @@ -3974,37 +3916,25 @@ int main(int argc, char *argv[]) * opening_funder_reply or opening_fundee. */ msg = NULL; while (!msg) { - int t; - struct timerel trel; - if (time_to_next_gossip(state->pps, &trel)) - t = time_to_msec(trel); - else - t = -1; /*~ If we get a signal which aborts the poll() call, valgrind * complains about revents being uninitialized. I'm not sure * that's correct, but it's easy to be sure. */ - pollfd[0].revents = pollfd[1].revents = pollfd[2].revents = 0; + pollfd[0].revents = pollfd[1].revents = 0; - poll(pollfd, ARRAY_SIZE(pollfd), t); + poll(pollfd, ARRAY_SIZE(pollfd), -1); /* Subtle: handle_master_in can do its own poll loop, so * don't try to service more than one fd per loop. */ /* First priority: messages from lightningd. */ if (pollfd[0].revents & POLLIN) msg = handle_master_in(state); /* Second priority: messages from peer. */ - else if (pollfd[2].revents & POLLIN) - msg = handle_peer_in(state); - /* Last priority: chit-chat from gossipd. */ else if (pollfd[1].revents & POLLIN) - handle_gossip_in(state); - else - try_read_gossip_store(state); + msg = handle_peer_in(state); /* If we've shutdown, we're done */ if (shutdown_complete(state)) - msg = towire_dualopend_shutdown_complete(state, - state->pps); + msg = towire_dualopend_shutdown_complete(state); /* Since we're the top-level event loop, we clean up */ clean_tmpctx(); } diff --git a/openingd/dualopend_wire.csv b/openingd/dualopend_wire.csv index 3b3620c7472f..f7305e6e009c 100644 --- a/openingd/dualopend_wire.csv +++ b/openingd/dualopend_wire.csv @@ -8,7 +8,6 @@ #include #include #include -#include #include #include @@ -23,7 +22,6 @@ msgdata,dualopend_init,our_config,channel_config, # Minimum/maximum configuration values we'll accept msgdata,dualopend_init,max_to_self_delay,u32, msgdata,dualopend_init,min_effective_htlc_capacity_msat,amount_msat, -msgdata,dualopend_init,pps,per_peer_state, msgdata,dualopend_init,our_basepoints,basepoints, msgdata,dualopend_init,our_funding_pubkey,pubkey, # Constraints in case the other end tries to open a channel. @@ -40,7 +38,6 @@ msgdata,dualopend_reinit,their_config,channel_config, msgdata,dualopend_reinit,channel_id,channel_id, msgdata,dualopend_reinit,max_to_self_delay,u32, msgdata,dualopend_reinit,min_effective_htlc_capacity_msat,amount_msat, -msgdata,dualopend_reinit,pps,per_peer_state, msgdata,dualopend_reinit,our_basepoints,basepoints, msgdata,dualopend_reinit,our_funding_pubkey,pubkey, msgdata,dualopend_reinit,their_funding_pubkey,pubkey, @@ -201,7 +198,6 @@ msgdata,dualopend_peer_locked,remote_per_commit,pubkey, # dualopend->master this channel has been locked msgtype,dualopend_channel_locked,7019 -msgdata,dualopend_channel_locked,pps,per_peer_state, # master->dualopend funding reached depth; tell peer msgtype,dualopend_depth_reached,7020 @@ -222,7 +218,6 @@ msgtype,dualopend_fail_fallen_behind,1028 # Shutdown is complete, ready for closing negotiation. + peer_fd & gossip_fd. msgtype,dualopend_shutdown_complete,7025 -msgdata,dualopend_shutdown_complete,per_peer_state,per_peer_state, # dualopend -> master: this was a dry run, here's some info about this open msgtype,dualopend_dry_run,7026 @@ -242,3 +237,9 @@ msgdata,dualopend_validate_lease,their_pubkey,pubkey, msgtype,dualopend_validate_lease_reply,7127 msgdata,dualopend_validate_lease_reply,err_msg,?wirestring, + +# Tell gossipd about this (as-yet) unannounced channel +msgtype,dualopend_local_private_channel,7015 +msgdata,dualopend_local_private_channel,capacity,amount_sat, +msgdata,dualopend_local_private_channel,len,u16, +msgdata,dualopend_local_private_channel,features,u8,len diff --git a/openingd/openingd.c b/openingd/openingd.c index 54f4be8462d9..964bfc5f0d72 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -21,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -31,13 +32,12 @@ #include #include #include -#include #include #include -/* stdin == lightningd, 3 == peer, 4 == gossipd, 5 = gossip_store, 6 = hsmd */ +/* stdin == lightningd, 3 == peer, 4 = hsmd */ #define REQ_FD STDIN_FILENO -#define HSM_FD 6 +#define HSM_FD 4 #if DEVELOPER /* If --dev-force-tmp-channel-id is set, it ends up here */ @@ -150,7 +150,7 @@ static void negotiation_failed(struct state *state, bool am_opener, msg = towire_errorfmt(NULL, &state->channel_id, "You gave bad parameters: %s", errmsg); - sync_crypto_write(state->pps, take(msg)); + peer_write(state->pps, take(msg)); negotiation_aborted(state, am_opener, errmsg); } @@ -177,13 +177,13 @@ static void set_reserve(struct state *state, const struct amount_sat dust_limit) /*~ Handle random messages we might get during opening negotiation, (eg. gossip) * returning the first non-handled one, or NULL if we aborted negotiation. */ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state, - bool am_opener) + bool am_opener, + const struct channel_id *alternate) { /* This is an event loop of its own. That's generally considered poor * form, but we use it in a very limited way. */ for (;;) { u8 *msg; - bool from_gossipd; char *err; bool warning; struct channel_id actual; @@ -193,21 +193,7 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state, clean_tmpctx(); /* This helper routine polls both the peer and gossipd. */ - msg = peer_or_gossip_sync_read(ctx, state->pps, &from_gossipd); - - /* Use standard helper for gossip msgs (forwards, if it's an - * error, exits). */ - if (from_gossipd) { - handle_gossip_msg(state->pps, take(msg)); - continue; - } - - /* Some messages go straight to gossipd. */ - if (is_msg_for_gossipd(msg)) { - gossip_rcvd_filter_add(state->pps->grf, msg); - wire_sync_write(state->pps->gossip_fd, take(msg)); - continue; - } + msg = wire_sync_read(ctx, state->pps->peer_fd); /* BOLT #1: * @@ -218,10 +204,6 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state, if (is_unknown_msg_discardable(msg)) continue; - /* Might be a timestamp filter request: handle. */ - if (handle_timestamp_filter(state->pps, msg)) - continue; - /* A helper which decodes an error. */ if (is_peer_error(tmpctx, msg, &state->channel_id, &err, &warning)) { @@ -250,15 +232,16 @@ static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state, * keeps things simple: if we wanted to change this, we would * probably be best with another daemon to de-multiplex them; * this could be connectd itself, in fact. */ - if (is_wrong_channel(msg, &state->channel_id, &actual)) { + if (is_wrong_channel(msg, &state->channel_id, &actual) + && is_wrong_channel(msg, alternate, &actual)) { status_debug("Rejecting %s for unknown channel_id %s", peer_wire_name(fromwire_peektype(msg)), type_to_string(tmpctx, struct channel_id, &actual)); - sync_crypto_write(state->pps, - take(towire_errorfmt(NULL, &actual, - "Multiple channels" - " unsupported"))); + peer_write(state->pps, + take(towire_errorfmt(NULL, &actual, + "Multiple channels" + " unsupported"))); tal_free(msg); continue; } @@ -394,14 +377,14 @@ static u8 *funder_channel_start(struct state *state, u8 channel_flags) &state->first_per_commitment_point[LOCAL], channel_flags, open_tlvs); - sync_crypto_write(state->pps, take(msg)); + peer_write(state->pps, take(msg)); /* This is usually a very transient state... */ peer_billboard(false, "Funding channel start: offered, now waiting for accept_channel"); /* ... since their reply should be immediate. */ - msg = opening_negotiate_msg(tmpctx, state, true); + msg = opening_negotiate_msg(tmpctx, state, true, NULL); if (!msg) return NULL; @@ -638,7 +621,7 @@ static bool funder_finalize_channel_setup(struct state *state, &state->funding.txid, state->funding.n, &sig->s); - sync_crypto_write(state->pps, msg); + peer_write(state->pps, msg); /* BOLT #2: * @@ -652,8 +635,10 @@ static bool funder_finalize_channel_setup(struct state *state, "Funding channel: create first tx, now waiting for their signature"); /* Now they send us their signature for that first commitment - * transaction. */ - msg = opening_negotiate_msg(tmpctx, state, true); + * transaction. Note that errors may refer to the temporary channel + * id (state->channel_id), but success should refer to the new + * "cid" */ + msg = opening_negotiate_msg(tmpctx, state, true, &cid); if (!msg) goto fail; @@ -770,7 +755,6 @@ static u8 *funder_channel_complete(struct state *state) tx, pbase, &sig, - state->pps, &state->their_points.revocation, &state->their_points.payment, &state->their_points.htlc, @@ -1046,13 +1030,13 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) &state->first_per_commitment_point[LOCAL], accept_tlvs); - sync_crypto_write(state->pps, take(msg)); + peer_write(state->pps, take(msg)); peer_billboard(false, "Incoming channel: accepted, now waiting for them to create funding tx"); /* This is a loop which handles gossip until we get a non-gossip msg */ - msg = opening_negotiate_msg(tmpctx, state, false); + msg = opening_negotiate_msg(tmpctx, state, false, NULL); if (!msg) return NULL; @@ -1230,7 +1214,6 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) local_commit, pbase, &theirsig, - state->pps, &theirs.revocation, &theirs.payment, &theirs.htlc, @@ -1254,7 +1237,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) * surprise. */ static u8 *handle_peer_in(struct state *state) { - u8 *msg = sync_crypto_read(tmpctx, state->pps); + u8 *msg = peer_read(tmpctx, state->pps); enum peer_wire t = fromwire_peektype(msg); struct channel_id channel_id; bool extracted; @@ -1262,19 +1245,8 @@ static u8 *handle_peer_in(struct state *state) if (t == WIRE_OPEN_CHANNEL) return fundee_channel(state, msg); - /* Handle custommsgs */ - enum peer_wire type = fromwire_peektype(msg); - if (type % 2 == 1 && !peer_wire_is_defined(type)) { - /* The message is not part of the messages we know how to - * handle. Assuming this is a custommsg, we just forward it to the - * master. */ - wire_sync_write(REQ_FD, take(towire_custommsg_in(NULL, msg))); - return NULL; - } - /* Handles standard cases, and legal unknown ones. */ - if (handle_peer_gossip_or_error(state->pps, - &state->channel_id, false, msg)) + if (handle_peer_error(state->pps, &state->channel_id, false, msg)) return NULL; extracted = extract_channel_id(msg, &channel_id); @@ -1282,10 +1254,9 @@ static u8 *handle_peer_in(struct state *state) /* Reestablish on some now-closed channel? Be nice. */ if (extracted && fromwire_peektype(msg) == WIRE_CHANNEL_REESTABLISH) { return towire_openingd_got_reestablish(NULL, - &channel_id, msg, - state->pps); + &channel_id, msg); } - sync_crypto_write(state->pps, + peer_write(state->pps, take(towire_warningfmt(NULL, extracted ? &channel_id : NULL, "Unexpected message %s: %s", @@ -1299,19 +1270,6 @@ static u8 *handle_peer_in(struct state *state) peer_failed_connection_lost(); } -/*~ If we see the gossip_fd readable, we read a whole message. Sure, we might - * block, but we trust gossipd. */ -static void handle_gossip_in(struct state *state) -{ - u8 *msg = wire_sync_read(NULL, state->pps->gossip_fd); - - if (!msg) - status_failed(STATUS_FAIL_GOSSIP_IO, - "Reading gossip: %s", strerror(errno)); - - handle_gossip_msg(state->pps, take(msg)); -} - /* Memory leak detection is DEVELOPER-only because we go to great lengths to * record the backtrace when allocations occur: without that, the leak * detection tends to be useless for diagnosing where the leak came from, but @@ -1337,17 +1295,6 @@ static void handle_dev_memleak(struct state *state, const u8 *msg) } #endif /* DEVELOPER */ -/* We were told to send a custommsg to the peer by `lightningd`. All the - * verification is done on the side of `lightningd` so we should be good to - * just forward it here. */ -static void openingd_send_custommsg(struct state *state, const u8 *msg) -{ - u8 *inner; - if (!fromwire_custommsg_out(tmpctx, msg, &inner)) - master_badmsg(WIRE_CUSTOMMSG_OUT, msg); - sync_crypto_write(state->pps, take(inner)); -} - /* Standard lightningd-fd-is-ready-to-read demux code. Again, we could hang * here, but if we can't trust our parent, who can we trust? */ static u8 *handle_master_in(struct state *state) @@ -1389,7 +1336,7 @@ static u8 *handle_master_in(struct state *state) master_badmsg(WIRE_OPENINGD_FUNDER_CANCEL, msg); msg = towire_errorfmt(NULL, &state->channel_id, "Channel open canceled by us"); - sync_crypto_write(state->pps, take(msg)); + peer_write(state->pps, take(msg)); negotiation_aborted(state, true, "Channel open canceled by RPC"); return NULL; case WIRE_OPENINGD_DEV_MEMLEAK: @@ -1409,34 +1356,16 @@ static u8 *handle_master_in(struct state *state) break; } - /* Now handle common messages. */ - switch ((enum common_wire)t) { - case WIRE_CUSTOMMSG_OUT: - openingd_send_custommsg(state, msg); - return NULL; - /* We send these. */ - case WIRE_CUSTOMMSG_IN: - break; - } - status_failed(STATUS_FAIL_MASTER_IO, "Unknown msg %s", tal_hex(tmpctx, msg)); } -static void try_read_gossip_store(struct state *state) -{ - u8 *msg = gossip_store_next(tmpctx, state->pps); - - if (msg) - sync_crypto_write(state->pps, take(msg)); -} - int main(int argc, char *argv[]) { setup_locale(); u8 *msg; - struct pollfd pollfd[3]; + struct pollfd pollfd[2]; struct state *state = tal(NULL, struct state); struct secret *none; struct channel_id *force_tmp_channel_id; @@ -1456,21 +1385,20 @@ int main(int argc, char *argv[]) &state->localconf, &state->max_to_self_delay, &state->min_effective_htlc_capacity, - &state->pps, &state->our_points, &state->our_funding_pubkey, &state->minimum_depth, &state->min_feerate, &state->max_feerate, - &force_tmp_channel_id, - &dev_fast_gossip)) + &force_tmp_channel_id)) master_badmsg(WIRE_OPENINGD_INIT, msg); #if DEVELOPER dev_force_tmp_channel_id = force_tmp_channel_id; #endif - /* 3 == peer, 4 == gossipd, 5 = gossip_store, 6 = hsmd */ - per_peer_state_set_fds(state->pps, 3, 4, 5); + /* 3 == peer, 4 = hsmd */ + state->pps = new_per_peer_state(state); + per_peer_state_set_fd(state->pps, 3); /*~ Initially we're not associated with a channel, but * handle_peer_gossip_or_error compares this. */ @@ -1507,52 +1435,38 @@ int main(int argc, char *argv[]) /*~ We manually run a little poll() loop here. With only three fds */ pollfd[0].fd = REQ_FD; pollfd[0].events = POLLIN; - pollfd[1].fd = state->pps->gossip_fd; + pollfd[1].fd = state->pps->peer_fd; pollfd[1].events = POLLIN; - pollfd[2].fd = state->pps->peer_fd; - pollfd[2].events = POLLIN; /* We exit when we get a conclusion to write to lightningd: either * opening_funder_reply or opening_fundee. */ msg = NULL; while (!msg) { - int t; - struct timerel trel; - if (time_to_next_gossip(state->pps, &trel)) - t = time_to_msec(trel); - else - t = -1; - /*~ If we get a signal which aborts the poll() call, valgrind * complains about revents being uninitialized. I'm not sure * that's correct, but it's easy to be sure. */ - pollfd[0].revents = pollfd[1].revents = pollfd[2].revents = 0; + pollfd[0].revents = pollfd[1].revents = 0; - poll(pollfd, ARRAY_SIZE(pollfd), t); + poll(pollfd, ARRAY_SIZE(pollfd), -1); /* Subtle: handle_master_in can do its own poll loop, so * don't try to service more than one fd per loop. */ /* First priority: messages from lightningd. */ if (pollfd[0].revents & POLLIN) msg = handle_master_in(state); /* Second priority: messages from peer. */ - else if (pollfd[2].revents & POLLIN) - msg = handle_peer_in(state); - /* Last priority: chit-chat from gossipd. */ else if (pollfd[1].revents & POLLIN) - handle_gossip_in(state); - else - try_read_gossip_store(state); + msg = handle_peer_in(state); /* Since we're the top-level event loop, we clean up */ clean_tmpctx(); } - /*~ Write message and hand back the peer fd and gossipd fd. This also - * means that if the peer or gossipd wrote us any messages we didn't - * read yet, it will simply be read by the next daemon. */ + /*~ Write message and hand back the peer fd. This also means that if + * the peer wrote us any messages we didn't read yet, it will simply + * be read by the next daemon. */ wire_sync_write(REQ_FD, msg); per_peer_state_fdpass_send(REQ_FD, state->pps); - status_debug("Sent %s with fds", + status_debug("Sent %s with fd", openingd_wire_name(fromwire_peektype(msg))); /* This frees the entire tal tree. */ diff --git a/openingd/openingd_wire.csv b/openingd/openingd_wire.csv index 7a688c7f692f..b8f0fc5b9d6f 100644 --- a/openingd/openingd_wire.csv +++ b/openingd/openingd_wire.csv @@ -5,7 +5,6 @@ #include #include #include -#include msgtype,openingd_init,6000 # Which network are we configured for? @@ -18,7 +17,6 @@ msgdata,openingd_init,our_config,channel_config, # Minimum/maximum configuration values we'll accept msgdata,openingd_init,max_to_self_delay,u32, msgdata,openingd_init,min_effective_htlc_capacity_msat,amount_msat, -msgdata,openingd_init,pps,per_peer_state, msgdata,openingd_init,our_basepoints,basepoints, msgdata,openingd_init,our_funding_pubkey,pubkey, # Constraints in case the other end tries to open a channel. @@ -26,14 +24,12 @@ msgdata,openingd_init,minimum_depth,u32, msgdata,openingd_init,min_feerate,u32, msgdata,openingd_init,max_feerate,u32, msgdata,openingd_init,dev_temporary_channel_id,?byte,32 -msgdata,openingd_init,dev_fast_gossip,bool, # Openingd->master: they tried to reestablish a channel. msgtype,openingd_got_reestablish,6001 msgdata,openingd_got_reestablish,channel_id,channel_id, msgdata,openingd_got_reestablish,len,u16, msgdata,openingd_got_reestablish,msg,u8,len -msgdata,openingd_got_reestablish,pps,per_peer_state, # Openingd->master: they offered channel, should we continue? msgtype,openingd_got_offer,6005 @@ -65,7 +61,6 @@ msgdata,openingd_funder_reply,their_config,channel_config, msgdata,openingd_funder_reply,first_commit,bitcoin_tx, msgdata,openingd_funder_reply,pbase,?penalty_base, msgdata,openingd_funder_reply,first_commit_sig,bitcoin_signature, -msgdata,openingd_funder_reply,pps,per_peer_state, msgdata,openingd_funder_reply,revocation_basepoint,pubkey, msgdata,openingd_funder_reply,payment_basepoint,pubkey, msgdata,openingd_funder_reply,htlc_basepoint,pubkey, @@ -119,7 +114,6 @@ msgdata,openingd_fundee,their_config,channel_config, msgdata,openingd_fundee,first_commit,bitcoin_tx, msgdata,openingd_fundee,pbase,?penalty_base, msgdata,openingd_fundee,first_commit_sig,bitcoin_signature, -msgdata,openingd_fundee,pps,per_peer_state, msgdata,openingd_fundee,revocation_basepoint,pubkey, msgdata,openingd_fundee,payment_basepoint,pubkey, msgdata,openingd_fundee,htlc_basepoint,pubkey, diff --git a/plugins/test/run-funder_policy.c b/plugins/test/run-funder_policy.c index 8efb543e5958..a91a5867615e 100644 --- a/plugins/test/run-funder_policy.c +++ b/plugins/test/run-funder_policy.c @@ -9,7 +9,7 @@ bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_bigsize called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for fromwire_node_id */ diff --git a/plugins/test/run-route-overlong.c b/plugins/test/run-route-overlong.c index 3999a31cfe87..2ca73fd9452e 100644 --- a/plugins/test/run-route-overlong.c +++ b/plugins/test/run-route-overlong.c @@ -21,7 +21,7 @@ bool feature_offered(const u8 *features UNNEEDED, size_t f UNNEEDED) bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED) { fprintf(stderr, "fromwire_bigsize called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for json_add_amount_msat_compat */ diff --git a/tests/test_closing.py b/tests/test_closing.py index ea0f448d45f1..cd54e6c54bff 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -292,7 +292,6 @@ def test_closing_different_fees(node_factory, bitcoind, executor): @pytest.mark.developer("needs DEVELOPER=1") def test_closing_negotiation_reconnect(node_factory, bitcoind): disconnects = ['-WIRE_CLOSING_SIGNED', - '@WIRE_CLOSING_SIGNED', '+WIRE_CLOSING_SIGNED'] l1, l2 = node_factory.line_graph(2, opts=[{'disconnect': disconnects, 'may_reconnect': True}, @@ -511,7 +510,7 @@ def test_closing_negotiation_step_700sat(node_factory, bitcoind, chainparams): closing_negotiation_step(node_factory, bitcoind, chainparams, opts) -@pytest.mark.developer("needs DEVELOPER=1") +@pytest.mark.developer("needs dev-disable-commit-after") def test_penalty_inhtlc(node_factory, bitcoind, executor, chainparams): """Test penalty transaction with an incoming HTLC""" @@ -519,12 +518,12 @@ def test_penalty_inhtlc(node_factory, bitcoind, executor, chainparams): coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py') # We suppress each one after first commit; HTLC gets added not fulfilled. # Feerates identical so we don't get gratuitous commit to update them - l1, l2 = node_factory.line_graph(2, opts=[{'disconnect': ['=WIRE_COMMITMENT_SIGNED-nocommit'], + l1, l2 = node_factory.line_graph(2, opts=[{'dev-disable-commit-after': 1, 'may_fail': True, 'feerates': (7500, 7500, 7500, 7500), 'allow_broken_log': True, 'plugin': coin_mvt_plugin}, - {'disconnect': ['=WIRE_COMMITMENT_SIGNED-nocommit'], + {'dev-disable-commit-after': 1, 'plugin': coin_mvt_plugin}]) channel_id = first_channel_id(l1, l2) @@ -536,8 +535,8 @@ def test_penalty_inhtlc(node_factory, bitcoind, executor, chainparams): assert len(l2.getactivechannels()) == 2 # They should both have commitments blocked now. - l1.daemon.wait_for_log('=WIRE_COMMITMENT_SIGNED-nocommit') - l2.daemon.wait_for_log('=WIRE_COMMITMENT_SIGNED-nocommit') + l1.daemon.wait_for_log('dev-disable-commit-after: disabling') + l2.daemon.wait_for_log('dev-disable-commit-after: disabling') # Make sure l1 got l2's commitment to the HTLC, and sent to master. l1.daemon.wait_for_log('got commitsig') @@ -607,7 +606,7 @@ def test_penalty_inhtlc(node_factory, bitcoind, executor, chainparams): assert account_balance(l2, channel_id) == 0 -@pytest.mark.developer("needs DEVELOPER=1") +@pytest.mark.developer("needs dev-disable-commit-after") def test_penalty_outhtlc(node_factory, bitcoind, executor, chainparams): """Test penalty transaction with an outgoing HTLC""" @@ -616,20 +615,20 @@ def test_penalty_outhtlc(node_factory, bitcoind, executor, chainparams): # First we need to get funds to l2, so suppress after second. # Feerates identical so we don't get gratuitous commit to update them l1, l2 = node_factory.line_graph(2, - opts=[{'disconnect': ['=WIRE_COMMITMENT_SIGNED*3-nocommit'], + opts=[{'dev-disable-commit-after': 3, 'may_fail': True, 'feerates': (7500, 7500, 7500, 7500), 'allow_broken_log': True, 'plugin': coin_mvt_plugin}, - {'disconnect': ['=WIRE_COMMITMENT_SIGNED*3-nocommit'], + {'dev-disable-commit-after': 3, 'plugin': coin_mvt_plugin}]) channel_id = first_channel_id(l1, l2) # Move some across to l2. l1.pay(l2, 200000000) - assert not l1.daemon.is_in_log('=WIRE_COMMITMENT_SIGNED') - assert not l2.daemon.is_in_log('=WIRE_COMMITMENT_SIGNED') + assert not l1.daemon.is_in_log('dev-disable-commit-after: disabling') + assert not l2.daemon.is_in_log('dev-disable-commit-after: disabling') # Now, this will get stuck due to l1 commit being disabled.. t = executor.submit(l2.pay, l1, 100000000) @@ -639,8 +638,8 @@ def test_penalty_outhtlc(node_factory, bitcoind, executor, chainparams): l1.daemon.wait_for_log('peer_in WIRE_COMMITMENT_SIGNED') # They should both have commitments blocked now. - l1.daemon.wait_for_log('dev_disconnect: =WIRE_COMMITMENT_SIGNED') - l2.daemon.wait_for_log('dev_disconnect: =WIRE_COMMITMENT_SIGNED') + l1.daemon.wait_for_log('dev-disable-commit-after: disabling') + l2.daemon.wait_for_log('dev-disable-commit-after: disabling') # Make sure both sides got revoke_and_ack for that commitment. l1.daemon.wait_for_log('peer_in WIRE_REVOKE_AND_ACK') @@ -1406,10 +1405,10 @@ def test_penalty_rbf_normal(node_factory, bitcoind, executor, chainparams): # l1 is the thief, which causes our honest upstanding lightningd # code to break, so l1 can fail. # Initially, disconnect before the HTLC can be resolved. - l1 = node_factory.get_node(disconnect=['=WIRE_COMMITMENT_SIGNED-nocommit'], + l1 = node_factory.get_node(options={'dev-disable-commit-after': 1}, may_fail=True, allow_broken_log=True) - l2 = node_factory.get_node(disconnect=['=WIRE_COMMITMENT_SIGNED-nocommit'], - options={'watchtime-blocks': to_self_delay}) + l2 = node_factory.get_node(options={'dev-disable-commit-after': 1, + 'watchtime-blocks': to_self_delay}) l1.rpc.connect(l2.info['id'], 'localhost', l2.port) l1.fundchannel(l2, 10**7) @@ -1422,8 +1421,8 @@ def test_penalty_rbf_normal(node_factory, bitcoind, executor, chainparams): assert len(l2.getactivechannels()) == 2 # Wait for the disconnection. - l1.daemon.wait_for_log('=WIRE_COMMITMENT_SIGNED-nocommit') - l2.daemon.wait_for_log('=WIRE_COMMITMENT_SIGNED-nocommit') + l1.daemon.wait_for_log('dev-disable-commit-after: disabling') + l2.daemon.wait_for_log('dev-disable-commit-after: disabling') # Make sure l1 gets the new HTLC. l1.daemon.wait_for_log('got commitsig') @@ -1512,10 +1511,10 @@ def test_penalty_rbf_burn(node_factory, bitcoind, executor, chainparams): # l1 is the thief, which causes our honest upstanding lightningd # code to break, so l1 can fail. # Initially, disconnect before the HTLC can be resolved. - l1 = node_factory.get_node(disconnect=['=WIRE_COMMITMENT_SIGNED-nocommit'], + l1 = node_factory.get_node(options={'dev-disable-commit-after': 1}, may_fail=True, allow_broken_log=True) - l2 = node_factory.get_node(disconnect=['=WIRE_COMMITMENT_SIGNED-nocommit'], - options={'watchtime-blocks': to_self_delay}) + l2 = node_factory.get_node(options={'dev-disable-commit-after': 1, + 'watchtime-blocks': to_self_delay}) l1.rpc.connect(l2.info['id'], 'localhost', l2.port) l1.fundchannel(l2, 10**7) @@ -1528,8 +1527,8 @@ def test_penalty_rbf_burn(node_factory, bitcoind, executor, chainparams): assert len(l2.getactivechannels()) == 2 # Wait for the disconnection. - l1.daemon.wait_for_log('=WIRE_COMMITMENT_SIGNED-nocommit') - l2.daemon.wait_for_log('=WIRE_COMMITMENT_SIGNED-nocommit') + l1.daemon.wait_for_log('dev-disable-commit-after: disabling') + l2.daemon.wait_for_log('dev-disable-commit-after: disabling') # Make sure l1 gets the new HTLC. l1.daemon.wait_for_log('got commitsig') @@ -1761,7 +1760,7 @@ def test_onchain_dust_out(node_factory, bitcoind, executor): coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py') # HTLC 1->2, 1 fails after it's irrevocably committed - disconnects = ['@WIRE_REVOKE_AND_ACK', 'permfail'] + disconnects = ['-WIRE_REVOKE_AND_ACK', 'permfail'] # Feerates identical so we don't get gratuitous commit to update them l1, l2 = node_factory.line_graph(2, opts=[{'disconnect': disconnects, @@ -3155,13 +3154,13 @@ def test_htlc_rexmit_while_closing(node_factory, executor): @pytest.mark.developer("needs dev_disconnect") def test_you_forgot_closed_channel(node_factory, executor): """Ideally you'd keep talking to us about closed channels: simple""" - disconnects = ['@WIRE_CLOSING_SIGNED'] + disconnects = ['xWIRE_CLOSING_SIGNED'] l1, l2 = node_factory.line_graph(2, opts=[{'may_reconnect': True, - 'dev-no-reconnect': None}, - {'may_reconnect': True, 'dev-no-reconnect': None, - 'disconnect': disconnects}]) + 'disconnect': disconnects}, + {'may_reconnect': True, + 'dev-no-reconnect': None}]) l1.pay(l2, 200000) @@ -3172,6 +3171,7 @@ 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) l1.rpc.connect(l2.info['id'], 'localhost', l2.port) fut.result(TIMEOUT) @@ -3179,13 +3179,13 @@ def test_you_forgot_closed_channel(node_factory, executor): @pytest.mark.developer("needs dev_disconnect") def test_you_forgot_closed_channel_onchain(node_factory, bitcoind, executor): """Ideally you'd keep talking to us about closed channels: even if close is mined""" - disconnects = ['@WIRE_CLOSING_SIGNED'] + disconnects = ['xWIRE_CLOSING_SIGNED'] l1, l2 = node_factory.line_graph(2, opts=[{'may_reconnect': True, - 'dev-no-reconnect': None}, - {'may_reconnect': True, 'dev-no-reconnect': None, - 'disconnect': disconnects}]) + 'disconnect': disconnects}, + {'may_reconnect': True, + 'dev-no-reconnect': None}]) l1.pay(l2, 200000) @@ -3207,6 +3207,8 @@ def no_new_blocks(req): wait_for(lambda: only_one(only_one(l2.rpc.listpeers()['peers'])['channels'])['state'] == 'ONCHAIN') # l1 reconnects, it should succeed. + # l1 will disconnect once it sees block + wait_for(lambda: only_one(l1.rpc.listpeers()['peers'])['connected'] is False) 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 eb62b1b9322b..ad7b04b2682f 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -289,7 +289,6 @@ def test_channel_abandon(node_factory, bitcoind): def test_disconnect(node_factory): # These should all make us fail disconnects = ['-WIRE_INIT', - '@WIRE_INIT', '+WIRE_INIT'] l1 = node_factory.get_node(disconnect=disconnects) l2 = node_factory.get_node() @@ -298,8 +297,6 @@ def test_disconnect(node_factory): l1.rpc.connect(l2.info['id'], 'localhost', l2.port) with pytest.raises(RpcError): l1.rpc.connect(l2.info['id'], 'localhost', l2.port) - with pytest.raises(RpcError): - l1.rpc.connect(l2.info['id'], 'localhost', l2.port) # Should have 3 connect fails. for d in disconnects: @@ -317,22 +314,16 @@ def test_disconnect(node_factory): def test_disconnect_opener(node_factory): # Now error on opener side during channel open. disconnects = ['-WIRE_OPEN_CHANNEL', - '@WIRE_OPEN_CHANNEL', '+WIRE_OPEN_CHANNEL', - '-WIRE_FUNDING_CREATED', - '@WIRE_FUNDING_CREATED'] + '-WIRE_FUNDING_CREATED'] if EXPERIMENTAL_DUAL_FUND: disconnects = ['-WIRE_OPEN_CHANNEL2', - '@WIRE_OPEN_CHANNEL2', '+WIRE_OPEN_CHANNEL2', '-WIRE_TX_ADD_INPUT', - '@WIRE_TX_ADD_INPUT', '+WIRE_TX_ADD_INPUT', '-WIRE_TX_ADD_OUTPUT', - '@WIRE_TX_ADD_OUTPUT', '+WIRE_TX_ADD_OUTPUT', '-WIRE_TX_COMPLETE', - '@WIRE_TX_COMPLETE', '+WIRE_TX_COMPLETE'] l1 = node_factory.get_node(disconnect=disconnects) @@ -361,14 +352,11 @@ def test_disconnect_opener(node_factory): def test_disconnect_fundee(node_factory): # Now error on fundee side during channel open. disconnects = ['-WIRE_ACCEPT_CHANNEL', - '@WIRE_ACCEPT_CHANNEL', '+WIRE_ACCEPT_CHANNEL'] if EXPERIMENTAL_DUAL_FUND: disconnects = ['-WIRE_ACCEPT_CHANNEL2', - '@WIRE_ACCEPT_CHANNEL2', '+WIRE_ACCEPT_CHANNEL2', '-WIRE_TX_COMPLETE', - '@WIRE_TX_COMPLETE', '+WIRE_TX_COMPLETE'] l1 = node_factory.get_node() @@ -397,16 +385,12 @@ def test_disconnect_fundee(node_factory): def test_disconnect_fundee_v2(node_factory): # Now error on fundee side during channel open, with them funding disconnects = ['-WIRE_ACCEPT_CHANNEL2', - '@WIRE_ACCEPT_CHANNEL2', '+WIRE_ACCEPT_CHANNEL2', '-WIRE_TX_ADD_INPUT', - '@WIRE_TX_ADD_INPUT', '+WIRE_TX_ADD_INPUT', '-WIRE_TX_ADD_OUTPUT', - '@WIRE_TX_ADD_OUTPUT', '+WIRE_TX_ADD_OUTPUT', '-WIRE_TX_COMPLETE', - '@WIRE_TX_COMPLETE', '+WIRE_TX_COMPLETE'] l1 = node_factory.get_node() @@ -440,9 +424,9 @@ def test_disconnect_fundee_v2(node_factory): def test_disconnect_half_signed(node_factory): # Now, these are the corner cases. Fundee sends funding_signed, # but opener doesn't receive it. - disconnects = ['@WIRE_FUNDING_SIGNED'] + disconnects = ['-WIRE_FUNDING_SIGNED'] if EXPERIMENTAL_DUAL_FUND: - disconnects = ['@WIRE_COMMITMENT_SIGNED'] + disconnects = ['-WIRE_COMMITMENT_SIGNED'] l1 = node_factory.get_node() l2 = node_factory.get_node(disconnect=disconnects) @@ -493,6 +477,7 @@ def test_reconnect_signed(node_factory): l2.daemon.wait_for_log(' to CHANNELD_NORMAL') +@pytest.mark.skip('needs blackhold support') @pytest.mark.developer @pytest.mark.openchannel('v1') @pytest.mark.openchannel('v2') @@ -532,6 +517,7 @@ def test_reconnect_openingd(node_factory): l2.daemon.wait_for_log(r'channeld-chan#[0-9]: pid [0-9]+, msgfd [0-9]+') +@pytest.mark.skip('needs blackhold support') @pytest.mark.developer def test_reconnect_gossiping(node_factory): # connectd thinks we're still gossiping; peer reconnects. @@ -565,7 +551,7 @@ def test_reconnect_no_update(node_factory, executor, bitcoind): reconnects. See comments for details. """ - disconnects = ["@WIRE_FUNDING_LOCKED", "@WIRE_SHUTDOWN"] + disconnects = ["-WIRE_FUNDING_LOCKED", "-WIRE_SHUTDOWN"] # Allow bad gossip because it might receive WIRE_CHANNEL_UPDATE before # announcement of the disconnection l1 = node_factory.get_node(may_reconnect=True, allow_bad_gossip=True) @@ -589,7 +575,7 @@ def test_reconnect_no_update(node_factory, executor, bitcoind): # For closingd reconnection l1.daemon.start() - # Close will trigger the @WIRE_SHUTDOWN and we then wait for the + # Close will trigger the -WIRE_SHUTDOWN and we then wait for the # automatic reconnection to trigger the retransmission. l1.rpc.close(l2.info['id'], 0) l2.daemon.wait_for_log(r"channeld.* Retransmitting funding_locked for channel") @@ -643,7 +629,6 @@ def test_connect_stresstest(node_factory, executor): def test_reconnect_normal(node_factory): # Should reconnect fine even if locked message gets lost. disconnects = ['-WIRE_FUNDING_LOCKED', - '@WIRE_FUNDING_LOCKED', '+WIRE_FUNDING_LOCKED'] l1 = node_factory.get_node(disconnect=disconnects, may_reconnect=True) @@ -658,9 +643,8 @@ def test_reconnect_normal(node_factory): @pytest.mark.openchannel('v2') def test_reconnect_sender_add1(node_factory): # Fail after add is OK, will cause payment failure though. - disconnects = ['-WIRE_UPDATE_ADD_HTLC-nocommit', - '+WIRE_UPDATE_ADD_HTLC-nocommit', - '@WIRE_UPDATE_ADD_HTLC-nocommit'] + disconnects = ['-WIRE_UPDATE_ADD_HTLC', + '+WIRE_UPDATE_ADD_HTLC'] # Feerates identical so we don't get gratuitous commit to update them l1 = node_factory.get_node(disconnect=disconnects, @@ -695,10 +679,8 @@ def test_reconnect_sender_add1(node_factory): @pytest.mark.openchannel('v2') def test_reconnect_sender_add(node_factory): disconnects = ['-WIRE_COMMITMENT_SIGNED', - '@WIRE_COMMITMENT_SIGNED', '+WIRE_COMMITMENT_SIGNED', '-WIRE_REVOKE_AND_ACK', - '@WIRE_REVOKE_AND_ACK', '+WIRE_REVOKE_AND_ACK'] if EXPERIMENTAL_DUAL_FUND: disconnects = ['=WIRE_COMMITMENT_SIGNED'] + disconnects @@ -731,10 +713,8 @@ def test_reconnect_sender_add(node_factory): @pytest.mark.openchannel('v2') def test_reconnect_receiver_add(node_factory): disconnects = ['-WIRE_COMMITMENT_SIGNED', - '@WIRE_COMMITMENT_SIGNED', '+WIRE_COMMITMENT_SIGNED', '-WIRE_REVOKE_AND_ACK', - '@WIRE_REVOKE_AND_ACK', '+WIRE_REVOKE_AND_ACK'] if EXPERIMENTAL_DUAL_FUND: @@ -765,14 +745,11 @@ def test_reconnect_receiver_fulfill(node_factory): # Ordering matters: after +WIRE_UPDATE_FULFILL_HTLC, channeld # will continue and try to send WIRE_COMMITMENT_SIGNED: if # that's the next failure, it will do two in one run. - disconnects = ['@WIRE_UPDATE_FULFILL_HTLC', - '+WIRE_UPDATE_FULFILL_HTLC', + disconnects = ['+WIRE_UPDATE_FULFILL_HTLC', '-WIRE_UPDATE_FULFILL_HTLC', '-WIRE_COMMITMENT_SIGNED', - '@WIRE_COMMITMENT_SIGNED', '+WIRE_COMMITMENT_SIGNED', '-WIRE_REVOKE_AND_ACK', - '@WIRE_REVOKE_AND_ACK', '+WIRE_REVOKE_AND_ACK'] l1 = node_factory.get_node(may_reconnect=True) l2 = node_factory.get_node(disconnect=disconnects, @@ -799,7 +776,6 @@ def test_reconnect_receiver_fulfill(node_factory): @pytest.mark.openchannel('v2') def test_shutdown_reconnect(node_factory): disconnects = ['-WIRE_SHUTDOWN', - '@WIRE_SHUTDOWN', '+WIRE_SHUTDOWN'] l1 = node_factory.get_node(disconnect=disconnects, may_reconnect=True) @@ -1795,7 +1771,7 @@ def test_multifunding_disconnect(node_factory): ''' Test disconnection during multifundchannel ''' - # TODO: Note that @WIRE_FUNDING_SIGNED does not + # TODO: Note that -WIRE_FUNDING_SIGNED does not # work. # See test_disconnect_half_signed. # If disconnected when the peer believes it sent @@ -1805,9 +1781,7 @@ def test_multifunding_disconnect(node_factory): # never send it. disconnects = ["-WIRE_INIT", "-WIRE_ACCEPT_CHANNEL", - "@WIRE_ACCEPT_CHANNEL", - "+WIRE_ACCEPT_CHANNEL", - "-WIRE_FUNDING_SIGNED"] + "+WIRE_ACCEPT_CHANNEL"] l1 = node_factory.get_node() l2 = node_factory.get_node(disconnect=disconnects) l3 = node_factory.get_node() @@ -1826,7 +1800,7 @@ def test_multifunding_disconnect(node_factory): l1.rpc.multifundchannel(destinations) # TODO: failing at the fundchannel_complete phase - # (@WIRE_FUNDING_SIGNED +@WIRE_FUNDING_SIGNED) + # (-WIRE_FUNDING_SIGNED +-WIRE_FUNDING_SIGNED) # leaves the peer (l2 in this case) in a state # where it is waiting for an incoming channel, # even though we no longer have a channel going to @@ -2106,14 +2080,14 @@ def test_channel_persistence(node_factory, bitcoind, executor): # mysteriously die while committing the first HTLC so we can # check that HTLCs reloaded from the DB work. # Feerates identical so we don't get gratuitous commit to update them - disconnect = ['=WIRE_COMMITMENT_SIGNED-nocommit'] - + disable_commit_after = 1 if EXPERIMENTAL_DUAL_FUND: - disconnect = ['=WIRE_COMMITMENT_SIGNED'] + disconnect + disable_commit_after = 2 l1 = node_factory.get_node(may_reconnect=True, feerates=(7500, 7500, 7500, 7500)) - l2 = node_factory.get_node(disconnect=disconnect, may_reconnect=True) + l2 = node_factory.get_node(options={'dev-disable-commit-after': disable_commit_after}, + may_reconnect=True) l1.rpc.connect(l2.info['id'], 'localhost', l2.port) # Neither node should have a channel open, they are just connected @@ -2140,7 +2114,7 @@ def test_channel_persistence(node_factory, bitcoind, executor): l2.daemon.kill() # Clear the disconnect and timer stop so we can proceed normally - del l2.daemon.opts['dev-disconnect'] + del l2.daemon.opts['dev-disable-commit-after'] # Wait for l1 to notice wait_for(lambda: 'connected' not in only_one(l1.rpc.listpeers()['peers'][0]['channels'])) @@ -2866,10 +2840,9 @@ def test_dataloss_protection(node_factory, bitcoind): @pytest.mark.developer("needs dev_disconnect") def test_restart_multi_htlc_rexmit(node_factory, bitcoind, executor): # l1 disables commit timer once we send first htlc, dies on commit - disconnects = ['=WIRE_UPDATE_ADD_HTLC-nocommit', - '-WIRE_COMMITMENT_SIGNED'] - l1, l2 = node_factory.line_graph(2, opts=[{'disconnect': disconnects, - 'may_reconnect': True}, + l1, l2 = node_factory.line_graph(2, opts=[{'disconnect': ['-WIRE_COMMITMENT_SIGNED'], + 'may_reconnect': True, + 'dev-disable-commit-after': 0}, {'may_reconnect': True}]) executor.submit(l1.pay, l2, 20000) @@ -3030,6 +3003,7 @@ def test_restart_many_payments(node_factory, bitcoind): wait_for(lambda: 'pending' not in [p['status'] for p in n.rpc.listsendpays()['payments']]) +@pytest.mark.skip('needs blackhold support') @pytest.mark.developer("need dev-disconnect") @pytest.mark.openchannel('v1') @pytest.mark.openchannel('v2') @@ -3085,6 +3059,7 @@ def test_fail_unconfirmed(node_factory, bitcoind, executor): l1.fundchannel(l2, 200000, wait_for_active=True) +@pytest.mark.skip('needs blackhold support') @pytest.mark.developer("need dev-disconnect") @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') @@ -3391,6 +3366,7 @@ def test_nonstatic_channel(node_factory, bitcoind): l1.rpc.close(l2.info['id']) +@pytest.mark.skip('needs blackhold support') @pytest.mark.developer("need --dev-timeout-secs") @pytest.mark.openchannel('v1') def test_connection_timeout(node_factory): @@ -3415,9 +3391,9 @@ def test_htlc_retransmit_order(node_factory, executor): l1, l2 = node_factory.line_graph(2, opts=[{'may_reconnect': True, 'feerates': (7500, 7500, 7500, 7500), - 'disconnect': ['=WIRE_UPDATE_ADD_HTLC-nocommit', - '=WIRE_UPDATE_ADD_HTLC*' + str(NUM_HTLCS - 1), - '-WIRE_COMMITMENT_SIGNED']}, + 'disconnect': ['=WIRE_UPDATE_ADD_HTLC*' + str(NUM_HTLCS), + '-WIRE_COMMITMENT_SIGNED'], + 'dev-disable-commit-after': 0}, {'may_reconnect': True}]) invoices = [l2.rpc.invoice(1000, str(x), str(x)) for x in range(NUM_HTLCS)] @@ -3430,7 +3406,7 @@ def test_htlc_retransmit_order(node_factory, executor): for inv in invoices: executor.submit(l1.rpc.sendpay, [routestep], inv['payment_hash'], payment_secret=inv['payment_secret']) - l1.daemon.wait_for_logs(['dev_disconnect'] * 2) + l1.daemon.wait_for_log('dev_disconnect') l1.rpc.call('dev-reenable-commit', [l2.info['id']]) l1.daemon.wait_for_log('dev_disconnect') @@ -3637,8 +3613,7 @@ def test_upgrade_statickey_fail(node_factory, executor, bitcoind): l1_disconnects = ['-WIRE_COMMITMENT_SIGNED', '-WIRE_REVOKE_AND_ACK'] l2_disconnects = ['-WIRE_REVOKE_AND_ACK', - '-WIRE_COMMITMENT_SIGNED', - '=WIRE_UPDATE_FAIL_HTLC-nocommit'] + '-WIRE_COMMITMENT_SIGNED'] l1, l2 = node_factory.line_graph(2, opts=[{'may_reconnect': True, 'dev-no-reconnect': None, @@ -3648,13 +3623,14 @@ def test_upgrade_statickey_fail(node_factory, executor, bitcoind): 'feerates': (7500, 7500, 7500, 7500)}, {'may_reconnect': True, 'dev-no-reconnect': None, - 'disconnect': l2_disconnects}]) + 'disconnect': l2_disconnects, + 'dev-disable-commit-after': 1}]) # This HTLC will fail l1.rpc.sendpay([{'msatoshi': 1000, 'id': l2.info['id'], 'delay': 5, 'channel': '1x1x1'}], '00' * 32, payment_secret='00' * 32) # Each one should cause one disconnection, no upgrade. - for d in l1_disconnects + l2_disconnects[:-1]: + for d in l1_disconnects + l2_disconnects: l1.daemon.wait_for_log('Peer connection lost') l2.daemon.wait_for_log('Peer connection lost') assert not l1.daemon.is_in_log('option_static_remotekey enabled') diff --git a/tests/test_gossip.py b/tests/test_gossip.py index 7696b2642490..245666b1b689 100644 --- a/tests/test_gossip.py +++ b/tests/test_gossip.py @@ -597,7 +597,8 @@ def test_gossip_no_empty_announcements(node_factory, bitcoind): # l3 sends CHANNEL_ANNOUNCEMENT to l2, but not CHANNEL_UDPATE. l1, l2, l3, l4 = node_factory.line_graph(4, opts=[{'log-level': 'io'}, {'log-level': 'io'}, - {'disconnect': ['+WIRE_CHANNEL_ANNOUNCEMENT'], + # Writes to l4 first, then l2 + {'disconnect': ['+WIRE_CHANNEL_ANNOUNCEMENT*2'], 'may_reconnect': True}, {'may_reconnect': True}], fundchannel=False) @@ -1260,6 +1261,7 @@ def test_node_reannounce(node_factory, bitcoind, chainparams): l1.start() wait_for(lambda: only_one(l2.rpc.listnodes(l1.info['id'])['nodes'])['alias'] == 'SENIORBEAM') + wait_for(lambda: only_one(l1.rpc.listnodes(l1.info['id'])['nodes'])['alias'] == 'SENIORBEAM') # Get node_announcements. msgs = l1.query_gossip('gossip_timestamp_filter', @@ -1269,6 +1271,7 @@ def test_node_reannounce(node_factory, bitcoind, chainparams): # channel_announcement and channel_updates. filters=['0109', '0102', '0100']) + print("\n\n\n***{}\n\n\n".format(msgs)) assert len(msgs) == 2 assert (bytes("SENIORBEAM", encoding="utf8").hex() in msgs[0] or bytes("SENIORBEAM", encoding="utf8").hex() in msgs[1]) @@ -1793,10 +1796,13 @@ def test_gossip_ratelimit(node_factory, bitcoind): canned gossip to the other partition consisting of l3. l3 should ratelimit the incoming gossip. + We get BROKEN logs because gossipd talks about non-existent channels to + lightningd ("**BROKEN** lightningd: Local update for bad scid 103x1x1"). """ l3, = node_factory.get_nodes( 1, - opts=[{'dev-gossip-time': 1568096251}] + opts=[{'dev-gossip-time': 1568096251, + 'allow_broken_log': True}] ) # Bump to block 102, so the following tx ends up in 103x1: @@ -1952,7 +1958,11 @@ def test_torport_onions(node_factory): @unittest.skipIf(not COMPAT, "needs COMPAT to convert obsolete gossip_store") def test_gossip_store_upgrade_v7_v8(node_factory): """Version 8 added feature bits to local channel announcements""" - l1 = node_factory.get_node(start=False) + + # We get BROKEN logs because gossipd talks about non-existent channels to + # lightningd ("**BROKEN** lightningd: Local update for bad scid 103x1x1"). + l1 = node_factory.get_node(start=False, + allow_broken_log=True) # A channel announcement with no channel_update. with open(os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, 'gossip_store'), 'wb') as f: diff --git a/tests/test_misc.py b/tests/test_misc.py index b7e2120cd62a..4afcb4751ebd 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -316,7 +316,7 @@ def test_htlc_out_timeout(node_factory, bitcoind, executor): """Test that we drop onchain if the peer doesn't time out HTLC""" # HTLC 1->2, 1 fails after it's irrevocably committed, can't reconnect - disconnects = ['@WIRE_REVOKE_AND_ACK'] + disconnects = ['-WIRE_REVOKE_AND_ACK'] # Feerates identical so we don't get gratuitous commit to update them l1 = node_factory.get_node(disconnect=disconnects, options={'dev-no-reconnect': None}, @@ -336,7 +336,7 @@ def test_htlc_out_timeout(node_factory, bitcoind, executor): executor.submit(l1.rpc.dev_pay, inv, use_shadow=False) # l1 will disconnect, and not reconnect. - l1.daemon.wait_for_log('dev_disconnect: @WIRE_REVOKE_AND_ACK') + l1.daemon.wait_for_log('dev_disconnect: -WIRE_REVOKE_AND_ACK') # Takes 6 blocks to timeout (cltv-final + 1), but we also give grace period of 1 block. # shadow route can add extra blocks! @@ -1139,7 +1139,9 @@ def test_funding_reorg_private(node_factory, bitcoind): # Rescan to detect reorg at restart and may_reconnect so channeld # will restart. Reorg can cause bad gossip msg. opts = {'funding-confirms': 2, 'rescan': 10, 'may_reconnect': True, - 'allow_bad_gossip': True} + 'allow_bad_gossip': True, + # gossipd send lightning update for original channel. + 'allow_broken_log': True} l1, l2 = node_factory.line_graph(2, fundchannel=False, opts=opts) l1.fundwallet(10000000) sync_blockheight(bitcoind, [l1]) # height 102 diff --git a/tests/test_opening.py b/tests/test_opening.py index 31e74d3d3e91..c56537bf81a9 100644 --- a/tests/test_opening.py +++ b/tests/test_opening.py @@ -508,7 +508,6 @@ def test_v2_rbf_multi(node_factory, bitcoind, chainparams): @pytest.mark.openchannel('v2') def test_rbf_reconnect_init(node_factory, bitcoind, chainparams): disconnects = ['-WIRE_INIT_RBF', - '@WIRE_INIT_RBF', '+WIRE_INIT_RBF'] l1, l2 = node_factory.get_nodes(2, @@ -559,7 +558,6 @@ def test_rbf_reconnect_init(node_factory, bitcoind, chainparams): @pytest.mark.openchannel('v2') def test_rbf_reconnect_ack(node_factory, bitcoind, chainparams): disconnects = ['-WIRE_ACK_RBF', - '@WIRE_ACK_RBF', '+WIRE_ACK_RBF'] l1, l2 = node_factory.get_nodes(2, @@ -611,13 +609,10 @@ def test_rbf_reconnect_ack(node_factory, bitcoind, chainparams): def test_rbf_reconnect_tx_construct(node_factory, bitcoind, chainparams): disconnects = ['=WIRE_TX_ADD_INPUT', # Initial funding succeeds '-WIRE_TX_ADD_INPUT', - '@WIRE_TX_ADD_INPUT', '+WIRE_TX_ADD_INPUT', '-WIRE_TX_ADD_OUTPUT', - '@WIRE_TX_ADD_OUTPUT', '+WIRE_TX_ADD_OUTPUT', '-WIRE_TX_COMPLETE', - '@WIRE_TX_COMPLETE', '+WIRE_TX_COMPLETE'] l1, l2 = node_factory.get_nodes(2, @@ -652,14 +647,14 @@ def test_rbf_reconnect_tx_construct(node_factory, bitcoind, chainparams): excess_as_change=True) # Run through TX_ADD wires - for d in disconnects[1:-3]: + for d in disconnects[1:-2]: l1.rpc.connect(l2.info['id'], 'localhost', l2.port) with pytest.raises(RpcError): l1.rpc.openchannel_bump(chan_id, chan_amount, initpsbt['psbt']) assert l1.rpc.getpeer(l2.info['id']) is not None # Now we finish off the completes failure check - for d in disconnects[-3:]: + for d in disconnects[-2:]: l1.rpc.connect(l2.info['id'], 'localhost', l2.port) bump = l1.rpc.openchannel_bump(chan_id, chan_amount, initpsbt['psbt']) with pytest.raises(RpcError): @@ -679,8 +674,6 @@ def test_rbf_reconnect_tx_sigs(node_factory, bitcoind, chainparams): disconnects = ['=WIRE_TX_SIGNATURES', # Initial funding succeeds '-WIRE_TX_SIGNATURES', # When we send tx-sigs, RBF '=WIRE_TX_SIGNATURES', # When we reconnect - '@WIRE_TX_SIGNATURES', # When we RBF again - '=WIRE_TX_SIGNATURES', # When we reconnect '+WIRE_TX_SIGNATURES'] # When we RBF again l1, l2 = node_factory.get_nodes(2, @@ -753,52 +746,16 @@ def test_rbf_reconnect_tx_sigs(node_factory, bitcoind, chainparams): l1.daemon.wait_for_log('peer_in WIRE_CHANNEL_REESTABLISH') l1.daemon.wait_for_log('peer_in WIRE_TX_SIGNATURES') - # Now we initiate the RBF + # 2nd RBF bump = l1.rpc.openchannel_bump(chan_id, chan_amount, initpsbt['psbt'], funding_feerate=next_feerate) update = l1.rpc.openchannel_update(chan_id, bump['psbt']) - - # Sign our inputs, and continue signed_psbt = l1.rpc.signpsbt(update['psbt'])['signed_psbt'] # Second time we error after we send our sigs with pytest.raises(RpcError, match='Owning subdaemon dualopend died'): l1.rpc.openchannel_signed(chan_id, signed_psbt) - # We reconnect and try again. feerate should have bumped - rate = int(find_next_feerate(l1, l2)[:-5]) - # We bump the feerate to beat the min-relay fee - next_feerate = '{}perkw'.format(rate * 2) - - startweight = 42 + 172 # base weight, funding output - initpsbt = l1.rpc.utxopsbt(chan_amount, next_feerate, startweight, - prev_utxos, reservedok=True, - min_witness_weight=110, - excess_as_change=True) - - l1.rpc.connect(l2.info['id'], 'localhost', l2.port) - - # l2 gets our sigs and broadcasts them - l2.daemon.wait_for_log('peer_in WIRE_CHANNEL_REESTABLISH') - l2.daemon.wait_for_log('peer_in WIRE_TX_SIGNATURES') - l2.daemon.wait_for_log('sendrawtx exit 0') - - # Wait until we've done re-establish, if we try to - # RBF again too quickly, it'll fail since they haven't - # had time to process our sigs yet - l1.daemon.wait_for_log('peer_in WIRE_CHANNEL_REESTABLISH') - l1.daemon.wait_for_log('peer_in WIRE_TX_SIGNATURES') - - # 3rd RBF - bump = l1.rpc.openchannel_bump(chan_id, chan_amount, initpsbt['psbt'], - funding_feerate=next_feerate) - update = l1.rpc.openchannel_update(chan_id, bump['psbt']) - signed_psbt = l1.rpc.signpsbt(update['psbt'])['signed_psbt'] - - # Third time we error after we send our sigs - with pytest.raises(RpcError, match='Owning subdaemon dualopend died'): - l1.rpc.openchannel_signed(chan_id, signed_psbt) - # l2 gets our sigs l2.daemon.wait_for_log('peer_in WIRE_TX_SIGNATURES') l2.daemon.wait_for_log('sendrawtx exit 0') diff --git a/tests/test_pay.py b/tests/test_pay.py index 96922a82f41a..c74e65802445 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -307,7 +307,7 @@ def test_pay_get_error_with_update(node_factory): # channel_update, and it should patch it to include a type prefix. The # prefix 0x0102 should be in the channel_update, but not in the # onionreply (negation of 0x0102 in the RE) - l1.daemon.wait_for_log(r'Extracted channel_update 0102.*from onionreply 10070088[0-9a-fA-F]{88}') + l1.daemon.wait_for_log(r'Extracted channel_update 0102.*from onionreply 1007008a[0-9a-fA-F]{276}$') # And now monitor for l1 to apply the channel_update we just extracted wait_for(lambda: not l1.is_channel_active(chanid2)) @@ -450,7 +450,7 @@ def test_payment_failed_persistence(node_factory, executor): @pytest.mark.developer("needs DEVELOPER=1") def test_payment_duplicate_uncommitted(node_factory, executor): # We want to test two payments at the same time, before we send commit - l1 = node_factory.get_node(disconnect=['=WIRE_UPDATE_ADD_HTLC-nocommit']) + l1 = node_factory.get_node(options={'dev-disable-commit-after': 0}) l2 = node_factory.get_node() l1.rpc.connect(l2.info['id'], 'localhost', l2.port) @@ -463,7 +463,7 @@ def test_payment_duplicate_uncommitted(node_factory, executor): fut = executor.submit(l1.rpc.pay, inv1['bolt11']) # Make sure that's started... - l1.daemon.wait_for_log('dev_disconnect: =WIRE_UPDATE_ADD_HTLC-nocommit') + l1.daemon.wait_for_log('peer_out WIRE_UPDATE_ADD_HTLC') # We should see it in listsendpays payments = l1.rpc.listsendpays()['payments'] @@ -1748,7 +1748,9 @@ def listpays_nofail(b11): def test_pay_routeboost(node_factory, bitcoind, compat): """Make sure we can use routeboost information. """ # l1->l2->l3--private-->l4 - l1, l2 = node_factory.line_graph(2, announce_channels=True, wait_for_announce=True) + # Note: l1 gets upset because it extracts update for private channel. + l1, l2 = node_factory.line_graph(2, announce_channels=True, wait_for_announce=True, + opts=[{'allow_bad_gossip': True}, {}]) l3, l4, l5 = node_factory.line_graph(3, announce_channels=False, wait_for_announce=False) # This should a "could not find a route" because that's true. @@ -2809,12 +2811,12 @@ def truncate_encode(i: int): assert(e.error['data']['raw_message'] == "400f00000000000003e80000006c") -@pytest.mark.developer("needs dev-disconnect, dev-no-htlc-timeout") +@pytest.mark.developer("needs dev-disable-commit-after, dev-no-htlc-timeout") @pytest.mark.openchannel('v1') @pytest.mark.openchannel('v2') def test_partial_payment(node_factory, bitcoind, executor): # We want to test two payments at the same time, before we send commit - l1, l2, l3, l4 = node_factory.get_nodes(4, [{}] + [{'disconnect': ['=WIRE_UPDATE_ADD_HTLC-nocommit'], 'dev-no-htlc-timeout': None}] * 2 + [{'plugin': os.path.join(os.getcwd(), 'tests/plugins/print_htlc_onion.py')}]) + l1, l2, l3, l4 = node_factory.get_nodes(4, [{}] + [{'dev-disable-commit-after': 0, 'dev-no-htlc-timeout': None}] * 2 + [{'plugin': os.path.join(os.getcwd(), 'tests/plugins/print_htlc_onion.py')}]) # Two routes to l4: one via l2, and one via l3. l1.rpc.connect(l2.info['id'], 'localhost', l2.port) @@ -2925,13 +2927,15 @@ def test_partial_payment(node_factory, bitcoind, executor): groupid=1, ) - # Make sure they've done the suppress-commitment thing before we unsuppress - l2.daemon.wait_for_log(r'dev_disconnect') - l3.daemon.wait_for_log(r'dev_disconnect') + # Make sure they've got the HTLCs before we unsuppress + l2.daemon.wait_for_logs('peer_in WIRE_UPDATE_ADD_HTLC') + l3.daemon.wait_for_log('peer_in WIRE_UPDATE_ADD_HTLC') # Now continue, payments will succeed due to MPP. l2.rpc.dev_reenable_commit(l4.info['id']) l3.rpc.dev_reenable_commit(l4.info['id']) + l2.rpc.dev_reenable_commit(l1.info['id']) + l3.rpc.dev_reenable_commit(l1.info['id']) res = l1.rpc.waitsendpay(payment_hash=inv['payment_hash'], partid=1) assert res['partid'] == 1 diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 2d65f6e7f0ed..9a07d747f782 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -95,10 +95,6 @@ struct onionreply *create_onionreply(const tal_t *ctx UNNEEDED, const struct secret *shared_secret UNNEEDED, const u8 *failure_msg UNNEEDED) { fprintf(stderr, "create_onionreply called!\n"); abort(); } -/* Generated stub for delay_then_reconnect */ -void delay_then_reconnect(struct channel *channel UNNEEDED, u32 seconds_delay UNNEEDED, - const struct wireaddr_internal *addrhint TAKES UNNEEDED) -{ fprintf(stderr, "delay_then_reconnect called!\n"); abort(); } /* Generated stub for derive_channel_id */ void derive_channel_id(struct channel_id *channel_id UNNEEDED, const struct bitcoin_outpoint *outpoint UNNEEDED) @@ -130,21 +126,14 @@ bool fromwire_channeld_offer_htlc_reply(const tal_t *ctx UNNEEDED, const void *p 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_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, bool *incoming UNNEEDED, struct per_peer_state **pps UNNEEDED, u8 **features UNNEEDED) +bool fromwire_connectd_peer_connected(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, struct node_id *id UNNEEDED, struct wireaddr_internal *addr UNNEEDED, bool *incoming UNNEEDED, u8 **features UNNEEDED) { fprintf(stderr, "fromwire_connectd_peer_connected called!\n"); abort(); } -/* Generated stub for fromwire_custommsg_in */ -bool fromwire_custommsg_in(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **msg UNNEEDED) -{ fprintf(stderr, "fromwire_custommsg_in called!\n"); abort(); } -/* Generated stub for fromwire_gossipd_get_stripped_cupdate_reply */ -bool fromwire_gossipd_get_stripped_cupdate_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **stripped_update UNNEEDED) -{ fprintf(stderr, "fromwire_gossipd_get_stripped_cupdate_reply called!\n"); abort(); } -u8 *towire_hsmd_new_channel(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED, u64 dbid UNNEEDED) -{ fprintf(stderr, "towire_hsmd_new_channel called!\n"); abort(); } -bool fromwire_hsmd_new_channel_reply(const void *p UNNEEDED) -{ fprintf(stderr, "fromwire_hsmd_new_channel_reply called!\n"); abort(); } /* Generated stub for fromwire_hsmd_get_output_scriptpubkey_reply */ bool fromwire_hsmd_get_output_scriptpubkey_reply(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, u8 **script UNNEEDED) { fprintf(stderr, "fromwire_hsmd_get_output_scriptpubkey_reply called!\n"); abort(); } +/* Generated stub for fromwire_hsmd_new_channel_reply */ +bool fromwire_hsmd_new_channel_reply(const void *p UNNEEDED) +{ fprintf(stderr, "fromwire_hsmd_new_channel_reply called!\n"); abort(); } /* Generated stub for fromwire_hsmd_sign_commitment_tx_reply */ bool fromwire_hsmd_sign_commitment_tx_reply(const void *p UNNEEDED, struct bitcoin_signature *sig UNNEEDED) { fprintf(stderr, "fromwire_hsmd_sign_commitment_tx_reply called!\n"); abort(); } @@ -154,6 +143,9 @@ bool fromwire_onchaind_dev_memleak_reply(const void *p UNNEEDED, bool *leak UNNE /* Generated stub for get_block_height */ u32 get_block_height(const struct chain_topology *topo UNNEEDED) { fprintf(stderr, "get_block_height called!\n"); abort(); } +/* Generated stub for get_channel_update */ +const u8 *get_channel_update(struct channel *channel UNNEEDED) +{ fprintf(stderr, "get_channel_update called!\n"); abort(); } /* Generated stub for htlc_is_trimmed */ bool htlc_is_trimmed(enum side htlc_owner UNNEEDED, struct amount_msat htlc_amount UNNEEDED, @@ -526,11 +518,6 @@ void outpointfilter_remove(struct outpointfilter *of UNNEEDED, bool param(struct command *cmd UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t params[] UNNEEDED, ...) { fprintf(stderr, "param called!\n"); abort(); } -/* Generated stub for param_bin_from_hex */ -struct command_result *param_bin_from_hex(struct command *cmd UNNEEDED, const char *name UNNEEDED, - const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, - u8 **bin UNNEEDED) -{ fprintf(stderr, "param_bin_from_hex called!\n"); abort(); } /* Generated stub for param_bool */ struct command_result *param_bool(struct command *cmd UNNEEDED, const char *name UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, @@ -587,7 +574,7 @@ struct onionpacket *parse_onionpacket(const tal_t *ctx UNNEEDED, { fprintf(stderr, "parse_onionpacket called!\n"); abort(); } /* Generated stub for payment_failed */ void payment_failed(struct lightningd *ld UNNEEDED, const struct htlc_out *hout UNNEEDED, - const char *localfail UNNEEDED, const u8 *failmsg_needs_update UNNEEDED) + const char *localfail UNNEEDED) { fprintf(stderr, "payment_failed called!\n"); abort(); } /* Generated stub for payment_store */ void payment_store(struct lightningd *ld UNNEEDED, struct wallet_payment *payment UNNEEDED) @@ -596,41 +583,27 @@ void payment_store(struct lightningd *ld UNNEEDED, struct wallet_payment *paymen void payment_succeeded(struct lightningd *ld UNNEEDED, struct htlc_out *hout UNNEEDED, const struct preimage *rval UNNEEDED) { fprintf(stderr, "payment_succeeded called!\n"); abort(); } -/* Generated stub for peer_get_owning_subd */ -struct subd *peer_get_owning_subd(struct peer *peer UNNEEDED) -{ fprintf(stderr, "peer_get_owning_subd called!\n"); abort(); } /* Generated stub for peer_memleak_done */ void peer_memleak_done(struct command *cmd UNNEEDED, struct subd *leaker UNNEEDED) { fprintf(stderr, "peer_memleak_done called!\n"); abort(); } /* Generated stub for peer_restart_dualopend */ void peer_restart_dualopend(struct peer *peer UNNEEDED, - struct per_peer_state *pps UNNEEDED, + int peer_fd UNNEEDED, struct channel *channel UNNEEDED) { fprintf(stderr, "peer_restart_dualopend called!\n"); abort(); } /* Generated stub for peer_start_channeld */ void peer_start_channeld(struct channel *channel UNNEEDED, - struct per_peer_state *pps UNNEEDED, + int peer_fd UNNEEDED, const u8 *fwd_msg UNNEEDED, bool reconnected 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 per_peer_state *pps UNNEEDED) +void peer_start_dualopend(struct peer *peer UNNEEDED, int peer_fd UNNEEDED) { fprintf(stderr, "peer_start_dualopend called!\n"); abort(); } /* Generated stub for peer_start_openingd */ -void peer_start_openingd(struct peer *peer UNNEEDED, - struct per_peer_state *pps UNNEEDED) +void peer_start_openingd(struct peer *peer UNNEEDED, int peer_fd UNNEEDED) { fprintf(stderr, "peer_start_openingd called!\n"); abort(); } -/* Generated stub for peer_wire_is_defined */ -bool peer_wire_is_defined(u16 type UNNEEDED) -{ fprintf(stderr, "peer_wire_is_defined called!\n"); abort(); } -/* Generated stub for peer_wire_name */ -const char *peer_wire_name(int e UNNEEDED) -{ fprintf(stderr, "peer_wire_name called!\n"); abort(); } -/* Generated stub for per_peer_state_set_fds */ -void per_peer_state_set_fds(struct per_peer_state *pps UNNEEDED, - int peer_fd UNNEEDED, int gossip_fd UNNEEDED, int gossip_store_fd UNNEEDED) -{ fprintf(stderr, "per_peer_state_set_fds called!\n"); abort(); } /* Generated stub for plugin_hook_call_ */ bool plugin_hook_call_(struct lightningd *ld UNNEEDED, const struct plugin_hook *hook UNNEEDED, tal_t *cb_arg STEALS UNNEEDED) @@ -655,7 +628,7 @@ u8 *serialize_onionpacket( const struct onionpacket *packet UNNEEDED) { fprintf(stderr, "serialize_onionpacket called!\n"); abort(); } /* Generated stub for subd_release_channel */ -void subd_release_channel(struct subd *owner UNNEEDED, void *channel UNNEEDED) +void subd_release_channel(struct subd *owner UNNEEDED, const void *channel UNNEEDED) { fprintf(stderr, "subd_release_channel called!\n"); abort(); } /* Generated stub for subd_req_ */ void subd_req_(const tal_t *ctx UNNEEDED, @@ -713,18 +686,12 @@ u8 *towire_channeld_sending_commitsig_reply(const tal_t *ctx UNNEEDED) /* Generated stub for towire_channeld_specific_feerates */ u8 *towire_channeld_specific_feerates(const tal_t *ctx UNNEEDED, u32 feerate_base UNNEEDED, u32 feerate_ppm UNNEEDED) { fprintf(stderr, "towire_channeld_specific_feerates called!\n"); abort(); } -/* Generated stub for towire_connectd_connect_to_peer */ -u8 *towire_connectd_connect_to_peer(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED, u32 seconds_waited UNNEEDED, const struct wireaddr_internal *addrhint UNNEEDED) -{ fprintf(stderr, "towire_connectd_connect_to_peer called!\n"); abort(); } /* Generated stub for towire_connectd_peer_disconnected */ u8 *towire_connectd_peer_disconnected(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED) { fprintf(stderr, "towire_connectd_peer_disconnected 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 struct per_peer_state *pps UNNEEDED, const u8 *msg UNNEEDED) +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_custommsg_out */ -u8 *towire_custommsg_out(const tal_t *ctx UNNEEDED, const u8 *msg UNNEEDED) -{ fprintf(stderr, "towire_custommsg_out called!\n"); abort(); } /* Generated stub for towire_errorfmt */ u8 *towire_errorfmt(const tal_t *ctx UNNEEDED, const struct channel_id *channel UNNEEDED, @@ -745,12 +712,12 @@ u8 *towire_final_incorrect_cltv_expiry(const tal_t *ctx UNNEEDED, u32 cltv_expir /* Generated stub for towire_final_incorrect_htlc_amount */ u8 *towire_final_incorrect_htlc_amount(const tal_t *ctx UNNEEDED, struct amount_msat incoming_htlc_amt UNNEEDED) { fprintf(stderr, "towire_final_incorrect_htlc_amount called!\n"); abort(); } -/* Generated stub for towire_gossipd_get_stripped_cupdate */ -u8 *towire_gossipd_get_stripped_cupdate(const tal_t *ctx UNNEEDED, const struct short_channel_id *channel_id UNNEEDED) -{ fprintf(stderr, "towire_gossipd_get_stripped_cupdate called!\n"); abort(); } /* Generated stub for towire_hsmd_get_output_scriptpubkey */ u8 *towire_hsmd_get_output_scriptpubkey(const tal_t *ctx UNNEEDED, u64 channel_id UNNEEDED, const struct node_id *peer_id UNNEEDED, const struct pubkey *commitment_point UNNEEDED) { fprintf(stderr, "towire_hsmd_get_output_scriptpubkey called!\n"); abort(); } +/* Generated stub for towire_hsmd_new_channel */ +u8 *towire_hsmd_new_channel(const tal_t *ctx UNNEEDED, const struct node_id *id UNNEEDED, u64 dbid UNNEEDED) +{ fprintf(stderr, "towire_hsmd_new_channel called!\n"); abort(); } /* Generated stub for towire_hsmd_sign_commitment_tx */ u8 *towire_hsmd_sign_commitment_tx(const tal_t *ctx UNNEEDED, const struct node_id *peer_id UNNEEDED, u64 channel_dbid UNNEEDED, const struct bitcoin_tx *tx UNNEEDED, const struct pubkey *remote_funding_key UNNEEDED) { fprintf(stderr, "towire_hsmd_sign_commitment_tx called!\n"); abort(); } @@ -798,6 +765,10 @@ u8 *towire_warningfmt(const tal_t *ctx UNNEEDED, const struct channel_id *channel UNNEEDED, const char *fmt UNNEEDED, ...) { fprintf(stderr, "towire_warningfmt called!\n"); abort(); } +/* Generated stub for try_reconnect */ +void try_reconnect(struct channel *channel UNNEEDED, u32 seconds_delay UNNEEDED, + const struct wireaddr_internal *addrhint TAKES UNNEEDED) +{ fprintf(stderr, "try_reconnect called!\n"); abort(); } /* Generated stub for watch_txid */ struct txwatch *watch_txid(const tal_t *ctx UNNEEDED, struct chain_topology *topo UNNEEDED, diff --git a/wire/Makefile b/wire/Makefile index 9651eaf1e895..44380df67b91 100644 --- a/wire/Makefile +++ b/wire/Makefile @@ -10,7 +10,6 @@ WIRE_HEADERS := wire/onion_defs.h \ wire/peer$(EXP)_wiregen.h \ wire/onion$(EXP)_wiregen.h \ wire/bolt12$(EXP)_wiregen.h \ - wire/common_wiregen.h \ wire/channel_type_wiregen.h \ wire/peer$(EXP)_printgen.h \ wire/onion$(EXP)_printgen.h @@ -22,7 +21,6 @@ WIRE_SRC := wire/wire_sync.c \ wire/peer_wire.c \ wire/tlvstream.c \ wire/towire.c \ - wire/common_wiregen.c \ wire/bolt12$(EXP)_wiregen.c \ wire/peer$(EXP)_wiregen.c \ wire/channel_type_wiregen.c \ diff --git a/wire/common_wire.csv b/wire/common_wire.csv deleted file mode 100644 index 7e607c806ccc..000000000000 --- a/wire/common_wire.csv +++ /dev/null @@ -1,10 +0,0 @@ -# A custom message that we got from a peer and don't know how to handle, so we -# forward it to the master for further handling. -msgtype,custommsg_in,1030 -msgdata,custommsg_in,msg_len,u16, -msgdata,custommsg_in,msg,u8,msg_len - -# A custom message that the master tells us to send to the peer. -msgtype,custommsg_out,1031 -msgdata,custommsg_out,msg_len,u16, -msgdata,custommsg_out,msg,u8,msg_len diff --git a/wire/peer_wire.c b/wire/peer_wire.c index 340085d282cc..35089e48f1d7 100644 --- a/wire/peer_wire.c +++ b/wire/peer_wire.c @@ -1,4 +1,5 @@ #include "config.h" +#include #include static bool unknown_type(enum peer_wire t) @@ -64,9 +65,63 @@ bool is_msg_for_gossipd(const u8 *cursor) case WIRE_REPLY_SHORT_CHANNEL_IDS_END: case WIRE_QUERY_CHANNEL_RANGE: case WIRE_REPLY_CHANNEL_RANGE: + return true; + case WIRE_WARNING: + case WIRE_INIT: + case WIRE_PING: + case WIRE_PONG: + case WIRE_ERROR: + case WIRE_OPEN_CHANNEL: + case WIRE_ACCEPT_CHANNEL: + case WIRE_FUNDING_CREATED: + case WIRE_FUNDING_SIGNED: + case WIRE_FUNDING_LOCKED: + case WIRE_SHUTDOWN: + case WIRE_CLOSING_SIGNED: + case WIRE_UPDATE_ADD_HTLC: + case WIRE_UPDATE_FULFILL_HTLC: + case WIRE_UPDATE_FAIL_HTLC: + case WIRE_UPDATE_FAIL_MALFORMED_HTLC: + case WIRE_COMMITMENT_SIGNED: + case WIRE_REVOKE_AND_ACK: + case WIRE_UPDATE_FEE: + case WIRE_UPDATE_BLOCKHEIGHT: + case WIRE_CHANNEL_REESTABLISH: + case WIRE_ANNOUNCEMENT_SIGNATURES: + case WIRE_GOSSIP_TIMESTAMP_FILTER: + case WIRE_TX_ADD_INPUT: + case WIRE_TX_REMOVE_INPUT: + case WIRE_TX_ADD_OUTPUT: + case WIRE_TX_REMOVE_OUTPUT: + case WIRE_TX_COMPLETE: + case WIRE_TX_SIGNATURES: + case WIRE_OPEN_CHANNEL2: + case WIRE_ACCEPT_CHANNEL2: + case WIRE_INIT_RBF: + case WIRE_ACK_RBF: case WIRE_OBS2_ONION_MESSAGE: case WIRE_ONION_MESSAGE: +#if EXPERIMENTAL_FEATURES + case WIRE_STFU: +#endif + break; + } + return false; +} + +bool is_msg_gossip_broadcast(const u8 *cursor) +{ + switch ((enum peer_wire)fromwire_peektype(cursor)) { + case WIRE_CHANNEL_ANNOUNCEMENT: + case WIRE_NODE_ANNOUNCEMENT: + case WIRE_CHANNEL_UPDATE: return true; + case WIRE_QUERY_SHORT_CHANNEL_IDS: + case WIRE_REPLY_SHORT_CHANNEL_IDS_END: + case WIRE_QUERY_CHANNEL_RANGE: + case WIRE_REPLY_CHANNEL_RANGE: + case WIRE_ONION_MESSAGE: + case WIRE_OBS2_ONION_MESSAGE: case WIRE_WARNING: case WIRE_INIT: case WIRE_PING: @@ -118,38 +173,234 @@ bool is_unknown_msg_discardable(const u8 *cursor) /* Extract channel_id from various packets, return true if possible. */ bool extract_channel_id(const u8 *in_pkt, struct channel_id *channel_id) { - struct amount_sat ignored_sat; - struct amount_msat ignored_msat; - u64 ignored_u64; - u32 ignored_u32; - u16 ignored_u16; - u8 ignored_u8; - struct pubkey ignored_pubkey; - struct bitcoin_blkid ignored_chainhash; - struct secret ignored_secret; - struct tlv_open_channel_tlvs *tlvs = tlv_open_channel_tlvs_new(tmpctx); -#if EXPERIMENTAL_FEATURES - struct tlv_channel_reestablish_tlvs *reestab_tlvs = tlv_channel_reestablish_tlvs_new(tmpctx); -#endif + const u8 *cursor = in_pkt; + size_t max = tal_bytelen(in_pkt); + enum peer_wire t; - if (fromwire_channel_reestablish(in_pkt, channel_id, - &ignored_u64, &ignored_u64, - &ignored_secret, &ignored_pubkey + t = fromwire_u16(&cursor, &max); + + /* We carefully quote bolts here, in case anything changes! */ + switch (t) { + /* These ones don't have a channel_id */ + case WIRE_INIT: + case WIRE_PING: + case WIRE_PONG: + case WIRE_CHANNEL_ANNOUNCEMENT: + case WIRE_NODE_ANNOUNCEMENT: + case WIRE_CHANNEL_UPDATE: + case WIRE_QUERY_SHORT_CHANNEL_IDS: + case WIRE_REPLY_SHORT_CHANNEL_IDS_END: + case WIRE_QUERY_CHANNEL_RANGE: + case WIRE_REPLY_CHANNEL_RANGE: + case WIRE_GOSSIP_TIMESTAMP_FILTER: + case WIRE_OBS2_ONION_MESSAGE: + case WIRE_ONION_MESSAGE: + return false; + + /* Special cases: */ + case WIRE_ERROR: + /* BOLT #1: + * 1. type: 17 (`error`) + * 2. data: + * * [`channel_id`:`channel_id`] + *... + * The channel is referred to by `channel_id`, unless + * `channel_id` is 0 + */ + /* fall thru */ + case WIRE_WARNING: + /* BOLT-warning #1: + * 1. type: 1 (`warning`) + * 2. data: + * * [`channel_id`:`channel_id`] + *... + * The channel is referred to by `channel_id`, unless + * `channel_id` is 0 + */ + if (!fromwire_channel_id(&cursor, &max, channel_id)) + return false; + if (memeqzero(channel_id->id, sizeof(channel_id->id))) + return false; + return true; + + case WIRE_OPEN_CHANNEL: + /* BOLT #2: + * 1. type: 32 (`open_channel`) + * 2. data: + * * [`chain_hash`:`chain_hash`] + * * [`32*byte`:`temporary_channel_id`] + */ + case WIRE_OPEN_CHANNEL2: + /* BOLT-dualfund #2: + * 1. type: 64 (`open_channel2`) + * 2. data: + * * [`chain_hash`:`chain_hash`] + * * [`channel_id`:`zerod_channel_id`] + */ + + /* Skip over chain_hash */ + fromwire_pad(&cursor, &max, sizeof(struct bitcoin_blkid)); + + /* These have them at the start */ + case WIRE_TX_ADD_INPUT: + /* BOLT-dualfund #2: + * 1. type: 66 (`tx_add_input`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_TX_ADD_OUTPUT: + /* BOLT-dualfund #2: + * 1. type: 67 (`tx_add_output`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_TX_REMOVE_INPUT: + /* BOLT-dualfund #2: + * 1. type: 68 (`tx_remove_input`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_TX_REMOVE_OUTPUT: + /* BOLT-dualfund #2: + * 1. type: 69 (`tx_remove_output`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_TX_COMPLETE: + /* BOLT-dualfund #2: + * 1. type: 70 (`tx_complete`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_TX_SIGNATURES: + /* BOLT-dualfund #2: + * 1. type: 71 (`tx_signatures`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_ACCEPT_CHANNEL: + /* BOLT #2: + * 1. type: 33 (`accept_channel`) + * 2. data: + * * [`32*byte`:`temporary_channel_id`] + */ + case WIRE_FUNDING_CREATED: + /* BOLT #2: + * 1. type: 34 (`funding_created`) + * 2. data: + * * [`32*byte`:`temporary_channel_id`] + */ + case WIRE_FUNDING_SIGNED: + /* BOLT #2: + * 1. type: 35 (`funding_signed`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_FUNDING_LOCKED: + /* BOLT #2: + * 1. type: 36 (`funding_locked`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_ACCEPT_CHANNEL2: + /* BOLT-dualfund #2: + * 1. type: 65 (`accept_channel2`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_INIT_RBF: + /* BOLT-dualfund #2: + * 1. type: 72 (`init_rbf`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_ACK_RBF: + /* BOLT-dualfund #2: + * 1. type: 73 (`ack_rbf`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_SHUTDOWN: + /* BOLT #2: + * 1. type: 38 (`shutdown`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_CLOSING_SIGNED: + /* BOLT #2: + * 1. type: 39 (`closing_signed`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_UPDATE_ADD_HTLC: + /* BOLT #2: + * 1. type: 128 (`update_add_htlc`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_UPDATE_FULFILL_HTLC: + /* BOLT #2: + * 1. type: 130 (`update_fulfill_htlc`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_UPDATE_FAIL_HTLC: + /* BOLT #2: + * 1. type: 131 (`update_fail_htlc`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_UPDATE_FAIL_MALFORMED_HTLC: + /* BOLT #2: + * 1. type: 135 (`update_fail_malformed_htlc`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_COMMITMENT_SIGNED: + /* BOLT #2: + * 1. type: 132 (`commitment_signed`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_REVOKE_AND_ACK: + /* BOLT #2: + * 1. type: 133 (`revoke_and_ack`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_UPDATE_FEE: + /* BOLT #2: + * 1. type: 134 (`update_fee`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_UPDATE_BLOCKHEIGHT: + /* BOLT-liquidity-ads #2: + * 1. type: 137 (`update_blockheight`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_CHANNEL_REESTABLISH: + /* BOLT #2: + * 1. type: 136 (`channel_reestablish`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ + case WIRE_ANNOUNCEMENT_SIGNATURES: + /* BOLT #7: + * 1. type: 259 (`announcement_signatures`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ #if EXPERIMENTAL_FEATURES - , reestab_tlvs + case WIRE_STFU: + /* BOLT-quiescent #2: + * 1. type: 2 (`stfu`) + * 2. data: + * * [`channel_id`:`channel_id`] + */ #endif - )) - return true; - if (fromwire_open_channel(in_pkt, &ignored_chainhash, - channel_id, &ignored_sat, - &ignored_msat, &ignored_sat, - &ignored_msat, &ignored_sat, - &ignored_msat, &ignored_u32, - &ignored_u16, &ignored_u16, - &ignored_pubkey, &ignored_pubkey, - &ignored_pubkey, &ignored_pubkey, - &ignored_pubkey, &ignored_pubkey, - &ignored_u8, tlvs)) - return true; + return fromwire_channel_id(&cursor, &max, channel_id); + } return false; } diff --git a/wire/peer_wire.h b/wire/peer_wire.h index 12c951b8ff3e..d57a84d20bd7 100644 --- a/wire/peer_wire.h +++ b/wire/peer_wire.h @@ -23,6 +23,8 @@ bool is_unknown_msg_discardable(const u8 *cursor); /* Return true if it's a message for gossipd. */ bool is_msg_for_gossipd(const u8 *cursor); +/* Return true if it's a gossip update or announcement. */ +bool is_msg_gossip_broadcast(const u8 *cursor); /* Extract channel_id from various packets, return true if possible. */ bool extract_channel_id(const u8 *in_pkt, struct channel_id *channel_id); diff --git a/wire/test/run-tlvstream.c b/wire/test/run-tlvstream.c index b658d85f89d9..76b27b61252e 100644 --- a/wire/test/run-tlvstream.c +++ b/wire/test/run-tlvstream.c @@ -26,7 +26,7 @@ static const char *reason; const struct chainparams *chainparams_by_chainhash(const struct bitcoin_blkid *chain_hash UNNEEDED) { fprintf(stderr, "chainparams_by_chainhash called!\n"); abort(); } /* Generated stub for fromwire_channel_id */ -void fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, +bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct channel_id *channel_id UNNEEDED) { fprintf(stderr, "fromwire_channel_id called!\n"); abort(); } /* Generated stub for towire_channel_id */ diff --git a/wire/wire_io.h b/wire/wire_io.h index fd6d773c349e..3dd7e55a1194 100644 --- a/wire/wire_io.h +++ b/wire/wire_io.h @@ -27,7 +27,7 @@ struct io_plan *io_read_wire_(struct io_conn *conn, /* Write message from data (tal_count(data) gives length). data can be take() */ struct io_plan *io_write_wire_(struct io_conn *conn, - const u8 *data, + const u8 *data TAKES, struct io_plan *(*next)(struct io_conn *, void *), void *next_arg);